#include "assert.h"
#include <vlc_input.h>
+#include <vlc_events.h>
/* Functions to register */
static const luaL_Reg p_reg[] =
* Extensions capabilities
* Note: #define and ppsz_capabilities must be in sync
*/
-#define EXT_HAS_MENU (1 << 0)
-#define EXT_TRIGGER_ONLY (1 << 1)
-#define EXT_INPUT_LISTENER (1 << 2)
+#define EXT_HAS_MENU (1 << 0) ///< Hook: menu
+#define EXT_TRIGGER_ONLY (1 << 1) ///< Hook: trigger. Not activable
+#define EXT_INPUT_LISTENER (1 << 2) ///< Hook: input_changed
+#define EXT_META_LISTENER (1 << 3) ///< Hook: meta_changed
const char* const ppsz_capabilities[] = {
"menu",
"trigger",
"input-listener",
+ "meta-listener",
NULL
};
vlc_value_t newval,
void *p_data );
+/* Input item callback: vlc_InputItemMetaChanged */
+static void inputItemMetaChanged( const vlc_event_t *p_event,
+ void *data );
+
/**
* Module entry-point
// Change input
input_thread_t *old = p_ext->p_sys->p_input;
+ input_item_t *p_item;
if( old )
+ {
+ // Untrack meta fetched events
+ if( p_ext->p_sys->i_capabilities & EXT_META_LISTENER )
+ {
+ p_item = input_GetItem( old );
+ vlc_event_detach( &p_item->event_manager,
+ vlc_InputItemMetaChanged,
+ inputItemMetaChanged,
+ p_ext );
+ vlc_gc_decref( p_item );
+ }
vlc_object_release( old );
+ }
+
p_ext->p_sys->p_input = p_input ? vlc_object_hold( p_input )
: p_input;
// Tell the script the input changed
if( p_ext->p_sys->i_capabilities & EXT_INPUT_LISTENER )
- PushCommand( p_ext, CMD_SET_INPUT );
+ {
+ PushCommandUnique( p_ext, CMD_SET_INPUT );
+ }
+
+ // Track meta fetched events
+ if( p_ext->p_sys->p_input &&
+ p_ext->p_sys->i_capabilities & EXT_META_LISTENER )
+ {
+ p_item = input_GetItem( p_ext->p_sys->p_input );
+ vlc_gc_incref( p_item );
+ vlc_event_attach( &p_item->event_manager,
+ vlc_InputItemMetaChanged,
+ inputItemMetaChanged,
+ p_ext );
+ }
UnlockExtension( p_ext );
break;
}
default:
- msg_Err( p_mgr, "Control '%d' not yet implemented in Extension",
- i_control );
+ msg_Warn( p_mgr, "Control '%d' not yet implemented in Extension",
+ i_control );
return VLC_EGENERIC;
}
if( !p_ext->p_sys->L )
return VLC_SUCCESS;
+ // Unset and release input objects
+ if( p_ext->p_sys->p_input )
+ {
+ if( p_ext->p_sys->i_capabilities & EXT_META_LISTENER )
+ {
+ // Release item
+ input_item_t *p_item = input_GetItem( p_ext->p_sys->p_input );
+ vlc_gc_decref( p_item );
+ }
+ vlc_object_release( p_ext->p_sys->p_input );
+ }
+
int i_ret = lua_ExecuteFunction( p_mgr, p_ext, "deactivate" );
/* Clear Lua State */
PushCommand( p_ext, CMD_CLICK, p_widget );
break;
case EXTENSION_EVENT_CLOSE:
- PushCommand( p_ext, CMD_CLOSE );
+ PushCommandUnique( p_ext, CMD_CLOSE );
break;
default:
msg_Dbg( p_this, "Received unknown UI event %d, discarded",
return VLC_SUCCESS;
}
+/** Callback on vlc_InputItemMetaChanged event
+ **/
+static void inputItemMetaChanged( const vlc_event_t *p_event,
+ void *data )
+{
+ assert( p_event && p_event->type == vlc_InputItemMetaChanged );
+
+ extension_t *p_ext = ( extension_t* ) data;
+ assert( p_ext != NULL );
+
+ PushCommandUnique( p_ext, CMD_UPDATE_META );
+}
+
/* Lock this extension. Can fail. */
bool LockExtension( extension_t *p_ext )
{
#define CMD_CLICK 4 /* Arg1 = extension_widget_t* */
#define CMD_CLOSE 5
#define CMD_SET_INPUT 6 /* No arg. Just signal current input changed */
+#define CMD_UPDATE_META 7 /* No arg. Just signal current input item meta
+ * changed */
struct extensions_manager_sys_t
{
bool IsActivated( extensions_manager_t *p_mgr, extension_t * );
int Deactivate( extensions_manager_t *p_mgr, extension_t * );
void WaitForDeactivation( extension_t *p_ext );
-int PushCommand( extension_t *p_ext, int i_command, ... );
+int __PushCommand( extension_t *p_ext, bool b_unique,
+ int i_command, ... );
+#define PushCommand( ext, cmd, ... ) \
+ __PushCommand( ext, false, cmd, ## __VA_ARGS__ )
+#define PushCommandUnique( ext, cmd, ... ) \
+ __PushCommand( ext, true, cmd, ## __VA_ARGS__ )
bool LockExtension( extension_t *p_ext );
void UnlockExtension( extension_t *p_ext );
case CMD_TRIGGERMENU:
free( command->data[0] ); // Arg1 is int*, to free
break;
+
+ default:
+ break;
}
free( command );
FreeCommands( next );
}
/** Push a UI command */
-int PushCommand( extension_t *p_ext,
- int i_command,
- ... )
+int __PushCommand( extension_t *p_ext,
+ bool b_unique,
+ int i_command,
+ ... )
{
vlc_mutex_lock( &p_ext->p_sys->command_lock );
case CMD_CLICK:
cmd->data[0] = va_arg( args, void* );
break;
- case CMD_CLOSE:
- // Nothing to do here
- break;
case CMD_TRIGGERMENU:
{
int *pi = malloc( sizeof( int ) );
cmd->data[0] = pi;
}
break;
+ case CMD_CLOSE:
+ case CMD_SET_INPUT:
+ case CMD_UPDATE_META:
+ // Nothing to do here
+ break;
default:
msg_Dbg( p_ext->p_sys->p_mgr,
"Unknown command send to extension: %d", i_command );
}
else
{
+ bool b_skip = false;
while( last->next != NULL )
{
- last = last->next;
+ if( b_unique && last->i_command == i_command )
+ {
+ // Do not push this 'unique' command a second time
+ b_skip = true;
+ break;
+ }
+ else
+ {
+ last = last->next;
+ }
}
- last->next = cmd;
+ if( !b_skip )
+ last->next = cmd;
}
vlc_cond_signal( &p_ext->p_sys->wait );
break;
}
+ case CMD_UPDATE_META:
+ {
+ lua_ExecuteFunction( p_mgr, p_ext, "meta_changed" );
+ break;
+ }
+
default:
{
msg_Dbg( p_mgr, "Unknown command in extension command queue: %d",