VLCMediaPlayer.m 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. /*****************************************************************************
  2. * VLCMediaPlayer.m: VLCKit.framework VLCMediaPlayer implementation
  3. *****************************************************************************
  4. * Copyright (C) 2007-2009 Pierre d'Herbemont
  5. * Copyright (C) 2007-2014 VLC authors and VideoLAN
  6. * Partial Copyright (C) 2009-2014 Felix Paul Kühne
  7. * $Id$
  8. *
  9. * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
  10. * Faustion Osuna <enrique.osuna # gmail.com>
  11. * Felix Paul Kühne <fkuehne # videolan.org>
  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 "VLCLibrary.h"
  28. #import "VLCMediaPlayer.h"
  29. #import "VLCEventManager.h"
  30. #import "VLCLibVLCBridging.h"
  31. #if !TARGET_OS_IPHONE
  32. # import "VLCVideoView.h"
  33. #endif
  34. #ifdef HAVE_CONFIG_H
  35. # include "config.h"
  36. #endif
  37. #if !TARGET_OS_IPHONE
  38. /* prevent system sleep */
  39. # import <CoreServices/CoreServices.h>
  40. /* FIXME: Ugly hack! */
  41. # ifdef __x86_64__
  42. # import <CoreServices/../Frameworks/OSServices.framework/Headers/Power.h>
  43. # endif
  44. #endif
  45. #include <vlc/vlc.h>
  46. /* Notification Messages */
  47. NSString *const VLCMediaPlayerTimeChanged = @"VLCMediaPlayerTimeChanged";
  48. NSString *const VLCMediaPlayerStateChanged = @"VLCMediaPlayerStateChanged";
  49. NSString * VLCMediaPlayerStateToString(VLCMediaPlayerState state)
  50. {
  51. static NSString * stateToStrings[] = {
  52. [VLCMediaPlayerStateStopped] = @"VLCMediaPlayerStateStopped",
  53. [VLCMediaPlayerStateOpening] = @"VLCMediaPlayerStateOpening",
  54. [VLCMediaPlayerStateBuffering] = @"VLCMediaPlayerStateBuffering",
  55. [VLCMediaPlayerStateEnded] = @"VLCMediaPlayerStateEnded",
  56. [VLCMediaPlayerStateError] = @"VLCMediaPlayerStateError",
  57. [VLCMediaPlayerStatePlaying] = @"VLCMediaPlayerStatePlaying",
  58. [VLCMediaPlayerStatePaused] = @"VLCMediaPlayerStatePaused"
  59. };
  60. return stateToStrings[state];
  61. }
  62. static void HandleMediaTimeChanged(const libvlc_event_t * event, void * self)
  63. {
  64. @autoreleasepool {
  65. [[VLCEventManager sharedManager] callOnMainThreadObject:(__bridge id)(self)
  66. withMethod:@selector(mediaPlayerTimeChanged:)
  67. withArgumentAsObject:@(event->u.media_player_time_changed.new_time)];
  68. [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject:(__bridge id)(self)
  69. withDelegateMethod:@selector(mediaPlayerTimeChanged:)
  70. withNotificationName:VLCMediaPlayerTimeChanged];
  71. }
  72. }
  73. static void HandleMediaPositionChanged(const libvlc_event_t * event, void * self)
  74. {
  75. @autoreleasepool {
  76. [[VLCEventManager sharedManager] callOnMainThreadObject:(__bridge id)(self)
  77. withMethod:@selector(mediaPlayerPositionChanged:)
  78. withArgumentAsObject:@(event->u.media_player_position_changed.new_position)];
  79. }
  80. }
  81. static void HandleMediaInstanceStateChanged(const libvlc_event_t * event, void * self)
  82. {
  83. VLCMediaPlayerState newState;
  84. if (event->type == libvlc_MediaPlayerPlaying)
  85. newState = VLCMediaPlayerStatePlaying;
  86. else if (event->type == libvlc_MediaPlayerPaused)
  87. newState = VLCMediaPlayerStatePaused;
  88. else if (event->type == libvlc_MediaPlayerEndReached || event->type == libvlc_MediaPlayerStopped)
  89. newState = VLCMediaPlayerStateStopped;
  90. else if (event->type == libvlc_MediaPlayerEncounteredError)
  91. newState = VLCMediaPlayerStateError;
  92. else if (event->type == libvlc_MediaPlayerBuffering)
  93. newState = VLCMediaPlayerStateBuffering;
  94. else if (event->type == libvlc_MediaPlayerOpening)
  95. newState = VLCMediaPlayerStateOpening;
  96. else {
  97. VKLog(@"%s: Unknown event", __FUNCTION__);
  98. return;
  99. }
  100. @autoreleasepool {
  101. [[VLCEventManager sharedManager] callOnMainThreadObject:(__bridge id)(self)
  102. withMethod:@selector(mediaPlayerStateChanged:)
  103. withArgumentAsObject:@(newState)];
  104. [[VLCEventManager sharedManager] callOnMainThreadDelegateOfObject:(__bridge id)(self)
  105. withDelegateMethod:@selector(mediaPlayerStateChanged:)
  106. withNotificationName:VLCMediaPlayerStateChanged];
  107. }
  108. }
  109. static void HandleMediaPlayerMediaChanged(const libvlc_event_t * event, void * self)
  110. {
  111. @autoreleasepool {
  112. [[VLCEventManager sharedManager] callOnMainThreadObject:(__bridge id)(self)
  113. withMethod:@selector(mediaPlayerMediaChanged:)
  114. withArgumentAsObject:[VLCMedia mediaWithLibVLCMediaDescriptor:event->u.media_player_media_changed.new_media]];
  115. }
  116. }
  117. // TODO: Documentation
  118. @interface VLCMediaPlayer (Private)
  119. - (id)initWithDrawable:(id)aDrawable options:(NSArray *)options;
  120. - (void)registerObservers;
  121. - (void)unregisterObservers;
  122. - (void)mediaPlayerTimeChanged:(NSNumber *)newTime;
  123. - (void)mediaPlayerPositionChanged:(NSNumber *)newTime;
  124. - (void)mediaPlayerStateChanged:(NSNumber *)newState;
  125. - (void)mediaPlayerMediaChanged:(VLCMedia *)media;
  126. @end
  127. @interface VLCMediaPlayer ()
  128. {
  129. VLCLibrary *_privateLibrary;
  130. void * _playerInstance; // Internal
  131. VLCMedia * _media; //< Current media being played
  132. VLCTime * _cachedTime; //< Cached time of the media being played
  133. VLCTime * _cachedRemainingTime; //< Cached remaining time of the media being played
  134. VLCMediaPlayerState _cachedState; //< Cached state of the media being played
  135. float _position; //< The position of the media being played
  136. id _drawable; //< The drawable associated to this media player
  137. VLCAudio *_audio;
  138. libvlc_equalizer_t *_equalizerInstance;
  139. BOOL _equalizerEnabled;
  140. }
  141. @end
  142. @implementation VLCMediaPlayer
  143. @synthesize libraryInstance = _privateLibrary;
  144. /* Bindings */
  145. + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
  146. {
  147. static NSDictionary * dict = nil;
  148. NSSet * superKeyPaths;
  149. if (!dict) {
  150. dict = @{@"playing": [NSSet setWithObject:@"state"],
  151. @"seekable": [NSSet setWithObjects:@"state", @"media", nil],
  152. @"canPause": [NSSet setWithObjects:@"state", @"media", nil],
  153. @"description": [NSSet setWithObjects:@"state", @"media", nil]};
  154. }
  155. if ((superKeyPaths = [super keyPathsForValuesAffectingValueForKey: key])) {
  156. NSMutableSet * ret = [NSMutableSet setWithSet:dict[key]];
  157. [ret unionSet:superKeyPaths];
  158. return ret;
  159. }
  160. return dict[key];
  161. }
  162. /* Constructor */
  163. - (instancetype)init
  164. {
  165. return [self initWithDrawable:nil options:nil];
  166. }
  167. #if !TARGET_OS_IPHONE
  168. - (instancetype)initWithVideoView:(VLCVideoView *)aVideoView
  169. {
  170. return [self initWithDrawable: aVideoView options:nil];
  171. }
  172. - (instancetype)initWithVideoLayer:(VLCVideoLayer *)aVideoLayer
  173. {
  174. return [self initWithDrawable: aVideoLayer options:nil];
  175. }
  176. - (instancetype)initWithVideoView:(VLCVideoView *)aVideoView options:(NSArray *)options
  177. {
  178. return [self initWithDrawable: aVideoView options:options];
  179. }
  180. - (instancetype)initWithVideoLayer:(VLCVideoLayer *)aVideoLayer options:(NSArray *)options
  181. {
  182. return [self initWithDrawable: aVideoLayer options:options];
  183. }
  184. #endif
  185. - (instancetype)initWithOptions:(NSArray *)options
  186. {
  187. return [self initWithDrawable:nil options:options];
  188. }
  189. - (void)dealloc
  190. {
  191. NSAssert(libvlc_media_player_get_state(_playerInstance) == libvlc_Stopped || libvlc_media_player_get_state(_playerInstance) == libvlc_NothingSpecial, @"You released the media player before ensuring that it is stopped");
  192. [self unregisterObservers];
  193. [[VLCEventManager sharedManager] cancelCallToObject:self];
  194. // Always get rid of the delegate first so we can stop sending messages to it
  195. // TODO: Should we tell the delegate that we're shutting down?
  196. _delegate = nil;
  197. // Clear our drawable as we are going to release it, we don't
  198. // want the core to use it from this point. This won't happen as
  199. // the media player must be stopped.
  200. libvlc_media_player_set_nsobject(_playerInstance, nil);
  201. if (_equalizerInstance) {
  202. libvlc_media_player_set_equalizer(_playerInstance, NULL);
  203. libvlc_audio_equalizer_release(_equalizerInstance);
  204. }
  205. libvlc_media_player_release(_playerInstance);
  206. if (_privateLibrary != [VLCLibrary sharedLibrary])
  207. libvlc_release(_privateLibrary.instance);
  208. }
  209. #if !TARGET_OS_IPHONE
  210. - (void)setVideoView:(VLCVideoView *)aVideoView
  211. {
  212. [self setDrawable: aVideoView];
  213. }
  214. - (void)setVideoLayer:(VLCVideoLayer *)aVideoLayer
  215. {
  216. [self setDrawable: aVideoLayer];
  217. }
  218. #endif
  219. - (void)setDrawable:(id)aDrawable
  220. {
  221. // Make sure that this instance has been associated with the drawing canvas.
  222. libvlc_media_player_set_nsobject(_playerInstance, (__bridge void *)(aDrawable));
  223. }
  224. - (id)drawable
  225. {
  226. return (__bridge id)(libvlc_media_player_get_nsobject(_playerInstance));
  227. }
  228. - (VLCAudio *)audio
  229. {
  230. if (!_audio)
  231. _audio = [[VLCAudio alloc] initWithMediaPlayer:self];
  232. return _audio;
  233. }
  234. #pragma mark -
  235. #pragma mark Video Tracks
  236. - (void)setCurrentVideoTrackIndex:(int)value
  237. {
  238. libvlc_video_set_track(_playerInstance, value);
  239. }
  240. - (int)currentVideoTrackIndex
  241. {
  242. int count = libvlc_video_get_track_count(_playerInstance);
  243. if (count <= 0)
  244. return NSNotFound;
  245. return libvlc_video_get_track(_playerInstance);
  246. }
  247. - (NSArray *)videoTrackNames
  248. {
  249. NSInteger count = libvlc_video_get_track_count(_playerInstance);
  250. if (count <= 0)
  251. return @[];
  252. libvlc_track_description_t *currentTrack = libvlc_video_get_track_description(_playerInstance);
  253. NSMutableArray *tempArray = [NSMutableArray array];
  254. while (currentTrack) {
  255. [tempArray addObject:@(currentTrack->psz_name)];
  256. currentTrack = currentTrack->p_next;
  257. }
  258. libvlc_track_description_list_release(currentTrack);
  259. return [NSArray arrayWithArray: tempArray];
  260. }
  261. - (NSArray *)videoTrackIndexes
  262. {
  263. NSInteger count = libvlc_video_get_track_count(_playerInstance);
  264. if (count <= 0)
  265. return @[];
  266. libvlc_track_description_t *currentTrack = libvlc_video_get_track_description(_playerInstance);
  267. NSMutableArray *tempArray = [NSMutableArray array];
  268. while (currentTrack) {
  269. [tempArray addObject:@(currentTrack->i_id)];
  270. currentTrack = currentTrack->p_next;
  271. }
  272. libvlc_track_description_list_release(currentTrack);
  273. return [NSArray arrayWithArray: tempArray];
  274. }
  275. - (NSArray *)videoTracks
  276. {
  277. NSInteger count = libvlc_video_get_track_count(_playerInstance);
  278. if (count <= 0)
  279. return @[];
  280. libvlc_track_description_t *tracks = libvlc_video_get_track_description(_playerInstance);
  281. NSMutableArray *tempArray = [NSMutableArray array];
  282. for (NSUInteger i = 0; i < count ; i++) {
  283. [tempArray addObject:@(tracks->psz_name)];
  284. tracks = tracks->p_next;
  285. }
  286. libvlc_track_description_list_release(tracks);
  287. return [NSArray arrayWithArray: tempArray];
  288. }
  289. - (int)numberOfVideoTracks
  290. {
  291. return libvlc_video_get_track_count(_playerInstance);
  292. }
  293. #pragma mark -
  294. #pragma mark Subtitles
  295. - (void)setCurrentVideoSubTitleIndex:(int)index
  296. {
  297. libvlc_video_set_spu(_playerInstance, index);
  298. }
  299. - (int)currentVideoSubTitleIndex
  300. {
  301. NSInteger count = libvlc_video_get_spu_count(_playerInstance);
  302. if (count <= 0)
  303. return NSNotFound;
  304. return libvlc_video_get_spu(_playerInstance);
  305. }
  306. - (NSArray *)videoSubTitlesNames
  307. {
  308. NSInteger count = libvlc_video_get_spu_count(_playerInstance);
  309. if (count <= 0)
  310. return @[];
  311. libvlc_track_description_t *currentTrack = libvlc_video_get_spu_description(_playerInstance);
  312. NSMutableArray *tempArray = [NSMutableArray array];
  313. while (currentTrack) {
  314. [tempArray addObject:@(currentTrack->psz_name)];
  315. currentTrack = currentTrack->p_next;
  316. }
  317. libvlc_track_description_list_release(currentTrack);
  318. return [NSArray arrayWithArray: tempArray];
  319. }
  320. - (NSArray *)videoSubTitlesIndexes
  321. {
  322. NSInteger count = libvlc_video_get_spu_count(_playerInstance);
  323. if (count <= 0)
  324. return @[];
  325. libvlc_track_description_t *currentTrack = libvlc_video_get_spu_description(_playerInstance);
  326. NSMutableArray *tempArray = [NSMutableArray array];
  327. while (currentTrack) {
  328. [tempArray addObject:@(currentTrack->i_id)];
  329. currentTrack = currentTrack->p_next;
  330. }
  331. libvlc_track_description_list_release(currentTrack);
  332. return [NSArray arrayWithArray: tempArray];
  333. }
  334. - (int)numberOfSubtitlesTracks
  335. {
  336. return libvlc_video_get_spu_count(_playerInstance);
  337. }
  338. - (BOOL)openVideoSubTitlesFromFile:(NSString *)path
  339. {
  340. return libvlc_video_set_subtitle_file(_playerInstance, [path UTF8String]);
  341. }
  342. - (NSArray *)videoSubTitles
  343. {
  344. libvlc_track_description_t *currentTrack = libvlc_video_get_spu_description(_playerInstance);
  345. NSMutableArray *tempArray = [NSMutableArray array];
  346. while (currentTrack) {
  347. [tempArray addObject:@(currentTrack->psz_name)];
  348. currentTrack = currentTrack->p_next;
  349. }
  350. libvlc_track_description_list_release(currentTrack);
  351. return [NSArray arrayWithArray: tempArray];
  352. }
  353. - (void)setCurrentVideoSubTitleDelay:(NSInteger)index
  354. {
  355. libvlc_video_set_spu_delay(_playerInstance, index);
  356. }
  357. - (NSInteger)currentVideoSubTitleDelay
  358. {
  359. return libvlc_video_get_spu_delay(_playerInstance);
  360. }
  361. #if TARGET_OS_IPHONE
  362. - (void)setTextRendererFontSize:(NSNumber *)fontSize
  363. {
  364. libvlc_video_set_textrenderer_int(_playerInstance, libvlc_textrender_fontsize, [fontSize intValue]);
  365. }
  366. #endif
  367. #if TARGET_OS_IPHONE
  368. - (void)setTextRendererFont:(NSString *)fontname
  369. {
  370. libvlc_video_set_textrenderer_string(_playerInstance, libvlc_textrender_font, [fontname UTF8String]);
  371. }
  372. #endif
  373. #if TARGET_OS_IPHONE
  374. - (void)setTextRendererFontColor:(NSNumber *)fontColor
  375. {
  376. libvlc_video_set_textrenderer_int(_playerInstance, libvlc_textrender_fontcolor, [fontColor intValue]);
  377. }
  378. #endif
  379. #pragma mark -
  380. #pragma mark Video Crop geometry
  381. - (void)setVideoCropGeometry:(char *)value
  382. {
  383. libvlc_video_set_crop_geometry(_playerInstance, value);
  384. }
  385. - (char *)videoCropGeometry
  386. {
  387. char * result = libvlc_video_get_crop_geometry(_playerInstance);
  388. return result;
  389. }
  390. - (void)setVideoAspectRatio:(char *)value
  391. {
  392. libvlc_video_set_aspect_ratio(_playerInstance, value);
  393. }
  394. - (char *)videoAspectRatio
  395. {
  396. char * result = libvlc_video_get_aspect_ratio(_playerInstance);
  397. return result;
  398. }
  399. - (void)setScaleFactor:(float)value
  400. {
  401. libvlc_video_set_scale(_playerInstance, value);
  402. }
  403. - (float)scaleFactor
  404. {
  405. return libvlc_video_get_scale(_playerInstance);
  406. }
  407. - (void)saveVideoSnapshotAt:(NSString *)path withWidth:(int)width andHeight:(int)height
  408. {
  409. int failure = libvlc_video_take_snapshot(_playerInstance, 0, [path UTF8String], width, height);
  410. if (failure)
  411. [[NSException exceptionWithName:@"Can't take a video snapshot" reason:@"No video output" userInfo:nil] raise];
  412. }
  413. - (void)setDeinterlaceFilter:(NSString *)name
  414. {
  415. if (!name || name.length < 1)
  416. libvlc_video_set_deinterlace(_playerInstance, NULL);
  417. else
  418. libvlc_video_set_deinterlace(_playerInstance, [name UTF8String]);
  419. }
  420. - (BOOL)adjustFilterEnabled
  421. {
  422. return libvlc_video_get_adjust_int(_playerInstance, libvlc_adjust_Enable);
  423. }
  424. - (void)setAdjustFilterEnabled:(BOOL)b_value
  425. {
  426. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, b_value);
  427. }
  428. - (float)contrast
  429. {
  430. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, 1);
  431. return libvlc_video_get_adjust_float(_playerInstance, libvlc_adjust_Contrast);
  432. }
  433. - (void)setContrast:(float)f_value
  434. {
  435. if (f_value <= 2. && f_value >= 0.) {
  436. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, 1);
  437. libvlc_video_set_adjust_float(_playerInstance,libvlc_adjust_Contrast, f_value);
  438. }
  439. }
  440. - (float)brightness
  441. {
  442. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, 1);
  443. return libvlc_video_get_adjust_float(_playerInstance, libvlc_adjust_Brightness);
  444. }
  445. - (void)setBrightness:(float)f_value
  446. {
  447. if (f_value <= 2. && f_value >= 0.) {
  448. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, 1);
  449. libvlc_video_set_adjust_float(_playerInstance, libvlc_adjust_Brightness, f_value);
  450. }
  451. }
  452. - (int)hue
  453. {
  454. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, 1);
  455. return libvlc_video_get_adjust_int(_playerInstance, libvlc_adjust_Hue);
  456. }
  457. - (void)setHue:(int)i_value
  458. {
  459. if (i_value <= 360 && i_value >= 0) {
  460. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, 1);
  461. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Hue, i_value);
  462. }
  463. }
  464. - (float)saturation
  465. {
  466. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, 1);
  467. return libvlc_video_get_adjust_float(_playerInstance, libvlc_adjust_Saturation);
  468. }
  469. - (void)setSaturation:(float)f_value
  470. {
  471. if (f_value <= 3. && f_value >= 0.) {
  472. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, 1);
  473. libvlc_video_set_adjust_float(_playerInstance, libvlc_adjust_Saturation, f_value);
  474. }
  475. }
  476. - (float)gamma
  477. {
  478. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, 1);
  479. return libvlc_video_get_adjust_float(_playerInstance, libvlc_adjust_Gamma);
  480. }
  481. - (void)setGamma:(float)f_value
  482. {
  483. if (f_value <= 10. && f_value >= 0.) {
  484. libvlc_video_set_adjust_int(_playerInstance, libvlc_adjust_Enable, 1);
  485. libvlc_video_set_adjust_float(_playerInstance, libvlc_adjust_Gamma, f_value);
  486. }
  487. }
  488. - (void)setRate:(float)value
  489. {
  490. libvlc_media_player_set_rate(_playerInstance, value);
  491. }
  492. - (float)rate
  493. {
  494. return libvlc_media_player_get_rate(_playerInstance);
  495. }
  496. - (CGSize)videoSize
  497. {
  498. unsigned height = 0, width = 0;
  499. int failure = libvlc_video_get_size(_playerInstance, 0, &width, &height);
  500. if (failure)
  501. return CGSizeZero;
  502. return CGSizeMake(width, height);
  503. }
  504. - (BOOL)hasVideoOut
  505. {
  506. return libvlc_media_player_has_vout(_playerInstance);
  507. }
  508. - (float)framesPerSecond
  509. {
  510. return libvlc_media_player_get_fps(_playerInstance);
  511. }
  512. - (void)setTime:(VLCTime *)value
  513. {
  514. // Time is managed in seconds, while duration is managed in microseconds
  515. // TODO: Redo VLCTime to provide value numberAsMilliseconds, numberAsMicroseconds, numberAsSeconds, numberAsMinutes, numberAsHours
  516. libvlc_media_player_set_time(_playerInstance, value ? [[value numberValue] longLongValue] : 0);
  517. }
  518. - (VLCTime *)time
  519. {
  520. return _cachedTime;
  521. }
  522. - (VLCTime *)remainingTime
  523. {
  524. return _cachedRemainingTime;
  525. }
  526. - (NSUInteger)fps
  527. {
  528. return libvlc_media_player_get_fps(_playerInstance);
  529. }
  530. #pragma mark -
  531. #pragma mark Chapters
  532. - (void)setCurrentChapterIndex:(int)value;
  533. {
  534. libvlc_media_player_set_chapter(_playerInstance, value);
  535. }
  536. - (int)currentChapterIndex
  537. {
  538. int count = libvlc_media_player_get_chapter_count(_playerInstance);
  539. if (count <= 0)
  540. return NSNotFound;
  541. int result = libvlc_media_player_get_chapter(_playerInstance);
  542. return result;
  543. }
  544. - (void)nextChapter
  545. {
  546. libvlc_media_player_next_chapter(_playerInstance);
  547. }
  548. - (void)previousChapter
  549. {
  550. libvlc_media_player_previous_chapter(_playerInstance);
  551. }
  552. - (NSArray *)chaptersForTitleIndex:(int)title
  553. {
  554. NSInteger count = libvlc_media_player_get_chapter_count(_playerInstance);
  555. if (count <= 0)
  556. return @[];
  557. libvlc_track_description_t *tracks = libvlc_video_get_chapter_description(_playerInstance, title);
  558. NSMutableArray *tempArray = [NSMutableArray array];
  559. for (NSInteger i = 0; i < count ; i++) {
  560. [tempArray addObject:@(tracks->psz_name)];
  561. tracks = tracks->p_next;
  562. }
  563. libvlc_track_description_list_release(tracks);
  564. return [NSArray arrayWithArray:tempArray];
  565. }
  566. #pragma mark -
  567. #pragma mark Titles
  568. - (void)setCurrentTitleIndex:(int)value
  569. {
  570. libvlc_media_player_set_title(_playerInstance, value);
  571. }
  572. - (int)currentTitleIndex
  573. {
  574. NSInteger count = libvlc_media_player_get_title_count(_playerInstance);
  575. if (count <= 0)
  576. return NSNotFound;
  577. return libvlc_media_player_get_title(_playerInstance);
  578. }
  579. - (NSUInteger)countOfTitles
  580. {
  581. NSUInteger result = libvlc_media_player_get_title_count(_playerInstance);
  582. return result;
  583. }
  584. - (NSArray *)titles
  585. {
  586. NSUInteger count = [self countOfTitles];
  587. if (count == 0)
  588. return [NSArray array];
  589. libvlc_track_description_t *tracks = libvlc_video_get_title_description(_playerInstance);
  590. NSMutableArray *tempArray = [NSMutableArray array];
  591. if (!tracks)
  592. return tempArray;
  593. while (1) {
  594. if (tracks->psz_name != nil)
  595. [tempArray addObject:@(tracks->psz_name)];
  596. if (tracks->p_next)
  597. tracks = tracks->p_next;
  598. else
  599. break;
  600. }
  601. libvlc_track_description_list_release(tracks);
  602. return [NSArray arrayWithArray: tempArray];
  603. }
  604. #pragma mark -
  605. #pragma mark Audio tracks
  606. - (void)setCurrentAudioTrackIndex:(int)value
  607. {
  608. libvlc_audio_set_track(_playerInstance, value);
  609. }
  610. - (int)currentAudioTrackIndex
  611. {
  612. NSInteger count = libvlc_audio_get_track_count(_playerInstance);
  613. if (count <= 0)
  614. return NSNotFound;
  615. return libvlc_audio_get_track(_playerInstance);
  616. }
  617. - (NSArray *)audioTrackNames
  618. {
  619. NSInteger count = libvlc_audio_get_track_count(_playerInstance);
  620. if (count <= 0)
  621. return @[];
  622. libvlc_track_description_t *currentTrack = libvlc_audio_get_track_description(_playerInstance);
  623. NSMutableArray *tempArray = [NSMutableArray array];
  624. while (currentTrack) {
  625. [tempArray addObject:@(currentTrack->psz_name)];
  626. currentTrack = currentTrack->p_next;
  627. }
  628. libvlc_track_description_list_release(currentTrack);
  629. return [NSArray arrayWithArray: tempArray];
  630. }
  631. - (NSArray *)audioTrackIndexes
  632. {
  633. NSInteger count = libvlc_audio_get_track_count(_playerInstance);
  634. if (count <= 0)
  635. return @[];
  636. libvlc_track_description_t *currentTrack = libvlc_audio_get_track_description(_playerInstance);
  637. NSMutableArray *tempArray = [NSMutableArray array];
  638. while (currentTrack) {
  639. [tempArray addObject:@(currentTrack->i_id)];
  640. currentTrack = currentTrack->p_next;
  641. }
  642. libvlc_track_description_list_release(currentTrack);
  643. return [NSArray arrayWithArray: tempArray];
  644. }
  645. - (NSArray *)audioTracks
  646. {
  647. NSInteger count = libvlc_audio_get_track_count(_playerInstance);
  648. if (count <= 0)
  649. return @[];
  650. libvlc_track_description_t *tracks = libvlc_audio_get_track_description(_playerInstance);
  651. NSMutableArray *tempArray = [NSMutableArray array];
  652. for (NSUInteger i = 0; i < count ; i++) {
  653. [tempArray addObject:@(tracks->psz_name)];
  654. tracks = tracks->p_next;
  655. }
  656. libvlc_track_description_list_release(tracks);
  657. return [NSArray arrayWithArray: tempArray];
  658. }
  659. - (int)numberOfAudioTracks
  660. {
  661. return libvlc_audio_get_track_count(_playerInstance);
  662. }
  663. - (void)setAudioChannel:(int)value
  664. {
  665. libvlc_audio_set_channel(_playerInstance, value);
  666. }
  667. - (int)audioChannel
  668. {
  669. return libvlc_audio_get_channel(_playerInstance);
  670. }
  671. - (void)setCurrentAudioPlaybackDelay:(NSInteger)index
  672. {
  673. libvlc_audio_set_delay(_playerInstance, index);
  674. }
  675. - (NSInteger)currentAudioPlaybackDelay
  676. {
  677. return libvlc_audio_get_delay(_playerInstance);
  678. }
  679. #pragma mark -
  680. #pragma mark equalizer
  681. - (void)setEqualizerEnabled:(BOOL)equalizerEnabled
  682. {
  683. _equalizerEnabled = equalizerEnabled;
  684. if (!_equalizerEnabled) {
  685. libvlc_media_player_set_equalizer(_playerInstance, NULL);
  686. if (_equalizerInstance)
  687. libvlc_audio_equalizer_release(_equalizerInstance);
  688. return;
  689. }
  690. if (!_equalizerInstance)
  691. _equalizerInstance = libvlc_audio_equalizer_new();
  692. libvlc_media_player_set_equalizer(_playerInstance, _equalizerInstance);
  693. }
  694. - (BOOL)equalizerEnabled
  695. {
  696. return _equalizerEnabled;
  697. }
  698. - (NSArray *)equalizerProfiles
  699. {
  700. unsigned count = libvlc_audio_equalizer_get_preset_count();
  701. NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:count];
  702. for (unsigned x = 0; x < count; x++)
  703. [array addObject:@(libvlc_audio_equalizer_get_preset_name(x))];
  704. return [NSArray arrayWithArray:array];
  705. }
  706. - (void)resetEqualizerFromProfile:(unsigned)profile
  707. {
  708. BOOL wasactive = NO;
  709. if (_equalizerInstance) {
  710. libvlc_media_player_set_equalizer(_playerInstance, NULL);
  711. libvlc_audio_equalizer_release(_equalizerInstance);
  712. wasactive = YES;
  713. }
  714. _equalizerInstance = libvlc_audio_equalizer_new_from_preset(profile);
  715. if (wasactive)
  716. libvlc_media_player_set_equalizer(_playerInstance, _equalizerInstance);
  717. }
  718. - (CGFloat)preAmplification
  719. {
  720. if (!_equalizerInstance)
  721. return 0.;
  722. return libvlc_audio_equalizer_get_preamp(_equalizerInstance);
  723. }
  724. - (void)setPreAmplification:(CGFloat)preAmplification
  725. {
  726. if (!_equalizerInstance)
  727. _equalizerInstance = libvlc_audio_equalizer_new();
  728. libvlc_audio_equalizer_set_preamp(_equalizerInstance, preAmplification);
  729. libvlc_media_player_set_equalizer(_playerInstance, _equalizerInstance);
  730. }
  731. - (unsigned)numberOfBands
  732. {
  733. return libvlc_audio_equalizer_get_band_count();
  734. }
  735. - (CGFloat)frequencyOfBandAtIndex:(unsigned int)index
  736. {
  737. return libvlc_audio_equalizer_get_band_frequency(index);
  738. }
  739. - (void)setAmplification:(CGFloat)amplification forBand:(unsigned int)index
  740. {
  741. if (!_equalizerInstance)
  742. _equalizerInstance = libvlc_audio_equalizer_new();
  743. libvlc_audio_equalizer_set_amp_at_index(_equalizerInstance, amplification, index);
  744. }
  745. - (CGFloat)amplificationOfBand:(unsigned int)index
  746. {
  747. if (!_equalizerInstance)
  748. return 0.;
  749. return libvlc_audio_equalizer_get_amp_at_index(_equalizerInstance, index);
  750. }
  751. #pragma mark -
  752. #pragma mark set/get media
  753. - (void)setMedia:(VLCMedia *)value
  754. {
  755. if (_media != value) {
  756. if (_media && [_media compare:value] == NSOrderedSame)
  757. return;
  758. _media = value;
  759. libvlc_media_player_set_media(_playerInstance, [_media libVLCMediaDescriptor]);
  760. }
  761. }
  762. - (VLCMedia *)media
  763. {
  764. return _media;
  765. }
  766. #pragma mark -
  767. #pragma mark playback
  768. - (BOOL)play
  769. {
  770. libvlc_media_player_play(_playerInstance);
  771. return YES;
  772. }
  773. - (void)pause
  774. {
  775. if ([NSThread isMainThread]) {
  776. /* Hack because we create a dead lock here, when the vout is stopped
  777. * and tries to recontact us on the main thread */
  778. /* FIXME: to do this properly we need to do some locking. We may want
  779. * to move that to libvlc */
  780. [self performSelectorInBackground:@selector(pause) withObject:nil];
  781. return;
  782. }
  783. // Pause the stream
  784. libvlc_media_player_pause(_playerInstance);
  785. }
  786. - (void)stop
  787. {
  788. if ([NSThread isMainThread]) {
  789. /* Hack because we create a dead lock here, when the vout is stopped
  790. * and tries to recontact us on the main thread */
  791. /* FIXME: to do this properly we need to do some locking. We may want
  792. * to move that to libvlc */
  793. [self performSelectorInBackground:@selector(stop) withObject:nil];
  794. return;
  795. }
  796. libvlc_media_player_stop(_playerInstance);
  797. }
  798. - (void)gotoNextFrame
  799. {
  800. libvlc_media_player_next_frame(_playerInstance);
  801. }
  802. - (void)fastForward
  803. {
  804. [self fastForwardAtRate: 2.0];
  805. }
  806. - (void)fastForwardAtRate:(float)rate
  807. {
  808. [self setRate:rate];
  809. }
  810. - (void)rewind
  811. {
  812. [self rewindAtRate: 2.0];
  813. }
  814. - (void)rewindAtRate:(float)rate
  815. {
  816. [self setRate: -rate];
  817. }
  818. - (void)jumpBackward:(int)interval
  819. {
  820. if ([self isSeekable]) {
  821. interval = interval * 1000;
  822. [self setTime: [VLCTime timeWithInt: ([[self time] intValue] - interval)]];
  823. }
  824. }
  825. - (void)jumpForward:(int)interval
  826. {
  827. if ([self isSeekable]) {
  828. interval = interval * 1000;
  829. [self setTime: [VLCTime timeWithInt: ([[self time] intValue] + interval)]];
  830. }
  831. }
  832. - (void)extraShortJumpBackward
  833. {
  834. [self jumpBackward:3];
  835. }
  836. - (void)extraShortJumpForward
  837. {
  838. [self jumpForward:3];
  839. }
  840. - (void)shortJumpBackward
  841. {
  842. [self jumpBackward:10];
  843. }
  844. - (void)shortJumpForward
  845. {
  846. [self jumpForward:10];
  847. }
  848. - (void)mediumJumpBackward
  849. {
  850. [self jumpBackward:60];
  851. }
  852. - (void)mediumJumpForward
  853. {
  854. [self jumpForward:60];
  855. }
  856. - (void)longJumpBackward
  857. {
  858. [self jumpBackward:300];
  859. }
  860. - (void)longJumpForward
  861. {
  862. [self jumpForward:300];
  863. }
  864. + (NSSet *)keyPathsForValuesAffectingIsPlaying
  865. {
  866. return [NSSet setWithObjects:@"state", nil];
  867. }
  868. - (BOOL)isPlaying
  869. {
  870. return libvlc_media_player_is_playing(_playerInstance);
  871. }
  872. - (BOOL)willPlay
  873. {
  874. return libvlc_media_player_will_play(_playerInstance);
  875. }
  876. - (VLCMediaPlayerState)state
  877. {
  878. return _cachedState;
  879. }
  880. - (float)position
  881. {
  882. return _position;
  883. }
  884. - (void)setPosition:(float)newPosition
  885. {
  886. libvlc_media_player_set_position(_playerInstance, newPosition);
  887. }
  888. - (BOOL)isSeekable
  889. {
  890. return libvlc_media_player_is_seekable(_playerInstance);
  891. }
  892. - (BOOL)canPause
  893. {
  894. return libvlc_media_player_can_pause(_playerInstance);
  895. }
  896. - (void *)libVLCMediaPlayer
  897. {
  898. return _playerInstance;
  899. }
  900. @end
  901. @implementation VLCMediaPlayer (Private)
  902. - (id)initWithDrawable:(id)aDrawable options:(NSArray *)options
  903. {
  904. if (self = [super init]) {
  905. _cachedTime = [VLCTime nullTime];
  906. _cachedRemainingTime = [VLCTime nullTime];
  907. _position = 0.0f;
  908. _cachedState = VLCMediaPlayerStateStopped;
  909. // Create a media instance, it doesn't matter what library we start off with
  910. // it will change depending on the media descriptor provided to the media
  911. // instance
  912. if (options && options.count > 0) {
  913. VKLog(@"creating player instance with private library as options were given");
  914. _privateLibrary = [[VLCLibrary alloc] initWithOptions:options];
  915. } else {
  916. VKLog(@"creating player instance using shared library");
  917. _privateLibrary = [VLCLibrary sharedLibrary];
  918. }
  919. libvlc_retain([_privateLibrary instance]);
  920. _playerInstance = libvlc_media_player_new([_privateLibrary instance]);
  921. libvlc_media_player_retain(_playerInstance);
  922. [self registerObservers];
  923. [self setDrawable:aDrawable];
  924. }
  925. return self;
  926. }
  927. - (void)registerObservers
  928. {
  929. // Attach event observers into the media instance
  930. libvlc_event_manager_t * p_em = libvlc_media_player_event_manager(_playerInstance);
  931. libvlc_event_attach(p_em, libvlc_MediaPlayerPlaying, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  932. libvlc_event_attach(p_em, libvlc_MediaPlayerPaused, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  933. libvlc_event_attach(p_em, libvlc_MediaPlayerEncounteredError, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  934. libvlc_event_attach(p_em, libvlc_MediaPlayerEndReached, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  935. libvlc_event_attach(p_em, libvlc_MediaPlayerStopped, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  936. libvlc_event_attach(p_em, libvlc_MediaPlayerOpening, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  937. libvlc_event_attach(p_em, libvlc_MediaPlayerBuffering, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  938. libvlc_event_attach(p_em, libvlc_MediaPlayerPositionChanged, HandleMediaPositionChanged, (__bridge void *)(self));
  939. libvlc_event_attach(p_em, libvlc_MediaPlayerTimeChanged, HandleMediaTimeChanged, (__bridge void *)(self));
  940. libvlc_event_attach(p_em, libvlc_MediaPlayerMediaChanged, HandleMediaPlayerMediaChanged, (__bridge void *)(self));
  941. }
  942. - (void)unregisterObservers
  943. {
  944. libvlc_event_manager_t * p_em = libvlc_media_player_event_manager(_playerInstance);
  945. libvlc_event_detach(p_em, libvlc_MediaPlayerPlaying, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  946. libvlc_event_detach(p_em, libvlc_MediaPlayerPaused, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  947. libvlc_event_detach(p_em, libvlc_MediaPlayerEncounteredError, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  948. libvlc_event_detach(p_em, libvlc_MediaPlayerEndReached, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  949. libvlc_event_detach(p_em, libvlc_MediaPlayerStopped, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  950. libvlc_event_detach(p_em, libvlc_MediaPlayerOpening, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  951. libvlc_event_detach(p_em, libvlc_MediaPlayerBuffering, HandleMediaInstanceStateChanged, (__bridge void *)(self));
  952. libvlc_event_detach(p_em, libvlc_MediaPlayerPositionChanged, HandleMediaPositionChanged, (__bridge void *)(self));
  953. libvlc_event_detach(p_em, libvlc_MediaPlayerTimeChanged, HandleMediaTimeChanged, (__bridge void *)(self));
  954. libvlc_event_detach(p_em, libvlc_MediaPlayerMediaChanged, HandleMediaPlayerMediaChanged, (__bridge void *)(self));
  955. }
  956. - (void)mediaPlayerTimeChanged:(NSNumber *)newTime
  957. {
  958. [self willChangeValueForKey:@"time"];
  959. [self willChangeValueForKey:@"remainingTime"];
  960. _cachedTime = [VLCTime timeWithNumber:newTime];
  961. double currentTime = [[_cachedTime numberValue] doubleValue];
  962. if (currentTime > 0) {
  963. double remaining = currentTime / _position * (1 - _position);
  964. _cachedRemainingTime = [VLCTime timeWithNumber:@(-remaining)];
  965. } else
  966. _cachedRemainingTime = [VLCTime nullTime];
  967. [self didChangeValueForKey:@"remainingTime"];
  968. [self didChangeValueForKey:@"time"];
  969. }
  970. #if !TARGET_OS_IPHONE
  971. - (void)delaySleep
  972. {
  973. UpdateSystemActivity(UsrActivity);
  974. }
  975. #endif
  976. - (void)mediaPlayerPositionChanged:(NSNumber *)newPosition
  977. {
  978. #if !TARGET_OS_IPHONE
  979. // This seems to be the most relevant place to delay sleeping and screen saver.
  980. [self delaySleep];
  981. #endif
  982. [self willChangeValueForKey:@"position"];
  983. _position = [newPosition floatValue];
  984. [self didChangeValueForKey:@"position"];
  985. }
  986. - (void)mediaPlayerStateChanged:(NSNumber *)newState
  987. {
  988. [self willChangeValueForKey:@"state"];
  989. _cachedState = [newState intValue];
  990. #if TARGET_OS_IPHONE
  991. // Disable idle timer if player is playing media
  992. // Exclusion can be made for audio only media
  993. [UIApplication sharedApplication].idleTimerDisabled = [self isPlaying];
  994. #endif
  995. [self didChangeValueForKey:@"state"];
  996. }
  997. - (void)mediaPlayerMediaChanged:(VLCMedia *)newMedia
  998. {
  999. [self willChangeValueForKey:@"media"];
  1000. if (_media != newMedia)
  1001. _media = newMedia;
  1002. [self didChangeValueForKey:@"media"];
  1003. }
  1004. @end