MKRWIFIDeviceManager.m 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. //
  2. // MKRWIFIDeviceManager.m
  3. // MKRAVPlayer
  4. //
  5. // Created by yyqxiaoyin on 2019/4/16.
  6. //
  7. #import "MKRWIFIDeviceManager.h"
  8. #import "NSString+MKRRadioManagerAdd.h"
  9. #import "UIDevice+MKRRadioManagerAdd.h"
  10. #import <pthread.h>
  11. #import <libAS-Control/ASControlTools.h>
  12. #import <libAS-Control/NSDictionary+MKRXml.h>
  13. #import <NSHashTable+MKRRadioManagerAdd.h>
  14. static inline void wd_main_queue(void (^block)(void)){
  15. if (pthread_main_np()) {
  16. block();
  17. }else{
  18. dispatch_async(dispatch_get_main_queue(), block);
  19. }
  20. }
  21. static inline void wd_playControl_queue(void (^block)(void)){
  22. dispatch_queue_t queue = dispatch_queue_create("com.maoking.playControlQueue", DISPATCH_QUEUE_SERIAL);
  23. dispatch_async(queue, block);
  24. }
  25. @interface MKRWIFIDeviceManager () <ASControlDelegate> {
  26. int _upnpErrorCode;
  27. NSMutableArray *_baseUrlArray;
  28. dispatch_source_t _searchTimer;
  29. NSString *_ssid;
  30. BOOL _shutDownUpnping;
  31. BOOL _updateLocalResourceLock;
  32. }
  33. @property (nonatomic, strong) NSHashTable *listeners;
  34. @end
  35. @implementation MKRWIFIDeviceManager
  36. - (instancetype)init {
  37. if (self = [super init]) {
  38. _upnpErrorCode = -1;
  39. wd_playControl_queue(^{
  40. [self startUpnp];
  41. });
  42. [ASControlTools sharedInstanceUPNP].delegate = self;
  43. }
  44. return self;
  45. }
  46. + (instancetype)shareManager {
  47. static MKRWIFIDeviceManager *manager = nil;
  48. static dispatch_once_t onceToken;
  49. dispatch_once(&onceToken, ^{
  50. manager = [[MKRWIFIDeviceManager alloc] init];
  51. });
  52. return manager;
  53. }
  54. - (void)addDeviceManagerListener:(id<MKRWIFIDeviceManagerDelegate>)listener{
  55. if (![self.listeners containsObject:listener]){
  56. [self.listeners addObject:listener];
  57. }
  58. }
  59. - (void)removeDeviceManagerListener:(id<MKRWIFIDeviceManagerDelegate>)listener{
  60. if ([self.listeners containsObject:listener]) {
  61. [self.listeners removeObject:listener];
  62. }
  63. }
  64. - (NSInteger)startUpnp {
  65. NSString *userPhoneName = [[UIDevice currentDevice] name];
  66. NSString *sharePath = NSHomeDirectory();
  67. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  68. NSString *DocumentSharePath = [paths objectAtIndex:0];
  69. NSString *sharePath2 = NSTemporaryDirectory();
  70. NSArray *dirArgv =[[NSArray alloc] initWithObjects:DocumentSharePath,sharePath2,nil];
  71. libupnp_RELoadUpnp();
  72. _upnpErrorCode = libupnp_UpnpStartTest([UIDevice currentDeviceMacAddress],userPhoneName,2,dirArgv,[UIDevice currentDeviceInfo],7);
  73. if (_upnpErrorCode == 0) {
  74. NSLog(@"upnp初始化成功");
  75. _upnpErrorCode = libupnp_UpnpSetWebServerRootDir(sharePath);
  76. }else if(_upnpErrorCode == -100) {
  77. NSLog(@"UpnpStart 无网络连接!! ==> %d ", _upnpErrorCode);
  78. }else{//UPNP_ERROR
  79. NSLog(@"UpnpStart Error!! ==> %d" ,_upnpErrorCode);
  80. }
  81. return _upnpErrorCode;
  82. }
  83. - (void)stopUpnp{
  84. wd_playControl_queue(^{
  85. libupnp_StopBuildFilesList();
  86. [NSThread sleepForTimeInterval:5];
  87. if(_upnpErrorCode == 0){
  88. libupnp_UpnpQuickExit();
  89. }
  90. });
  91. }
  92. - (void)reloadUpnp{
  93. NSString *ssid = [UIDevice currentSSID];
  94. if ([ssid isEqualToString:_ssid]) {
  95. return;
  96. }
  97. if (_shutDownUpnping) {
  98. return;
  99. }
  100. _ssid = ssid;
  101. wd_playControl_queue(^{
  102. _shutDownUpnping = YES;
  103. libupnp_StopBuildFilesList();
  104. int exitCount = 0;
  105. while (_updateLocalResourceLock) {
  106. exitCount++;
  107. [NSThread sleepForTimeInterval:1.0];
  108. if (exitCount > 10)
  109. break;
  110. }
  111. _updateLocalResourceLock = NO;
  112. [self searchDeviceWithSearchTime:20 timeBlock:nil];
  113. });
  114. }
  115. - (void)searchDeviceWithSearchTime:(int)searchTime
  116. timeBlock:(void(^)(NSInteger time))timeBlock {
  117. wd_playControl_queue(^{
  118. _updateLocalResourceLock = YES;
  119. if (_upnpErrorCode != 0) {
  120. if ([self startUpnp] == 0) {
  121. [self checkBaseURL];
  122. libupnp_BuildFilesList();
  123. }
  124. }
  125. libupnp_SearchDevice(20);
  126. });
  127. _ssid = [UIDevice currentSSID];
  128. __block int count = searchTime +1;
  129. _searchTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
  130. dispatch_source_set_timer(_searchTimer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
  131. dispatch_source_set_event_handler(_searchTimer, ^{
  132. if (timeBlock) {
  133. wd_main_queue(^{
  134. timeBlock(count);
  135. });
  136. }
  137. count --;
  138. if (count == 0) {
  139. dispatch_source_cancel(self->_searchTimer);
  140. }
  141. });
  142. dispatch_source_set_cancel_handler(_searchTimer, ^{
  143. dispatch_async(dispatch_get_main_queue(), ^{
  144. NSLog(@"搜索结束");
  145. });
  146. });
  147. dispatch_resume(_searchTimer);
  148. }
  149. - (void)checkBaseURL{
  150. NSMutableArray *baseURLArray = [NSMutableArray array];
  151. for (NSString *baseValue in _baseUrlArray) {
  152. NSString *tempStr = [baseValue stringByReplacingOccurrencesOfString:@"49152" withString:@"MaoKing"];
  153. tempStr = [tempStr stringByReplacingOccurrencesOfString:@"49153" withString:@"MaoKing"];
  154. tempStr = [tempStr stringByReplacingOccurrencesOfString:@"49154" withString:@"MaoKing"];
  155. [baseURLArray addObject:[tempStr stringByReplacingOccurrencesOfString:@"MaoKing" withString:@"49152"]];
  156. [baseURLArray addObject:[tempStr stringByReplacingOccurrencesOfString:@"MaoKing" withString:@"49153"]];
  157. [baseURLArray addObject:[tempStr stringByReplacingOccurrencesOfString:@"MaoKing" withString:@"49154"]];
  158. }
  159. if([baseURLArray count] > 0)libupnp_FirstCheckByBaseURL((int)[baseURLArray count] , baseURLArray);
  160. }
  161. #pragma mark - ASControlDelegate
  162. -(void)ReceivedPlayCallBack:(NSString *)nUDN{
  163. NSLog(@"收到播放回调%@",nUDN);
  164. wd_main_queue(^{
  165. if ([nUDN containsString:self.device.deviceUUID]) {
  166. self.currentResource.resourceStatus.playState = MKRResourcePlayStatePlaying;
  167. [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceivePlayStateChange:),MKRResourcePlayStatePlaying];
  168. }
  169. });
  170. }
  171. -(void)ReceivedPauseCallBack:(NSString *)nUDN{
  172. NSLog(@"收到暂停回调%@",nUDN);
  173. wd_main_queue(^{
  174. if ([nUDN containsString:self.device.deviceUUID]) {
  175. self.currentResource.resourceStatus.playState = MKRResourcePlayStatePause;
  176. [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceivePlayStateChange:),MKRResourcePlayStatePause];
  177. }
  178. });
  179. }
  180. -(void)ReceivedStopCallBack:(NSString *)nUDN{
  181. NSLog(@"收到停止回调%@",nUDN);
  182. wd_main_queue(^{
  183. if ([nUDN containsString:self.device.deviceUUID]) {
  184. self.currentResource.resourceStatus.playState = MKRResourcePlayStateStopped;
  185. [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceivePlayStateChange:),MKRResourcePlayStateStopped];
  186. }
  187. });
  188. }
  189. -(void)ReceivedSetVolumeCallBack:(NSString *)nUDN Volume:(NSInteger)Volume{
  190. wd_main_queue(^{
  191. if ([nUDN containsString:self.device.deviceUUID]) {
  192. NSLog(@"收到设备音量回调SetZoneVolumeCallBack:%zd",Volume);
  193. [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceiveVolumeChange:),(float)Volume];
  194. }
  195. });
  196. }
  197. -(void)ReceivedSetMuteCallBack:(NSString *)nUDN Mute:(NSInteger)Mute{
  198. NSLog(@"%s",__func__);
  199. }
  200. -(void)ReceivedSetZoneMuteCallBack:(NSString *)nUDN Mute:(NSInteger)Mute{
  201. NSLog(@"%s",__func__);
  202. }
  203. -(void)ReceivedSetGroupIdCallBack:(NSString *)nUDN GrouId:(NSString *)GroupId{
  204. NSLog(@"%s",__func__);
  205. }
  206. -(void)ReceivedSetSleepStateCallBack:(NSString *)nUDN SleepState:(NSString *)SleepState{
  207. NSLog(@"%s",__func__);
  208. }
  209. -(void)ReceivedSetSoundSourceCallBack:(NSString *)nUDN SoundSource:(NSString *)SoundSource{
  210. NSLog(@"%s",__func__);
  211. }
  212. -(void)ReceivedSetVolumeChannelCallBack:(NSString *)nUDN Channel:(NSString *)Channel {
  213. NSLog(@"ReceivedSetVolumeChannelCallBack-------------%@ ",Channel);
  214. }
  215. -(void)ReceivedSetZoneVolumeCallBack:(NSString *)nUDN Volume:(NSInteger)Volume {
  216. NSLog(@"%s",__func__);
  217. }
  218. -(void)CallBackRemoveZoneMedia:(NSString *)nByeUDN BaseURL:(NSString *)BaseURL{
  219. NSLog(@"%s",__func__);
  220. wd_main_queue(^{
  221. [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceiveDeviceOffline:),nByeUDN];
  222. });
  223. }
  224. -(void)CallBackRemoveRenderer:(NSString *)nByeUDN BaseURL:(NSString *)BaseURL
  225. {
  226. NSLog(@"CallBackRemoveRenderer---------%@",nByeUDN);
  227. NSLog(@"%s",__func__);
  228. }
  229. -(void)CallBackRemoveDMS:(NSString *)nByeUDN BaseURL:(NSString *)BaseURL{
  230. NSLog(@"%s",__func__);
  231. }
  232. -(void)CallBackAddZoneMedia:(NSArray *)nStr Size:(NSInteger)size{
  233. NSLog(@"搜索到设备:%@",nStr);
  234. NSLog(@"%s",__func__);
  235. wd_playControl_queue(^{
  236. [self addDevice:nStr];
  237. });
  238. }
  239. - (void)updateClockID:(NSString *)clockID clockDic:(NSDictionary *)clockDic clockTime:(NSString *)clockTime operationType:(BOOL)isOn deleteClock:(BOOL)isDelete{
  240. NSLog(@"%s",__func__);
  241. }
  242. -(void)CallBackAddMediaServer:(NSArray *)nStr Size:(NSInteger)size{
  243. NSLog(@"%s",__func__);
  244. }
  245. -(void)CallBackAddMediaRenderer:(NSArray *)nStr Size:(NSInteger)size{
  246. NSLog(@"%s",__func__);
  247. }
  248. -(void)ReceivedChangeChannelCallBack:(NSString *)nUDN Channel:(NSString *)channel{
  249. NSLog(@"%s",__func__);
  250. NSLog(@"收到频道改变回调%@",nUDN);
  251. wd_main_queue(^{
  252. if ([nUDN containsString:self.device.deviceUUID]) {
  253. [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didReceivePlayingChannelChange:),[channel integerValue]];
  254. }
  255. });
  256. }
  257. -(void)getLocalIp:(NSString *)Ip{
  258. NSLog(@"%s",__func__);
  259. }
  260. -(void)AddLocalResource:(NSArray *)oneSongID3Info{
  261. NSLog(@"%s",__func__);
  262. }
  263. -(void)UpdateLocalResourceFinish{
  264. NSLog(@"%s",__func__);
  265. }
  266. - (void)addDevice:(NSArray *)array {
  267. NSMutableDictionary *deviceDict = [NSMutableDictionary dictionary];
  268. [deviceDict setObject:array[0] forKey:@"deviceName"];
  269. [deviceDict setObject:array[1] forKey:@"deviceUUID"];
  270. [deviceDict setObject:array[2] forKey:@"deviceBaseUrl"];
  271. [deviceDict setObject:array[5] forKey:@"connectionManagerUrl"];
  272. [deviceDict setObject:array[7] forKey:@"avTransportUrl"];
  273. [deviceDict setObject:array[9] forKey:@"renderingControlUrl"];
  274. [deviceDict setObject:array[11] forKey:@"groupManagementUrl"];
  275. NSArray *deviceInfo = [[ASControlTools sharedInstanceUPNP] libupnp_GetDeviceInfo:array[11] ServiceTYPE:array[10]];
  276. if(deviceInfo == nil || [deviceInfo isEqual:[NSNull null]]){
  277. return;
  278. }
  279. [deviceDict setObject:deviceInfo[0] forKey:@"devGId"];
  280. [deviceDict setObject:deviceInfo[1] forKey:@"devWiFiDB"];
  281. [deviceDict setObject:[deviceInfo[16] length]?deviceInfo[16]: @"AWAKE" forKey:@"devSleepStatus"];
  282. [deviceDict setObject:[deviceInfo[17] length]?deviceInfo[17]: @"WIFI" forKey:@"devSource"];
  283. [deviceDict setObject:[deviceInfo[28] length]?deviceInfo[28]:@"WIFI" forKey:@"devSourceList"];
  284. [deviceDict setObject:deviceInfo[12] forKey:@"channelLR"];
  285. [deviceDict setObject:[deviceInfo[29] length] ? deviceInfo[29]: @"0.0.0.0" forKey:@"devType"];
  286. [deviceDict setObject:[deviceInfo[32] length] ? deviceInfo[32]: @"" forKey:@"deviceClockInfo"];
  287. [deviceDict setObject:[deviceInfo[33] length]? deviceInfo[33]:@"NULL" forKey:@"devPower"];
  288. [deviceDict setObject:[deviceInfo[36] length] ? deviceInfo[36]:@"NULL" forKey:@"devUserID"];
  289. NSString *devFlag = [NSString stringWithFormat:@"%@-%@",deviceInfo[9],deviceInfo[10]];
  290. [deviceDict setObject:devFlag forKey:@"devFlag"];
  291. [deviceDict setObject:[deviceInfo[18] length] ?deviceInfo[18]:@"MJ_M" forKey:@"devProductModel"];
  292. [deviceDict setObject:[deviceInfo[39] length] ?deviceInfo[39] :@"0" forKey:@"devOpenLowPowerNotice"];
  293. [deviceDict setObject:[deviceInfo[19] length] ? deviceInfo[19] : @"1.0.0" forKey:@"devVersion"];
  294. [deviceDict setObject:[deviceInfo[41] length] ? deviceInfo[41] :@"" forKey:@"devDuerAccessToken"];
  295. [deviceDict setObject:[deviceInfo[42] length] ?deviceInfo[42] : @"" forKey:@"devDuerRefreshToken"];
  296. [deviceDict setObject:deviceInfo[13] forKey:@"volume"];
  297. [deviceDict setObject:deviceInfo[14] forKey:@"mute"];
  298. [deviceDict setObject:[deviceInfo[40] length] ?deviceInfo[40] :@"-1" forKey:@"devPauseShutDownTime"];
  299. NSString *devNowStatus = [deviceInfo[2] length] ? deviceInfo[2] : @"STOPPED";
  300. [deviceDict setObject:devNowStatus forKey:@"devNowStatus"];
  301. [deviceDict setObject:[deviceInfo[30] length] ?deviceInfo[30] :@"REPEAT_ALL" forKey:@"devNowPlayMode"];
  302. NSURL *url = [NSURL URLWithString:array[2]];
  303. [deviceDict setObject:url.URLByDeletingLastPathComponent.absoluteString?:@"" forKey:@"devIP"];
  304. if([devNowStatus isEqualToString:@"PAUSED_PLAYBACK"]){
  305. NSString *devNowPlaying = [NSString stringWithFormat:@"Pause:%@",deviceInfo[3]];
  306. [deviceDict setObject:devNowPlaying forKey:@"devNowPlaying"];
  307. }else if([devNowStatus isEqualToString:@"PLAYING"]){
  308. [deviceDict setObject:deviceInfo[3] forKey:@"devNowPlaying"];
  309. }
  310. [deviceDict setObject:deviceInfo[4] forKey:@"devNowArtist"];
  311. if([deviceDict[@"devNowPlaying"] isEqualToString:@"Unknown:TrackMetaData Incomplete"]){
  312. [deviceDict setObject:@"No Music" forKey:@"devNowPlaying"];
  313. }
  314. if([deviceDict[@"devNowArtist"] isEqualToString:@"Unknown:TrackMetaData Incomplete"])
  315. {
  316. [deviceDict setObject:@"Unknown" forKey:@"devNowArtist"];
  317. }
  318. if(deviceDict[@"devNowArtist"] == nil||[deviceDict[@"devNowArtist"] isEqual:[NSNull null]]){
  319. [deviceDict setObject:@"Unknown" forKey:@"devNowArtist"];
  320. }
  321. [deviceDict setObject:@"1" forKey:@"isOnLine"];
  322. wd_main_queue(^{
  323. id<MKRWIFIDeviceManagerDelegate> obj;
  324. NSEnumerator *enumerator = [self.listeners objectEnumerator];
  325. while ((obj = [enumerator nextObject]) != nil) {
  326. if ([obj respondsToSelector:@selector(didSearchNewDevice:)]) {
  327. [obj didSearchNewDevice:deviceDict];
  328. }
  329. }
  330. });
  331. }
  332. - (void)setM3UList:(MKRM3UListModel *)m3uListModel{
  333. self.currentTempM3UListModel = m3uListModel;
  334. libupnp_SetNewM3UListV2(m3uListModel.secondsList,
  335. m3uListModel.artistList,
  336. m3uListModel.titleList,
  337. m3uListModel.urlList,
  338. m3uListModel.songFromList,
  339. m3uListModel.vipCanPlay,
  340. m3uListModel.channelNO,
  341. m3uListModel.playModeString,
  342. m3uListModel.timeString,
  343. m3uListModel.startIndex,
  344. m3uListModel.endIndex,
  345. m3uListModel.m3uSize,
  346. m3uListModel.channelID,
  347. m3uListModel.channelInfoString);
  348. }
  349. - (void)setAVTransportURIWithSong:(id <MKRRadioResorce>)song
  350. device:(id <MKRUPnPDevice>)device{
  351. NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
  352. NSString *channelNumString = @(song.songChannel).stringValue;
  353. NSString *userID = self.userID;
  354. NSString *songUrlString = [NSString stringWithFormat:@"AIRSMART//ID_%zd//",song.songID];
  355. NSString *songFrom = [NSString stringWithFormat:@"1//%zd//%zd//",[MKRM3UListModel convertAudioTypeWithSorceType:song.sourceType],song.songID];
  356. libupnp_SetAVTransportURIV2(
  357. device.avTransportUrl,
  358. songUrlString,
  359. song.songName?:@"",
  360. song.songArtist?:@"",
  361. song.songAlbum?:@"",
  362. song.songAlbumCover?:@"",
  363. @"0",
  364. @"null",
  365. @"null",
  366. timestamp,
  367. channelNumString,
  368. @"0",
  369. userID?:@"",
  370. @(song.songID).stringValue,
  371. songFrom,
  372. song.songAlbumID?:@""
  373. );
  374. }
  375. - (void)playWithDevice:(id <MKRUPnPDevice>)device {
  376. wd_playControl_queue(^{
  377. libupnp_Play(device.avTransportUrl);
  378. });
  379. }
  380. - (void)_playPlayFlag:(NSString *)playFlag
  381. device:(id <MKRUPnPDevice>)device
  382. timeStamp:(NSTimeInterval)timeStamp{
  383. NSString *playListUrl = [NSString stringWithFormat:@"%@/web/playlist",[ASControlTools sharedInstanceUPNP].myIp];
  384. NSString *timestamp = [NSString stringWithFormat:@"%.0f", timeStamp];
  385. NSString *userID = self.userID;
  386. libupnp_PlayNumFlagV2(
  387. device.avTransportUrl,
  388. playFlag,
  389. timestamp,
  390. userID,
  391. playListUrl,
  392. @"0"
  393. );
  394. }
  395. - (void)playSongWithChannelNO:(NSInteger)channelNO
  396. firstPlayingSong:(id<MKRRadioResorce>)firstPlayingSong
  397. device:(id<MKRUPnPDevice>)device
  398. timeStamp:(NSTimeInterval)timeStamp{
  399. self.currentTempM3UListModel = nil;
  400. wd_playControl_queue(^{
  401. NSString *playFlag = [NSString stringWithFormat:@"%zd",channelNO];
  402. [self _playPlayFlag:playFlag device:device timeStamp:timeStamp];
  403. });
  404. }
  405. - (void)playSongWithChannelNO:(NSInteger)channelNO
  406. firstPlayingSong:(id<MKRRadioResorce>)firstPlayingSong
  407. index:(NSInteger)index
  408. device:(id<MKRUPnPDevice>)device
  409. timeStamp:(NSTimeInterval)timeStamp{
  410. self.currentTempM3UListModel = nil;
  411. wd_playControl_queue(^{
  412. if (firstPlayingSong && firstPlayingSong.songID) {
  413. [self setAVTransportURIWithSong:firstPlayingSong device:device];
  414. }
  415. NSString *playFlag = [NSString stringWithFormat:@"%zd-%zd",channelNO,index];
  416. [self _playPlayFlag:playFlag device:device timeStamp:timeStamp];
  417. });
  418. }
  419. - (void)playTempChannelSongs:(NSArray<id<MKRRadioResorce>> *)songs
  420. index:(NSInteger)index
  421. device:(id<MKRUPnPDevice>)device
  422. timeStamp:(NSTimeInterval)timeStamp{
  423. [self playTempChannelSongs:songs index:index device:device timeStamp:timeStamp playMode:MKRRadioPlayModeOrder];
  424. }
  425. - (void)playTempChannelSongs:(NSArray<id<MKRRadioResorce>> *)songs
  426. index:(NSInteger)index
  427. device:(id<MKRUPnPDevice>)device
  428. timeStamp:(NSTimeInterval)timeStamp
  429. playMode:(MKRRadioPlayMode)playMode{
  430. MKRM3UListModel *m3uModel = [MKRM3UListModel tempChannelM3UModelWithSongs:songs startIndex:index];
  431. m3uModel.userID = self.userID;
  432. m3uModel.playModeString = [self playModeStringWithPlayMode:playMode];
  433. [MKRWIFIDeviceManager shareManager].currentTempM3UListModel = m3uModel;
  434. wd_playControl_queue(^{
  435. [[MKRWIFIDeviceManager shareManager] setM3UList:m3uModel];
  436. id <MKRRadioResorce> song = songs[index];
  437. song.songChannel = 13;
  438. [self setAVTransportURIWithSong:song device:device];
  439. NSString *playFlag = [NSString stringWithFormat:@"13-%zd",index];
  440. [self _playPlayFlag:playFlag device:device timeStamp:timeStamp];
  441. });
  442. }
  443. - (void)playTempChannelSongs:(NSArray<id<MKRRadioResorce>> *)songs
  444. device:(id<MKRUPnPDevice>)device
  445. timeStamp:(NSTimeInterval)timeStamp{
  446. [self playTempChannelSongs:songs device:device timeStamp:timeStamp playMode:MKRRadioPlayModeOrder];
  447. }
  448. - (void)playTempChannelSongs:(NSArray<id<MKRRadioResorce>> *)songs
  449. device:(id<MKRUPnPDevice>)device
  450. timeStamp:(NSTimeInterval)timeStamp
  451. playMode:(MKRRadioPlayMode)playMode{
  452. MKRM3UListModel *m3uModel = [MKRM3UListModel tempChannelM3UModelWithSongs:songs startIndex:index];
  453. m3uModel.userID = self.userID;
  454. m3uModel.playModeString = [self playModeStringWithPlayMode:playMode];
  455. [MKRWIFIDeviceManager shareManager].currentTempM3UListModel = m3uModel;
  456. wd_playControl_queue(^{
  457. [[MKRWIFIDeviceManager shareManager] setM3UList:m3uModel];
  458. id <MKRRadioResorce> song = songs[0];
  459. song.songChannel = 13;
  460. [self setAVTransportURIWithSong:song device:device];
  461. [self _playPlayFlag:@"13" device:device timeStamp:timeStamp];
  462. });
  463. }
  464. - (void)pauseWithDevice:(id <MKRUPnPDevice>)device {
  465. wd_playControl_queue(^{
  466. libupnp_Pause(device.avTransportUrl);
  467. });
  468. }
  469. - (void)nextWithDevice:(id <MKRUPnPDevice>)device{
  470. wd_playControl_queue(^{
  471. libupnp_Next(device.avTransportUrl);
  472. });
  473. }
  474. - (void)previousWithDevice:(id <MKRUPnPDevice>)device{
  475. wd_playControl_queue(^{
  476. libupnp_Previous(device.avTransportUrl);
  477. });
  478. }
  479. - (void)stopWithDevice:(id <MKRUPnPDevice>)device{
  480. wd_playControl_queue(^{
  481. libupnp_Stop(device.avTransportUrl);
  482. });
  483. }
  484. - (void)setVolume:(int)volume device:(id <MKRUPnPDevice>)device{
  485. wd_playControl_queue(^{
  486. libupnp_SetZoneVolume(
  487. device.groupManagementUrl,
  488. @"urn:schemas-upnp-org:service:GroupManagement:1",
  489. @"Master",
  490. volume
  491. );
  492. });
  493. }
  494. - (void)seekToTimeInterval:(NSInteger)timeInterval device:(id <MKRUPnPDevice>)device {
  495. NSString *timeString = [NSString HHmmssFormatStrig:timeInterval];
  496. wd_playControl_queue(^{
  497. libupnp_SetMediaSeek(device.avTransportUrl, timeString);
  498. });
  499. }
  500. - (void)clearChannelWithChannelNO:(NSString *)channelNO device:(id <MKRUPnPDevice>)device {
  501. NSString *channelID = [NSString stringWithFormat:@"CHANNEL_UPDATE_%@",channelNO];
  502. NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
  503. wd_playControl_queue(^{
  504. libupnp_SetChannelClear(device.groupManagementUrl, channelID, timestamp);
  505. });
  506. }
  507. - (void)updateChannel:(NSString *)channelFlag device:(id<MKRUPnPDevice>)device{
  508. wd_playControl_queue(^{
  509. NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
  510. NSInteger channelNo = [channelFlag integerValue];
  511. NSString *playListUrl = @"null";
  512. if (channelNo >= 13) {
  513. playListUrl = [NSString stringWithFormat:@"%@/web/playlist",[ASControlTools sharedInstanceUPNP].myIp];
  514. }
  515. int result = libupnp_SetChannelUpdateV2(device.groupManagementUrl, self.userID, timestamp, channelFlag, playListUrl);
  516. });
  517. }
  518. - (void)setPlayMode:(MKRRadioPlayMode)playMode device:(id<MKRUPnPDevice>)device channelNO:(NSInteger)channelNO{
  519. NSString *playModeString = @"";
  520. switch (playMode) {
  521. case MKRRadioPlayModeOrder:{
  522. playModeString = @"REPEAT_ALL";
  523. }
  524. break;
  525. case MKRRadioPlayModeSingle:{
  526. playModeString = @"REPEAT_ONE";
  527. }
  528. break;
  529. case MKRRadioPlayModeRandom:{
  530. playModeString = @"SHUFFLE";
  531. }
  532. break;
  533. default:{
  534. playModeString = @"REPEAT_ALL";
  535. }
  536. break;
  537. }
  538. NSString *channelFlag = [NSString stringWithFormat:@"CHANNEL_UPDATE_%zd",channelNO];
  539. wd_playControl_queue(^{
  540. int result = libupnp_SetChannelPlayModeV2(device.groupManagementUrl, channelFlag, playModeString, self.userID);
  541. });
  542. }
  543. - (void)updateTempChannelPlayMode:(MKRRadioPlayMode)playMode songs:(NSArray <id <MKRRadioResorce>> *)songs index:(NSInteger)index device:(id<MKRUPnPDevice>)device{
  544. if (!self.currentTempM3UListModel) {
  545. MKRM3UListModel *m3uModel = [MKRM3UListModel tempChannelM3UModelWithSongs:songs startIndex:index];
  546. m3uModel.userID = self.userID;
  547. m3uModel.playModeString = [self playModeStringWithPlayMode:playMode];
  548. self.currentTempM3UListModel = m3uModel;
  549. }
  550. self.currentTempM3UListModel.playModeString = [self playModeStringWithPlayMode:playMode];
  551. wd_playControl_queue(^{
  552. [self setM3UList:self.currentTempM3UListModel];
  553. [self updateChannel:@(13).stringValue device:device];
  554. });
  555. }
  556. - (void)setLowPowerNoticeEnable:(BOOL)enable device:(id<MKRUPnPDevice>)device{
  557. wd_playControl_queue(^{
  558. libupnp_SetLowBatteryNotification(device.groupManagementUrl,enable);
  559. });
  560. }
  561. - (NSDictionary *)parsePlayInfoString:(NSString *)playInfoXmlString{
  562. NSMutableDictionary *resultDic = [NSMutableDictionary dictionaryWithDictionary:[NSDictionary mkr_dictionaryWithXML:playInfoXmlString]];
  563. NSString *metaDataString = [resultDic objectForKey:@"TrackMetaData"];
  564. if ([metaDataString isKindOfClass:NSString.class]) {
  565. metaDataString = [metaDataString stringByReplacingOccurrencesOfString:@"&" withString:@"mkr_***"];
  566. NSDictionary *metaDic = [NSDictionary mkr_dictionaryWithXML:metaDataString];
  567. NSDictionary *metaItemDic = metaDic[@"item"];
  568. if (![metaItemDic isKindOfClass:NSDictionary.class]) {
  569. metaItemDic = @{};
  570. }
  571. [resultDic setObject:metaDic[@"item"]?:@{} forKey:@"TrackMetaData"];
  572. return resultDic;
  573. }else{
  574. return nil;
  575. }
  576. }
  577. - (id <MKRRadioResorce>)getPlayingStatusWithDevice:(id <MKRUPnPDevice>)device {
  578. wd_playControl_queue(^{
  579. NSString *resultString = [[ASControlTools sharedInstanceUPNP] libupnp_getPlayInfoString:device.avTransportUrl];
  580. NSMutableDictionary *resultDic = [self parsePlayInfoString:resultString];
  581. if (!resultDic || !resultDic.allKeys.count) {
  582. return ;
  583. }
  584. if ([resultDic[@"TrackMetaData"][@"upnp:songInfoID"] isKindOfClass:NSString.class]) {
  585. NSInteger songID = [resultDic[@"TrackMetaData"][@"upnp:songInfoID"] integerValue];
  586. if (songID != self.currentResource.songID) {
  587. self.currentResource = [self defaultSong];
  588. }
  589. }
  590. @synchronized (self.currentResource) {
  591. if ([resultDic[@"TrackMetaData"][@"upnp:songType"] isKindOfClass:NSString.class]) {
  592. NSInteger sourceType = [MKRM3UListModel convertSorceTypeWithAudioType:[resultDic[@"TrackMetaData"][@"upnp:songType"] integerValue]];
  593. self.currentResource.sourceType = sourceType;
  594. }
  595. if ([resultDic[@"TrackMetaData"][@"upnp:songName"] isKindOfClass:NSString.class]) {
  596. self.currentResource.songName = resultDic[@"TrackMetaData"][@"upnp:songName"];
  597. }
  598. if ([resultDic[@"TrackMetaData"][@"upnp:songPlayer"] isKindOfClass:NSString.class]) {
  599. if (self.currentResource.sourceType == MKRSourceTypeHandPick || self.currentResource.sourceType == MKRSourceTypeBroadcast) {
  600. self.currentResource.songName = resultDic[@"TrackMetaData"][@"upnp:songPlayer"];
  601. }else{
  602. self.currentResource.songArtist = resultDic[@"TrackMetaData"][@"upnp:songPlayer"];
  603. }
  604. }
  605. if ([resultDic[@"TrackMetaData"][@"upnp:songThumb"] isKindOfClass:NSString.class]) {
  606. self.currentResource.songAlbumCover = resultDic[@"TrackMetaData"][@"upnp:songThumb"];
  607. }
  608. if ([resultDic[@"TrackMetaData"][@"upnp:songInfoID"] isKindOfClass:NSString.class]) {
  609. self.currentResource.songID = [resultDic[@"TrackMetaData"][@"upnp:songInfoID"] integerValue];
  610. }
  611. if ([resultDic[@"TrackMetaData"][@"upnp:songPlatform"] isKindOfClass:NSString.class]) {
  612. self.currentResource.songFrom = [resultDic[@"TrackMetaData"][@"upnp:songPlatform"] integerValue];
  613. }
  614. if ([resultDic[@"TrackDuration"] isKindOfClass:NSString.class]) {
  615. self.currentResource.resourceStatus.totalTime = [NSString secondsFromHHmmssFormatStrig:resultDic[@"TrackDuration"]];
  616. }
  617. if ([resultDic[@"RelTime"] isKindOfClass:NSString.class]) {
  618. self.currentResource.resourceStatus.currentTime = [NSString secondsFromHHmmssFormatStrig:resultDic[@"RelTime"]];
  619. }
  620. if ([resultDic[@"CurrentTransportState"] isKindOfClass:NSString.class]) {
  621. self.currentResource.resourceStatus.playState = [self.currentResource.resourceStatus updatePlayState:resultDic[@"CurrentTransportState"]];
  622. }
  623. if ([resultDic[@"TrackMetaData"][@"upnp:songAlbumID"] isKindOfClass:NSString.class]) {
  624. id songAlbumID = resultDic[@"TrackMetaData"][@"upnp:songAlbumID"];
  625. if ([songAlbumID isKindOfClass:NSString.class]) {
  626. self.currentResource.songAlbumID = resultDic[@"TrackMetaData"][@"upnp:songAlbumID"];
  627. }
  628. }
  629. if ([resultDic[@"TrackMetaData"][@"upnp:songAlbumID"] isKindOfClass:NSString.class]) {
  630. id songAlbumID = resultDic[@"TrackMetaData"][@"upnp:songAlbumID"];
  631. if ([songAlbumID isKindOfClass:NSString.class]) {
  632. self.currentResource.songAlbumID = resultDic[@"TrackMetaData"][@"upnp:songAlbumID"];
  633. }
  634. }
  635. NSString *channelString = resultDic[@"TrackMetaData"][@"upnp:songFlag"];
  636. NSInteger songChannel = 0;
  637. if ([channelString containsString:@"-"]) {
  638. NSArray *channelStringArr = [channelString componentsSeparatedByString:@"-"];
  639. songChannel = [[channelStringArr firstObject] integerValue];
  640. }else{
  641. songChannel = [channelString integerValue];
  642. }
  643. self.currentResource.songChannel = songChannel;
  644. NSString *songChannelUid = [NSString stringWithFormat:@"%@-%zd",self.userID,songChannel];
  645. self.currentResource.songChannelUid = songChannelUid;
  646. self.currentResource.songFlag = [NSString stringWithFormat:@"%@_%zd",songChannelUid,self.currentResource.songID];
  647. wd_main_queue(^{
  648. [self.listeners makeObjectsPerformSelectorWithObjects:@selector(didGetPlayInfo:),self.currentResource];
  649. });
  650. }
  651. });
  652. return self.currentResource;
  653. }
  654. - (void)mkr_setObject:(id)obj forKey:(NSString *)key{
  655. }
  656. - (NSString *)playModeStringWithPlayMode:(MKRRadioPlayMode)playmode{
  657. switch (playmode) {
  658. case MKRRadioPlayModeOrder:{
  659. return @"REPEAT_ALL";
  660. }
  661. break;
  662. case MKRRadioPlayModeSingle:{
  663. return @"REPEAT_ONE";
  664. }
  665. break;
  666. case MKRRadioPlayModeRandom:{
  667. return @"SHUFFLE";
  668. }
  669. break;
  670. default:{
  671. return @"REPEAT_ALL";
  672. }
  673. break;
  674. }
  675. }
  676. - (id<MKRRadioResorce>)currentResource{
  677. if (!_currentResource) {
  678. _currentResource = [[MKRRadioResorce alloc] init];
  679. _currentResource.songName = @"猫王妙播";
  680. _currentResource.songArtist = @"Keep radio on!";
  681. if (!_currentResource.resourceStatus) {
  682. _currentResource.resourceStatus = [[MKRPlayResourceStatus alloc] init];
  683. }
  684. }
  685. return _currentResource;
  686. }
  687. - (id<MKRRadioResorce>)defaultSong{
  688. MKRRadioResorce *song = [[MKRRadioResorce alloc] init];
  689. song.songName = @"猫王妙播";
  690. song.songArtist = @"Keep radio on!";
  691. song.resourceStatus = [[MKRPlayResourceStatus alloc] init];
  692. return song;
  693. }
  694. - (NSHashTable *)listeners{
  695. if (!_listeners) {
  696. _listeners = [NSHashTable weakObjectsHashTable];
  697. }
  698. return _listeners;
  699. }
  700. @end