[vlc-devel] [PATCH] Add addons management API
Francois Cartegnie
fcvlcdev at free.fr
Fri Feb 7 23:41:19 CET 2014
Hi,
This is a separate commit regarding the upcoming addons management.
Basically, addons management is done using new modules types:
* addons finder : lists addons from a repository and provide way to retrieve
content that will be passed to storage.
* addons storage : provide addons listing (maintains a catalog) installing and
removing functions.
This allows using alternate repositories and switching to a smarter
lua scripts listing method / storage.
Not on this patch:
Current implementation has an "addons storage" matching our current filesystem
layout and providing a "finder" submodule for querying installed addons.
There's also a repository "addons finder" module for a rewritten addons.v.o,
which will use a new .vlp package + manifest.
>From early work, an open desktop (current addons.vo) based "finder",
which is likely not to be commited at all.
François
---
include/vlc_addons.h | 221 +++++++++++++++++++++++
include/vlc_common.h | 1 +
include/vlc_events.h | 13 +-
src/Makefile.am | 1 +
src/libvlccore.sym | 9 +
src/misc/addons.c | 485 +++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 729 insertions(+), 1 deletion(-)
create mode 100644 include/vlc_addons.h
create mode 100644 src/misc/addons.c
diff --git a/include/vlc_addons.h b/include/vlc_addons.h
new file mode 100644
index 0000000..8d16b35
--- /dev/null
+++ b/include/vlc_addons.h
@@ -0,0 +1,221 @@
+/*****************************************************************************
+ * vlc_addons.h : addons handling and describing
+ *****************************************************************************
+ * Copyright (C) 2013 VideoLAN and authors
+ *
+ * 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.
+ *****************************************************************************/
+
+#ifndef VLC_ADDONS_H
+#define VLC_ADDONS_H 1
+
+#include <vlc_arrays.h>
+#include <vlc_events.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+typedef enum addon_type_t
+{
+ ADDON_UNKNOWN = 0,
+ ADDON_EXTENSION,
+ ADDON_PLAYLIST_PARSER,
+ ADDON_SERVICE_DISCOVERY,
+ ADDON_SKIN2,
+ ADDON_PLUGIN,
+ ADDON_OTHER
+} addon_type_t;
+
+typedef enum addon_state_t
+{
+ ADDON_NOTINSTALLED = 0,
+ ADDON_INSTALLING,
+ ADDON_INSTALLED,
+ ADDON_UNINSTALLING
+} addon_state_t;
+
+typedef enum addon_flags_t
+{
+ ADDON_BROKEN = 1, /* Have install inconsistency */
+ ADDON_MANAGEABLE = 1 << 1, /* Have manifest, can install or uninstall files */
+ ADDON_UPDATABLE = 1 << 2,
+} addon_flags_t;
+
+#define ADDON_UUID_SIZE 16
+#define ADDON_UUID_PSZ_SIZE (ADDON_UUID_SIZE * 2 + 4)
+typedef uint8_t addon_uuid_t[ADDON_UUID_SIZE];
+
+typedef struct addon_file_t
+{
+ addon_type_t e_filetype;
+ char *psz_download_uri;
+ char *psz_filename;
+} addon_file_t;
+
+struct addon_entry_t
+{
+ vlc_mutex_t lock;
+
+ addon_type_t e_type;
+ addon_state_t e_state;
+ addon_flags_t e_flags;
+
+ /* data describing addon */
+ addon_uuid_t uuid;
+ char *psz_name;
+ char *psz_summary;
+ char *psz_description;
+ char *psz_source_uri; /* webpage, ... */
+ char *psz_image_uri;
+ char *psz_image_data; /* base64, png */
+ char *psz_version;
+
+ /* stats */
+ long int i_downloads;
+ long int i_score;
+
+ /* Lister */
+ char *psz_source_module;
+
+ /* files list */
+ char *psz_archive_uri; /* Archive */
+ DECL_ARRAY(addon_file_t *) files;
+
+ /* custom data storage (if needed by module/source) */
+ void * p_custom;
+};
+typedef struct addon_entry_t addon_entry_t;
+
+typedef struct addons_finder_t addons_finder_t;
+typedef struct addons_finder_sys_t addons_finder_sys_t;
+struct addons_finder_t
+{
+ VLC_COMMON_MEMBERS
+
+ int ( * pf_find )( addons_finder_t * );
+ int ( * pf_retrieve )( addons_finder_t *, addon_entry_t * );
+ DECL_ARRAY( addon_entry_t * ) entries;
+ char *psz_uri;
+
+ addons_finder_sys_t *p_sys;
+};
+
+typedef struct addons_storage_t addons_storage_t;
+typedef struct addons_storage_sys_t addons_storage_sys_t;
+struct addons_storage_t
+{
+ VLC_COMMON_MEMBERS
+
+ int ( * pf_install )( addons_storage_t *, addon_entry_t * );
+ int ( * pf_remove )( addons_storage_t *, addon_entry_t * );
+ int ( * pf_catalog ) ( addons_storage_t *, addon_entry_t **, int );
+
+ addons_storage_sys_t *p_sys;
+};
+
+typedef struct addons_manager_private_t addons_manager_private_t;
+/**
+ *
+ */
+/*FIXME*/
+typedef struct vlc_event_manager_t vlc_event_manager_t;
+
+struct addons_manager_t
+{
+ vlc_event_manager_t * p_event_manager;
+
+ addons_manager_private_t *p_priv;
+};
+typedef struct addons_manager_t addons_manager_t;
+
+/**
+ * addon entry lifecycle
+ */
+VLC_API addon_entry_t *addon_entry_New( void );
+VLC_API addon_entry_t *addon_entry_Hold(addon_entry_t *);
+VLC_API void addon_entry_Release(addon_entry_t *);
+
+/**
+ * addons manager lifecycle
+ */
+VLC_API addons_manager_t *addons_manager_New( vlc_object_t * );
+VLC_API void addons_manager_Delete( addons_manager_t * );
+
+/**
+ * Charge currently installed, usable and manageable addons
+ * (default "addons storage" module)
+ */
+VLC_API int addons_manager_LoadCatalog( addons_manager_t * );
+
+/**
+ * Gather addons info from repository (default "addons finder" module)
+ * If psz_uri is not NULL, only gather info from the pointed package.
+ */
+VLC_API void addons_manager_Gather( addons_manager_t *, const char *psz_uri );
+
+/**
+ * Install or Remove the addon identified by its uuid
+ */
+VLC_API int addons_manager_Install( addons_manager_t *p_manager, const addon_uuid_t uuid );
+VLC_API int addons_manager_Remove( addons_manager_t *p_manager, const addon_uuid_t uuid );
+
+/**
+ * String uuid to binary uuid helpers
+ */
+static inline bool addons_uuid_read( const char *psz_uuid, addon_uuid_t *p_uuid )
+{
+ if ( !psz_uuid ) return false;
+ if ( strlen( psz_uuid ) < ADDON_UUID_PSZ_SIZE ) return false;
+
+ int i = 0, j = 0;
+ while ( i<ADDON_UUID_PSZ_SIZE )
+ {
+ if ( *( psz_uuid + i ) == '-' )
+ i++;
+ int v;
+ sscanf( psz_uuid + i, "%02"PRIx8, &v );
+ (*p_uuid)[j++] = v & 0xFF;
+ i+=2;
+ }
+
+ return true;
+}
+
+static inline char * addons_uuid_to_psz( const addon_uuid_t * p_uuid )
+{
+ char *psz = (char*) calloc( ADDON_UUID_PSZ_SIZE + 1 , sizeof(char) );
+ if ( psz )
+ {
+ int i=0;
+ char *p = psz;
+ while ( i < ADDON_UUID_SIZE )
+ {
+ if ( i == 4 || i== 7 || i== 9 || i== 11 )
+ *p++ = '-';
+ int v = 0xFF & (*p_uuid)[i];
+ sprintf( p, "%02"PRIx8, v );
+ p += 2;
+ i++;
+ }
+ }
+ return psz;
+}
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/vlc_common.h b/include/vlc_common.h
index 62b1260..7e84f16 100644
--- a/include/vlc_common.h
+++ b/include/vlc_common.h
@@ -335,6 +335,7 @@ typedef struct vlm_message_t vlm_message_t;
/* misc */
typedef struct vlc_meta_t vlc_meta_t;
typedef struct input_stats_t input_stats_t;
+typedef struct addon_entry_t addon_entry_t;
/* Update */
typedef struct update_t update_t;
diff --git a/include/vlc_events.h b/include/vlc_events.h
index 9e37f7f..9a6166a 100644
--- a/include/vlc_events.h
+++ b/include/vlc_events.h
@@ -27,6 +27,7 @@
#include <vlc_arrays.h>
#include <vlc_meta.h>
+#include <vlc_addons.h>
/**
* \file
@@ -129,7 +130,12 @@ typedef enum vlc_event_type_t {
vlc_ServicesDiscoveryItemRemoved,
vlc_ServicesDiscoveryItemRemoveAll,
vlc_ServicesDiscoveryStarted,
- vlc_ServicesDiscoveryEnded
+ vlc_ServicesDiscoveryEnded,
+
+ /* Addons Manager events */
+ vlc_AddonFound,
+ vlc_AddonsDiscoveryEnded,
+ vlc_AddonChanged
} vlc_event_type_t;
/* Event definition */
@@ -202,6 +208,11 @@ typedef struct vlc_event_t
void * unused;
} services_discovery_ended;
+ /* Addons */
+ struct vlc_addon_generic_event
+ {
+ addon_entry_t * p_entry;
+ } addon_generic_event;
} u;
} vlc_event_t;
diff --git a/src/Makefile.am b/src/Makefile.am
index 474da25..ab4b744 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -475,6 +475,7 @@ SOURCES_libvlc_common = \
misc/xml.c \
extras/libc.c \
extras/tdestroy.c \
+ misc/addons.c \
misc/filter.c \
misc/filter_chain.c \
misc/http_auth.c \
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 3fc39d7..1ed906a 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -641,3 +641,12 @@ vlc_keycode2str
vlc_str2keycode
fingerprinter_Create
fingerprinter_Destroy
+addons_manager_New
+addons_manager_Delete
+addons_manager_Gather
+addons_manager_LoadCatalog
+addons_manager_Install
+addons_manager_Remove
+addon_entry_New
+addon_entry_Hold
+addon_entry_Release
diff --git a/src/misc/addons.c b/src/misc/addons.c
new file mode 100644
index 0000000..8e8659c
--- /dev/null
+++ b/src/misc/addons.c
@@ -0,0 +1,485 @@
+/*****************************************************************************
+ * addons.c: VLC addons manager
+ *****************************************************************************
+ * Copyright (C) 2014 VLC authors and VideoLAN
+ *
+ * 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_atomic.h>
+#include <vlc_modules.h>
+#include <vlc_arrays.h>
+#include <vlc_events.h>
+#include "libvlc.h"
+
+#include <vlc_addons.h>
+
+/*****************************************************************************
+ * Structures/definitions
+ *****************************************************************************/
+
+typedef struct addon_entry_owner
+{
+ addon_entry_t entry;
+ atomic_uint refs;
+} addon_entry_owner_t;
+
+struct addons_manager_private_t
+{
+ vlc_object_t *p_parent;
+
+ struct
+ {
+ vlc_thread_t *p_thread;
+ bool b_live;
+ vlc_mutex_t lock;
+ char *psz_uri_hint; /* uri hint for non repo based install */
+ DECL_ARRAY(addon_entry_t*) entries;
+ } finder;
+
+ struct
+ {
+ vlc_thread_t *p_thread;
+ bool b_live;
+ vlc_mutex_t lock;
+ DECL_ARRAY(addon_entry_t*) entries;
+ } installer;
+};
+
+static void *FinderThread( void * );
+static void LoadLocalStorage( addons_manager_t *p_manager );
+
+/*****************************************************************************
+ * Public functions
+ *****************************************************************************/
+
+addon_entry_t * addon_entry_New()
+{
+ addon_entry_owner_t *owner = calloc( 1, sizeof(addon_entry_owner_t) );
+ if( unlikely(owner == NULL) )
+ return NULL;
+
+ atomic_init( &owner->refs, 1 );
+
+ addon_entry_t *p_entry = &owner->entry;
+ vlc_mutex_init( &p_entry->lock );
+ ARRAY_INIT( p_entry->files );
+ return p_entry;
+}
+
+addon_entry_t * addon_entry_Hold( addon_entry_t * p_entry )
+{
+ addon_entry_owner_t *owner = (addon_entry_owner_t *) p_entry;
+
+ atomic_fetch_add( &owner->refs, 1 );
+ return p_entry;
+}
+
+void addon_entry_Release( addon_entry_t * p_entry )
+{
+ addon_entry_owner_t *owner = (addon_entry_owner_t *) p_entry;
+
+ if( atomic_fetch_sub(&owner->refs, 1) != 1 )
+ return;
+
+ free( p_entry->psz_name );
+ free( p_entry->psz_summary );
+ free( p_entry->psz_description );
+ free( p_entry->psz_archive_uri );
+ free( p_entry->psz_image_uri );
+ free( p_entry->psz_image_data );
+ free( p_entry->psz_source_module );
+ free( p_entry->psz_version );
+ free( p_entry->p_custom );
+
+ addon_file_t *p_file;
+ FOREACH_ARRAY( p_file, p_entry->files )
+ free( p_file->psz_filename );
+ free( p_file->psz_download_uri );
+ FOREACH_END()
+ ARRAY_RESET( p_entry->files );
+
+ vlc_mutex_destroy( &p_entry->lock );
+ free( owner );
+}
+
+addons_manager_t *addons_manager_New( vlc_object_t *p_this )
+{
+ addons_manager_t *p_manager = malloc( sizeof(addons_manager_t) );
+ if ( !p_manager ) return NULL;
+
+ p_manager->p_priv = malloc( sizeof(addons_manager_private_t) );
+ if ( !p_manager->p_priv )
+ {
+ free( p_manager );
+ return NULL;
+ }
+
+ p_manager->p_event_manager = malloc( sizeof(vlc_event_manager_t) );
+ if ( !p_manager->p_event_manager )
+ {
+ free( p_manager->p_priv );
+ free( p_manager );
+ return NULL;
+ }
+
+ p_manager->p_priv->p_parent = p_this;
+
+#define INIT_QUEUE( name ) \
+ p_manager->p_priv->name.b_live = false;\
+ p_manager->p_priv->name.p_thread = NULL;\
+ vlc_mutex_init( &p_manager->p_priv->name.lock );\
+ ARRAY_INIT( p_manager->p_priv->name.entries );
+
+ INIT_QUEUE( finder )
+ INIT_QUEUE( installer )
+ p_manager->p_priv->finder.psz_uri_hint = NULL;
+
+ vlc_event_manager_t *em = p_manager->p_event_manager;
+ vlc_event_manager_init( em, p_manager );
+ vlc_event_manager_register_event_type(em, vlc_AddonFound);
+ vlc_event_manager_register_event_type(em, vlc_AddonsDiscoveryEnded);
+ vlc_event_manager_register_event_type(em, vlc_AddonChanged);
+
+ return p_manager;
+}
+
+void addons_manager_Delete( addons_manager_t *p_manager )
+{
+ if ( p_manager->p_priv->finder.b_live )
+ vlc_cancel( *p_manager->p_priv->finder.p_thread );
+ if ( p_manager->p_priv->installer.b_live )
+ vlc_cancel( *p_manager->p_priv->installer.p_thread );
+
+ vlc_event_manager_fini( p_manager->p_event_manager );
+
+#define FREE_QUEUE( name ) \
+ vlc_mutex_lock( &p_manager->p_priv->name.lock );\
+ FOREACH_ARRAY( addon_entry_t *p_entry, p_manager->p_priv->name.entries )\
+ addon_entry_Release( p_entry );\
+ FOREACH_END();\
+ ARRAY_RESET( p_manager->p_priv->name.entries );\
+ vlc_mutex_unlock( &p_manager->p_priv->name.lock );\
+ vlc_mutex_destroy( &p_manager->p_priv->name.lock );
+
+ FREE_QUEUE( finder )
+ FREE_QUEUE( installer )
+ free( p_manager->p_priv->finder.psz_uri_hint );
+
+ free( p_manager->p_priv );
+ free( p_manager->p_event_manager );
+ free( p_manager );
+}
+
+void addons_manager_Gather( addons_manager_t *p_manager, const char *psz_uri )
+{
+ vlc_mutex_lock( &p_manager->p_priv->finder.lock );
+ if ( psz_uri )
+ {
+ p_manager->p_priv->finder.psz_uri_hint = strdup( psz_uri );
+ }
+ if( !p_manager->p_priv->finder.b_live )
+ {
+ if( vlc_clone_detach( p_manager->p_priv->finder.p_thread, FinderThread, p_manager,
+ VLC_THREAD_PRIORITY_LOW ) )
+ msg_Err( p_manager->p_priv->p_parent,
+ "cannot spawn entries provider thread" );
+ else
+ p_manager->p_priv->finder.b_live = true;
+ }
+ vlc_mutex_unlock( &p_manager->p_priv->finder.lock );
+}
+
+/*****************************************************************************
+ * Private functions
+ *****************************************************************************/
+
+static addon_entry_t * getHeldEntryByUUID( addons_manager_t *p_manager,
+ const addon_uuid_t uuid )
+{
+ addon_entry_t *p_return = NULL;
+ vlc_mutex_lock( &p_manager->p_priv->finder.lock );
+ FOREACH_ARRAY( addon_entry_t *p_entry, p_manager->p_priv->finder.entries )
+ if ( !memcmp( p_entry->uuid, uuid, sizeof( addon_uuid_t ) ) )
+ {
+ p_return = p_entry;
+ addon_entry_Hold( p_return );
+ break;
+ }
+ FOREACH_END()
+ vlc_mutex_unlock( &p_manager->p_priv->finder.lock );
+ return p_return;
+}
+
+static void MergeSources( addons_manager_t *p_manager,
+ addon_entry_t **pp_addons, int i_count )
+{
+ addon_entry_t *p_entry, *p_manager_entry;
+ addon_uuid_t zerouuid;
+ memset( zerouuid, 0, sizeof( addon_uuid_t ) );
+ for ( int i=0; i < i_count; i++ )
+ {
+ p_entry = pp_addons[i];
+ if ( memcmp( p_entry->uuid, zerouuid, sizeof( addon_uuid_t ) ) )
+ p_manager_entry = getHeldEntryByUUID( p_manager, p_entry->uuid );
+ else
+ p_manager_entry = NULL;
+ if ( !p_manager_entry )
+ {
+ ARRAY_APPEND( p_manager->p_priv->finder.entries, p_entry );
+ vlc_event_t event;
+ event.type = vlc_AddonFound;
+ event.u.addon_generic_event.p_entry = p_entry;
+ vlc_event_send( p_manager->p_event_manager, &event );
+ }
+ else
+ {
+ addon_entry_Release( p_manager_entry );
+ }
+ }
+}
+
+static void LoadLocalStorage( addons_manager_t *p_manager )
+{
+ addons_finder_t *p_finder =
+ vlc_custom_create( p_manager->p_priv->p_parent, sizeof( *p_finder ), "entries finder" );
+
+ module_t *p_module = module_need( p_finder, "addons finder",
+ "addons.store.list", true );
+ if( p_module )
+ {
+ ARRAY_INIT( p_finder->entries );
+ p_finder->pf_find( p_finder );
+ module_unneed( p_finder, p_module );
+
+ MergeSources( p_manager, p_finder->entries.p_elems, p_finder->entries.i_size );
+
+ ARRAY_RESET( p_finder->entries );
+ }
+ vlc_object_release( p_finder );
+}
+
+static void *FinderThread( void *p_data )
+{
+ addons_manager_t *p_manager = p_data;
+ int i_cancel;
+ p_manager->p_priv->finder.b_live = true;
+
+ addons_finder_t *p_finder =
+ vlc_custom_create( p_manager->p_priv->p_parent, sizeof( *p_finder ), "entries finder" );
+
+ if( p_finder != NULL )
+ {
+ module_t *p_module;
+ ARRAY_INIT( p_finder->entries );
+ p_finder->psz_uri = p_manager->p_priv->finder.psz_uri_hint;
+ p_manager->p_priv->finder.psz_uri_hint = NULL;
+
+ p_module = module_need( p_finder, "addons finder", NULL, false );
+ if( p_module )
+ {
+ i_cancel = vlc_savecancel();
+ p_finder->pf_find( p_finder );
+ vlc_restorecancel( i_cancel );
+ module_unneed( p_finder, p_module );
+
+ MergeSources( p_manager, p_finder->entries.p_elems, p_finder->entries.i_size );
+ }
+
+ ARRAY_RESET( p_finder->entries );
+ free( p_finder->psz_uri );
+ vlc_object_release( p_finder );
+ }
+
+ p_manager->p_priv->finder.b_live = false;
+
+ vlc_event_t event;
+ event.type = vlc_AddonsDiscoveryEnded;
+ event.u.addon_generic_event.p_entry = NULL;
+ vlc_event_send( p_manager->p_event_manager, &event );
+
+ return NULL;
+}
+
+static int addons_manager_WriteCatalog( addons_manager_t *p_manager )
+{
+ int i_return = VLC_EGENERIC;
+
+ addons_storage_t *p_storage =
+ vlc_custom_create( p_manager->p_priv->p_parent, sizeof( *p_storage ), "entries storage" );
+
+ module_t *p_module = module_need( p_storage, "addons storage",
+ "addons.store.install", true );
+ if( p_module )
+ {
+ vlc_mutex_lock( &p_manager->p_priv->finder.lock );
+ i_return = p_storage->pf_catalog( p_storage, p_manager->p_priv->finder.entries.p_elems,
+ p_manager->p_priv->finder.entries.i_size );
+ vlc_mutex_unlock( &p_manager->p_priv->finder.lock );
+ module_unneed( p_storage, p_module );
+ }
+ vlc_object_release( p_storage );
+
+ return i_return;
+}
+
+int addons_manager_LoadCatalog( addons_manager_t *p_manager )
+{
+ LoadLocalStorage( p_manager );
+ return VLC_SUCCESS;
+}
+
+static int installOrRemoveAddon( addons_manager_t *p_manager, addon_entry_t *p_entry, bool b_install )
+{
+ int i_return = VLC_EGENERIC;
+
+ addons_storage_t *p_storage =
+ vlc_custom_create( p_manager->p_priv->p_parent, sizeof( *p_storage ), "entries storage" );
+
+ module_t *p_module = module_need( p_storage, "addons storage",
+ "addons.store.install", true );
+ if( p_module )
+ {
+ if ( b_install )
+ i_return = p_storage->pf_install( p_storage, p_entry );
+ else
+ i_return = p_storage->pf_remove( p_storage, p_entry );
+ module_unneed( p_storage, p_module );
+ msg_Dbg( p_manager->p_priv->p_parent, "InstallAddon returns %d", i_return );
+ }
+ vlc_object_release( p_storage );
+
+ return i_return;
+}
+
+static void *InstallerThread( void *p_data )
+{
+ addons_manager_t *p_manager = p_data;
+ int i_ret, i_cancel;
+ vlc_event_t event;
+ event.type = vlc_AddonChanged;
+
+ for( ;; )
+ {
+ vlc_testcancel();
+ vlc_mutex_lock( &p_manager->p_priv->installer.lock );
+ if ( !p_manager->p_priv->installer.entries.i_size )
+ {
+ /* No queued addons */
+ vlc_mutex_unlock( &p_manager->p_priv->installer.lock );
+ p_manager->p_priv->installer.b_live = false;
+ break;
+ }
+
+ addon_entry_t *p_entry = p_manager->p_priv->installer.entries.p_elems[0];
+ ARRAY_REMOVE( p_manager->p_priv->installer.entries, 0 );
+ addon_entry_Hold( p_entry );
+ vlc_mutex_unlock( &p_manager->p_priv->installer.lock );
+
+ vlc_mutex_lock( &p_entry->lock );
+ /* DO WORK */
+ if ( p_entry->e_state == ADDON_INSTALLED )
+ {
+ p_entry->e_state = ADDON_UNINSTALLING;
+ vlc_mutex_unlock( &p_entry->lock );
+
+ /* notify */
+ event.u.addon_generic_event.p_entry = p_entry;
+ vlc_event_send( p_manager->p_event_manager, &event );
+
+ i_cancel = vlc_savecancel();
+ i_ret = installOrRemoveAddon( p_manager, p_entry, false );
+ vlc_restorecancel( i_cancel );
+
+ vlc_mutex_lock( &p_entry->lock );
+ p_entry->e_state = ( i_ret == VLC_SUCCESS ) ? ADDON_NOTINSTALLED
+ : ADDON_INSTALLED;
+ vlc_mutex_unlock( &p_entry->lock );
+ }
+ else if ( p_entry->e_state == ADDON_NOTINSTALLED )
+ {
+ p_entry->e_state = ADDON_INSTALLING;
+ vlc_mutex_unlock( &p_entry->lock );
+
+ /* notify */
+ event.u.addon_generic_event.p_entry = p_entry;
+ vlc_event_send( p_manager->p_event_manager, &event );
+
+ i_cancel = vlc_savecancel();
+ i_ret = installOrRemoveAddon( p_manager, p_entry, true );
+ vlc_restorecancel( i_cancel );
+
+ vlc_mutex_lock( &p_entry->lock );
+ p_entry->e_state = ( i_ret == VLC_SUCCESS ) ? ADDON_INSTALLED
+ : ADDON_NOTINSTALLED;
+ vlc_mutex_unlock( &p_entry->lock );
+ }
+ else
+ vlc_mutex_unlock( &p_entry->lock );
+ /* !DO WORK */
+
+ event.u.addon_generic_event.p_entry = p_entry;
+ vlc_event_send( p_manager->p_event_manager, &event );
+
+ addon_entry_Release( p_entry );
+ }
+
+ i_cancel = vlc_savecancel();
+ addons_manager_WriteCatalog( p_manager );
+ vlc_restorecancel( i_cancel );
+
+ return NULL;
+}
+
+static int InstallEntry( addons_manager_t *p_manager, addon_entry_t *p_entry )
+{
+ if ( p_entry->e_type == ADDON_UNKNOWN ||
+ p_entry->e_type == ADDON_PLUGIN ||
+ p_entry->e_type == ADDON_OTHER )
+ return VLC_EBADVAR;
+
+ vlc_mutex_lock( &p_manager->p_priv->installer.lock );
+ ARRAY_APPEND( p_manager->p_priv->installer.entries, p_entry );
+ if( !p_manager->p_priv->installer.b_live )
+ {
+ if( vlc_clone_detach( p_manager->p_priv->installer.p_thread, InstallerThread, p_manager,
+ VLC_THREAD_PRIORITY_LOW ) )
+ msg_Err( p_manager->p_priv->p_parent,
+ "cannot spawn addons installer thread" );
+ else
+ p_manager->p_priv->installer.b_live = true;
+ }
+ vlc_mutex_unlock( &p_manager->p_priv->installer.lock );
+ return VLC_SUCCESS;
+}
+
+int addons_manager_Install( addons_manager_t *p_manager, const addon_uuid_t uuid )
+{
+ addon_entry_t *p_install_entry = getHeldEntryByUUID( p_manager, uuid );
+ if ( ! p_install_entry ) return VLC_EGENERIC;
+ int i_ret = InstallEntry( p_manager, p_install_entry );
+ addon_entry_Release( p_install_entry );
+ return i_ret;
+}
+
+int addons_manager_Remove( addons_manager_t *p_manager, const addon_uuid_t uuid )
+{
+ return addons_manager_Install( p_manager, uuid );
+}
--
1.8.5.3
More information about the vlc-devel
mailing list