|
@@ -10,6 +10,8 @@
|
|
|
#import "UIDevice+MKRRadioManagerAdd.h"
|
|
|
#import <pthread.h>
|
|
|
#import <libAS-Control/ASControlTools.h>
|
|
|
+#import <libAS-Control/NSDictionary+MKRXml.h>
|
|
|
+#import <NSHashTable+MKRRadioManagerAdd.h>
|
|
|
|
|
|
static inline void wd_main_queue(void (^block)(void)){
|
|
|
if (pthread_main_np()) {
|
|
@@ -19,10 +21,18 @@ static inline void wd_main_queue(void (^block)(void)){
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static inline void wd_playControl_queue(void (^block)(void)){
|
|
|
+ dispatch_queue_t queue = dispatch_queue_create("com.maoking.playControlQueue", DISPATCH_QUEUE_SERIAL);
|
|
|
+ dispatch_async(queue, block);
|
|
|
+}
|
|
|
+
|
|
|
@interface MKRWIFIDeviceManager () <ASControlDelegate> {
|
|
|
int _upnpErrorCode;
|
|
|
NSMutableArray *_baseUrlArray;
|
|
|
dispatch_source_t _searchTimer;
|
|
|
+ NSString *_ssid;
|
|
|
+ BOOL _shutDownUpnping;
|
|
|
+ BOOL _updateLocalResourceLock;
|
|
|
}
|
|
|
|
|
|
@property (nonatomic, strong) NSHashTable *listeners;
|
|
@@ -34,7 +44,9 @@ static inline void wd_main_queue(void (^block)(void)){
|
|
|
- (instancetype)init {
|
|
|
if (self = [super init]) {
|
|
|
_upnpErrorCode = -1;
|
|
|
- [self startUpnp];
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ [self startUpnp];
|
|
|
+ });
|
|
|
[ASControlTools sharedInstanceUPNP].delegate = self;
|
|
|
}
|
|
|
return self;
|
|
@@ -81,15 +93,53 @@ static inline void wd_main_queue(void (^block)(void)){
|
|
|
return _upnpErrorCode;
|
|
|
}
|
|
|
|
|
|
+- (void)stopUpnp{
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ libupnp_StopBuildFilesList();
|
|
|
+ [NSThread sleepForTimeInterval:5];
|
|
|
+ if(_upnpErrorCode == 0){
|
|
|
+ libupnp_UpnpQuickExit();
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (void)reloadUpnp{
|
|
|
+ NSString *ssid = [UIDevice currentSSID];
|
|
|
+ if ([ssid isEqualToString:_ssid]) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (_shutDownUpnping) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ _ssid = ssid;
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ _shutDownUpnping = YES;
|
|
|
+ libupnp_StopBuildFilesList();
|
|
|
+ int exitCount = 0;
|
|
|
+ while (_updateLocalResourceLock) {
|
|
|
+ exitCount++;
|
|
|
+ [NSThread sleepForTimeInterval:1.0];
|
|
|
+ if (exitCount > 10)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ _updateLocalResourceLock = NO;
|
|
|
+ [self searchDeviceWithSearchTime:20 timeBlock:nil];
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
- (void)searchDeviceWithSearchTime:(int)searchTime
|
|
|
timeBlock:(void(^)(NSInteger time))timeBlock {
|
|
|
- if (_upnpErrorCode == 0) {//开始搜索设备
|
|
|
- [self checkBaseURL];
|
|
|
- libupnp_BuildFilesList();
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ _updateLocalResourceLock = YES;
|
|
|
+ if (_upnpErrorCode != 0) {
|
|
|
+ if ([self startUpnp] == 0) {
|
|
|
+ [self checkBaseURL];
|
|
|
+ libupnp_BuildFilesList();
|
|
|
+ }
|
|
|
+ }
|
|
|
libupnp_SearchDevice(20);
|
|
|
- } else {
|
|
|
- [self startUpnp];
|
|
|
- }
|
|
|
+ });
|
|
|
+ _ssid = [UIDevice currentSSID];
|
|
|
__block int count = searchTime +1;
|
|
|
_searchTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
|
|
|
dispatch_source_set_timer(_searchTimer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
|
|
@@ -128,19 +178,42 @@ static inline void wd_main_queue(void (^block)(void)){
|
|
|
#pragma mark - ASControlDelegate
|
|
|
|
|
|
-(void)ReceivedPlayCallBack:(NSString *)nUDN{
|
|
|
- NSLog(@"%s",__func__);
|
|
|
+ NSLog(@"收到播放回调%@",nUDN);
|
|
|
+ wd_main_queue(^{
|
|
|
+ if ([nUDN containsString:self.device.deviceUUID]) {
|
|
|
+ self.currentResource.resourceStatus.playState = MKRResourcePlayStatePlaying;
|
|
|
+ [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceivePlayStateChange:),MKRResourcePlayStatePlaying];
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-(void)ReceivedPauseCallBack:(NSString *)nUDN{
|
|
|
- NSLog(@"%s",__func__);
|
|
|
+ NSLog(@"收到暂停回调%@",nUDN);
|
|
|
+ wd_main_queue(^{
|
|
|
+ if ([nUDN containsString:self.device.deviceUUID]) {
|
|
|
+ self.currentResource.resourceStatus.playState = MKRResourcePlayStatePause;
|
|
|
+ [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceivePlayStateChange:),MKRResourcePlayStatePause];
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-(void)ReceivedStopCallBack:(NSString *)nUDN{
|
|
|
- NSLog(@"%s",__func__);
|
|
|
+ NSLog(@"收到停止回调%@",nUDN);
|
|
|
+ wd_main_queue(^{
|
|
|
+ if ([nUDN containsString:self.device.deviceUUID]) {
|
|
|
+ self.currentResource.resourceStatus.playState = MKRResourcePlayStateStopped;
|
|
|
+ [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceivePlayStateChange:),MKRResourcePlayStateStopped];
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-(void)ReceivedSetVolumeCallBack:(NSString *)nUDN Volume:(NSInteger)Volume{
|
|
|
- NSLog(@"%s",__func__);
|
|
|
+ wd_main_queue(^{
|
|
|
+ if ([nUDN containsString:self.device.deviceUUID]) {
|
|
|
+ NSLog(@"收到设备音量回调SetZoneVolumeCallBack:%zd",Volume);
|
|
|
+ [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceiveVolumeChange:),(float)Volume];
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-(void)ReceivedSetMuteCallBack:(NSString *)nUDN Mute:(NSInteger)Mute{
|
|
@@ -173,7 +246,9 @@ static inline void wd_main_queue(void (^block)(void)){
|
|
|
|
|
|
-(void)CallBackRemoveZoneMedia:(NSString *)nByeUDN BaseURL:(NSString *)BaseURL{
|
|
|
NSLog(@"%s",__func__);
|
|
|
-
|
|
|
+ wd_main_queue(^{
|
|
|
+ [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceiveDeviceOffline:),nByeUDN];
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-(void)CallBackRemoveRenderer:(NSString *)nByeUDN BaseURL:(NSString *)BaseURL
|
|
@@ -189,7 +264,9 @@ static inline void wd_main_queue(void (^block)(void)){
|
|
|
-(void)CallBackAddZoneMedia:(NSArray *)nStr Size:(NSInteger)size{
|
|
|
NSLog(@"搜索到设备:%@",nStr);
|
|
|
NSLog(@"%s",__func__);
|
|
|
- [self addDevice:nStr];
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ [self addDevice:nStr];
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- (void)updateClockID:(NSString *)clockID clockDic:(NSDictionary *)clockDic clockTime:(NSString *)clockTime operationType:(BOOL)isOn deleteClock:(BOOL)isDelete{
|
|
@@ -208,6 +285,12 @@ static inline void wd_main_queue(void (^block)(void)){
|
|
|
|
|
|
-(void)ReceivedChangeChannelCallBack:(NSString *)nUDN Channel:(NSString *)channel{
|
|
|
NSLog(@"%s",__func__);
|
|
|
+ NSLog(@"收到频道改变回调%@",nUDN);
|
|
|
+ wd_main_queue(^{
|
|
|
+ if ([nUDN containsString:self.device.deviceUUID]) {
|
|
|
+ [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceivePlayingChannelChange:),[channel integerValue]];
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-(void)getLocalIp:(NSString *)Ip{
|
|
@@ -242,6 +325,7 @@ static inline void wd_main_queue(void (^block)(void)){
|
|
|
[deviceDict setObject:[deviceInfo[28] length]?deviceInfo[28]:@"WIFI" forKey:@"devSourceList"];
|
|
|
[deviceDict setObject:deviceInfo[12] forKey:@"channelLR"];
|
|
|
[deviceDict setObject:[deviceInfo[29] length] ? deviceInfo[29]: @"0.0.0.0" forKey:@"devType"];
|
|
|
+ [deviceDict setObject:[deviceInfo[32] length] ? deviceInfo[32]: @"" forKey:@"deviceClockInfo"];
|
|
|
[deviceDict setObject:[deviceInfo[33] length]? deviceInfo[33]:@"NULL" forKey:@"devPower"];
|
|
|
[deviceDict setObject:[deviceInfo[36] length] ? deviceInfo[36]:@"NULL" forKey:@"devUserID"];
|
|
|
NSString *devFlag = [NSString stringWithFormat:@"%@-%@",deviceInfo[9],deviceInfo[10]];
|
|
@@ -256,7 +340,7 @@ static inline void wd_main_queue(void (^block)(void)){
|
|
|
[deviceDict setObject:[deviceInfo[40] length] ?deviceInfo[40] :@"-1" forKey:@"devPauseShutDownTime"];
|
|
|
NSString *devNowStatus = [deviceInfo[2] length] ? deviceInfo[2] : @"STOPPED";
|
|
|
[deviceDict setObject:devNowStatus forKey:@"devNowStatus"];
|
|
|
- [deviceDict setObject:@"REPEAT_ALL" forKey:@"devNowPlayMode"];
|
|
|
+ [deviceDict setObject:[deviceInfo[30] length] ?deviceInfo[30] :@"REPEAT_ALL" forKey:@"devNowPlayMode"];
|
|
|
NSURL *url = [NSURL URLWithString:array[2]];
|
|
|
[deviceDict setObject:url.URLByDeletingLastPathComponent.absoluteString?:@"" forKey:@"devIP"];
|
|
|
if([devNowStatus isEqualToString:@"PAUSED_PLAYBACK"]){
|
|
@@ -277,175 +361,406 @@ static inline void wd_main_queue(void (^block)(void)){
|
|
|
[deviceDict setObject:@"Unknown" forKey:@"devNowArtist"];
|
|
|
}
|
|
|
[deviceDict setObject:@"1" forKey:@"isOnLine"];
|
|
|
- id<MKRWIFIDeviceManagerDelegate> obj;
|
|
|
- NSEnumerator *enumerator = [self.listeners objectEnumerator];
|
|
|
- while ((obj = [enumerator nextObject]) != nil) {
|
|
|
- wd_main_queue(^{
|
|
|
+ wd_main_queue(^{
|
|
|
+ id<MKRWIFIDeviceManagerDelegate> obj;
|
|
|
+ NSEnumerator *enumerator = [self.listeners objectEnumerator];
|
|
|
+ while ((obj = [enumerator nextObject]) != nil) {
|
|
|
if ([obj respondsToSelector:@selector(didSearchNewDevice:)]) {
|
|
|
[obj didSearchNewDevice:deviceDict];
|
|
|
}
|
|
|
- });
|
|
|
- }
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-- (void)setM3UList:(MKRM3UListModel *)m3uListModel {
|
|
|
- libupnp_SetNewM3UList(
|
|
|
- m3uListModel.secondsList,
|
|
|
- m3uListModel.artistList,
|
|
|
- m3uListModel.titleList,
|
|
|
- m3uListModel.urlList,
|
|
|
- m3uListModel.cueList,
|
|
|
- m3uListModel.startTimeList,
|
|
|
- m3uListModel.endTimeList,
|
|
|
- m3uListModel.vipCanPlay,
|
|
|
- m3uListModel.albumList,
|
|
|
- m3uListModel.albumArtUriList,
|
|
|
- m3uListModel.durationList,
|
|
|
- m3uListModel.protocolInfoList,
|
|
|
- m3uListModel.upnpclassList,
|
|
|
- m3uListModel.channelNumList,
|
|
|
- m3uListModel.songOrderList,
|
|
|
- m3uListModel.userID,
|
|
|
- m3uListModel.songIDList,
|
|
|
- m3uListModel.songFromList,
|
|
|
- m3uListModel.songAlbumIDList,
|
|
|
- m3uListModel.channelNO,
|
|
|
- m3uListModel.playModeString,
|
|
|
- m3uListModel.timeString,
|
|
|
- m3uListModel.channelPure,
|
|
|
- m3uListModel.channelAlbumID,
|
|
|
- m3uListModel.channelInfoString,
|
|
|
- m3uListModel.userID,
|
|
|
- m3uListModel.startIndex,
|
|
|
- m3uListModel.endIndex,
|
|
|
- m3uListModel.m3uSize,
|
|
|
- @""
|
|
|
- );
|
|
|
+- (void)setM3UList:(MKRM3UListModel *)m3uListModel{
|
|
|
+ self.currentTempM3UListModel = m3uListModel;
|
|
|
+ libupnp_SetNewM3UListV2(m3uListModel.secondsList,
|
|
|
+ m3uListModel.artistList,
|
|
|
+ m3uListModel.titleList,
|
|
|
+ m3uListModel.urlList,
|
|
|
+ m3uListModel.songFromList,
|
|
|
+ m3uListModel.vipCanPlay,
|
|
|
+ m3uListModel.channelNO,
|
|
|
+ m3uListModel.playModeString,
|
|
|
+ m3uListModel.timeString,
|
|
|
+ m3uListModel.startIndex,
|
|
|
+ m3uListModel.endIndex,
|
|
|
+ m3uListModel.m3uSize,
|
|
|
+ m3uListModel.channelID,
|
|
|
+ m3uListModel.channelInfoString);
|
|
|
}
|
|
|
|
|
|
- (void)setAVTransportURIWithSong:(id <MKRRadioResorce>)song
|
|
|
- device:(id <MKRUPnPDevice>)device
|
|
|
- userID:(NSString *)userID {
|
|
|
+ device:(id <MKRUPnPDevice>)device{
|
|
|
NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
|
|
|
- NSString *channelNumString = [NSString stringWithFormat:@"CHANNEL_UPDATE_%zd",song.songChannel];
|
|
|
- libupnp_SetAVTransportURI(
|
|
|
- device.avTransportUrl,
|
|
|
- song.songUrl,
|
|
|
- song.songName,
|
|
|
- song.songArtist,
|
|
|
- song.songAlbum,
|
|
|
- song.songAlbumCover,
|
|
|
- @"0",
|
|
|
- @"null",
|
|
|
- @"null",
|
|
|
- timestamp,
|
|
|
- channelNumString,
|
|
|
- @"0",
|
|
|
- userID,
|
|
|
- @(song.songID).stringValue,
|
|
|
- @(song.songFrom).stringValue,
|
|
|
- song.songAlbumID?:@""
|
|
|
- );
|
|
|
+ NSString *channelNumString = @(song.songChannel).stringValue;
|
|
|
+ NSString *userID = self.userID;
|
|
|
+ NSString *songUrlString = [NSString stringWithFormat:@"AIRSMART//ID_%zd//",song.songID];
|
|
|
+ NSString *songFrom = [NSString stringWithFormat:@"1//%zd//%zd//",[MKRM3UListModel convertAudioTypeWithSorceType:song.sourceType],song.songID];
|
|
|
+ libupnp_SetAVTransportURIV2(
|
|
|
+ device.avTransportUrl,
|
|
|
+ songUrlString,
|
|
|
+ song.songName?:@"",
|
|
|
+ song.songArtist?:@"",
|
|
|
+ song.songAlbum?:@"",
|
|
|
+ song.songAlbumCover?:@"",
|
|
|
+ @"0",
|
|
|
+ @"null",
|
|
|
+ @"null",
|
|
|
+ timestamp,
|
|
|
+ channelNumString,
|
|
|
+ @"0",
|
|
|
+ userID?:@"",
|
|
|
+ @(song.songID).stringValue,
|
|
|
+ songFrom,
|
|
|
+ song.songAlbumID?:@""
|
|
|
+ );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- (void)playWithDevice:(id <MKRUPnPDevice>)device {
|
|
|
- libupnp_Play(device.avTransportUrl);
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ libupnp_Play(device.avTransportUrl);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-- (void)playSongWithChannelNO:(NSInteger)channelNO
|
|
|
- index:(NSInteger)index
|
|
|
- device:(id <MKRUPnPDevice>)device
|
|
|
- userID:(NSString *)userID {
|
|
|
- NSString *playFlag = [NSString stringWithFormat:@"%zd-%zd",channelNO,index];
|
|
|
+- (void)_playPlayFlag:(NSString *)playFlag
|
|
|
+ device:(id <MKRUPnPDevice>)device
|
|
|
+ timeStamp:(NSTimeInterval)timeStamp{
|
|
|
NSString *playListUrl = [NSString stringWithFormat:@"%@/web/playlist",[ASControlTools sharedInstanceUPNP].myIp];
|
|
|
- NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
|
|
|
- libupnp_PlayNumFlag(
|
|
|
- device.avTransportUrl,
|
|
|
- playFlag,
|
|
|
- timestamp,
|
|
|
- userID,
|
|
|
- playListUrl,
|
|
|
- @"1"
|
|
|
- );
|
|
|
+ NSString *timestamp = [NSString stringWithFormat:@"%.0f", timeStamp];
|
|
|
+ NSString *userID = self.userID;
|
|
|
+ libupnp_PlayNumFlagV2(
|
|
|
+ device.avTransportUrl,
|
|
|
+ playFlag,
|
|
|
+ timestamp,
|
|
|
+ userID,
|
|
|
+ playListUrl,
|
|
|
+ @"0"
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+- (void)playSongWithChannelNO:(NSInteger)channelNO
|
|
|
+ firstPlayingSong:(id<MKRRadioResorce>)firstPlayingSong
|
|
|
+ device:(id<MKRUPnPDevice>)device
|
|
|
+ timeStamp:(NSTimeInterval)timeStamp{
|
|
|
+ self.currentTempM3UListModel = nil;
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ NSString *playFlag = [NSString stringWithFormat:@"%zd",channelNO];
|
|
|
+ [self _playPlayFlag:playFlag device:device timeStamp:timeStamp];
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- (void)playSongWithChannelNO:(NSInteger)channelNO
|
|
|
- device:(id <MKRUPnPDevice>)device
|
|
|
- userID:(NSString *)userID {
|
|
|
- [self playSongWithChannelNO:channelNO index:0 device:device userID:userID];
|
|
|
+ firstPlayingSong:(id<MKRRadioResorce>)firstPlayingSong
|
|
|
+ index:(NSInteger)index
|
|
|
+ device:(id<MKRUPnPDevice>)device
|
|
|
+ timeStamp:(NSTimeInterval)timeStamp{
|
|
|
+ self.currentTempM3UListModel = nil;
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ if (firstPlayingSong && firstPlayingSong.songID) {
|
|
|
+ [self setAVTransportURIWithSong:firstPlayingSong device:device];
|
|
|
+ }
|
|
|
+ NSString *playFlag = [NSString stringWithFormat:@"%zd-%zd",channelNO,index];
|
|
|
+ [self _playPlayFlag:playFlag device:device timeStamp:timeStamp];
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (void)playTempChannelSongs:(NSArray<id<MKRRadioResorce>> *)songs
|
|
|
+ index:(NSInteger)index
|
|
|
+ device:(id<MKRUPnPDevice>)device
|
|
|
+ timeStamp:(NSTimeInterval)timeStamp{
|
|
|
+ [self playTempChannelSongs:songs index:index device:device timeStamp:timeStamp playMode:MKRRadioPlayModeOrder];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)playTempChannelSongs:(NSArray<id<MKRRadioResorce>> *)songs
|
|
|
+ index:(NSInteger)index
|
|
|
+ device:(id<MKRUPnPDevice>)device
|
|
|
+ timeStamp:(NSTimeInterval)timeStamp
|
|
|
+ playMode:(MKRRadioPlayMode)playMode{
|
|
|
+ MKRM3UListModel *m3uModel = [MKRM3UListModel tempChannelM3UModelWithSongs:songs startIndex:index];
|
|
|
+ m3uModel.userID = self.userID;
|
|
|
+ m3uModel.playModeString = [self playModeStringWithPlayMode:playMode];
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ [[MKRWIFIDeviceManager shareManager] setM3UList:m3uModel];
|
|
|
+ id <MKRRadioResorce> song = songs[index];
|
|
|
+ song.songChannel = 13;
|
|
|
+ [self setAVTransportURIWithSong:song device:device];
|
|
|
+ NSString *playFlag = [NSString stringWithFormat:@"13-%zd",index];
|
|
|
+ [self _playPlayFlag:playFlag device:device timeStamp:timeStamp];
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (void)playTempChannelSongs:(NSArray<id<MKRRadioResorce>> *)songs
|
|
|
+ device:(id<MKRUPnPDevice>)device
|
|
|
+ timeStamp:(NSTimeInterval)timeStamp{
|
|
|
+ [self playTempChannelSongs:songs device:device timeStamp:timeStamp playMode:MKRRadioPlayModeOrder];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)playTempChannelSongs:(NSArray<id<MKRRadioResorce>> *)songs
|
|
|
+ device:(id<MKRUPnPDevice>)device
|
|
|
+ timeStamp:(NSTimeInterval)timeStamp
|
|
|
+ playMode:(MKRRadioPlayMode)playMode{
|
|
|
+ MKRM3UListModel *m3uModel = [MKRM3UListModel tempChannelM3UModelWithSongs:songs startIndex:index];
|
|
|
+ m3uModel.userID = self.userID;
|
|
|
+ m3uModel.playModeString = [self playModeStringWithPlayMode:playMode];
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ [[MKRWIFIDeviceManager shareManager] setM3UList:m3uModel];
|
|
|
+ id <MKRRadioResorce> song = songs[0];
|
|
|
+ song.songChannel = 13;
|
|
|
+ [self setAVTransportURIWithSong:song device:device];
|
|
|
+ [self _playPlayFlag:@"13" device:device timeStamp:timeStamp];
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- (void)pauseWithDevice:(id <MKRUPnPDevice>)device {
|
|
|
- libupnp_Pause(device.avTransportUrl);
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ libupnp_Pause(device.avTransportUrl);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- (void)nextWithDevice:(id <MKRUPnPDevice>)device{
|
|
|
- libupnp_Previous(device.avTransportUrl);
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ libupnp_Next(device.avTransportUrl);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- (void)previousWithDevice:(id <MKRUPnPDevice>)device{
|
|
|
- libupnp_Previous(device.avTransportUrl);
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ libupnp_Previous(device.avTransportUrl);
|
|
|
+ });
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- (void)stopWithDevice:(id <MKRUPnPDevice>)device{
|
|
|
- libupnp_Stop(device.avTransportUrl);
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ libupnp_Stop(device.avTransportUrl);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- (void)setVolume:(int)volume device:(id <MKRUPnPDevice>)device{
|
|
|
- libupnp_SetZoneVolume(
|
|
|
- device.groupManagementUrl,
|
|
|
- @"urn:schemas-upnp-org:service:GroupManagement:1",
|
|
|
- @"Master",
|
|
|
- volume
|
|
|
- );
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ libupnp_SetZoneVolume(
|
|
|
+ device.groupManagementUrl,
|
|
|
+ @"urn:schemas-upnp-org:service:GroupManagement:1",
|
|
|
+ @"Master",
|
|
|
+ volume
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- (void)seekToTimeInterval:(NSInteger)timeInterval device:(id <MKRUPnPDevice>)device {
|
|
|
NSString *timeString = [NSString HHmmssFormatStrig:timeInterval];
|
|
|
- libupnp_SetMediaSeek(device.avTransportUrl, timeString);
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ libupnp_SetMediaSeek(device.avTransportUrl, timeString);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
- (void)clearChannelWithChannelNO:(NSString *)channelNO device:(id <MKRUPnPDevice>)device {
|
|
|
NSString *channelID = [NSString stringWithFormat:@"CHANNEL_UPDATE_%@",channelNO];
|
|
|
NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
|
|
|
- libupnp_SetChannelClear(device.groupManagementUrl, channelID, timestamp);
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ libupnp_SetChannelClear(device.groupManagementUrl, channelID, timestamp);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-- (id <MKRRadioResorce>)getPlayingStatusWithDevice:(id <MKRUPnPDevice>)device {
|
|
|
- NSArray *dmrPositionInfo = [[ASControlTools sharedInstanceUPNP] libupnp_GetPositionInfo:device.avTransportUrl];
|
|
|
- if (dmrPositionInfo.count < 16) {
|
|
|
- //执行检查设备是否掉线操作
|
|
|
+- (void)updateChannel:(NSString *)channelFlag device:(id<MKRUPnPDevice>)device{
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
|
|
|
+ NSInteger channelNo = [channelFlag integerValue];
|
|
|
+ NSString *playListUrl = @"null";
|
|
|
+ if (channelNo >= 13) {
|
|
|
+ playListUrl = [NSString stringWithFormat:@"%@/web/playlist",[ASControlTools sharedInstanceUPNP].myIp];
|
|
|
+ }
|
|
|
+ int result = libupnp_SetChannelUpdateV2(device.groupManagementUrl, self.userID, timestamp, channelFlag, playListUrl);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setPlayMode:(MKRRadioPlayMode)playMode device:(id<MKRUPnPDevice>)device channelNO:(NSInteger)channelNO{
|
|
|
+ NSString *playModeString = @"";
|
|
|
+ switch (playMode) {
|
|
|
+ case MKRRadioPlayModeOrder:{
|
|
|
+ playModeString = @"REPEAT_ALL";
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MKRRadioPlayModeSingle:{
|
|
|
+ playModeString = @"REPEAT_ONE";
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MKRRadioPlayModeRandom:{
|
|
|
+ playModeString = @"SHUFFLE";
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:{
|
|
|
+ playModeString = @"REPEAT_ALL";
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ NSString *channelFlag = [NSString stringWithFormat:@"CHANNEL_UPDATE_%zd",channelNO];
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ int result = libupnp_SetChannelPlayModeV2(device.groupManagementUrl, channelFlag, playModeString, self.userID);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (void)updateTempChannelPlayMode:(MKRRadioPlayMode)playMode songs:(NSArray <id <MKRRadioResorce>> *)songs index:(NSInteger)index device:(id<MKRUPnPDevice>)device{
|
|
|
+ if (!self.currentTempM3UListModel) {
|
|
|
+ MKRM3UListModel *m3uModel = [MKRM3UListModel tempChannelM3UModelWithSongs:songs startIndex:index];
|
|
|
+ m3uModel.userID = self.userID;
|
|
|
+ m3uModel.playModeString = [self playModeStringWithPlayMode:playMode];
|
|
|
+ self.currentTempM3UListModel = m3uModel;
|
|
|
}
|
|
|
- MKRRadioResorce *resource = [[MKRRadioResorce alloc] init];
|
|
|
- resource.songName = dmrPositionInfo[2];
|
|
|
- resource.songArtist = dmrPositionInfo[3];
|
|
|
- resource.songAlbumCover = dmrPositionInfo[5];
|
|
|
- resource.songUrl = dmrPositionInfo[7];
|
|
|
- resource.songID = [dmrPositionInfo[16] integerValue];
|
|
|
- NSString *songFrom = dmrPositionInfo[17];
|
|
|
- if ([songFrom containsString:@"//"]) {
|
|
|
- NSArray *arr = [songFrom componentsSeparatedByString:@"//"];
|
|
|
- if (arr.count > 1) {
|
|
|
- songFrom = arr[1];
|
|
|
+ self.currentTempM3UListModel.playModeString = [self playModeStringWithPlayMode:playMode];
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ [self setM3UList:self.currentTempM3UListModel];
|
|
|
+ [self updateChannel:@(13).stringValue device:device];
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (void)setLowPowerNoticeEnable:(BOOL)enable device:(id<MKRUPnPDevice>)device{
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ libupnp_SetLowBatteryNotification(device.groupManagementUrl,enable);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+- (NSDictionary *)parsePlayInfoString:(NSString *)playInfoXmlString{
|
|
|
+ NSMutableDictionary *resultDic = [NSMutableDictionary dictionaryWithDictionary:[NSDictionary mkr_dictionaryWithXML:playInfoXmlString]];
|
|
|
+ NSString *metaDataString = [resultDic objectForKey:@"TrackMetaData"];
|
|
|
+ if ([metaDataString isKindOfClass:NSString.class]) {
|
|
|
+ metaDataString = [metaDataString stringByReplacingOccurrencesOfString:@"&" withString:@"mkr_***"];
|
|
|
+ NSDictionary *metaDic = [NSDictionary mkr_dictionaryWithXML:metaDataString];
|
|
|
+ NSDictionary *metaItemDic = metaDic[@"item"];
|
|
|
+ if (![metaItemDic isKindOfClass:NSDictionary.class]) {
|
|
|
+ metaItemDic = @{};
|
|
|
+ }
|
|
|
+ [resultDic setObject:metaDic[@"item"]?:@{} forKey:@"TrackMetaData"];
|
|
|
+ return resultDic;
|
|
|
+ }else{
|
|
|
+ return nil;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (id <MKRRadioResorce>)getPlayingStatusWithDevice:(id <MKRUPnPDevice>)device {
|
|
|
+ wd_playControl_queue(^{
|
|
|
+ NSString *resultString = [[ASControlTools sharedInstanceUPNP] libupnp_getPlayInfoString:device.avTransportUrl];
|
|
|
+ NSMutableDictionary *resultDic = [self parsePlayInfoString:resultString];
|
|
|
+ if (!resultDic || !resultDic.allKeys.count) {
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ if ([resultDic[@"TrackMetaData"][@"upnp:songInfoID"] isKindOfClass:NSString.class]) {
|
|
|
+ NSInteger songID = [resultDic[@"TrackMetaData"][@"upnp:songInfoID"] integerValue];
|
|
|
+ if (songID != self.currentResource.songID) {
|
|
|
+ self.currentResource = [self defaultSong];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @synchronized (self.currentResource) {
|
|
|
+ if ([resultDic[@"TrackMetaData"][@"upnp:songType"] isKindOfClass:NSString.class]) {
|
|
|
+ NSInteger sourceType = [MKRM3UListModel convertSorceTypeWithAudioType:[resultDic[@"TrackMetaData"][@"upnp:songType"] integerValue]];
|
|
|
+ self.currentResource.sourceType = sourceType;
|
|
|
+ }
|
|
|
+ if ([resultDic[@"TrackMetaData"][@"upnp:songName"] isKindOfClass:NSString.class]) {
|
|
|
+ self.currentResource.songName = resultDic[@"TrackMetaData"][@"upnp:songName"];
|
|
|
+ }
|
|
|
+ if ([resultDic[@"TrackMetaData"][@"upnp:songPlayer"] isKindOfClass:NSString.class]) {
|
|
|
+ if (self.currentResource.sourceType == MKRSourceTypeHandPick || self.currentResource.sourceType == MKRSourceTypeBroadcast) {
|
|
|
+ self.currentResource.songName = resultDic[@"TrackMetaData"][@"upnp:songPlayer"];
|
|
|
+ }else{
|
|
|
+ self.currentResource.songArtist = resultDic[@"TrackMetaData"][@"upnp:songPlayer"];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ([resultDic[@"TrackMetaData"][@"upnp:songThumb"] isKindOfClass:NSString.class]) {
|
|
|
+ self.currentResource.songAlbumCover = resultDic[@"TrackMetaData"][@"upnp:songThumb"];
|
|
|
+ }
|
|
|
+ if ([resultDic[@"TrackMetaData"][@"upnp:songInfoID"] isKindOfClass:NSString.class]) {
|
|
|
+ self.currentResource.songID = [resultDic[@"TrackMetaData"][@"upnp:songInfoID"] integerValue];
|
|
|
+ }
|
|
|
+ if ([resultDic[@"TrackMetaData"][@"upnp:songPlatform"] isKindOfClass:NSString.class]) {
|
|
|
+ self.currentResource.songFrom = [resultDic[@"TrackMetaData"][@"upnp:songPlatform"] integerValue];
|
|
|
+ }
|
|
|
+ if ([resultDic[@"TrackDuration"] isKindOfClass:NSString.class]) {
|
|
|
+ self.currentResource.resourceStatus.totalTime = [NSString secondsFromHHmmssFormatStrig:resultDic[@"TrackDuration"]];
|
|
|
+ }
|
|
|
+ if ([resultDic[@"RelTime"] isKindOfClass:NSString.class]) {
|
|
|
+ self.currentResource.resourceStatus.currentTime = [NSString secondsFromHHmmssFormatStrig:resultDic[@"RelTime"]];
|
|
|
+ }
|
|
|
+ if ([resultDic[@"CurrentTransportState"] isKindOfClass:NSString.class]) {
|
|
|
+ self.currentResource.resourceStatus.playState = [self.currentResource.resourceStatus updatePlayState:resultDic[@"CurrentTransportState"]];
|
|
|
+ }
|
|
|
+ if ([resultDic[@"TrackMetaData"][@"upnp:songAlbumID"] isKindOfClass:NSString.class]) {
|
|
|
+ id songAlbumID = resultDic[@"TrackMetaData"][@"upnp:songAlbumID"];
|
|
|
+ if ([songAlbumID isKindOfClass:NSString.class]) {
|
|
|
+ self.currentResource.songAlbumID = resultDic[@"TrackMetaData"][@"upnp:songAlbumID"];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ([resultDic[@"TrackMetaData"][@"upnp:songAlbumID"] isKindOfClass:NSString.class]) {
|
|
|
+ id songAlbumID = resultDic[@"TrackMetaData"][@"upnp:songAlbumID"];
|
|
|
+ if ([songAlbumID isKindOfClass:NSString.class]) {
|
|
|
+ self.currentResource.songAlbumID = resultDic[@"TrackMetaData"][@"upnp:songAlbumID"];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ NSString *channelString = resultDic[@"TrackMetaData"][@"upnp:songFlag"];
|
|
|
+ NSInteger songChannel = 0;
|
|
|
+ if ([channelString containsString:@"-"]) {
|
|
|
+ NSArray *channelStringArr = [channelString componentsSeparatedByString:@"-"];
|
|
|
+ songChannel = [[channelStringArr firstObject] integerValue];
|
|
|
+ }else{
|
|
|
+ songChannel = [channelString integerValue];
|
|
|
+ }
|
|
|
+ self.currentResource.songChannel = songChannel;
|
|
|
+ NSString *songChannelUid = [NSString stringWithFormat:@"%@-%@-%zd",self.userID,device.deviceUUID,songChannel];
|
|
|
+ self.currentResource.songChannelUid = songChannelUid;
|
|
|
+ self.currentResource.songFlag = [NSString stringWithFormat:@"%@_%zd",songChannelUid,self.currentResource.songID];
|
|
|
+ wd_main_queue(^{
|
|
|
+ [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didGetPlayInfo:),self.currentResource];
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return self.currentResource;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)mkr_setObject:(id)obj forKey:(NSString *)key{
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+- (NSString *)playModeStringWithPlayMode:(MKRRadioPlayMode)playmode{
|
|
|
+ switch (playmode) {
|
|
|
+ case MKRRadioPlayModeOrder:{
|
|
|
+ return @"REPEAT_ALL";
|
|
|
}
|
|
|
+ break;
|
|
|
+ case MKRRadioPlayModeSingle:{
|
|
|
+ return @"REPEAT_ONE";
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case MKRRadioPlayModeRandom:{
|
|
|
+ return @"SHUFFLE";
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:{
|
|
|
+ return @"REPEAT_ALL";
|
|
|
+ }
|
|
|
+ break;
|
|
|
}
|
|
|
- resource.songFrom = (MKRSourcePlatform)[songFrom integerValue];
|
|
|
- NSString *channelString = dmrPositionInfo[8];
|
|
|
- if (![channelString containsString:@"Unknown:TrackMetaData Incomplete"]) {
|
|
|
- if ([channelString containsString:@"CHANNEL_UPDATE_"]) {
|
|
|
- resource.songChannel = [[channelString componentsSeparatedByString:@"CHANNEL_UPDATE_"].lastObject integerValue];
|
|
|
- } else {
|
|
|
- resource.songChannel = [channelString integerValue];
|
|
|
+}
|
|
|
+
|
|
|
+- (id<MKRRadioResorce>)currentResource{
|
|
|
+ if (!_currentResource) {
|
|
|
+ _currentResource = [[MKRRadioResorce alloc] init];
|
|
|
+ _currentResource.songName = @"猫王妙播";
|
|
|
+ _currentResource.songArtist = @"Keep radio on!";
|
|
|
+ if (!_currentResource.resourceStatus) {
|
|
|
+ _currentResource.resourceStatus = [[MKRPlayResourceStatus alloc] init];
|
|
|
}
|
|
|
}
|
|
|
- // resource.songLength = [self secondsFromTimeString:dmrPositionInfo[1]];
|
|
|
- // MKRPlayResourceStatus *status = [MKRPlayResourceStatus new];
|
|
|
- // status.currentTime = [[self secondsFromTimeString:dmrPositionInfo[10]] integerValue];
|
|
|
- // status.totalTime = [oneSong.songLength integerValue];
|
|
|
- NSString *songChannelUid = [NSString stringWithFormat:@"%@-%@-%zd",self.userID,device.deviceUUID,resource.songChannel];
|
|
|
- resource.songChannelUid = songChannelUid;
|
|
|
- resource.songFlag = [NSString stringWithFormat:@"%@_%@_%@",songChannelUid,resource.songID,songFrom];
|
|
|
- return resource;
|
|
|
+ return _currentResource;
|
|
|
+}
|
|
|
+
|
|
|
+- (id<MKRRadioResorce>)defaultSong{
|
|
|
+ MKRRadioResorce *song = [[MKRRadioResorce alloc] init];
|
|
|
+ song.songName = @"猫王妙播";
|
|
|
+ song.songArtist = @"Keep radio on!";
|
|
|
+ song.resourceStatus = [[MKRPlayResourceStatus alloc] init];
|
|
|
+ return song;
|
|
|
}
|
|
|
|
|
|
- (NSHashTable *)listeners{
|