[vlc-commits] macosx: refactor use of VLCInputItem

Felix Paul Kühne git at videolan.org
Mon Jul 1 13:09:52 CEST 2019


vlc | branch: master | Felix Paul Kühne <felix at feepk.net> | Mon Jul  1 13:08:29 2019 +0200| [4041ab70b2266b89a2dadccbf4e678fc091bd073] | committer: Felix Paul Kühne

macosx: refactor use of VLCInputItem

This way, code can be deduplicated and the information panel be cleaned

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=4041ab70b2266b89a2dadccbf4e678fc091bd073
---

 modules/gui/macosx/menus/VLCMainMenu.m             |  12 +-
 modules/gui/macosx/menus/VLCStatusBarIcon.m        |  83 ++-------
 .../macosx/panels/VLCInformationWindowController.h |  10 +-
 .../macosx/panels/VLCInformationWindowController.m | 201 ++++++++-------------
 .../panels/dialogs/VLCResumeDialogController.h     |   5 +-
 .../panels/dialogs/VLCResumeDialogController.m     |   8 +-
 .../playlist/VLCPlaybackContinuityController.m     |  56 +++---
 modules/gui/macosx/playlist/VLCPlayerController.h  |   5 +-
 modules/gui/macosx/playlist/VLCPlayerController.m  |  62 ++-----
 .../gui/macosx/playlist/VLCPlaylistController.h    |   3 +-
 .../gui/macosx/playlist/VLCPlaylistController.m    |  10 +-
 .../windows/mainwindow/VLCControlsBarCommon.m      |   9 +-
 .../macosx/windows/video/VLCFSPanelController.m    |  31 +---
 .../macosx/windows/video/VLCVideoWindowCommon.m    |  30 +--
 14 files changed, 182 insertions(+), 343 deletions(-)

