Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  VLCLibraryController.m  Sprache: unbekannt

 
Spracherkennung für: .m vermutete Sprache: Masm {Masm[57] Cobol[48] Python[38]} [Methode: maximale Elemente, drei Dimensionen]

/*****************************************************************************
 * VLCLibraryController.m: MacOS X interface module
 *****************************************************************************
 * Copyright (C) 2019 VLC authors and VideoLAN
 *
 * Authors: Felix Paul Kühne <fkuehne # videolan -dot- org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#import "VLCLibraryController.h"

#import "extensions/NSString+Helpers.h"

#import "main/VLCMain.h"

#import "playqueue/VLCPlayQueueController.h"
#import "playqueue/VLCPlayerController.h"

#import "library/VLCInputItem.h"
#import "library/VLCLibraryModel.h"
#import "library/VLCLibraryDataTypes.h"
#import "library/VLCMediaLibraryFolderObserver.h"

#import "playqueue/VLCPlayQueueItem.h"
#import "playqueue/VLCPlayQueueModel.h"

#import <vlc_media_library.h>
#import <vlc_modules.h>

typedef int (*folder_action_f)(vlc_medialibrary_t*, const char*);

@interface VLCLibraryController()
{
    vlc_medialibrary_t *_p_libraryInstance;
}
@end

@implementation VLCLibraryController

- (instancetype)init
{
    self = [super init];
    if (self) {
        if (self.shouldUseMediaLibrary) {
            _p_libraryInstance = vlc_ml_instance_get(getIntf());
        } else {
            return self;
        }

        if (!_p_libraryInstance && self.shouldUseMediaLibrary) {
            msg_Info(getIntf(), "VLC runs without media library support");

            NSUserDefaults * const defaults = NSUserDefaults.standardUserDefaults;
            NSString * const suppressKey = @"VLCSuppressMediaLibraryFailedAlert";
            if (![defaults boolForKey:suppressKey]) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSAlert * const alert = [[NSAlert alloc] init];
                    alert.messageText = _NS("Media Library Unavailable");
                    alert.informativeText = _NS("The media library module could not be loaded. "
                                                "Library features such as browsing your media "
                                                "collection will not be available.");
                    alert.alertStyle = NSAlertStyleWarning;
                    [alert addButtonWithTitle:_NS("OK")];
                    alert.showsSuppressionButton = YES;
                    alert.suppressionButton.title = _NS("Do not show this message again");
                    [alert runModal];
                    if (alert.suppressionButton.state == NSControlStateValueOn) {
                        [defaults setBool:YES forKey:suppressKey];
                    }
                });
            }

            return self;
        }

        // Reset suppression so the alert reappears if a future load fails.
        [NSUserDefaults.standardUserDefaults removeObjectForKey:@"VLCSuppressMediaLibraryFailedAlert"];
        _libraryModel = [[VLCLibraryModel alloc] initWithLibrary:_p_libraryInstance];
        _unsorted = YES;

        NSNotificationCenter *defaultNotificationCenter = NSNotificationCenter.defaultCenter;
        [defaultNotificationCenter addObserver:self
                                      selector:@selector(playbackStateChanged:)
                                          name:VLCPlayerStateChanged
                                        object:nil];
        [defaultNotificationCenter addObserver:self
                                      selector:@selector(monitoredFolderChanged:)
                                          name:VLCMediaLibraryFolderFSEvent
                                        object:nil];
    }
    return self;
}

- (void)dealloc
{
    [NSNotificationCenter.defaultCenter removeObserver:self];
    _p_libraryInstance = NULL;
}

- (void)playbackStateChanged:(NSNotification *)aNotification
{
    if (!_p_libraryInstance) {
        return;
    }
    VLCPlayerController *playerController = aNotification.object;
    if (playerController.playerState == VLC_PLAYER_STATE_PLAYING) {
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
            vlc_ml_pause_background(self->_p_libraryInstance);
        });
    } else {
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
            vlc_ml_resume_background(self->_p_libraryInstance);
        });
    }
}

- (void)monitoredFolderChanged:(NSNotification *)notification
{
    NSURL * const folderURL = (NSURL *)notification.object;
    [self reloadFolderWithFileURL:folderURL];
}

- (int)appendItemToPlayQueue:(VLCMediaLibraryMediaItem *)mediaItem playImmediately:(BOOL)playImmediately
{
    if (!_p_libraryInstance) {
        return VLC_EACCES;
    }
    input_item_t *p_inputItem = vlc_ml_get_input_item(_p_libraryInstance, mediaItem.libraryID);
    if (!p_inputItem) {
        msg_Err(getIntf(), "No input item found for media id %lli", mediaItem.libraryID);
        return VLC_ENOENT;
    }
    int ret = [VLCMain.sharedInstance.playQueueController addInputItem:p_inputItem atPosition:-1 startPlayback:playImmediately];
    input_item_Release(p_inputItem);
    return ret;
}

- (int)appendItemsToPlayQueue:(NSArray <VLCMediaLibraryMediaItem *> *)mediaItemArray playFirstItemImmediately:(BOOL)playFirstItemImmediately
{
    if (!_p_libraryInstance) {
        return VLC_EACCES;
    }

    NSUInteger itemCount = [mediaItemArray count];
    int ret = VLC_SUCCESS;
    for (NSUInteger x = 0; x < itemCount; x++) {
        if (unlikely(x == 0 && playFirstItemImmediately)) {
            ret = [self appendItemToPlayQueue:mediaItemArray[x] playImmediately:YES];
        } else {
            ret = [self appendItemToPlayQueue:mediaItemArray[x] playImmediately:NO];
        }
        if (unlikely(ret != VLC_SUCCESS)) {
            break;
        }
    }
    return ret;
}

#pragma mark - folder management

- (int)performFolderAction:(folder_action_f)action withFileUrl:(NSURL *)fileURL
{
    if (!_p_libraryInstance) {
        return VLC_EACCES;
    }
    if (!fileURL) {
        return VLC_EINVAL;
    }

    return action(_p_libraryInstance, fileURL.absoluteString.UTF8String);
}

- (int)addFolderWithFileURL:(NSURL *)fileURL
{
    return [self performFolderAction:vlc_ml_add_folder withFileUrl:fileURL];
}

- (int)banFolderWithFileURL:(NSURL *)fileURL
{
    return [self performFolderAction:vlc_ml_ban_folder withFileUrl:fileURL];
}

- (int)unbanFolderWithFileURL:(NSURL *)fileURL
{
    return [self performFolderAction:vlc_ml_unban_folder withFileUrl:fileURL];
}

- (int)removeFolderWithFileURL:(NSURL *)fileURL
{
    return [self performFolderAction:vlc_ml_remove_folder withFileUrl:fileURL];
}

- (int)reloadFolderWithFileURL:(NSURL *)fileURL
{
    if (!_p_libraryInstance) {
        return VLC_EACCES;
    }
    if (!fileURL) {
        return VLC_EINVAL;
    }
    return vlc_ml_reload_folder(_p_libraryInstance, fileURL.absoluteString.UTF8String);
}

- (void)reloadMediaLibraryFoldersForInputItems:(NSArray<VLCInputItem *> *)inputItems
{
    NSArray<VLCMediaLibraryEntryPoint *> * const entryPoints = self.libraryModel.listOfMonitoredFolders;
    NSMutableSet<NSString *> * const reloadMRLs = NSMutableSet.set;
    NSMutableSet<VLCInputItem *> * const checkedInputItems = NSMutableSet.set;

    for (VLCMediaLibraryEntryPoint * const entryPoint in entryPoints) {
        for (VLCInputItem * const inputItem in inputItems) {
            if ([checkedInputItems containsObject:inputItem]) {
                continue;
            }

            if ([inputItem.decodedMRL hasPrefix:entryPoint.decodedMRL]) {
                [reloadMRLs addObject:entryPoint.MRL];
                [checkedInputItems addObject:inputItem];
                break;
            }
        }
    }

    for (NSString * const entryPointMRL in reloadMRLs) {
        NSURL * const entryPointURL = [NSURL URLWithString:entryPointMRL];
        [self reloadFolderWithFileURL:entryPointURL];
    }
}

- (int)clearHistory
{
    if (!_p_libraryInstance) {
        return VLC_EACCES;
    }
    return vlc_ml_clear_history(_p_libraryInstance, VLC_ML_HISTORY_TYPE_GLOBAL);
}

#pragma mark - Playlist creation

- (void)showCreatePlaylistDialogForPlayQueue
{
    VLCPlayQueueController * const playQueueController = VLCMain.sharedInstance.playQueueController;
    NSArray<VLCPlayQueueItem *> * const items = playQueueController.playQueueModel.playQueueItems;
    [self showCreatePlaylistDialogForPlayQueueItems:items];
}

- (void)showCreatePlaylistDialogForPlayQueueItems:(NSArray<VLCPlayQueueItem *> *)items
{
    if (!items || items.count == 0) {
        return;
    }

    NSString * const playlistName = [self runCreatePlaylistDialog];
    if (!playlistName) {
        return;
    }

    if (![self createPlaylistWithName:playlistName fromPlayQueueItems:items]) {
        msg_Err(getIntf(), "Failed to create playlist '%s' from play queue items", playlistName.UTF8String);
    }
}

- (void)showCreatePlaylistDialogForMediaItems:(NSArray<VLCMediaLibraryMediaItem *> *)mediaItems
{
    if (!mediaItems || mediaItems.count == 0) {
        return;
    }

    NSString * const playlistName = [self runCreatePlaylistDialog];
    if (!playlistName) {
        return;
    }

    if (![self createPlaylistWithName:playlistName fromMediaItems:mediaItems]) {
        msg_Err(getIntf(), "Failed to create playlist '%s' from media items", playlistName.UTF8String);
    }
}

- (void)showRenamePlaylistDialogForPlaylist:(VLCMediaLibraryPlaylist *)playlist
{
    if (playlist == nil || playlist.readOnly) {
        return;
    }

    NSString * const playlistName = [self runRenamePlaylistDialogForPlaylist:playlist];
    if (!playlistName) {
        return;
    }

    [playlist renameTo:playlistName];
}

- (nullable NSString *)runCreatePlaylistDialog
{
    return [self runPlaylistNameDialogWithTitle:_NS("Create New Playlist")
                                informativeText:_NS("Enter a name for the new playlist:")
                             primaryButtonTitle:_NS("Create")
                                    initialName:nil
                             requireNameChange:NO];
}

- (nullable NSString *)runRenamePlaylistDialogForPlaylist:(VLCMediaLibraryPlaylist *)playlist
{
    return [self runPlaylistNameDialogWithTitle:_NS("Rename playlist")
                                informativeText:_NS("Please enter the new playlist name:")
                             primaryButtonTitle:_NS("Rename")
                                    initialName:playlist.displayString
                             requireNameChange:YES];
}

- (nullable NSString *)runPlaylistNameDialogWithTitle:(NSString *)title
                                      informativeText:(NSString *)informativeText
                                   primaryButtonTitle:(NSString *)primaryButtonTitle
                                          initialName:(nullable NSString *)initialName
                                   requireNameChange:(BOOL)requireNameChange
{
    NSAlert * const alert = [[NSAlert alloc] init];
    alert.messageText = title;
    alert.informativeText = informativeText;
    NSButton * const primaryButton = [alert addButtonWithTitle:primaryButtonTitle];
    primaryButton.enabled = NO;
    [alert addButtonWithTitle:_NS("Cancel")];

    NSTextField * const input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 24)];
    input.stringValue = initialName ?: @"";
    input.placeholderString = _NS("Playlist Name");
    alert.accessoryView = input;
    alert.window.initialFirstResponder = input;

    NSCharacterSet * const whitespace = NSCharacterSet.whitespaceAndNewlineCharacterSet;
    NSString * const currentName =
        [(initialName ?: @"") stringByTrimmingCharactersInSet:whitespace];
    id observer = [NSNotificationCenter.defaultCenter
        addObserverForName:NSControlTextDidChangeNotification
                   object:input
                    queue:NSOperationQueue.mainQueue
               usingBlock:^(NSNotification * __unused note) {
        NSString * const newName =
            [input.stringValue stringByTrimmingCharactersInSet:whitespace];
        primaryButton.enabled = newName.length > 0 &&
            (!requireNameChange || ![newName isEqualToString:currentName]);
    }];

    const NSModalResponse response = [alert runModal];
    [NSNotificationCenter.defaultCenter removeObserver:observer];

    if (response != NSAlertFirstButtonReturn) {
        return nil;
    }

    NSString * const name = [input.stringValue stringByTrimmingCharactersInSet:whitespace];
    if (name.length == 0 || (requireNameChange && [name isEqualToString:currentName])) {
        return nil;
    }
    return name;
}

- (BOOL)createPlaylistWithName:(NSString *)playlistName fromPlayQueueItems:(NSArray<VLCPlayQueueItem *> *)items
{
    if (!_p_libraryInstance || !playlistName || playlistName.length == 0) {
        return NO;
    }
    
    vlc_ml_playlist_t * const playlist = vlc_ml_playlist_create(_p_libraryInstance, playlistName.UTF8String);
    if (!playlist) {
        msg_Err(getIntf(), "Failed to create playlist with name: %s", playlistName.UTF8String);
        return NO;
    }
    
    const int64_t playlistId = playlist->i_id;
    vlc_ml_playlist_release(playlist);
    
    for (VLCPlayQueueItem * const item in items) {
        VLCMediaLibraryMediaItem * const mediaLibraryItem = item.mediaLibraryItem;
        
        if (!mediaLibraryItem) {
            msg_Warn(getIntf(), "No media library item found for playqueue item with name '%s'", item.title.UTF8String);
            continue;
        }
        
        const int64_t mediaId = mediaLibraryItem.libraryID;
        const int result = vlc_ml_playlist_append(_p_libraryInstance, playlistId, &mediaId, 1);
        if (result != VLC_SUCCESS) {
            msg_Warn(getIntf(), "Failed to add media library item %lld to playlist", mediaLibraryItem.libraryID);
        }
    }
    
    return YES;
}

- (BOOL)createPlaylistWithName:(NSString *)playlistName fromMediaItems:(NSArray<VLCMediaLibraryMediaItem *> *)mediaItems
{
    if (!_p_libraryInstance || !playlistName || playlistName.length == 0) {
        return NO;
    }

    vlc_ml_playlist_t * const playlist = vlc_ml_playlist_create(_p_libraryInstance, playlistName.UTF8String);
    if (!playlist) {
        msg_Err(getIntf(), "Failed to create playlist with name: %s", playlistName.UTF8String);
        return NO;
    }

    const int64_t playlistId = playlist->i_id;
    vlc_ml_playlist_release(playlist);

    VLCMediaLibraryPlaylist * const mlPlaylist =
        [VLCMediaLibraryPlaylist playlistForLibraryID:playlistId];
    [mlPlaylist appendMediaItems:mediaItems];

    return YES;
}

- (void)sortByCriteria:(enum vlc_ml_sorting_criteria_t)sortCriteria andDescending:(bool)descending
{
    _unsorted = NO;
    _lastSortingCriteria = sortCriteria;
    _descendingLibrarySorting = descending;
    [_libraryModel sortByCriteria:sortCriteria andDescending:descending];
}

- (void)filterByString:(NSString*)filterString
{
    self.libraryModel.filterString = filterString;
}

- (BOOL)shouldUseMediaLibrary
{
    return module_exists("medialibrary") && var_InheritBool(getIntf(), "media-library");
}

@end

[Dauer der Verarbeitung: 0.4 Sekunden, vorverarbeitet 2026-10-24]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104857
#Domains=439304