You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1652 lines
59 KiB
1652 lines
59 KiB
/*****************************************************************************
|
|
* medialib.cpp: medialibrary module
|
|
*****************************************************************************
|
|
* Copyright © 2008-2018 VLC authors, VideoLAN and VideoLabs
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser 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.
|
|
*****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <vlc_common.h>
|
|
#include <vlc_plugin.h>
|
|
#include <vlc_url.h>
|
|
#include <vlc_media_library.h>
|
|
#include <vlc_dialog.h>
|
|
#include "medialibrary.h"
|
|
#include "fs/fs.h"
|
|
|
|
#include <medialibrary/IMedia.h>
|
|
#include <medialibrary/IAlbumTrack.h>
|
|
#include <medialibrary/IAlbum.h>
|
|
#include <medialibrary/IArtist.h>
|
|
#include <medialibrary/IGenre.h>
|
|
#include <medialibrary/IMetadata.h>
|
|
#include <medialibrary/IShow.h>
|
|
#include <medialibrary/IPlaylist.h>
|
|
|
|
#include <sstream>
|
|
#include <initializer_list>
|
|
|
|
class Logger : public medialibrary::ILogger
|
|
{
|
|
public:
|
|
Logger( vlc_object_t* obj ) : m_obj( obj ) {}
|
|
|
|
private:
|
|
virtual void Error( const std::string& msg ) override
|
|
{
|
|
msg_Err( m_obj, "%s", msg.c_str() );
|
|
}
|
|
virtual void Warning( const std::string& msg ) override
|
|
{
|
|
msg_Warn( m_obj, "%s", msg.c_str() );
|
|
}
|
|
virtual void Info( const std::string& msg ) override
|
|
{
|
|
msg_Dbg( m_obj, "%s", msg.c_str() );
|
|
}
|
|
virtual void Debug( const std::string& msg ) override
|
|
{
|
|
msg_Dbg( m_obj, "%s", msg.c_str() );
|
|
}
|
|
virtual void Verbose( const std::string& msg ) override
|
|
{
|
|
msg_Dbg( m_obj, "%s", msg.c_str() );
|
|
}
|
|
|
|
private:
|
|
vlc_object_t* m_obj;
|
|
};
|
|
|
|
namespace
|
|
{
|
|
|
|
void assignToEvent( vlc_ml_event_t* ev, vlc_ml_media_t* m ) { ev->creation.p_media = m; }
|
|
void assignToEvent( vlc_ml_event_t* ev, vlc_ml_artist_t* a ) { ev->creation.p_artist = a; }
|
|
void assignToEvent( vlc_ml_event_t* ev, vlc_ml_album_t* a ) { ev->creation.p_album = a; }
|
|
void assignToEvent( vlc_ml_event_t* ev, vlc_ml_genre_t* g ) { ev->creation.p_genre = g; }
|
|
void assignToEvent( vlc_ml_event_t* ev, vlc_ml_playlist_t* p ) { ev->creation.p_playlist = p; }
|
|
|
|
template <typename To, typename From>
|
|
void wrapEntityCreatedEventCallback( vlc_medialibrary_module_t* ml,
|
|
const std::vector<From>& entities,
|
|
vlc_ml_event_type evType )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = evType;
|
|
for ( const auto& e : entities )
|
|
{
|
|
auto val = vlc::wrap_cptr<To>( static_cast<To*>( calloc( 1, sizeof( To ) ) ),
|
|
static_cast<void(*)(To*)>( vlc_ml_release ) );
|
|
if ( unlikely( val == nullptr ) )
|
|
return;
|
|
if ( Convert( e.get(), *val ) == false )
|
|
return;
|
|
assignToEvent( &ev, val.get() );
|
|
ml->cbs->pf_send_event( ml, &ev );
|
|
}
|
|
}
|
|
|
|
void wrapEntityModifiedEventCallback( vlc_medialibrary_module_t* ml,
|
|
const std::vector<int64_t>& ids,
|
|
vlc_ml_event_type evType )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = evType;
|
|
for ( const auto& id : ids )
|
|
{
|
|
ev.modification.i_entity_id = id;
|
|
ml->cbs->pf_send_event( ml, &ev );
|
|
}
|
|
}
|
|
|
|
void wrapEntityDeletedEventCallback( vlc_medialibrary_module_t* ml,
|
|
const std::vector<int64_t>& ids, vlc_ml_event_type evType )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = evType;
|
|
for ( const auto& id : ids )
|
|
{
|
|
ev.deletion.i_entity_id = id;
|
|
ml->cbs->pf_send_event( ml, &ev );
|
|
}
|
|
}
|
|
|
|
} // end of anonymous namespace
|
|
|
|
void MediaLibrary::onMediaAdded( std::vector<medialibrary::MediaPtr> media )
|
|
{
|
|
wrapEntityCreatedEventCallback<vlc_ml_media_t>( m_vlc_ml, media, VLC_ML_EVENT_MEDIA_ADDED );
|
|
}
|
|
|
|
void MediaLibrary::onMediaModified( std::vector<int64_t> mediaIds )
|
|
{
|
|
wrapEntityModifiedEventCallback( m_vlc_ml, mediaIds, VLC_ML_EVENT_MEDIA_UPDATED );
|
|
}
|
|
|
|
void MediaLibrary::onMediaDeleted( std::vector<int64_t> mediaIds )
|
|
{
|
|
wrapEntityDeletedEventCallback( m_vlc_ml, mediaIds, VLC_ML_EVENT_MEDIA_DELETED );
|
|
}
|
|
|
|
void MediaLibrary::onArtistsAdded( std::vector<medialibrary::ArtistPtr> artists )
|
|
{
|
|
wrapEntityCreatedEventCallback<vlc_ml_artist_t>( m_vlc_ml, artists, VLC_ML_EVENT_ARTIST_ADDED );
|
|
}
|
|
|
|
void MediaLibrary::onArtistsModified( std::vector<int64_t> artistIds )
|
|
{
|
|
wrapEntityModifiedEventCallback( m_vlc_ml, artistIds, VLC_ML_EVENT_ARTIST_UPDATED );
|
|
}
|
|
|
|
void MediaLibrary::onArtistsDeleted( std::vector<int64_t> artistIds )
|
|
{
|
|
wrapEntityDeletedEventCallback( m_vlc_ml, artistIds, VLC_ML_EVENT_ARTIST_DELETED );
|
|
}
|
|
|
|
void MediaLibrary::onAlbumsAdded( std::vector<medialibrary::AlbumPtr> albums )
|
|
{
|
|
wrapEntityCreatedEventCallback<vlc_ml_album_t>( m_vlc_ml, albums, VLC_ML_EVENT_ALBUM_ADDED );
|
|
}
|
|
|
|
void MediaLibrary::onAlbumsModified( std::vector<int64_t> albumIds )
|
|
{
|
|
wrapEntityModifiedEventCallback( m_vlc_ml, albumIds, VLC_ML_EVENT_ALBUM_UPDATED );
|
|
}
|
|
|
|
void MediaLibrary::onAlbumsDeleted( std::vector<int64_t> albumIds )
|
|
{
|
|
wrapEntityDeletedEventCallback( m_vlc_ml, albumIds, VLC_ML_EVENT_ALBUM_DELETED );
|
|
}
|
|
|
|
void MediaLibrary::onPlaylistsAdded( std::vector<medialibrary::PlaylistPtr> playlists )
|
|
{
|
|
wrapEntityCreatedEventCallback<vlc_ml_playlist_t>( m_vlc_ml, playlists, VLC_ML_EVENT_PLAYLIST_ADDED );
|
|
}
|
|
|
|
void MediaLibrary::onPlaylistsModified( std::vector<int64_t> playlistIds )
|
|
{
|
|
wrapEntityModifiedEventCallback( m_vlc_ml, playlistIds, VLC_ML_EVENT_PLAYLIST_UPDATED );
|
|
}
|
|
|
|
void MediaLibrary::onPlaylistsDeleted( std::vector<int64_t> playlistIds )
|
|
{
|
|
wrapEntityDeletedEventCallback( m_vlc_ml, playlistIds, VLC_ML_EVENT_PLAYLIST_DELETED );
|
|
}
|
|
|
|
void MediaLibrary::onGenresAdded( std::vector<medialibrary::GenrePtr> genres )
|
|
{
|
|
wrapEntityCreatedEventCallback<vlc_ml_genre_t>( m_vlc_ml, genres, VLC_ML_EVENT_GENRE_ADDED );
|
|
}
|
|
|
|
void MediaLibrary::onGenresModified( std::vector<int64_t> genreIds )
|
|
{
|
|
wrapEntityModifiedEventCallback( m_vlc_ml, genreIds, VLC_ML_EVENT_GENRE_UPDATED );
|
|
}
|
|
|
|
void MediaLibrary::onGenresDeleted( std::vector<int64_t> genreIds )
|
|
{
|
|
wrapEntityDeletedEventCallback( m_vlc_ml, genreIds, VLC_ML_EVENT_GENRE_DELETED );
|
|
}
|
|
|
|
void MediaLibrary::onMediaGroupAdded( std::vector<medialibrary::MediaGroupPtr> )
|
|
{
|
|
}
|
|
|
|
void MediaLibrary::onMediaGroupModified( std::vector<int64_t> )
|
|
{
|
|
}
|
|
|
|
void MediaLibrary::onMediaGroupDeleted( std::vector<int64_t> )
|
|
{
|
|
}
|
|
|
|
void MediaLibrary::onDiscoveryStarted( const std::string& entryPoint )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_DISCOVERY_STARTED;
|
|
ev.discovery_started.psz_entry_point = entryPoint.c_str();
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onDiscoveryProgress( const std::string& entryPoint )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_DISCOVERY_PROGRESS;
|
|
ev.discovery_progress.psz_entry_point = entryPoint.c_str();
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onDiscoveryCompleted( const std::string& entryPoint, bool success )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_DISCOVERY_COMPLETED;
|
|
ev.discovery_completed.psz_entry_point = entryPoint.c_str();
|
|
ev.discovery_completed.b_success = success;
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onReloadStarted( const std::string& entryPoint )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_RELOAD_STARTED;
|
|
ev.reload_started.psz_entry_point = entryPoint.c_str();
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onReloadCompleted( const std::string& entryPoint, bool success )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_RELOAD_COMPLETED;
|
|
ev.reload_completed.psz_entry_point = entryPoint.c_str();
|
|
ev.reload_completed.b_success = success;
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onEntryPointAdded( const std::string& entryPoint, bool success )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_ENTRY_POINT_ADDED;
|
|
ev.entry_point_added.psz_entry_point = entryPoint.c_str();
|
|
ev.entry_point_added.b_success = success;
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onEntryPointRemoved( const std::string& entryPoint, bool success )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_ENTRY_POINT_REMOVED;
|
|
ev.entry_point_removed.psz_entry_point = entryPoint.c_str();
|
|
ev.entry_point_removed.b_success = success;
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onEntryPointBanned( const std::string& entryPoint, bool success )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_ENTRY_POINT_BANNED;
|
|
ev.entry_point_banned.psz_entry_point = entryPoint.c_str();
|
|
ev.entry_point_banned.b_success = success;
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onEntryPointUnbanned( const std::string& entryPoint, bool success )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_ENTRY_POINT_UNBANNED;
|
|
ev.entry_point_unbanned.psz_entry_point = entryPoint.c_str();
|
|
ev.entry_point_unbanned.b_success = success;
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onParsingStatsUpdated( uint32_t progress )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_PARSING_PROGRESS_UPDATED;
|
|
ev.parsing_progress.i_percent = progress;
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onBackgroundTasksIdleChanged( bool idle )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_BACKGROUND_IDLE_CHANGED;
|
|
ev.background_idle_changed.b_idle = idle;
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onMediaThumbnailReady( medialibrary::MediaPtr media,
|
|
medialibrary::ThumbnailSizeType sizeType,
|
|
bool success )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_MEDIA_THUMBNAIL_GENERATED;
|
|
ev.media_thumbnail_generated.b_success = success;
|
|
ev.media_thumbnail_generated.i_size = static_cast<vlc_ml_thumbnail_size_t>( sizeType );
|
|
auto mPtr = vlc::wrap_cptr<vlc_ml_media_t>(
|
|
static_cast<vlc_ml_media_t*>( calloc( 1, sizeof( vlc_ml_media_t ) ) ),
|
|
vlc_ml_media_release );
|
|
if ( unlikely( mPtr == nullptr ) )
|
|
return;
|
|
ev.media_thumbnail_generated.p_media = mPtr.get();
|
|
if ( Convert( media.get(), *mPtr ) == false )
|
|
return;
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onHistoryChanged( medialibrary::HistoryType historyType )
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_HISTORY_CHANGED;
|
|
switch ( historyType )
|
|
{
|
|
case medialibrary::HistoryType::Media:
|
|
ev.history_changed.history_type = VLC_ML_HISTORY_TYPE_MEDIA;
|
|
break;
|
|
case medialibrary::HistoryType::Network:
|
|
ev.history_changed.history_type = VLC_ML_HISTORY_TYPE_NETWORK;
|
|
break;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
void MediaLibrary::onRescanStarted()
|
|
{
|
|
vlc_ml_event_t ev;
|
|
ev.i_type = VLC_ML_EVENT_RESCAN_STARTED;
|
|
m_vlc_ml->cbs->pf_send_event( m_vlc_ml, &ev );
|
|
}
|
|
|
|
MediaLibrary::MediaLibrary( vlc_medialibrary_module_t* ml )
|
|
: m_vlc_ml( ml )
|
|
{
|
|
m_ml.reset( NewMediaLibrary() );
|
|
|
|
m_logger.reset( new Logger( VLC_OBJECT( m_vlc_ml ) ) );
|
|
m_ml->setVerbosity( var_InheritInteger( VLC_OBJECT( m_vlc_ml ), "verbose" ) >= 4 ?
|
|
medialibrary::LogLevel::Debug : medialibrary::LogLevel::Info );
|
|
m_ml->setLogger( m_logger.get() );
|
|
}
|
|
|
|
bool MediaLibrary::Init()
|
|
{
|
|
if ( m_ml->isInitialized() == true )
|
|
return true;
|
|
auto userDir = vlc::wrap_cptr( config_GetUserDir( VLC_USERDATA_DIR ) );
|
|
std::string mlDir = std::string{ userDir.get() } + "/ml/";
|
|
|
|
auto initStatus = m_ml->initialize( mlDir + "ml.db", mlDir + "/mlstorage/", this );
|
|
switch ( initStatus )
|
|
{
|
|
case medialibrary::InitializeResult::AlreadyInitialized:
|
|
return true;
|
|
case medialibrary::InitializeResult::Failed:
|
|
msg_Err( m_vlc_ml, "Medialibrary failed to initialize" );
|
|
return false;
|
|
case medialibrary::InitializeResult::DbReset:
|
|
msg_Info( m_vlc_ml, "Database was reset" );
|
|
break;
|
|
case medialibrary::InitializeResult::Success:
|
|
msg_Dbg( m_vlc_ml, "MediaLibrary successfully initialized" );
|
|
break;
|
|
case medialibrary::InitializeResult::DbCorrupted:
|
|
{
|
|
auto res = vlc_dialog_wait_question(VLC_OBJECT( m_vlc_ml ),
|
|
VLC_DIALOG_QUESTION_NORMAL, _( "Ignore" ), _( "Recover" ),
|
|
_( "Recreate" ), _( "Media database corrupted" ),
|
|
"Your media database appears to be corrupted. You can try to "
|
|
"recover it, recreate it entirely, or ignore this error (the "
|
|
"mediacenter will be disabled)." );
|
|
switch ( res )
|
|
{
|
|
case 1:
|
|
m_ml->clearDatabase( true );
|
|
break;
|
|
case 2:
|
|
m_ml->clearDatabase( false );
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
m_ml->addParserService( std::make_shared<MetadataExtractor>( VLC_OBJECT( m_vlc_ml ) ) );
|
|
try
|
|
{
|
|
m_ml->addThumbnailer( std::make_shared<Thumbnailer>( m_vlc_ml ) );
|
|
}
|
|
catch ( const std::runtime_error& ex )
|
|
{
|
|
msg_Err( m_vlc_ml, "Failed to provide a thumbnailer module to the "
|
|
"medialib: %s", ex.what() );
|
|
return false;
|
|
}
|
|
|
|
auto networkFs = std::make_shared<vlc::medialibrary::SDFileSystemFactory>( VLC_OBJECT( m_vlc_ml ), "smb://");
|
|
m_ml->addNetworkFileSystemFactory( networkFs );
|
|
m_ml->setDiscoverNetworkEnabled( true );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool MediaLibrary::Start()
|
|
{
|
|
if ( Init() == false )
|
|
return false;
|
|
|
|
auto startRes = m_ml->start();
|
|
switch ( startRes )
|
|
{
|
|
case medialibrary::StartResult::Failed:
|
|
msg_Err( m_vlc_ml, "Failed to start the MediaLibrary" );
|
|
return false;
|
|
case medialibrary::StartResult::AlreadyStarted:
|
|
return true;
|
|
case medialibrary::StartResult::Success:
|
|
break;
|
|
}
|
|
|
|
// Reload entry points we already know about, and then add potential new ones.
|
|
// Doing it the other way around would cause the initial scan to be performed
|
|
// twice, as we start discovering the new folders, then reload them.
|
|
m_ml->reload();
|
|
|
|
auto folders = vlc::wrap_cptr( var_InheritString( m_vlc_ml, "ml-folders" ) );
|
|
if ( folders != nullptr && strlen( folders.get() ) > 0 )
|
|
{
|
|
std::istringstream ss( folders.get() );
|
|
std::string folder;
|
|
while ( std::getline( ss, folder, ';' ) )
|
|
m_ml->discover( folder );
|
|
}
|
|
else
|
|
{
|
|
std::string varValue;
|
|
for( auto&& target : { VLC_VIDEOS_DIR, VLC_MUSIC_DIR } )
|
|
{
|
|
auto folder = vlc::wrap_cptr( config_GetUserDir( target ) );
|
|
if( folder == nullptr )
|
|
continue;
|
|
auto folderMrl = vlc::wrap_cptr( vlc_path2uri( folder.get(), nullptr ) );
|
|
m_ml->discover( folderMrl.get() );
|
|
varValue += std::string{ ";" } + folderMrl.get();
|
|
}
|
|
if ( varValue.empty() == false )
|
|
config_PutPsz( "ml-folders", varValue.c_str()+1 ); /* skip initial ';' */
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int MediaLibrary::Control( int query, va_list args )
|
|
{
|
|
switch ( query )
|
|
{
|
|
case VLC_ML_ADD_FOLDER:
|
|
case VLC_ML_REMOVE_FOLDER:
|
|
case VLC_ML_BAN_FOLDER:
|
|
case VLC_ML_UNBAN_FOLDER:
|
|
case VLC_ML_RELOAD_FOLDER:
|
|
case VLC_ML_RESUME_BACKGROUND:
|
|
case VLC_ML_MEDIA_GENERATE_THUMBNAIL:
|
|
{
|
|
/* These operations require the media library to be started
|
|
* ie. that the background threads are started */
|
|
if ( Start() == false )
|
|
return VLC_EGENERIC;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch ( query )
|
|
{
|
|
case VLC_ML_ADD_FOLDER:
|
|
case VLC_ML_REMOVE_FOLDER:
|
|
case VLC_ML_BAN_FOLDER:
|
|
case VLC_ML_UNBAN_FOLDER:
|
|
{
|
|
const char* mrl = va_arg( args, const char* );
|
|
switch( query )
|
|
{
|
|
case VLC_ML_ADD_FOLDER:
|
|
m_ml->discover( mrl );
|
|
break;
|
|
case VLC_ML_REMOVE_FOLDER:
|
|
m_ml->removeEntryPoint( mrl );
|
|
break;
|
|
case VLC_ML_BAN_FOLDER:
|
|
m_ml->banFolder( mrl );
|
|
break;
|
|
case VLC_ML_UNBAN_FOLDER:
|
|
m_ml->unbanFolder( mrl );
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case VLC_ML_LIST_FOLDERS:
|
|
{
|
|
auto entryPoints = m_ml->entryPoints()->all();
|
|
auto res = ml_convert_list<vlc_ml_entry_point_list_t,
|
|
vlc_ml_entry_point_t>( entryPoints );
|
|
*(va_arg( args, vlc_ml_entry_point_list_t**) ) = res;
|
|
break;
|
|
}
|
|
case VLC_ML_IS_INDEXED:
|
|
{
|
|
auto mrl = va_arg( args, const char* );
|
|
auto res = va_arg( args, bool* );
|
|
*res = m_ml->isIndexed( mrl );
|
|
break;
|
|
}
|
|
case VLC_ML_RELOAD_FOLDER:
|
|
{
|
|
auto mrl = va_arg( args, const char* );
|
|
if ( mrl == nullptr )
|
|
m_ml->reload();
|
|
else
|
|
m_ml->reload( mrl );
|
|
break;
|
|
}
|
|
case VLC_ML_PAUSE_BACKGROUND:
|
|
m_ml->pauseBackgroundOperations();
|
|
break;
|
|
case VLC_ML_RESUME_BACKGROUND:
|
|
m_ml->resumeBackgroundOperations();
|
|
break;
|
|
case VLC_ML_CLEAR_HISTORY:
|
|
m_ml->clearHistory();
|
|
break;
|
|
case VLC_ML_NEW_EXTERNAL_MEDIA:
|
|
{
|
|
auto mrl = va_arg( args, const char* );
|
|
auto media = m_ml->addExternalMedia( mrl );
|
|
if ( media == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, vlc_ml_media_t**) = CreateAndConvert<vlc_ml_media_t>( media.get() );
|
|
return VLC_SUCCESS;
|
|
}
|
|
case VLC_ML_NEW_STREAM:
|
|
{
|
|
auto mrl = va_arg( args, const char* );
|
|
auto media = m_ml->addStream( mrl );
|
|
if ( media == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, vlc_ml_media_t**) = CreateAndConvert<vlc_ml_media_t>( media.get() );
|
|
return VLC_SUCCESS;
|
|
}
|
|
case VLC_ML_MEDIA_INCREASE_PLAY_COUNT:
|
|
case VLC_ML_MEDIA_GET_MEDIA_PLAYBACK_STATE:
|
|
case VLC_ML_MEDIA_SET_MEDIA_PLAYBACK_STATE:
|
|
case VLC_ML_MEDIA_GET_ALL_MEDIA_PLAYBACK_STATES:
|
|
case VLC_ML_MEDIA_SET_ALL_MEDIA_PLAYBACK_STATES:
|
|
case VLC_ML_MEDIA_SET_THUMBNAIL:
|
|
case VLC_ML_MEDIA_GENERATE_THUMBNAIL:
|
|
case VLC_ML_MEDIA_ADD_EXTERNAL_MRL:
|
|
case VLC_ML_MEDIA_SET_TYPE:
|
|
return controlMedia( query, args );
|
|
default:
|
|
return VLC_EGENERIC;
|
|
}
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
int MediaLibrary::List( int listQuery, const vlc_ml_query_params_t* params, va_list args )
|
|
{
|
|
if ( Init() == false )
|
|
return VLC_EGENERIC;
|
|
|
|
medialibrary::QueryParameters p{};
|
|
medialibrary::QueryParameters* paramsPtr = nullptr;
|
|
uint32_t nbItems = 0;
|
|
uint32_t offset = 0;
|
|
const char* psz_pattern = nullptr;
|
|
if ( params )
|
|
{
|
|
p.desc = params->b_desc;
|
|
p.sort = sortingCriteria( params->i_sort );
|
|
nbItems = params->i_nbResults;
|
|
offset = params->i_offset;
|
|
psz_pattern = params->psz_pattern;
|
|
paramsPtr = &p;
|
|
}
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_MEDIA_OF:
|
|
case VLC_ML_COUNT_MEDIA_OF:
|
|
case VLC_ML_LIST_ARTISTS_OF:
|
|
case VLC_ML_COUNT_ARTISTS_OF:
|
|
case VLC_ML_LIST_ALBUMS_OF:
|
|
case VLC_ML_COUNT_ALBUMS_OF:
|
|
{
|
|
auto parentType = va_arg( args, int );
|
|
listQuery = filterListChildrenQuery( listQuery, parentType );
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
switch( listQuery )
|
|
{
|
|
case VLC_ML_LIST_ALBUM_TRACKS:
|
|
case VLC_ML_COUNT_ALBUM_TRACKS:
|
|
case VLC_ML_LIST_ALBUM_ARTISTS:
|
|
case VLC_ML_COUNT_ALBUM_ARTISTS:
|
|
return listAlbums( listQuery, paramsPtr, psz_pattern, nbItems, offset, args );
|
|
|
|
case VLC_ML_LIST_ARTIST_ALBUMS:
|
|
case VLC_ML_COUNT_ARTIST_ALBUMS:
|
|
case VLC_ML_LIST_ARTIST_TRACKS:
|
|
case VLC_ML_COUNT_ARTIST_TRACKS:
|
|
return listArtists( listQuery, paramsPtr, psz_pattern, nbItems, offset, args );
|
|
|
|
case VLC_ML_LIST_VIDEOS:
|
|
{
|
|
medialibrary::Query<medialibrary::IMedia> query;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchVideo( psz_pattern, paramsPtr );
|
|
else
|
|
query = m_ml->videoFiles( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
auto res = ml_convert_list<vlc_ml_media_list_t, vlc_ml_media_t>(
|
|
query->items( nbItems, offset ) );
|
|
*va_arg( args, vlc_ml_media_list_t**) = res;
|
|
break;
|
|
}
|
|
case VLC_ML_COUNT_VIDEOS:
|
|
{
|
|
medialibrary::Query<medialibrary::IMedia> query;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchVideo( psz_pattern, paramsPtr );
|
|
else
|
|
query = m_ml->videoFiles( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, size_t* ) = query->count();
|
|
break;
|
|
}
|
|
case VLC_ML_LIST_AUDIOS:
|
|
{
|
|
medialibrary::Query<medialibrary::IMedia> query;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchAudio( psz_pattern, paramsPtr );
|
|
else
|
|
query = m_ml->audioFiles( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
auto res = ml_convert_list<vlc_ml_media_list_t, vlc_ml_media_t>(
|
|
query->items( nbItems, offset ) );
|
|
*va_arg( args, vlc_ml_media_list_t**) = res;
|
|
break;
|
|
}
|
|
case VLC_ML_COUNT_AUDIOS:
|
|
{
|
|
medialibrary::Query<medialibrary::IMedia> query;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchAudio( psz_pattern, paramsPtr );
|
|
else
|
|
query = m_ml->audioFiles( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, size_t* ) = query->count();
|
|
break;
|
|
}
|
|
case VLC_ML_LIST_ALBUMS:
|
|
{
|
|
medialibrary::Query<medialibrary::IAlbum> query;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchAlbums( psz_pattern, paramsPtr );
|
|
else
|
|
query = m_ml->albums( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
auto res = ml_convert_list<vlc_ml_album_list_t, vlc_ml_album_t>(
|
|
query->items( nbItems, offset ) );
|
|
*va_arg( args, vlc_ml_album_list_t**) = res;
|
|
break;
|
|
}
|
|
case VLC_ML_COUNT_ALBUMS:
|
|
{
|
|
medialibrary::Query<medialibrary::IAlbum> query;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchAlbums( psz_pattern, paramsPtr );
|
|
else
|
|
query = m_ml->albums( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, size_t* ) = query->count();
|
|
break;
|
|
}
|
|
case VLC_ML_LIST_GENRES:
|
|
{
|
|
medialibrary::Query<medialibrary::IGenre> query;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchGenre( psz_pattern, paramsPtr );
|
|
else
|
|
query = m_ml->genres( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
auto res = ml_convert_list<vlc_ml_genre_list_t,vlc_ml_genre_t>(
|
|
query->items( nbItems, offset ) );
|
|
*va_arg( args, vlc_ml_genre_list_t**) = res;
|
|
break;
|
|
}
|
|
case VLC_ML_COUNT_GENRES:
|
|
{
|
|
medialibrary::Query<medialibrary::IGenre> query;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchGenre( psz_pattern, paramsPtr );
|
|
else
|
|
query = m_ml->genres( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, size_t* ) = query->count();
|
|
break;
|
|
}
|
|
case VLC_ML_LIST_ARTISTS:
|
|
{
|
|
medialibrary::Query<medialibrary::IArtist> query;
|
|
bool includeAll = va_arg( args, int ) != 0;
|
|
auto artistsIncluded = includeAll ? medialibrary::ArtistIncluded::All :
|
|
medialibrary::ArtistIncluded::AlbumArtistOnly;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchArtists( psz_pattern, artistsIncluded, paramsPtr );
|
|
else
|
|
query = m_ml->artists( artistsIncluded, paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
auto res = ml_convert_list<vlc_ml_artist_list_t, vlc_ml_artist_t>(
|
|
query->items( nbItems, offset ) );
|
|
*va_arg( args, vlc_ml_artist_list_t**) = res;
|
|
break;
|
|
}
|
|
case VLC_ML_COUNT_ARTISTS:
|
|
{
|
|
medialibrary::Query<medialibrary::IArtist> query;
|
|
bool includeAll = va_arg( args, int ) != 0;
|
|
auto artistsIncluded = includeAll ? medialibrary::ArtistIncluded::All :
|
|
medialibrary::ArtistIncluded::AlbumArtistOnly;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchArtists( psz_pattern, artistsIncluded, paramsPtr );
|
|
else
|
|
query = m_ml->artists( artistsIncluded, paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, size_t* ) = query->count();
|
|
break;
|
|
}
|
|
case VLC_ML_LIST_GENRE_ARTISTS:
|
|
case VLC_ML_COUNT_GENRE_ARTISTS:
|
|
case VLC_ML_LIST_GENRE_TRACKS:
|
|
case VLC_ML_COUNT_GENRE_TRACKS:
|
|
case VLC_ML_LIST_GENRE_ALBUMS:
|
|
case VLC_ML_COUNT_GENRE_ALBUMS:
|
|
return listGenre( listQuery, paramsPtr, psz_pattern, nbItems, offset, args );
|
|
|
|
case VLC_ML_LIST_MEDIA_LABELS:
|
|
case VLC_ML_COUNT_MEDIA_LABELS:
|
|
{
|
|
auto media = m_ml->media( va_arg( args, int64_t ) );
|
|
if ( media == nullptr )
|
|
return VLC_EGENERIC;
|
|
auto query = media->labels();
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_MEDIA_LABELS:
|
|
*va_arg( args, vlc_ml_label_list_t**) =
|
|
ml_convert_list<vlc_ml_label_list_t, vlc_ml_label_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_MEDIA_LABELS:
|
|
*va_arg( args, size_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
case VLC_ML_LIST_SHOWS:
|
|
{
|
|
medialibrary::Query<medialibrary::IShow> query;
|
|
if ( psz_pattern != nullptr )
|
|
query = m_ml->searchShows( psz_pattern, paramsPtr );
|
|
else
|
|
query = m_ml->shows( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, vlc_ml_show_list_t** ) =
|
|
ml_convert_list<vlc_ml_show_list_t, vlc_ml_show_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
}
|
|
case VLC_ML_COUNT_SHOWS:
|
|
{
|
|
auto query = m_ml->shows( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, int64_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
}
|
|
case VLC_ML_LIST_SHOW_EPISODES:
|
|
case VLC_ML_COUNT_SHOW_EPISODES:
|
|
{
|
|
auto show = m_ml->show( va_arg( args, int64_t ) );
|
|
if ( show == nullptr )
|
|
return VLC_EGENERIC;
|
|
medialibrary::Query<medialibrary::IMedia> query;
|
|
if ( psz_pattern != nullptr )
|
|
query = show->searchEpisodes( psz_pattern, paramsPtr );
|
|
else
|
|
query = show->episodes( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_SHOW_EPISODES:
|
|
*va_arg( args, vlc_ml_media_list_t**) =
|
|
ml_convert_list<vlc_ml_media_list_t, vlc_ml_media_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_SHOW_EPISODES:
|
|
*va_arg( args, int64_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
case VLC_ML_LIST_PLAYLIST_MEDIA:
|
|
case VLC_ML_COUNT_PLAYLIST_MEDIA:
|
|
case VLC_ML_LIST_PLAYLISTS:
|
|
case VLC_ML_COUNT_PLAYLISTS:
|
|
return listPlaylist( listQuery, paramsPtr, psz_pattern, nbItems, offset, args );
|
|
case VLC_ML_LIST_HISTORY:
|
|
{
|
|
auto query = m_ml->history();
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, vlc_ml_media_list_t**) =
|
|
ml_convert_list<vlc_ml_media_list_t, vlc_ml_media_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
}
|
|
case VLC_ML_LIST_STREAM_HISTORY:
|
|
{
|
|
auto query = m_ml->streamHistory();
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
*va_arg( args, vlc_ml_media_list_t**) =
|
|
ml_convert_list<vlc_ml_media_list_t, vlc_ml_media_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
}
|
|
}
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
void* MediaLibrary::Get( int query, va_list args )
|
|
{
|
|
if ( Init() == false )
|
|
return nullptr;
|
|
|
|
switch ( query )
|
|
{
|
|
case VLC_ML_GET_MEDIA:
|
|
{
|
|
auto id = va_arg( args, int64_t );
|
|
auto media = m_ml->media( id );
|
|
return CreateAndConvert<vlc_ml_media_t>( media.get() );
|
|
}
|
|
case VLC_ML_GET_INPUT_ITEM:
|
|
{
|
|
auto id = va_arg( args, int64_t );
|
|
auto media = m_ml->media( id );
|
|
return MediaToInputItem( media.get() );
|
|
}
|
|
case VLC_ML_GET_ALBUM:
|
|
{
|
|
auto id = va_arg( args, int64_t );
|
|
auto album = m_ml->album( id );
|
|
return CreateAndConvert<vlc_ml_album_t>( album.get() );
|
|
}
|
|
case VLC_ML_GET_ARTIST:
|
|
{
|
|
auto id = va_arg( args, int64_t );
|
|
auto artist = m_ml->artist( id );
|
|
return CreateAndConvert<vlc_ml_artist_t>( artist.get() );
|
|
}
|
|
case VLC_ML_GET_GENRE:
|
|
{
|
|
auto id = va_arg( args, int64_t );
|
|
auto genre = m_ml->genre( id );
|
|
return CreateAndConvert<vlc_ml_genre_t>( genre.get() );
|
|
}
|
|
case VLC_ML_GET_SHOW:
|
|
{
|
|
auto id = va_arg( args, int64_t );
|
|
auto show = m_ml->show( id );
|
|
return CreateAndConvert<vlc_ml_show_t>( show.get() );
|
|
}
|
|
case VLC_ML_GET_PLAYLIST:
|
|
{
|
|
auto id = va_arg( args, int64_t );
|
|
auto playlist = m_ml->playlist( id );
|
|
return CreateAndConvert<vlc_ml_playlist_t>( playlist.get() );
|
|
}
|
|
case VLC_ML_GET_MEDIA_BY_MRL:
|
|
{
|
|
auto mrl = va_arg( args, const char* );
|
|
auto media = m_ml->media( mrl );
|
|
return CreateAndConvert<vlc_ml_media_t>( media.get() );
|
|
}
|
|
case VLC_ML_GET_INPUT_ITEM_BY_MRL:
|
|
{
|
|
auto mrl = va_arg( args, const char* );
|
|
auto media = m_ml->media( mrl );
|
|
if ( media == nullptr )
|
|
return nullptr;
|
|
return MediaToInputItem( media.get() );
|
|
}
|
|
default:
|
|
vlc_assert_unreachable();
|
|
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
medialibrary::IMedia::MetadataType MediaLibrary::metadataType( int meta )
|
|
{
|
|
switch ( meta )
|
|
{
|
|
case VLC_ML_PLAYBACK_STATE_RATING:
|
|
return medialibrary::IMedia::MetadataType::Rating;
|
|
case VLC_ML_PLAYBACK_STATE_PROGRESS:
|
|
return medialibrary::IMedia::MetadataType::Progress;
|
|
case VLC_ML_PLAYBACK_STATE_SPEED:
|
|
return medialibrary::IMedia::MetadataType::Speed;
|
|
case VLC_ML_PLAYBACK_STATE_TITLE:
|
|
return medialibrary::IMedia::MetadataType::Title;
|
|
case VLC_ML_PLAYBACK_STATE_CHAPTER:
|
|
return medialibrary::IMedia::MetadataType::Chapter;
|
|
case VLC_ML_PLAYBACK_STATE_PROGRAM:
|
|
return medialibrary::IMedia::MetadataType::Program;
|
|
case VLC_ML_PLAYBACK_STATE_SEEN:
|
|
return medialibrary::IMedia::MetadataType::Seen;
|
|
case VLC_ML_PLAYBACK_STATE_VIDEO_TRACK:
|
|
return medialibrary::IMedia::MetadataType::VideoTrack;
|
|
case VLC_ML_PLAYBACK_STATE_ASPECT_RATIO:
|
|
return medialibrary::IMedia::MetadataType::AspectRatio;
|
|
case VLC_ML_PLAYBACK_STATE_ZOOM:
|
|
return medialibrary::IMedia::MetadataType::Zoom;
|
|
case VLC_ML_PLAYBACK_STATE_CROP:
|
|
return medialibrary::IMedia::MetadataType::Crop;
|
|
case VLC_ML_PLAYBACK_STATE_DEINTERLACE:
|
|
return medialibrary::IMedia::MetadataType::Deinterlace;
|
|
case VLC_ML_PLAYBACK_STATE_VIDEO_FILTER:
|
|
return medialibrary::IMedia::MetadataType::VideoFilter;
|
|
case VLC_ML_PLAYBACK_STATE_AUDIO_TRACK:
|
|
return medialibrary::IMedia::MetadataType::AudioTrack;
|
|
case VLC_ML_PLAYBACK_STATE_GAIN:
|
|
return medialibrary::IMedia::MetadataType::Gain;
|
|
case VLC_ML_PLAYBACK_STATE_AUDIO_DELAY:
|
|
return medialibrary::IMedia::MetadataType::AudioDelay;
|
|
case VLC_ML_PLAYBACK_STATE_SUBTITLE_TRACK:
|
|
return medialibrary::IMedia::MetadataType::SubtitleTrack;
|
|
case VLC_ML_PLAYBACK_STATE_SUBTITLE_DELAY:
|
|
return medialibrary::IMedia::MetadataType::SubtitleDelay;
|
|
case VLC_ML_PLAYBACK_STATE_APP_SPECIFIC:
|
|
return medialibrary::IMedia::MetadataType::ApplicationSpecific;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
|
|
medialibrary::SortingCriteria MediaLibrary::sortingCriteria(int sort)
|
|
{
|
|
switch ( sort )
|
|
{
|
|
case VLC_ML_SORTING_DEFAULT:
|
|
return medialibrary::SortingCriteria::Default;
|
|
case VLC_ML_SORTING_ALPHA:
|
|
return medialibrary::SortingCriteria::Alpha;
|
|
case VLC_ML_SORTING_DURATION:
|
|
return medialibrary::SortingCriteria::Duration;
|
|
case VLC_ML_SORTING_INSERTIONDATE:
|
|
return medialibrary::SortingCriteria::InsertionDate;
|
|
case VLC_ML_SORTING_LASTMODIFICATIONDATE:
|
|
return medialibrary::SortingCriteria::LastModificationDate;
|
|
case VLC_ML_SORTING_RELEASEDATE:
|
|
return medialibrary::SortingCriteria::ReleaseDate;
|
|
case VLC_ML_SORTING_FILESIZE:
|
|
return medialibrary::SortingCriteria::FileSize;
|
|
case VLC_ML_SORTING_ARTIST:
|
|
return medialibrary::SortingCriteria::Artist;
|
|
case VLC_ML_SORTING_PLAYCOUNT:
|
|
return medialibrary::SortingCriteria::PlayCount;
|
|
case VLC_ML_SORTING_ALBUM:
|
|
return medialibrary::SortingCriteria::Album;
|
|
case VLC_ML_SORTING_FILENAME:
|
|
return medialibrary::SortingCriteria::Filename;
|
|
case VLC_ML_SORTING_TRACKNUMBER:
|
|
return medialibrary::SortingCriteria::TrackNumber;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
|
|
int MediaLibrary::getMeta( const medialibrary::IMedia& media, int meta, char** result )
|
|
{
|
|
auto& md = media.metadata( metadataType( meta ) );
|
|
if ( md.isSet() == false )
|
|
{
|
|
*result = nullptr;
|
|
return VLC_SUCCESS;
|
|
}
|
|
*result = strdup( md.asStr().c_str() );
|
|
if ( *result == nullptr )
|
|
return VLC_ENOMEM;
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
int MediaLibrary::getMeta( const medialibrary::IMedia& media,
|
|
vlc_ml_playback_states_all* res )
|
|
{
|
|
auto metas = media.metadata();
|
|
res->progress = -1.f;
|
|
res->rate = .0f;
|
|
res->zoom = -1.f;
|
|
res->current_title = -1;
|
|
// For tracks, -1 means disabled, so we can't use it for "unset"
|
|
res->current_video_track = res->current_audio_track =
|
|
res->current_subtitle_track = nullptr;
|
|
res->aspect_ratio = res->crop = res->deinterlace =
|
|
res->video_filter = nullptr;
|
|
for ( const auto& meta : metas )
|
|
{
|
|
#define COPY_META( field ) res->field = strdup( meta.second.c_str() ); \
|
|
if ( res->field == nullptr ) return VLC_ENOMEM;
|
|
|
|
switch ( meta.first )
|
|
{
|
|
case medialibrary::IMedia::MetadataType::Progress:
|
|
res->progress = atof( meta.second.c_str() );
|
|
break;
|
|
case medialibrary::IMedia::MetadataType::Speed:
|
|
res->rate = atof( meta.second.c_str() );
|
|
break;
|
|
case medialibrary::IMedia::MetadataType::Title:
|
|
res->current_title = atoi( meta.second.c_str() );
|
|
break;
|
|
case medialibrary::IMedia::MetadataType::VideoTrack:
|
|
COPY_META( current_video_track );
|
|
break;
|
|
case medialibrary::IMedia::MetadataType::AspectRatio:
|
|
COPY_META( aspect_ratio );
|
|
break;
|
|
case medialibrary::IMedia::MetadataType::Zoom:
|
|
res->zoom = atof( meta.second.c_str() );
|
|
break;
|
|
case medialibrary::IMedia::MetadataType::Crop:
|
|
COPY_META( crop );
|
|
break;
|
|
case medialibrary::IMedia::MetadataType::Deinterlace:
|
|
COPY_META( deinterlace );
|
|
break;
|
|
case medialibrary::IMedia::MetadataType::VideoFilter:
|
|
COPY_META( video_filter );
|
|
break;
|
|
case medialibrary::IMedia::MetadataType::AudioTrack:
|
|
COPY_META( current_audio_track );
|
|
break;
|
|
case medialibrary::IMedia::MetadataType::SubtitleTrack:
|
|
COPY_META( current_subtitle_track );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
#undef COPY_META
|
|
}
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
int MediaLibrary::setMeta( medialibrary::IMedia& media, int meta, const char* value )
|
|
{
|
|
bool res;
|
|
if ( value == nullptr )
|
|
res = media.unsetMetadata( metadataType( meta ) );
|
|
else
|
|
res = media.setMetadata( metadataType( meta ), value );
|
|
if ( res == false )
|
|
return VLC_EGENERIC;
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
int MediaLibrary::setMeta( medialibrary::IMedia& media,
|
|
const vlc_ml_playback_states_all* values )
|
|
{
|
|
using MT = medialibrary::IMedia::MetadataType;
|
|
std::unordered_map<MT, std::string> metas;
|
|
if ( values->progress >= .0f )
|
|
metas[MT::Progress] = std::to_string( values->progress );
|
|
if ( values->rate != .0f )
|
|
metas[MT::Speed] = std::to_string( values->rate );
|
|
if ( values->zoom != .0f )
|
|
metas[MT::Zoom] = std::to_string( values->zoom );
|
|
if ( values->current_title >= 0 )
|
|
metas[MT::Title] = std::to_string( values->current_title );
|
|
if ( values->aspect_ratio != nullptr )
|
|
metas[MT::AspectRatio] = values->aspect_ratio;
|
|
if ( values->crop != nullptr )
|
|
metas[MT::Crop] = values->crop;
|
|
if ( values->deinterlace != nullptr )
|
|
metas[MT::Deinterlace] = values->deinterlace;
|
|
if ( values->video_filter != nullptr )
|
|
metas[MT::VideoFilter] = values->video_filter;
|
|
if ( values->current_video_track != nullptr )
|
|
metas[MT::VideoTrack] = values->current_video_track;
|
|
if ( values->current_audio_track != nullptr )
|
|
metas[MT::AudioTrack] = values->current_audio_track;
|
|
if ( values->current_subtitle_track != nullptr )
|
|
metas[MT::SubtitleTrack] = values->current_subtitle_track;
|
|
|
|
if ( media.setMetadata( std::move( metas ) ) == false )
|
|
return VLC_EGENERIC;
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
int MediaLibrary::controlMedia( int query, va_list args )
|
|
{
|
|
auto mediaId = va_arg( args, int64_t );
|
|
auto m = m_ml->media( mediaId );
|
|
if ( m == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch( query )
|
|
{
|
|
case VLC_ML_MEDIA_INCREASE_PLAY_COUNT:
|
|
if ( m->increasePlayCount() == false )
|
|
return VLC_EGENERIC;
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_MEDIA_GET_MEDIA_PLAYBACK_STATE:
|
|
{
|
|
auto meta = va_arg( args, int );
|
|
auto res = va_arg( args, char** );
|
|
return getMeta( *m, meta, res );
|
|
}
|
|
case VLC_ML_MEDIA_SET_MEDIA_PLAYBACK_STATE:
|
|
{
|
|
auto meta = va_arg( args, int );
|
|
auto value = va_arg( args, const char* );
|
|
return setMeta( *m, meta, value );
|
|
}
|
|
case VLC_ML_MEDIA_GET_ALL_MEDIA_PLAYBACK_STATES:
|
|
{
|
|
auto res = va_arg( args, vlc_ml_playback_states_all* );
|
|
return getMeta( *m, res );
|
|
}
|
|
case VLC_ML_MEDIA_SET_ALL_MEDIA_PLAYBACK_STATES:
|
|
{
|
|
auto res = va_arg( args, const vlc_ml_playback_states_all* );
|
|
return setMeta( *m, res );
|
|
}
|
|
case VLC_ML_MEDIA_SET_THUMBNAIL:
|
|
{
|
|
auto mrl = va_arg( args, const char* );
|
|
auto sizeType = va_arg( args, int );
|
|
m->setThumbnail( mrl, static_cast<medialibrary::ThumbnailSizeType>( sizeType ) );
|
|
return VLC_SUCCESS;
|
|
}
|
|
case VLC_ML_MEDIA_GENERATE_THUMBNAIL:
|
|
{
|
|
auto sizeType = va_arg( args, int );
|
|
auto width = va_arg( args, uint32_t );
|
|
auto height = va_arg( args, uint32_t );
|
|
auto position = va_arg( args, double );
|
|
auto res = m->requestThumbnail( static_cast<medialibrary::ThumbnailSizeType>( sizeType ),
|
|
width, height, position );
|
|
return res == true ? VLC_SUCCESS : VLC_EGENERIC;
|
|
}
|
|
case VLC_ML_MEDIA_ADD_EXTERNAL_MRL:
|
|
{
|
|
auto mrl = va_arg( args, const char* );
|
|
auto type = va_arg( args, int );
|
|
medialibrary::IFile::Type mlType;
|
|
switch ( type )
|
|
{
|
|
case VLC_ML_FILE_TYPE_UNKNOWN:
|
|
// The type can't be main since this is added to an existing media
|
|
// which must already have a file
|
|
case VLC_ML_FILE_TYPE_MAIN:
|
|
case VLC_ML_FILE_TYPE_PLAYLIST:
|
|
return VLC_EGENERIC;
|
|
case VLC_ML_FILE_TYPE_PART:
|
|
mlType = medialibrary::IFile::Type::Part;
|
|
break;
|
|
case VLC_ML_FILE_TYPE_SOUNDTRACK:
|
|
mlType = medialibrary::IFile::Type::Soundtrack;
|
|
break;
|
|
case VLC_ML_FILE_TYPE_SUBTITLE:
|
|
mlType = medialibrary::IFile::Type::Subtitles;
|
|
break;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
if ( m->addExternalMrl( mrl, mlType ) == nullptr )
|
|
return VLC_EGENERIC;
|
|
return VLC_SUCCESS;
|
|
}
|
|
case VLC_ML_MEDIA_SET_TYPE:
|
|
{
|
|
auto type = va_arg( args, int );
|
|
if ( m->setType( static_cast<medialibrary::IMedia::Type>( type ) ) == false )
|
|
return VLC_EGENERIC;
|
|
return VLC_SUCCESS;
|
|
}
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
|
|
int MediaLibrary::filterListChildrenQuery( int query, int parentType )
|
|
{
|
|
switch( query )
|
|
{
|
|
case VLC_ML_LIST_MEDIA_OF:
|
|
switch ( parentType )
|
|
{
|
|
case VLC_ML_PARENT_ALBUM:
|
|
return VLC_ML_LIST_ALBUM_TRACKS;
|
|
case VLC_ML_PARENT_ARTIST:
|
|
return VLC_ML_LIST_ARTIST_TRACKS;
|
|
case VLC_ML_PARENT_SHOW:
|
|
return VLC_ML_LIST_SHOW_EPISODES;
|
|
case VLC_ML_PARENT_GENRE:
|
|
return VLC_ML_LIST_GENRE_TRACKS;
|
|
case VLC_ML_PARENT_PLAYLIST:
|
|
return VLC_ML_LIST_PLAYLIST_MEDIA;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
case VLC_ML_COUNT_MEDIA_OF:
|
|
switch ( parentType )
|
|
{
|
|
case VLC_ML_PARENT_ALBUM:
|
|
return VLC_ML_COUNT_ALBUM_TRACKS;
|
|
case VLC_ML_PARENT_ARTIST:
|
|
return VLC_ML_COUNT_ARTIST_TRACKS;
|
|
case VLC_ML_PARENT_SHOW:
|
|
return VLC_ML_COUNT_SHOW_EPISODES;
|
|
case VLC_ML_PARENT_GENRE:
|
|
return VLC_ML_COUNT_GENRE_TRACKS;
|
|
case VLC_ML_PARENT_PLAYLIST:
|
|
return VLC_ML_COUNT_PLAYLIST_MEDIA;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
case VLC_ML_LIST_ALBUMS_OF:
|
|
switch ( parentType )
|
|
{
|
|
case VLC_ML_PARENT_ARTIST:
|
|
return VLC_ML_LIST_ARTIST_ALBUMS;
|
|
case VLC_ML_PARENT_GENRE:
|
|
return VLC_ML_LIST_GENRE_ALBUMS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
case VLC_ML_COUNT_ALBUMS_OF:
|
|
switch ( parentType )
|
|
{
|
|
case VLC_ML_PARENT_ARTIST:
|
|
return VLC_ML_COUNT_ARTIST_ALBUMS;
|
|
case VLC_ML_PARENT_GENRE:
|
|
return VLC_ML_COUNT_GENRE_ALBUMS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
case VLC_ML_LIST_ARTISTS_OF:
|
|
switch ( parentType )
|
|
{
|
|
case VLC_ML_PARENT_ALBUM:
|
|
return VLC_ML_LIST_ALBUM_ARTISTS;
|
|
case VLC_ML_PARENT_GENRE:
|
|
return VLC_ML_LIST_GENRE_ARTISTS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
case VLC_ML_COUNT_ARTISTS_OF:
|
|
switch ( parentType )
|
|
{
|
|
case VLC_ML_PARENT_ALBUM:
|
|
return VLC_ML_COUNT_ALBUM_ARTISTS;
|
|
case VLC_ML_PARENT_GENRE:
|
|
return VLC_ML_COUNT_GENRE_ARTISTS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
|
|
int MediaLibrary::listAlbums( int listQuery, const medialibrary::QueryParameters* paramsPtr,
|
|
const char* pattern, uint32_t nbItems, uint32_t offset, va_list args )
|
|
{
|
|
auto album = m_ml->album( va_arg( args, int64_t ) );
|
|
if ( album == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_ALBUM_TRACKS:
|
|
case VLC_ML_COUNT_ALBUM_TRACKS:
|
|
{
|
|
medialibrary::Query<medialibrary::IMedia> query;
|
|
if ( pattern != nullptr )
|
|
query = album->searchTracks( pattern, paramsPtr );
|
|
else
|
|
query = album->tracks( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_ALBUM_TRACKS:
|
|
*va_arg( args, vlc_ml_media_list_t**) =
|
|
ml_convert_list<vlc_ml_media_list_t, vlc_ml_media_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_ALBUM_TRACKS:
|
|
*va_arg( args, size_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
case VLC_ML_LIST_ALBUM_ARTISTS:
|
|
case VLC_ML_COUNT_ALBUM_ARTISTS:
|
|
{
|
|
auto query = album->artists( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_ALBUM_ARTISTS:
|
|
*va_arg( args, vlc_ml_artist_list_t**) =
|
|
ml_convert_list<vlc_ml_artist_list_t, vlc_ml_artist_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_ALBUM_ARTISTS:
|
|
*va_arg( args, size_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
|
|
int MediaLibrary::listArtists( int listQuery, const medialibrary::QueryParameters* paramsPtr,
|
|
const char* pattern, uint32_t nbItems, uint32_t offset,
|
|
va_list args )
|
|
{
|
|
auto artist = m_ml->artist( va_arg( args, int64_t ) );
|
|
if ( artist == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch( listQuery )
|
|
{
|
|
case VLC_ML_LIST_ARTIST_ALBUMS:
|
|
case VLC_ML_COUNT_ARTIST_ALBUMS:
|
|
{
|
|
medialibrary::Query<medialibrary::IAlbum> query;
|
|
if ( pattern != nullptr )
|
|
query = artist->searchAlbums( pattern, paramsPtr );
|
|
else
|
|
query = artist->albums( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_ARTIST_ALBUMS:
|
|
*va_arg( args, vlc_ml_album_list_t**) =
|
|
ml_convert_list<vlc_ml_album_list_t, vlc_ml_album_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_ARTIST_ALBUMS:
|
|
*va_arg( args, size_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
case VLC_ML_LIST_ARTIST_TRACKS:
|
|
case VLC_ML_COUNT_ARTIST_TRACKS:
|
|
{
|
|
medialibrary::Query<medialibrary::IMedia> query;
|
|
if ( pattern != nullptr )
|
|
query = artist->searchTracks( pattern, paramsPtr );
|
|
else
|
|
query = artist->tracks( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_ARTIST_TRACKS:
|
|
*va_arg( args, vlc_ml_media_list_t**) =
|
|
ml_convert_list<vlc_ml_media_list_t, vlc_ml_media_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_ARTIST_TRACKS:
|
|
*va_arg( args, size_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
|
|
int MediaLibrary::listGenre( int listQuery, const medialibrary::QueryParameters* paramsPtr,
|
|
const char* pattern, uint32_t nbItems, uint32_t offset, va_list args )
|
|
{
|
|
auto genre = m_ml->genre( va_arg( args, int64_t ) );
|
|
if ( genre == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch( listQuery )
|
|
{
|
|
case VLC_ML_LIST_GENRE_ARTISTS:
|
|
case VLC_ML_COUNT_GENRE_ARTISTS:
|
|
{
|
|
medialibrary::Query<medialibrary::IArtist> query;
|
|
if ( pattern != nullptr )
|
|
query = genre->searchArtists( pattern, paramsPtr );
|
|
else
|
|
query = genre->artists( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_GENRE_ARTISTS:
|
|
*va_arg( args, vlc_ml_artist_list_t**) =
|
|
ml_convert_list<vlc_ml_artist_list_t, vlc_ml_artist_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_GENRE_ARTISTS:
|
|
*va_arg( args, size_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
case VLC_ML_LIST_GENRE_TRACKS:
|
|
case VLC_ML_COUNT_GENRE_TRACKS:
|
|
{
|
|
medialibrary::Query<medialibrary::IMedia> query;
|
|
if ( pattern != nullptr )
|
|
query = genre->searchTracks( pattern, paramsPtr );
|
|
else
|
|
query = genre->tracks( medialibrary::IGenre::TracksIncluded::All,
|
|
paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_GENRE_TRACKS:
|
|
*va_arg( args, vlc_ml_media_list_t**) =
|
|
ml_convert_list<vlc_ml_media_list_t, vlc_ml_media_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_GENRE_TRACKS:
|
|
*va_arg( args, size_t*) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
case VLC_ML_LIST_GENRE_ALBUMS:
|
|
case VLC_ML_COUNT_GENRE_ALBUMS:
|
|
{
|
|
medialibrary::Query<medialibrary::IAlbum> query;
|
|
if ( pattern != nullptr )
|
|
query = genre->searchAlbums( pattern, paramsPtr );
|
|
else
|
|
query = genre->albums( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_GENRE_ALBUMS:
|
|
*va_arg( args, vlc_ml_album_list_t**) =
|
|
ml_convert_list<vlc_ml_album_list_t, vlc_ml_album_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_GENRE_ALBUMS:
|
|
*va_arg( args, size_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
|
|
int MediaLibrary::listPlaylist( int listQuery, const medialibrary::QueryParameters* paramsPtr,
|
|
const char* pattern, uint32_t nbItems, uint32_t offset, va_list args )
|
|
{
|
|
switch( listQuery )
|
|
{
|
|
case VLC_ML_LIST_PLAYLISTS:
|
|
case VLC_ML_COUNT_PLAYLISTS:
|
|
{
|
|
medialibrary::Query<medialibrary::IPlaylist> query;
|
|
if ( pattern != nullptr )
|
|
query = m_ml->searchPlaylists( pattern, paramsPtr );
|
|
else
|
|
query = m_ml->playlists( paramsPtr );
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_PLAYLISTS:
|
|
*va_arg( args, vlc_ml_playlist_list_t** ) =
|
|
ml_convert_list<vlc_ml_playlist_list_t, vlc_ml_playlist_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_PLAYLISTS:
|
|
*va_arg( args, size_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
case VLC_ML_LIST_PLAYLIST_MEDIA:
|
|
case VLC_ML_COUNT_PLAYLIST_MEDIA:
|
|
{
|
|
auto playlist = m_ml->playlist( va_arg( args, int64_t ) );
|
|
if ( playlist == nullptr )
|
|
return VLC_EGENERIC;
|
|
medialibrary::Query<medialibrary::IMedia> query;
|
|
if ( pattern != nullptr )
|
|
query = playlist->searchMedia( pattern, paramsPtr );
|
|
else
|
|
query = playlist->media();
|
|
if ( query == nullptr )
|
|
return VLC_EGENERIC;
|
|
switch ( listQuery )
|
|
{
|
|
case VLC_ML_LIST_PLAYLIST_MEDIA:
|
|
*va_arg( args, vlc_ml_media_list_t**) =
|
|
ml_convert_list<vlc_ml_media_list_t, vlc_ml_media_t>(
|
|
query->items( nbItems, offset ) );
|
|
return VLC_SUCCESS;
|
|
case VLC_ML_COUNT_PLAYLIST_MEDIA:
|
|
*va_arg( args, size_t* ) = query->count();
|
|
return VLC_SUCCESS;
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
}
|
|
|
|
static void* Get( vlc_medialibrary_module_t* module, int query, va_list args )
|
|
{
|
|
auto ml = static_cast<MediaLibrary*>( module->p_sys );
|
|
return ml->Get( query, args );
|
|
}
|
|
|
|
static int List( vlc_medialibrary_module_t* module, int query,
|
|
const vlc_ml_query_params_t* params, va_list args )
|
|
{
|
|
auto ml = static_cast<MediaLibrary*>( module->p_sys );
|
|
return ml->List( query, params, args );
|
|
}
|
|
|
|
static int Control( vlc_medialibrary_module_t* module, int query, va_list args )
|
|
{
|
|
auto ml = static_cast<MediaLibrary*>( module->p_sys );
|
|
return ml->Control( query, args );
|
|
}
|
|
|
|
static int Open( vlc_object_t* obj )
|
|
{
|
|
auto* p_ml = reinterpret_cast<vlc_medialibrary_module_t*>( obj );
|
|
|
|
try
|
|
{
|
|
p_ml->p_sys = new MediaLibrary( p_ml );
|
|
}
|
|
catch ( const std::exception& ex )
|
|
{
|
|
msg_Err( obj, "Failed to instantiate/initialize medialibrary: %s", ex.what() );
|
|
return VLC_EGENERIC;
|
|
}
|
|
p_ml->pf_control = Control;
|
|
p_ml->pf_get = Get;
|
|
p_ml->pf_list = List;
|
|
return VLC_SUCCESS;
|
|
}
|
|
|
|
static void Close( vlc_object_t* obj )
|
|
{
|
|
vlc_medialibrary_module_t *module = reinterpret_cast<vlc_medialibrary_module_t*>( obj );
|
|
MediaLibrary* p_ml = static_cast<MediaLibrary*>( module->p_sys );
|
|
delete p_ml;
|
|
}
|
|
|
|
#define ML_FOLDER_TEXT _( "Folders discovered by the media library" )
|
|
#define ML_FOLDER_LONGTEXT _( "Semicolon separated list of folders to discover " \
|
|
"media from" )
|
|
|
|
vlc_module_begin()
|
|
set_shortname(N_("media library"))
|
|
set_description(N_( "Organize your media" ))
|
|
set_category(CAT_ADVANCED)
|
|
set_subcategory(SUBCAT_ADVANCED_MISC)
|
|
set_capability("medialibrary", 100)
|
|
set_callbacks(Open, Close)
|
|
add_string( "ml-folders", nullptr, ML_FOLDER_TEXT, ML_FOLDER_LONGTEXT, false )
|
|
vlc_module_end()
|
|
|