diff --git a/modules/gui/macosx/menus/VLCMainMenu.m b/modules/gui/macosx/menus/VLCMainMenu.m
index b5b5c78e98..e208db4929 100644
--- a/modules/gui/macosx/menus/VLCMainMenu.m
+++ b/modules/gui/macosx/menus/VLCMainMenu.m
@@ -604,9 +604,9 @@ typedef NS_ENUM(NSInteger, VLCObjectType) {
 {
     [self updateTrackHandlingMenus:aNotification];
 
-    input_item_t *p_mediaItem = _playerController.currentMedia;
+    VLCInputItem *inputItem = _playerController.currentMedia;
 
-    if (p_mediaItem != NULL) {
+    if (inputItem != NULL) {
         audio_output_t *p_aout = [_playerController mainAudioOutput];
         if (p_aout != NULL) {
             [self setupVarMenuItem:_channels
@@ -655,7 +655,7 @@ typedef NS_ENUM(NSInteger, VLCObjectType) {
         }
         [_postprocessing setEnabled:YES];
         [self setSubmenusEnabled:YES];
-        input_item_Release(p_mediaItem);
+        inputItem = nil;
 
         [self setRateControlsEnabled:_playerController.rateChangable];
     } else {
@@ -1751,7 +1751,7 @@ typedef NS_ENUM(NSInteger, VLCObjectType) {
 - (BOOL)validateMenuItem:(NSMenuItem *)mi
 {
     BOOL enabled = YES;
-    input_item_t *inputItem = _playlistController.currentlyPlayingInputItem;
+    VLCInputItem *inputItem = _playlistController.currentlyPlayingInputItem;
 
     if (mi == _stop || mi == _voutMenustop || mi == _dockMenustop) {
         if (!inputItem)
@@ -1823,9 +1823,7 @@ typedef NS_ENUM(NSInteger, VLCObjectType) {
         }
     }
 
-    if (inputItem) {
-        input_item_Release(inputItem);
-    }
+    inputItem = nil;
 
     return enabled;
 }
diff --git a/modules/gui/macosx/menus/VLCStatusBarIcon.m b/modules/gui/macosx/menus/VLCStatusBarIcon.m
index 45cfd93ce1..834e1d220c 100644
--- a/modules/gui/macosx/menus/VLCStatusBarIcon.m
+++ b/modules/gui/macosx/menus/VLCStatusBarIcon.m
@@ -23,14 +23,11 @@
 
 #import "VLCStatusBarIcon.h"
 
-#import <vlc_common.h>
-#import <vlc_input.h>
-#import <vlc_url.h>
-
 #import "extensions/NSString+Helpers.h"
 #import "main/VLCMain.h"
 #import "playlist/VLCPlaylistController.h"
 #import "playlist/VLCPlayerController.h"
+#import "library/VLCInputItem.h"
 
 @interface VLCStatusBarIcon ()
 {
@@ -233,10 +230,10 @@
 {
     VLCPlayerController *playerController = aNotification.object;
 
-    input_item_t *p_item = playerController.currentMedia;
+    VLCInputItem *inputItem = playerController.currentMedia;
 
-    if (p_item) {
-        vlc_tick_t duration = input_item_GetDuration(p_item);
+    if (inputItem) {
+        vlc_tick_t duration = inputItem.duration;
         vlc_tick_t time = playerController.time;
 
         if (duration == 0) {
@@ -254,8 +251,6 @@
             [totalField setStringValue:[NSString stringWithTimeFromTicks:duration]];
         }
         [self setStoppedStatus:NO];
-
-        input_item_Release(p_item);
     } else {
         /* Nothing playing */
         [progressField setStringValue:@"--:--"];
@@ -267,19 +262,14 @@
 #pragma mark -
 #pragma mark Update functions
 
-- (void)updateCachedURLOfCurrentMedia:(input_item_t *)media
+- (void)updateCachedURLOfCurrentMedia:(VLCInputItem *)inputItem
 {
-    if (!media) {
-        _currentPlaybackUrl = nil;
-        return;
-    }
-    char *psz_url = vlc_uri_decode(input_item_GetURI(media));
-    if (!psz_url) {
+    if (!inputItem) {
         _currentPlaybackUrl = nil;
         return;
     }
-    _currentPlaybackUrl = toNSStr(psz_url);
-    free(psz_url);
+
+    _currentPlaybackUrl = inputItem.decodedMRL;
 }
 
 - (void)hasPreviousChanged:(NSNotification *)aNotification
@@ -302,18 +292,17 @@
     NSString        *nowPlaying;
     NSString        *artist;
     NSString        *album;
-    input_item_t    *mediaItem  = NULL;
 
     VLCPlayerController *playerController = aNotification.object;
     enum vlc_player_state playerState = playerController.playerState;
-    mediaItem = playerController.currentMedia;
+    VLCInputItem *inputItem = playerController.currentMedia;
 
     switch (playerState) {
         case VLC_PLAYER_STATE_PLAYING:
             [self setStoppedStatus:NO];
             [self setProgressTimeEnabled:YES];
             [pathActionItem setEnabled:YES];
-            [self updateCachedURLOfCurrentMedia:mediaItem];
+            [self updateCachedURLOfCurrentMedia:inputItem];
             break;
         case VLC_PLAYER_STATE_STOPPED:
             [self setStoppedStatus:YES];
@@ -325,56 +314,18 @@
             [self setStoppedStatus:NO];
             [self setProgressTimeEnabled:YES];
             [pathActionItem setEnabled:YES];
-            [self updateCachedURLOfCurrentMedia:mediaItem];
+            [self updateCachedURLOfCurrentMedia:inputItem];
             [playPauseButton setState:NSOffState];
         default:
             break;
     }
 
-    if (mediaItem) {
-        /* Something is playing */
-        static char *tmp_cstr = NULL;
-
-        // Get Coverart
-        tmp_cstr = input_item_GetArtworkURL(mediaItem);
-        if (tmp_cstr) {
-            NSString *tempStr = toNSStr(tmp_cstr);
-            if (![tempStr hasPrefix:@"attachment://"]) {
-                coverArtImage = [[NSImage alloc]
-                                 initWithContentsOfURL:[NSURL URLWithString:tempStr]];
-            }
-            FREENULL(tmp_cstr);
-        }
-
-        // Get Titel
-        tmp_cstr = input_item_GetTitleFbName(mediaItem);
-        if (tmp_cstr) {
-            title = toNSStr(tmp_cstr);
-            FREENULL(tmp_cstr);
-        }
-
-        // Get Now Playing
-        tmp_cstr = input_item_GetNowPlaying(mediaItem);
-        if (tmp_cstr) {
-            nowPlaying = toNSStr(tmp_cstr);
-            FREENULL(tmp_cstr);
-        }
-
-        // Get author
-        tmp_cstr = input_item_GetArtist(mediaItem);
-        if (tmp_cstr) {
-            artist = toNSStr(tmp_cstr);
-            FREENULL(tmp_cstr);
-        }
-
-        // Get album
-        tmp_cstr = input_item_GetAlbum(mediaItem);
-        if (tmp_cstr) {
-            album = toNSStr(tmp_cstr);
-            FREENULL(tmp_cstr);
-        }
-
-        input_item_Release(mediaItem);
+    if (inputItem) {
+        coverArtImage = [[NSImage alloc] initWithContentsOfURL:inputItem.artworkURL];
+        title = inputItem.title;
+        nowPlaying = inputItem.nowPlaying;
+        artist = inputItem.artist;
+        album = inputItem.albumName;
     } else {
         /* Nothing playing */
         title = _NS("VLC media player");
diff --git a/modules/gui/macosx/panels/VLCInformationWindowController.h b/modules/gui/macosx/panels/VLCInformationWindowController.h
index f6a5b78242..ea4b4089a0 100644
--- a/modules/gui/macosx/panels/VLCInformationWindowController.h
+++ b/modules/gui/macosx/panels/VLCInformationWindowController.h
@@ -22,11 +22,10 @@
  *****************************************************************************/
 
 #import <Cocoa/Cocoa.h>
-#import <vlc_common.h>
 
- at interface VLCInformationWindowController : NSWindowController
+ at class VLCInputItem;
 
- at property (readonly) input_item_t *item;
+ at interface VLCInformationWindowController : NSWindowController
 
 @property (readwrite, weak) IBOutlet NSOutlineView *outlineView;
 @property (readwrite, weak) IBOutlet NSSegmentedControl *segmentedView;
@@ -84,12 +83,11 @@
 @property (readwrite, weak) IBOutlet NSTextField *videoDecodedLabel;
 @property (readwrite, weak) IBOutlet NSTextField *videoDecodedTextField;
 
+ at property (readwrite, strong, nonatomic) VLCInputItem *representedInputItem;
+
 - (IBAction)toggleWindow:(id)sender;
 
 - (IBAction)metaFieldChanged:(id)sender;
 - (IBAction)saveMetaData:(id)sender;
-- (IBAction)downloadCoverArt:(id)sender;
-
-- (void)updatePanelWithItem:(input_item_t *)newInputItem;
 
 @end
diff --git a/modules/gui/macosx/panels/VLCInformationWindowController.m b/modules/gui/macosx/panels/VLCInformationWindowController.m
index f3da3b4994..10f8d61f80 100644
--- a/modules/gui/macosx/panels/VLCInformationWindowController.m
+++ b/modules/gui/macosx/panels/VLCInformationWindowController.m
@@ -24,11 +24,11 @@
 #import "VLCInformationWindowController.h"
 
 #import "extensions/NSString+Helpers.h"
-#import "main/CompatibilityFixes.h"
 #import "main/VLCMain.h"
 #import "playlist/VLCPlaylistController.h"
 #import "playlist/VLCPlayerController.h"
 #import "windows/video/VLCVideoOutputProvider.h"
+#import "library/VLCInputItem.h"
 
 #import <vlc_url.h>
 
@@ -51,11 +51,9 @@
 
 @interface VLCInformationWindowController () <NSOutlineViewDataSource>
 {
-    VLCCodecInformationTreeItem *rootItem;
+    VLCCodecInformationTreeItem *_rootCodecInformationItem;
 
-    input_item_t *_mediaItem;
-
-    BOOL b_stats;
+    BOOL _statisticsEnabled;
 }
 @end
 
@@ -84,9 +82,6 @@
 
 - (void)dealloc
 {
-    if (_mediaItem)
-        input_item_Release(_mediaItem);
-
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 
@@ -94,11 +89,25 @@
 {
     [self.window setExcludedFromWindowsMenu: YES];
     [self.window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
-
-    [self.window setTitle: _NS("Media Information")];
+    [self.window setInitialFirstResponder: _uriLabel];
 
     _outlineView.dataSource = self;
 
+    [self initStrings];
+
+    _statisticsEnabled = var_InheritBool(getIntf(), "stats");
+    if (!_statisticsEnabled) {
+        if ([_segmentedView segmentCount] >= 3)
+            [_segmentedView setSegmentCount: 2];
+    } else {
+        [self initMediaPanelStats];
+    }
+}
+
+- (void)initStrings
+{
+    [self.window setTitle: _NS("Media Information")];
+
     [_uriLabel setStringValue: _NS("Location")];
     [_titleLabel setStringValue: _NS("Title")];
     [_authorLabel setStringValue: _NS("Artist")];
@@ -136,27 +145,13 @@
     [_audioDecodedLabel setStringValue: _NS("Decoded blocks")];
     [_playedAudioBuffersLabel setStringValue: _NS("Played buffers")];
     [_lostAudioBuffersLabel setStringValue: _NS("Lost buffers")];
-
-    [self.window setInitialFirstResponder: _uriLabel];
-
-    b_stats = var_InheritBool(getIntf(), "stats");
-    if (!b_stats) {
-        if ([_segmentedView segmentCount] >= 3)
-            [_segmentedView setSegmentCount: 2];
-    }
-    else
-        [self initMediaPanelStats];
-
-    /* We may be awoken from nib way after initialisation
-     * Update ourselves */
-    [self updatePanelWithItem:_mediaItem];
 }
 
 - (void)updateCocoaWindowLevel:(NSNotification *)aNotification
 {
-    NSInteger i_level = [aNotification.userInfo[VLCWindowLevelKey] integerValue];
-    if (self.isWindowLoaded && [self.window isVisible] && [self.window level] != i_level)
-        [self.window setLevel: i_level];
+    NSInteger windowLevel = [aNotification.userInfo[VLCWindowLevelKey] integerValue];
+    if (self.isWindowLoaded && [self.window isVisible] && [self.window level] != windowLevel)
+        [self.window setLevel: windowLevel];
 }
 
 - (IBAction)toggleWindow:(id)sender
@@ -191,23 +186,20 @@
 - (void)currentPlaylistItemChanged:(NSNotification *)aNotification
 {
     VLCPlaylistController *playlistController = [[VLCMain sharedInstance] playlistController];
-    input_item_t *currentMediaItem = playlistController.currentlyPlayingInputItem;
-    [self updatePanelWithItem:currentMediaItem];
+    VLCInputItem *currentMediaItem = playlistController.currentlyPlayingInputItem;
+    [self setRepresentedInputItem:currentMediaItem];
 }
 
-- (void)updatePanelWithItem:(input_item_t *)newInputItem;
+- (void)setRepresentedInputItem:(VLCInputItem *)representedInputItem
 {
-    if (newInputItem != _mediaItem) {
-        if (_mediaItem)
-            input_item_Release(_mediaItem);
-        [_saveMetaDataButton setEnabled: NO];
-        _mediaItem = newInputItem;
-    }
+    _representedInputItem = representedInputItem;
+
+    [_saveMetaDataButton setEnabled: NO];
 
     if (!self.isWindowLoaded)
         return;
 
-    if (!_mediaItem) {
+    if (!_representedInputItem) {
         /* Erase */
 #define SET( foo ) \
 [_##foo##TextField setStringValue:@""];
@@ -227,53 +219,33 @@
 #undef SET
         [_imageWell setImage: [NSImage imageNamed: @"noart.png"]];
     } else {
-        if (!input_item_IsPreparsed(_mediaItem))
-            libvlc_MetadataRequest(vlc_object_instance(getIntf()), _mediaItem, META_REQUEST_OPTION_NONE,
-                                   NULL, NULL, -1, NULL);
-
-        /* fill uri info */
-        char *psz_url = vlc_uri_decode(input_item_GetURI(_mediaItem));
-        [_uriTextField setStringValue:toNSStr(psz_url)];
-        free(psz_url);
-
-        /* fill title info */
-        char *psz_title = input_item_GetTitle(_mediaItem);
-        if (!psz_title)
-            psz_title = input_item_GetName(_mediaItem);
-        [_titleTextField setStringValue:toNSStr(psz_title)];
-        free(psz_title);
-
-#define SET( foo, bar ) \
-char *psz_##foo = input_item_Get##bar ( _mediaItem ); \
-[_##foo##TextField setStringValue:toNSStr(psz_##foo)]; \
-FREENULL( psz_##foo );
-
-        /* fill the other fields */
-        SET( author, Artist );
-        SET( collection, Album );
-        SET( seqNum, TrackNum );
-        SET( genre, Genre );
-        SET( copyright, Copyright );
-        SET( publisher, Publisher );
-        SET( nowPlaying, NowPlaying );
-        SET( language, Language );
-        SET( date, Date );
-        SET( description, Description );
-        SET( encodedby, EncodedBy );
-
-#undef SET
+        if (!_representedInputItem.preparsed) {
+            [_representedInputItem preparseInputItem];
+        }
 
-        char *psz_meta;
-        NSImage *image;
-        psz_meta = input_item_GetArtURL(_mediaItem);
-
-        /* FIXME Can also be attachment:// */
-        if (psz_meta && strncmp(psz_meta, "attachment://", 13))
-            image = [[NSImage alloc] initWithContentsOfURL: [NSURL URLWithString:toNSStr(psz_meta)]];
-        else
-            image = [NSImage imageNamed: @"noart.png"];
-        [_imageWell setImage: image];
-        FREENULL(psz_meta);
+        _uriTextField.stringValue = _representedInputItem.MRL;
+        _titleTextField.stringValue = _representedInputItem.title;
+        _authorTextField.stringValue = _representedInputItem.artist;
+        _collectionTextField.stringValue = _representedInputItem.albumName;
+        _seqNumTextField.stringValue = _representedInputItem.trackNumber;
+        _genreTextField.stringValue = _representedInputItem.genre;
+        _copyrightTextField.stringValue = _representedInputItem.copyright;
+        _publisherTextField.stringValue = _representedInputItem.publisher;
+        _nowPlayingTextField.stringValue = _representedInputItem.nowPlaying;
+        _languageTextField.stringValue = _representedInputItem.language;
+        _dateTextField.stringValue = _representedInputItem.date;
+        _descriptionTextField.stringValue = _representedInputItem.contentDescription;
+        _encodedbyTextField.stringValue = _representedInputItem.encodedBy;
+
+        NSURL *artworkURL = _representedInputItem.artworkURL;
+        NSImage *artwork;
+        if (artworkURL) {
+            artwork = [[NSImage alloc] initWithContentsOfURL:_representedInputItem.artworkURL];
+        }
+        if (!artwork) {
+            artwork = [NSImage imageNamed: @"noart.png"];
+        }
+        [_imageWell setImage:artwork];
     }
 
     /* reload the codec details table */
@@ -282,7 +254,7 @@ FREENULL( psz_##foo );
 
 - (void)updateStatistics:(NSNotification *)aNotification
 {
-    if (!self.isWindowLoaded || !b_stats)
+    if (!self.isWindowLoaded || !_statisticsEnabled)
         return;
 
     if (![self.window isVisible])
@@ -317,15 +289,16 @@ FREENULL( psz_##foo );
 
 - (void)updateStreamsList
 {
-    rootItem = [[VLCCodecInformationTreeItem alloc] init];
+    _rootCodecInformationItem = [[VLCCodecInformationTreeItem alloc] init];
 
-    if (_mediaItem) {
-        vlc_mutex_lock(&_mediaItem->lock);
+    if (_representedInputItem) {
+        input_item_t *p_input = _representedInputItem.vlcInputItem;
+        vlc_mutex_lock(&p_input->lock);
         // build list of streams
         NSMutableArray *streams = [NSMutableArray array];
 
-        for (int i = 0; i < _mediaItem->i_categories; i++) {
-            info_category_t *cat = _mediaItem->pp_categories[i];
+        for (int i = 0; i < p_input->i_categories; i++) {
+            info_category_t *cat = p_input->pp_categories[i];
             info_t *info;
 
             VLCCodecInformationTreeItem *subItem = [[VLCCodecInformationTreeItem alloc] init];
@@ -345,8 +318,8 @@ FREENULL( psz_##foo );
             [streams addObject:subItem];
         }
 
-        rootItem.children = [streams copy];
-        vlc_mutex_unlock(&_mediaItem->lock);
+        _rootCodecInformationItem.children = [streams copy];
+        vlc_mutex_unlock(&p_input->lock);
     }
 
     [_outlineView reloadData];
@@ -360,7 +333,7 @@ FREENULL( psz_##foo );
 
 - (IBAction)saveMetaData:(id)sender
 {
-    if (!_mediaItem) {
+    if (!_representedInputItem) {
         NSAlert *alert = [[NSAlert alloc] init];
         [alert setMessageText:_NS("Error while saving meta")];
         [alert setInformativeText:_NS("VLC was unable to save the meta data.")];
@@ -369,44 +342,30 @@ FREENULL( psz_##foo );
         return;
     }
 
-    #define utf8( _blub ) \
-        [[_blub stringValue] UTF8String]
-
-    input_item_SetName( _mediaItem, utf8( _titleTextField ) );
-    input_item_SetTitle( _mediaItem, utf8( _titleTextField ) );
-    input_item_SetArtist( _mediaItem, utf8( _authorTextField ) );
-    input_item_SetAlbum( _mediaItem, utf8( _collectionTextField ) );
-    input_item_SetGenre( _mediaItem, utf8( _genreTextField ) );
-    input_item_SetTrackNum( _mediaItem, utf8( _seqNumTextField ) );
-    input_item_SetDate( _mediaItem, utf8( _dateTextField ) );
-    input_item_SetCopyright( _mediaItem, utf8( _copyrightTextField ) );
-    input_item_SetPublisher( _mediaItem, utf8( _publisherTextField ) );
-    input_item_SetDescription( _mediaItem, utf8( _descriptionTextField ) );
-    input_item_SetLanguage( _mediaItem, utf8( _languageTextField ) );
-
-    input_item_WriteMeta(VLC_OBJECT(getIntf()), _mediaItem);
-
-    [self updatePanelWithItem: _mediaItem];
-
+    _representedInputItem.name = _titleTextField.stringValue;
+    _representedInputItem.title = _titleTextField.stringValue;
+    _representedInputItem.artist = _authorTextField.stringValue;
+    _representedInputItem.albumName = _collectionTextField.stringValue;
+    _representedInputItem.genre = _genreTextField.stringValue;
+    _representedInputItem.trackNumber = _seqNumTextField.stringValue;
+    _representedInputItem.date = _dateTextField.stringValue;
+    _representedInputItem.copyright = _copyrightTextField.stringValue;
+    _representedInputItem.publisher = _publisherTextField.stringValue;
+    _representedInputItem.contentDescription = _descriptionTextField.stringValue;
+    _representedInputItem.language = _languageTextField.stringValue;
+
+    [_representedInputItem writeMetadataToFile];
     [_saveMetaDataButton setEnabled: NO];
 }
 
-- (IBAction)downloadCoverArt:(id)sender
-{
-    if (_mediaItem)
-        libvlc_ArtRequest(vlc_object_instance(getIntf()), _mediaItem, META_REQUEST_OPTION_NONE,
-                          NULL, NULL);
-}
-
 @end
 
-
 @implementation VLCInformationWindowController (NSTableDataSource)
 
 - (NSInteger)outlineView:(NSOutlineView *)outlineView
   numberOfChildrenOfItem:(id)item
 {
-    return (item == nil) ? [rootItem children].count : [item children].count;
+    return (item == nil) ? [_rootCodecInformationItem children].count : [item children].count;
 }
 
 - (BOOL)outlineView:(NSOutlineView *)outlineView
@@ -418,7 +377,7 @@ FREENULL( psz_##foo );
             child:(NSInteger)index
            ofItem:(id)item
 {
-    return (item == nil) ? [rootItem children][index] : [item children][index];
+    return (item == nil) ? [_rootCodecInformationItem children][index] : [item children][index];
 }
 
 - (id)outlineView:(NSOutlineView *)outlineView
diff --git a/modules/gui/macosx/panels/dialogs/VLCResumeDialogController.h b/modules/gui/macosx/panels/dialogs/VLCResumeDialogController.h
index 811294dc0f..306f6fe556 100644
--- a/modules/gui/macosx/panels/dialogs/VLCResumeDialogController.h
+++ b/modules/gui/macosx/panels/dialogs/VLCResumeDialogController.h
@@ -23,8 +23,7 @@
 
 #import <Cocoa/Cocoa.h>
 
-#import <vlc_common.h>
-#import <vlc_input.h>
+ at class VLCInputItem;
 
 enum ResumeResult {
     RESUME_RESTART,
@@ -49,7 +48,7 @@ typedef void(^CompletionBlock)(enum ResumeResult);
 - (IBAction)buttonClicked:(id)sender;
 - (IBAction)resumeSettingChanged:(id)sender;
 
-- (void)showWindowWithItem:(input_item_t *)p_item withLastPosition:(NSInteger)pos completionBlock:(CompletionBlock)block;
+- (void)showWindowWithItem:(VLCInputItem *)inputItem withLastPosition:(NSInteger)pos completionBlock:(CompletionBlock)block;
 
 - (void)cancel;
 
diff --git a/modules/gui/macosx/panels/dialogs/VLCResumeDialogController.m b/modules/gui/macosx/panels/dialogs/VLCResumeDialogController.m
index 6d60c78f3a..fe2bc5cb4e 100644
--- a/modules/gui/macosx/panels/dialogs/VLCResumeDialogController.m
+++ b/modules/gui/macosx/panels/dialogs/VLCResumeDialogController.m
@@ -27,6 +27,7 @@
 #import "main/VLCMain.h"
 #import "extensions/NSString+Helpers.h"
 #import "windows/video/VLCVideoOutputProvider.h"
+#import "library/VLCInputItem.h"
 
 @interface VLCResumeDialogController()
 {
@@ -63,7 +64,7 @@
     [o_always_resume_chk setTitle:_NS("Always continue media playback")];
 }
 
-- (void)showWindowWithItem:(input_item_t *)p_item withLastPosition:(NSInteger)pos completionBlock:(CompletionBlock)block
+- (void)showWindowWithItem:(VLCInputItem *)inputItem withLastPosition:(NSInteger)pos completionBlock:(CompletionBlock)block
 {
     NSWindow *w = [self window];
 
@@ -74,10 +75,7 @@
     o_restartButtonLabel = [o_restartButtonLabel stringByAppendingFormat:@" (%d)", currentResumeTimeout];
     [o_restart_btn setTitle:o_restartButtonLabel];
 
-    char *psz_title_name = input_item_GetTitleFbName(p_item);
-    NSString *o_title = toNSStr(psz_title_name);
-    free(psz_title_name);
-    NSString *labelString = [NSString stringWithFormat:_NS("Playback of \"%@\" will continue at %@"), o_title, [NSString stringWithTime:pos]];
+    NSString *labelString = [NSString stringWithFormat:_NS("Playback of \"%@\" will continue at %@"), inputItem.title, [NSString stringWithTime:pos]];
     [o_text_lbl setStringValue:labelString];
     [o_always_resume_chk setState: NSOffState];
 
diff --git a/modules/gui/macosx/playlist/VLCPlaybackContinuityController.m b/modules/gui/macosx/playlist/VLCPlaybackContinuityController.m
index 88b8a3bd0f..975922909d 100644
--- a/modules/gui/macosx/playlist/VLCPlaybackContinuityController.m
+++ b/modules/gui/macosx/playlist/VLCPlaybackContinuityController.m
@@ -28,12 +28,13 @@
 #import "panels/dialogs/VLCResumeDialogController.h"
 #import "playlist/VLCPlaylistController.h"
 #import "playlist/VLCPlayerController.h"
+#import "library/VLCInputItem.h"
 
 #import <vlc_url.h>
 
 @interface VLCPlaybackContinuityController()
 {
-    input_item_t *p_current_input;
+    VLCInputItem *_currentInput;
 }
 @end
 
@@ -72,9 +73,9 @@
 
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 
-    if (p_current_input) {
+    if (_currentInput) {
         /* continue playback where you left off */
-        [self storePlaybackPositionForItem:p_current_input player:[VLCMain sharedInstance].playlistController.playerController];
+        [self storePlaybackPositionForItem:_currentInput player:[VLCMain sharedInstance].playlistController.playerController];
     }
 }
 
@@ -85,10 +86,10 @@
     [[mainInstance resumeDialog] cancel];
 
     // object is hold here and released then it is dead
-    p_current_input = [[mainInstance playlistController] currentlyPlayingInputItem];
-    if (p_current_input) {
+    _currentInput = [[mainInstance playlistController] currentlyPlayingInputItem];
+    if (_currentInput) {
         VLCPlaylistController *playlistController = aNotification.object;
-        [self continuePlaybackWhereYouLeftOff:p_current_input player:playlistController.playerController];
+        [self continuePlaybackWhereYouLeftOff:_currentInput player:playlistController.playerController];
     }
 }
 
@@ -105,16 +106,14 @@
 
     if (playerState == VLC_PLAYER_STATE_STOPPED || playerState == VLC_PLAYER_STATE_STOPPING) {
         /* continue playback where you left off */
-        if (p_current_input)
-            [self storePlaybackPositionForItem:p_current_input player:playerController];
+        if (_currentInput)
+            [self storePlaybackPositionForItem:_currentInput player:playerController];
     }
 }
 
-- (BOOL)isValidResumeItem:(input_item_t *)p_item
+- (BOOL)isValidResumeItem:(VLCInputItem *)inputItem
 {
-    char *psz_url = input_item_GetURI(p_item);
-    NSString *urlString = toNSStr(psz_url);
-    free(psz_url);
+    NSString *urlString = inputItem.MRL;
 
     if ([urlString isEqualToString:@""])
         return NO;
@@ -134,13 +133,13 @@
     return YES;
 }
 
-- (void)continuePlaybackWhereYouLeftOff:(input_item_t *)p_input_item player:(VLCPlayerController *)playerController
+- (void)continuePlaybackWhereYouLeftOff:(VLCInputItem *)inputItem player:(VLCPlayerController *)playerController
 {
     NSDictionary *recentlyPlayedFiles = [[NSUserDefaults standardUserDefaults] objectForKey:@"recentlyPlayedMedia"];
     if (!recentlyPlayedFiles)
         return;
 
-    if (!p_input_item)
+    if (!inputItem)
         return;
 
     /* allow the user to over-write the start/stop/run-time */
@@ -154,14 +153,13 @@
 #endif
 
     /* check for file existance before resuming */
-    if (![self isValidResumeItem:p_input_item])
+    if (![self isValidResumeItem:inputItem])
         return;
 
-    char *psz_url = vlc_uri_decode(input_item_GetURI(p_input_item));
-    if (!psz_url)
+    NSString *url = inputItem.MRL;
+    if (!url) {
         return;
-    NSString *url = toNSStr(psz_url);
-    free(psz_url);
+    }
 
     NSNumber *lastPosition = [recentlyPlayedFiles objectForKey:url];
     if (!lastPosition || lastPosition.intValue <= 0)
@@ -187,35 +185,33 @@
         return;
     }
 
-    [[[VLCMain sharedInstance] resumeDialog] showWindowWithItem:p_input_item
-                                    withLastPosition:lastPosition.intValue
-                                     completionBlock:completionBlock];
+    [[[VLCMain sharedInstance] resumeDialog] showWindowWithItem:inputItem
+                                               withLastPosition:lastPosition.intValue
+                                                completionBlock:completionBlock];
 
 }
 
-- (void)storePlaybackPositionForItem:(input_item_t *)p_input_item player:(VLCPlayerController *)playerController
+- (void)storePlaybackPositionForItem:(VLCInputItem *)inputItem player:(VLCPlayerController *)playerController
 {
     if (!var_InheritBool(getIntf(), "macosx-recentitems"))
         return;
 
-    if (!p_input_item)
+    if (!inputItem)
         return;
 
-    if (![self isValidResumeItem:p_input_item])
+    if (![self isValidResumeItem:inputItem])
         return;
 
-    char *psz_url = vlc_uri_decode(input_item_GetURI(p_input_item));
-    if (!psz_url)
+    NSString *url = inputItem.MRL;
+    if (!url)
         return;
-    NSString *url = toNSStr(psz_url);
-    free(psz_url);
 
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
     NSMutableDictionary *mutDict = [[NSMutableDictionary alloc] initWithDictionary:[defaults objectForKey:@"recentlyPlayedMedia"]];
 
     float relativePos = playerController.position;
     long long pos = SEC_FROM_VLC_TICK(playerController.time);
-    long long dur = SEC_FROM_VLC_TICK(input_item_GetDuration(p_input_item));
+    long long dur = SEC_FROM_VLC_TICK(inputItem.duration);
 
     NSMutableArray *mediaList = [[defaults objectForKey:@"recentlyPlayedMediaList"] mutableCopy];
 
diff --git a/modules/gui/macosx/playlist/VLCPlayerController.h b/modules/gui/macosx/playlist/VLCPlayerController.h
index dd1f1f38d8..33f952f33e 100644
--- a/modules/gui/macosx/playlist/VLCPlayerController.h
+++ b/modules/gui/macosx/playlist/VLCPlayerController.h
@@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
 @class VLCInputStats;
 @class VLCTrackMetaData;
 @class VLCProgramMetaData;
+ at class VLCInputItem;
 
 extern NSString *VLCPlayerElementaryStreamID;
 extern NSString *VLCTick;
@@ -315,13 +316,13 @@ extern const CGFloat VLCVolumeDefault;
  * @return the current media item, NULL if none
  * @note it is the receiver's obligation to release the input item
  */
- at property (readonly, nullable) input_item_t * currentMedia;
+ at property (readonly, nullable) VLCInputItem * currentMedia;
 /**
  * set the current media item
  * @note this is typically done by the associated playlist so you should not need to do it
  * @return VLC_SUCCESS on success, another VLC error on failure
  */
-- (int)setCurrentMedia:(input_item_t *)currentMedia;
+- (int)setCurrentMedia:(VLCInputItem *)currentMedia;
 
 /**
  * returns the duration of the current media in vlc ticks
diff --git a/modules/gui/macosx/playlist/VLCPlayerController.m b/modules/gui/macosx/playlist/VLCPlayerController.m
index ca310e0bc6..0434759292 100644
--- a/modules/gui/macosx/playlist/VLCPlayerController.m
+++ b/modules/gui/macosx/playlist/VLCPlayerController.m
@@ -29,6 +29,7 @@
 #import "os-integration/VLCRemoteControlService.h"
 #import "os-integration/iTunes.h"
 #import "os-integration/Spotify.h"
+#import "library/VLCInputItem.h"
 
 #import "windows/video/VLCVoutView.h"
 #import "windows/video/VLCVideoWindowCommon.h"
@@ -727,25 +728,26 @@ static const struct vlc_player_aout_cbs player_aout_callbacks = {
 
 #pragma mark - player callback delegations
 
-- (input_item_t *)currentMedia
+- (VLCInputItem *)currentMedia
 {
-    input_item_t *inputItem;
+    VLCInputItem *inputItem;
+    input_item_t *p_input;
     vlc_player_Lock(_p_player);
-    inputItem = vlc_player_GetCurrentMedia(_p_player);
-    if (inputItem) {
-        input_item_Hold(inputItem);
+    p_input = vlc_player_GetCurrentMedia(_p_player);
+    if (p_input) {
+        inputItem = [[VLCInputItem alloc] initWithInputItem:p_input];
     }
     vlc_player_Unlock(_p_player);
     return inputItem;
 }
 
-- (int)setCurrentMedia:(input_item_t *)currentMedia
+- (int)setCurrentMedia:(VLCInputItem *)currentMedia
 {
     if (currentMedia == NULL) {
         return VLC_ENOITEM;
     }
     vlc_player_Lock(_p_player);
-    int ret = vlc_player_SetCurrentMedia(_p_player, currentMedia);
+    int ret = vlc_player_SetCurrentMedia(_p_player, currentMedia.vlcInputItem);
     vlc_player_Unlock(_p_player);
     return ret;
 }
@@ -758,69 +760,37 @@ static const struct vlc_player_aout_cbs player_aout_callbacks = {
 
 - (vlc_tick_t)durationOfCurrentMediaItem
 {
-    input_item_t *p_item = self.currentMedia;
-
-    if (!p_item) {
+    if (!self.currentMedia) {
         return -1;
     }
 
-    vlc_tick_t duration = input_item_GetDuration(p_item);
-    input_item_Release(p_item);
-
-    return duration;
+    return self.currentMedia.duration;
 }
 
 - (NSURL *)URLOfCurrentMediaItem;
 {
-    input_item_t *p_item = self.currentMedia;
-    if (!p_item) {
-        return nil;
-    }
-
-    char *psz_url = vlc_uri_decode(input_item_GetURI(p_item));
-    if (!psz_url) {
+    if (!self.currentMedia) {
         return nil;
     }
-    NSURL *url = [NSURL URLWithString:toNSStr(psz_url)];
-    free(psz_url);
-    input_item_Release(p_item);
 
-    return url;
+    return [NSURL URLWithString:self.currentMedia.MRL];
 }
 
 - (NSString*)nameOfCurrentMediaItem;
 {
-    input_item_t *p_item = self.currentMedia;
-    if (!p_item) {
+    if (!self.currentMedia) {
         return nil;
     }
 
-    NSString *name;
-    static char *tmp_cstr = NULL;
-
-    // Get Title
-    tmp_cstr = input_item_GetTitleFbName(p_item);
-    if (tmp_cstr) {
-        name = toNSStr(tmp_cstr);
-        FREENULL(tmp_cstr);
-    }
-
+    NSString *name = self.currentMedia.name;
     if (!name) {
-        char *psz_uri = input_item_GetURI(p_item);
-        if (!psz_uri) {
-            input_item_Release(p_item);
-            return nil;
-        }
-        NSURL *url = [NSURL URLWithString:toNSStr(psz_uri)];
-        free(psz_uri);
-
+        NSURL *url = [NSURL URLWithString:self.currentMedia.MRL];
         if ([url isFileURL])
             name = [[NSFileManager defaultManager] displayNameAtPath:[url path]];
         else
             name = [url absoluteString];
     }
 
-    input_item_Release(p_item);
     return name;
 }
 
diff --git a/modules/gui/macosx/playlist/VLCPlaylistController.h b/modules/gui/macosx/playlist/VLCPlaylistController.h
index 4d7e6c2704..bec3b8a1f1 100644
--- a/modules/gui/macosx/playlist/VLCPlaylistController.h
+++ b/modules/gui/macosx/playlist/VLCPlaylistController.h
@@ -30,6 +30,7 @@ NS_ASSUME_NONNULL_BEGIN
 @class VLCPlayerController;
 @class VLCPlaylistExportModuleDescription;
 @class VLCOpenInputMetadata;
+ at class VLCInputItem;
 
 extern NSString *VLCPlaybackOrderChanged;
 extern NSString *VLCPlaybackRepeatChanged;
@@ -78,7 +79,7 @@ extern NSString *VLCPlaylistItemsRemoved;
  @note the receiver is responsible for releasing the input item
  @note Subscribe to the VLCPlaylistCurrentItemChanged notification to be notified about changes
  */
- at property (readonly, nullable) input_item_t *currentlyPlayingInputItem;
+ at property (readonly, nullable) VLCInputItem *currentlyPlayingInputItem;
 
 /**
  * indicates whether there is a previous item in the list the user could go back to
diff --git a/modules/gui/macosx/playlist/VLCPlaylistController.m b/modules/gui/macosx/playlist/VLCPlaylistController.m
index f09570df32..ba145fd469 100644
--- a/modules/gui/macosx/playlist/VLCPlaylistController.m
+++ b/modules/gui/macosx/playlist/VLCPlaylistController.m
@@ -32,6 +32,7 @@
 #import "playlist/VLCPlaylistDataSource.h"
 #import "playlist/VLCPlayerController.h"
 #import "windows/VLCOpenInputMetadata.h"
+#import "library/VLCInputItem.h"
 
 NSString *VLCPlaybackOrderChanged = @"VLCPlaybackOrderChanged";
 NSString *VLCPlaybackRepeatChanged = @"VLCPlaybackRepeatChanged";
@@ -513,13 +514,14 @@ static const struct vlc_playlist_callbacks playlist_callbacks = {
 
 #pragma mark - properties
 
-- (input_item_t *)currentlyPlayingInputItem
+- (VLCInputItem *)currentlyPlayingInputItem
 {
     vlc_player_t *player = vlc_playlist_GetPlayer(_p_playlist);
+    VLCInputItem *inputItem;
     vlc_player_Lock(player);
-    input_item_t *inputItem = vlc_player_GetCurrentMedia(player);
-    if (inputItem) {
-        input_item_Hold(inputItem);
+    input_item_t *vlcInputItem = vlc_player_GetCurrentMedia(player);
+    if (vlcInputItem) {
+        inputItem = [[VLCInputItem alloc] initWithInputItem:vlcInputItem];
     }
     vlc_player_Unlock(player);
     return inputItem;
diff --git a/modules/gui/macosx/windows/mainwindow/VLCControlsBarCommon.m b/modules/gui/macosx/windows/mainwindow/VLCControlsBarCommon.m
index 916f506b56..de64eb5fb6 100644
--- a/modules/gui/macosx/windows/mainwindow/VLCControlsBarCommon.m
+++ b/modules/gui/macosx/windows/mainwindow/VLCControlsBarCommon.m
@@ -27,6 +27,7 @@
 #import "main/VLCMain.h"
 #import "playlist/VLCPlaylistController.h"
 #import "playlist/VLCPlayerController.h"
+#import "library/VLCInputItem.h"
 
 #import "views/VLCBottomBarView.h"
 #import "views/VLCDragDropView.h"
@@ -265,9 +266,9 @@
 
 - (void)updateTimeSlider:(NSNotification *)aNotification;
 {
-    input_item_t *p_item = _playerController.currentMedia;
+    VLCInputItem *inputItem = _playerController.currentMedia;
 
-    if (!p_item) {
+    if (!inputItem) {
         // Nothing playing
         [self.timeSlider setKnobHidden:YES];
         [self.timeSlider setFloatValue: 0.0];
@@ -280,7 +281,7 @@
     [self.timeSlider setKnobHidden:NO];
     [self.timeSlider setFloatValue:(10000. * _playerController.position)];
 
-    vlc_tick_t duration = input_item_GetDuration(p_item);
+    vlc_tick_t duration = inputItem.duration;
     bool buffering = _playerController.playerState == VLC_PLAYER_STATE_STARTED;
     if (duration == -1) {
         // No duration, disable slider
@@ -297,8 +298,6 @@
                                          negative:self.timeField.timeRemaining];
     [self.timeField setStringValue:time];
     [self.timeField setNeedsDisplay:YES];
-
-    input_item_Release(p_item);
 }
 
 - (void)playerStateUpdated:(NSNotification *)aNotification
diff --git a/modules/gui/macosx/windows/video/VLCFSPanelController.m b/modules/gui/macosx/windows/video/VLCFSPanelController.m
index 8b260cd07c..21bb703a63 100644
--- a/modules/gui/macosx/windows/video/VLCFSPanelController.m
+++ b/modules/gui/macosx/windows/video/VLCFSPanelController.m
@@ -34,6 +34,7 @@
 #import "views/VLCDefaultValueSlider.h"
 #import "views/VLCTimeField.h"
 #import "views/VLCSlider.h"
+#import "library/VLCInputItem.h"
 
 NSString *VLCFSPanelShouldBecomeActive = @"VLCFSPanelShouldBecomeActive";
 NSString *VLCFSPanelShouldBecomeInactive = @"VLCFSPanelShouldBecomeInactive";
@@ -270,27 +271,12 @@ static NSString *kAssociatedFullscreenRect = @"VLCFullscreenAssociatedWindowRect
 {
     NSString *title;
     NSString *nowPlaying;
-    input_item_t *mediaItem = _playerController.currentMedia;
+    VLCInputItem *inputItem = _playerController.currentMedia;
 
-    if (mediaItem) {
+    if (inputItem) {
         /* Something is playing */
-        static char *tmp_cstr = NULL;
-
-        // Get Title
-        tmp_cstr = input_item_GetTitleFbName(mediaItem);
-        if (tmp_cstr) {
-            title = toNSStr(tmp_cstr);
-            FREENULL(tmp_cstr);
-        }
-
-        // Get Now Playing
-        tmp_cstr = input_item_GetNowPlaying(mediaItem);
-        if (tmp_cstr) {
-            nowPlaying = toNSStr(tmp_cstr);
-            FREENULL(tmp_cstr);
-        }
-
-        input_item_Release(mediaItem);
+        title = inputItem.title;
+        nowPlaying = inputItem.nowPlaying;
     } else {
         /* Nothing playing */
         title = _NS("VLC media player");
@@ -306,10 +292,10 @@ static NSString *kAssociatedFullscreenRect = @"VLCFullscreenAssociatedWindowRect
 - (void)updatePositionAndTime:(NSNotification *)aNotification
 {
     VLCPlayerController *playerController = aNotification.object;
-    input_item_t *p_item = playerController.currentMedia;
+    VLCInputItem *inputItem = playerController.currentMedia;
 
     /* If nothing is playing, reset times and slider */
-    if (!p_item) {
+    if (!inputItem) {
         [_timeSlider setFloatValue:0.0];
         [_elapsedTime setStringValue:@""];
         [_remainingOrTotalTime setHidden:YES];
@@ -319,7 +305,7 @@ static NSString *kAssociatedFullscreenRect = @"VLCFullscreenAssociatedWindowRect
     [_timeSlider setFloatValue:(10000. * playerController.position)];
 
     vlc_tick_t time =_playerController.time;
-    vlc_tick_t duration = input_item_GetDuration(p_item);
+    vlc_tick_t duration = inputItem.duration;
 
     bool buffering = playerController.playerState == VLC_PLAYER_STATE_STARTED;
     if (duration == -1) {
@@ -345,7 +331,6 @@ static NSString *kAssociatedFullscreenRect = @"VLCFullscreenAssociatedWindowRect
     NSString *playbackPosition = toNSStr(secstotimestr(psz_time, (int)SEC_FROM_VLC_TICK(time)));
 
     [_elapsedTime setStringValue:playbackPosition];
-    input_item_Release(p_item);
 }
 
 - (void)capabilitiesChanged:(NSNotification *)aNotification
diff --git a/modules/gui/macosx/windows/video/VLCVideoWindowCommon.m b/modules/gui/macosx/windows/video/VLCVideoWindowCommon.m
index cd362fd3a9..bf4a5188d2 100644
--- a/modules/gui/macosx/windows/video/VLCVideoWindowCommon.m
+++ b/modules/gui/macosx/windows/video/VLCVideoWindowCommon.m
@@ -34,6 +34,7 @@
 #import "playlist/VLCPlaylistController.h"
 #import "playlist/VLCPlayerController.h"
 #import "library/VLCLibraryWindow.h"
+#import "library/VLCInputItem.h"
 #import "views/VLCBottomBarView.h"
 
 const CGFloat VLCVideoWindowCommonMinimalHeight = 70.;
@@ -127,41 +128,22 @@ NSString *VLCWindowShouldShowController = @"VLCWindowShouldShowController";
 - (void)mediaMetadataChanged:(NSNotification *)aNotification
 {
     VLCPlaylistController *playlistController = [[VLCMain sharedInstance] playlistController];
-    input_item_t *mediaItem = [playlistController currentlyPlayingInputItem];
-    if (mediaItem == NULL || _playerController.playerState == VLC_PLAYER_STATE_STOPPED) {
+    VLCInputItem *inputItem = [playlistController currentlyPlayingInputItem];
+    if (inputItem == NULL || _playerController.playerState == VLC_PLAYER_STATE_STOPPED) {
         [self setTitle:_NS("VLC media player")];
         self.representedURL = nil;
         return;
     }
 
-    NSString *title, *nowPlaying = nil;
-    char *tmp_cstr = NULL;
-
-    tmp_cstr = input_item_GetTitleFbName(mediaItem);
-    if (tmp_cstr) {
-        title = toNSStr(tmp_cstr);
-        FREENULL(tmp_cstr);
-    }
-
-    tmp_cstr = input_item_GetNowPlaying(mediaItem);
-    if (tmp_cstr) {
-        nowPlaying = toNSStr(tmp_cstr);
-        FREENULL(tmp_cstr);
-    }
-
+    NSString *title = inputItem.title;
+    NSString *nowPlaying = inputItem.nowPlaying;
     if (nowPlaying) {
         [self setTitle:[NSString stringWithFormat:@"%@ — %@", title, nowPlaying]];
     } else {
         [self setTitle:title];
     }
 
-    tmp_cstr = input_item_GetURI(mediaItem);
-    if (tmp_cstr) {
-        self.representedURL = [NSURL URLWithString:toNSStr(tmp_cstr)];
-        FREENULL(tmp_cstr);
-    }
-
-    input_item_Release(mediaItem);
+    self.representedURL = [NSURL URLWithString:inputItem.MRL];
 }
 
 - (void)setTitle:(NSString *)title




More information about the vlc-commits mailing list