VLCMediaListPlayer.m 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*****************************************************************************
  2. * VLCMediaListPlayer.m: VLCKit.framework VLCMediaListPlayer implementation
  3. *****************************************************************************
  4. * Copyright (C) 2009 Pierre d'Herbemont
  5. * Partial Copyright (C) 2009-2017 Felix Paul Kühne
  6. * Copyright (C) 2009-2019 VLC authors and VideoLAN
  7. * $Id$
  8. *
  9. * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
  10. * Felix Paul Kühne <fkuehne # videolan.org>
  11. * Soomin Lee <bubu # mikan.io>
  12. *
  13. * This program is free software; you can redistribute it and/or modify it
  14. * under the terms of the GNU Lesser General Public License as published by
  15. * the Free Software Foundation; either version 2.1 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU Lesser General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Lesser General Public License
  24. * along with this program; if not, write to the Free Software Foundation,
  25. * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  26. *****************************************************************************/
  27. #import "VLCMediaListPlayer.h"
  28. #import "VLCMedia.h"
  29. #import "VLCMediaPlayer.h"
  30. #import "VLCMediaList.h"
  31. #import "VLCLibVLCBridging.h"
  32. #import "VLCLibrary.h"
  33. #import "VLCEventManager.h"
  34. @interface VLCMediaListPlayer () {
  35. void *instance;
  36. VLCMedia *_rootMedia;
  37. VLCMediaPlayer *_mediaPlayer;
  38. VLCMediaList *_mediaList;
  39. VLCRepeatMode _repeatMode;
  40. dispatch_queue_t _libVLCBackgroundQueue;
  41. }
  42. @end
  43. static void HandleMediaListPlayerPlayed(const libvlc_event_t * event, void * self)
  44. {
  45. @autoreleasepool {
  46. [[VLCEventManager sharedManager] callOnMainThreadObject:(__bridge id)(self)
  47. withMethod:@selector(mediaListPlayerPlayed)
  48. withArgumentAsObject:nil];
  49. }
  50. }
  51. static void HandleMediaListPlayerNextItemSet(const libvlc_event_t * event, void * self)
  52. {
  53. @autoreleasepool {
  54. VLCMedia *media = [[VLCMedia alloc]
  55. initWithLibVLCMediaDescriptor:event->u.media_list_player_next_item_set.item];
  56. [[VLCEventManager sharedManager] callOnMainThreadObject:(__bridge id)(self)
  57. withMethod:@selector(mediaListPlayerNextItemSet:)
  58. withArgumentAsObject:media];
  59. }
  60. }
  61. static void HandleMediaListPlayerStopped(const libvlc_event_t * event, void * self)
  62. {
  63. @autoreleasepool {
  64. [[VLCEventManager sharedManager] callOnMainThreadObject:(__bridge id)(self)
  65. withMethod:@selector(mediaListPlayerStopped)
  66. withArgumentAsObject:nil];
  67. }
  68. }
  69. @implementation VLCMediaListPlayer
  70. - (instancetype)initWithOptions:(NSArray *)options andDrawable:(id)drawable
  71. {
  72. if (self = [super init]) {
  73. _libVLCBackgroundQueue = dispatch_queue_create("libvlcQueue", DISPATCH_QUEUE_SERIAL);
  74. VLCLibrary *library;
  75. if (options != nil) {
  76. library = [[VLCLibrary alloc] initWithOptions:options];
  77. } else
  78. library = [VLCLibrary sharedLibrary];
  79. instance = libvlc_media_list_player_new([library instance]);
  80. _mediaPlayer = [[VLCMediaPlayer alloc] initWithLibVLCInstance:libvlc_media_list_player_get_media_player(instance) andLibrary:library];
  81. if (drawable != nil)
  82. [_mediaPlayer setDrawable:drawable];
  83. [self registerObservers];
  84. }
  85. return self;
  86. }
  87. - (void)registerObservers
  88. {
  89. __block libvlc_event_manager_t * p_em = libvlc_media_list_player_event_manager(instance);
  90. if (!p_em) {
  91. return;
  92. }
  93. dispatch_sync(_libVLCBackgroundQueue,^{
  94. libvlc_event_attach(p_em, libvlc_MediaListPlayerPlayed,
  95. HandleMediaListPlayerPlayed, (__bridge void *)(self));
  96. libvlc_event_attach(p_em, libvlc_MediaListPlayerNextItemSet,
  97. HandleMediaListPlayerNextItemSet, (__bridge void *)(self));
  98. libvlc_event_attach(p_em, libvlc_MediaListPlayerStopped,
  99. HandleMediaListPlayerStopped, (__bridge void *)(self));
  100. });
  101. }
  102. - (void)unregisterObservers
  103. {
  104. libvlc_event_manager_t * p_em = libvlc_media_list_player_event_manager(instance);
  105. if (!p_em) {
  106. return;
  107. }
  108. libvlc_event_detach(p_em, libvlc_MediaListPlayerPlayed,
  109. HandleMediaListPlayerPlayed, (__bridge void *)(self));
  110. libvlc_event_detach(p_em, libvlc_MediaListPlayerNextItemSet,
  111. HandleMediaListPlayerNextItemSet, (__bridge void *)(self));
  112. libvlc_event_detach(p_em, libvlc_MediaListPlayerStopped,
  113. HandleMediaListPlayerStopped, (__bridge void *)(self));
  114. }
  115. - (instancetype)initWithOptions:(NSArray *)options
  116. {
  117. return [self initWithOptions:options andDrawable:nil];
  118. }
  119. - (instancetype)init
  120. {
  121. return [self initWithOptions:nil andDrawable:nil];
  122. }
  123. - (instancetype)initWithDrawable:(id)drawable
  124. {
  125. return [self initWithOptions:nil andDrawable:drawable];
  126. }
  127. - (void)dealloc
  128. {
  129. [_mediaPlayer stop];
  130. [self unregisterObservers];
  131. libvlc_media_list_player_release(instance);
  132. }
  133. - (VLCMediaPlayer *)mediaPlayer
  134. {
  135. return _mediaPlayer;
  136. }
  137. - (void)setMediaList:(VLCMediaList *)mediaList
  138. {
  139. if (_mediaList == mediaList)
  140. return;
  141. _mediaList = mediaList;
  142. libvlc_media_list_player_set_media_list(instance, [mediaList libVLCMediaList]);
  143. [self willChangeValueForKey:@"rootMedia"];
  144. _rootMedia = nil;
  145. [self didChangeValueForKey:@"rootMedia"];
  146. }
  147. - (VLCMediaList *)mediaList
  148. {
  149. return _mediaList;
  150. }
  151. - (void)setRootMedia:(VLCMedia *)media
  152. {
  153. if (_rootMedia == media)
  154. return;
  155. _rootMedia = nil;
  156. VLCMediaList *mediaList = [[VLCMediaList alloc] init];
  157. if (media)
  158. [mediaList addMedia:media];
  159. // This will clean rootMedia
  160. [self setMediaList:mediaList];
  161. // Thus set rootMedia here.
  162. _rootMedia = media;
  163. }
  164. - (VLCMedia *)rootMedia
  165. {
  166. return _rootMedia;
  167. }
  168. - (void)playMedia:(VLCMedia *)media
  169. {
  170. dispatch_async(_libVLCBackgroundQueue, ^{
  171. libvlc_media_list_player_play_item(instance, [media libVLCMediaDescriptor]);
  172. });
  173. }
  174. - (void)play
  175. {
  176. dispatch_async(_libVLCBackgroundQueue, ^{
  177. libvlc_media_list_player_play(instance);
  178. });
  179. }
  180. - (void)pause
  181. {
  182. dispatch_async(_libVLCBackgroundQueue, ^{
  183. libvlc_media_list_player_set_pause(instance, 1);
  184. });
  185. }
  186. - (void)stop
  187. {
  188. dispatch_async(_libVLCBackgroundQueue, ^{
  189. libvlc_media_list_player_stop_async(instance);
  190. });
  191. }
  192. - (BOOL)next
  193. {
  194. return libvlc_media_list_player_next(instance) == 0 ? YES : NO;
  195. }
  196. - (BOOL)previous
  197. {
  198. return libvlc_media_list_player_previous(instance) == 0 ? YES : NO;
  199. }
  200. - (BOOL)playItemAtIndex:(int)index
  201. {
  202. return libvlc_media_list_player_play_item_at_index(instance, index) == 0 ? YES : NO;
  203. }
  204. - (void)playItemAtNumber:(NSNumber *)index
  205. {
  206. dispatch_async(_libVLCBackgroundQueue, ^{
  207. libvlc_media_list_player_play_item_at_index(instance, [index intValue]);
  208. });
  209. }
  210. - (void)setRepeatMode:(VLCRepeatMode)repeatMode
  211. {
  212. libvlc_playback_mode_t mode;
  213. switch (repeatMode) {
  214. case VLCRepeatAllItems:
  215. mode = libvlc_playback_mode_loop;
  216. break;
  217. case VLCDoNotRepeat:
  218. mode = libvlc_playback_mode_default;
  219. break;
  220. case VLCRepeatCurrentItem:
  221. mode = libvlc_playback_mode_repeat;
  222. break;
  223. default:
  224. NSAssert(0, @"Should not be reached");
  225. break;
  226. }
  227. libvlc_media_list_player_set_playback_mode(instance, mode);
  228. _repeatMode = repeatMode;
  229. }
  230. - (VLCRepeatMode)repeatMode
  231. {
  232. return _repeatMode;
  233. }
  234. #pragma mark - Delegate methods
  235. - (void)mediaListPlayerPlayed
  236. {
  237. if ([_delegate respondsToSelector:@selector(mediaListPlayerPlayed)]) {
  238. [_delegate mediaListPlayerFinishedPlayback:self];
  239. }
  240. }
  241. - (void)mediaListPlayerNextItemSet:(VLCMedia *)media
  242. {
  243. if ([_delegate respondsToSelector:@selector(mediaListPlayer:nextMedia:)]) {
  244. [_delegate mediaListPlayer:self nextMedia:media];
  245. }
  246. }
  247. - (void)mediaListPlayerStopped
  248. {
  249. if ([_delegate respondsToSelector:@selector(mediaListPlayerStopped)]) {
  250. [_delegate mediaListPlayerStopped:self];
  251. }
  252. }
  253. @end