📄 dbus.c
字号:
var_DelCallback( p_playlist, "item-append", TrackListChangeEmit, p_intf ); var_DelCallback( p_playlist, "item-deleted", TrackListChangeEmit, p_intf ); var_DelCallback( p_playlist, "random", StatusChangeEmit, p_intf ); var_DelCallback( p_playlist, "repeat", StatusChangeEmit, p_intf ); var_DelCallback( p_playlist, "loop", StatusChangeEmit, p_intf ); p_input = p_playlist->p_input; if ( p_input ) { vlc_object_yield( p_input ); var_DelCallback( p_input, "state", StateChange, p_intf ); vlc_object_release( p_input ); } PL_UNLOCK; pl_Release( p_intf ); dbus_connection_unref( p_intf->p_sys->p_conn ); free( p_intf->p_sys );}/***************************************************************************** * Run: main loop *****************************************************************************/static void Run ( intf_thread_t *p_intf ){ while( !intf_ShouldDie( p_intf ) ) { msleep( INTF_IDLE_SLEEP ); dbus_connection_read_write_dispatch( p_intf->p_sys->p_conn, 0 ); }}/****************************************************************************** * CapsChange: player capabilities change signal *****************************************************************************/DBUS_SIGNAL( CapsChangeSignal ){ SIGNAL_INIT( "CapsChange" ); OUT_ARGUMENTS; ADD_INT32( &((intf_thread_t*)p_data)->p_sys->i_caps ); SIGNAL_SEND;}/****************************************************************************** * TrackListChange: tracklist order / length change signal *****************************************************************************/DBUS_SIGNAL( TrackListChangeSignal ){ /* emit the new tracklist lengh */ SIGNAL_INIT("TrackListChange"); OUT_ARGUMENTS; playlist_t *p_playlist = pl_Yield( (vlc_object_t*) p_data ); dbus_int32_t i_elements = p_playlist->current.i_size; pl_Release( (vlc_object_t*) p_data ); ADD_INT32( &i_elements ); SIGNAL_SEND;}/***************************************************************************** * TrackListChangeEmit: Emits the TrackListChange signal *****************************************************************************//* FIXME: It is not called on tracklist reordering */static int TrackListChangeEmit( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ VLC_UNUSED(oldval); intf_thread_t *p_intf = p_data; if( !strcmp( psz_var, "item-append" ) || !strcmp( psz_var, "item-remove" ) ) { /* don't signal when items are added/removed in p_category */ playlist_t *p_playlist = (playlist_t*)p_this; playlist_add_t *p_add = newval.p_address; playlist_item_t *p_item; p_item = playlist_ItemGetById( p_playlist, p_add->i_node, pl_Locked ); assert( p_item ); while( p_item->p_parent ) p_item = p_item->p_parent; if( p_item == p_playlist->p_root_category ) return VLC_SUCCESS; } if( p_intf->b_dead ) return VLC_SUCCESS; UpdateCaps( p_intf, true ); TrackListChangeSignal( p_intf->p_sys->p_conn, p_data ); return VLC_SUCCESS;}/***************************************************************************** * TrackChange: Playlist item change callback *****************************************************************************/DBUS_SIGNAL( TrackChangeSignal ){ /* emit the metadata of the new item */ SIGNAL_INIT( "TrackChange" ); OUT_ARGUMENTS; input_item_t *p_item = (input_item_t*) p_data; GetInputMeta ( p_item, &args ); SIGNAL_SEND;}/***************************************************************************** * StatusChange: Player status change signal *****************************************************************************/DBUS_SIGNAL( StatusChangeSignal ){ /* send the updated status info on the bus */ SIGNAL_INIT( "StatusChange" ); OUT_ARGUMENTS; /* we're called from a callback of input_thread_t, so it can not be * destroyed before we return */ MarshalStatus( (intf_thread_t*) p_data, &args, false ); SIGNAL_SEND;}/***************************************************************************** * StateChange: callback on input "state" *****************************************************************************/static int StateChange( vlc_object_t *p_this, const char* psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ VLC_UNUSED(psz_var); VLC_UNUSED(oldval); intf_thread_t *p_intf = ( intf_thread_t* ) p_data; intf_sys_t *p_sys = p_intf->p_sys; if( p_intf->b_dead ) return VLC_SUCCESS; UpdateCaps( p_intf, true ); if( !p_sys->b_meta_read && newval.i_int == PLAYING_S ) { input_item_t *p_item = input_GetItem( (input_thread_t*)p_this ); if( p_item ) { p_sys->b_meta_read = true; TrackChangeSignal( p_sys->p_conn, p_item ); } } if( newval.i_int == PLAYING_S || newval.i_int == PAUSE_S || newval.i_int == STOP_S || newval.i_int == END_S ) { StatusChangeSignal( p_sys->p_conn, (void*) p_intf ); } return VLC_SUCCESS;}/***************************************************************************** * StatusChangeEmit: Emits the StatusChange signal *****************************************************************************/static int StatusChangeEmit( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ VLC_UNUSED(p_this); VLC_UNUSED(psz_var); VLC_UNUSED(oldval); VLC_UNUSED(newval); intf_thread_t *p_intf = p_data; if( p_intf->b_dead ) return VLC_SUCCESS; UpdateCaps( p_intf, false ); StatusChangeSignal( p_intf->p_sys->p_conn, p_data ); return VLC_SUCCESS;}/***************************************************************************** * TrackChange: callback on playlist "playlist-current" *****************************************************************************/static int TrackChange( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ intf_thread_t *p_intf = ( intf_thread_t* ) p_data; intf_sys_t *p_sys = p_intf->p_sys; playlist_t *p_playlist; input_thread_t *p_input = NULL; input_item_t *p_item = NULL; VLC_UNUSED( p_this ); VLC_UNUSED( psz_var ); VLC_UNUSED( oldval ); VLC_UNUSED( newval ); if( p_intf->b_dead ) return VLC_SUCCESS; p_sys->b_meta_read = false; p_playlist = pl_Yield( p_intf ); p_input = p_playlist->p_input; if( !p_input ) { PL_UNLOCK; pl_Release( p_intf ); return VLC_SUCCESS; } vlc_object_yield( p_input ); pl_Release( p_intf ); p_item = input_GetItem( p_input ); if( !p_item ) { vlc_object_release( p_input ); return VLC_EGENERIC; } if( input_item_IsPreparsed( p_item ) ) { p_sys->b_meta_read = true; TrackChangeSignal( p_sys->p_conn, p_item ); } var_AddCallback( p_input, "state", StateChange, p_intf ); vlc_object_release( p_input ); return VLC_SUCCESS;}/***************************************************************************** * UpdateCaps: update p_sys->i_caps ****************************************************************************/static int UpdateCaps( intf_thread_t* p_intf, bool b_playlist_locked ){ intf_sys_t* p_sys = p_intf->p_sys; dbus_int32_t i_caps = CAPS_CAN_HAS_TRACKLIST; playlist_t* p_playlist = pl_Yield( p_intf ); if( !b_playlist_locked ) PL_LOCK; if( p_playlist->current.i_size > 0 ) i_caps |= CAPS_CAN_PLAY | CAPS_CAN_GO_PREV | CAPS_CAN_GO_NEXT; if( p_playlist->p_input ) { /* XXX: if UpdateCaps() is called too early, these are * unconditionnaly true */ if( var_GetBool( p_playlist->p_input, "can-pause" ) ) i_caps |= CAPS_CAN_PAUSE; if( var_GetBool( p_playlist->p_input, "seekable" ) ) i_caps |= CAPS_CAN_SEEK; } if( !b_playlist_locked ) PL_UNLOCK; pl_Release( p_intf ); if( p_sys->b_meta_read ) i_caps |= CAPS_CAN_PROVIDE_METADATA; if( i_caps != p_intf->p_sys->i_caps ) { p_sys->i_caps = i_caps; CapsChangeSignal( p_intf->p_sys->p_conn, (vlc_object_t*)p_intf ); } return VLC_SUCCESS;}/***************************************************************************** * GetInputMeta: Fill a DBusMessage with the given input item metadata *****************************************************************************/#define ADD_META( entry, type, data ) \ if( data ) { \ dbus_message_iter_open_container( &dict, DBUS_TYPE_DICT_ENTRY, \ NULL, &dict_entry ); \ dbus_message_iter_append_basic( &dict_entry, DBUS_TYPE_STRING, \ &ppsz_meta_items[entry] ); \ dbus_message_iter_open_container( &dict_entry, DBUS_TYPE_VARIANT, \ type##_AS_STRING, &variant ); \ dbus_message_iter_append_basic( &variant, \ type, \ & data ); \ dbus_message_iter_close_container( &dict_entry, &variant ); \ dbus_message_iter_close_container( &dict, &dict_entry ); }#define ADD_VLC_META_STRING( entry, item ) \ { \ char * psz = input_item_Get##item( p_input );\ ADD_META( entry, DBUS_TYPE_STRING, \ psz ); \ free( psz ); \ }static int GetInputMeta( input_item_t* p_input, DBusMessageIter *args ){ DBusMessageIter dict, dict_entry, variant; /* We need the track length to be expressed in milli-seconds * instead of µ-seconds */ dbus_int64_t i_length = ( input_item_GetDuration( p_input ) / 1000 ); const char* ppsz_meta_items[] = { "title", "artist", "genre", "copyright", "album", "tracknum", "description", "rating", "date", "setting", "url", "language", "nowplaying", "publisher", "encodedby", "arturl", "trackid", "status", "location", "length", "video-codec", "audio-codec", "video-bitrate", "audio-bitrate", "audio-samplerate" }; dbus_message_iter_open_container( args, DBUS_TYPE_ARRAY, "{sv}", &dict ); ADD_VLC_META_STRING( 0, Title ); ADD_VLC_META_STRING( 1, Artist ); ADD_VLC_META_STRING( 2, Genre ); ADD_VLC_META_STRING( 3, Copyright ); ADD_VLC_META_STRING( 4, Album ); ADD_VLC_META_STRING( 5, TrackNum ); ADD_VLC_META_STRING( 6, Description ); ADD_VLC_META_STRING( 7, Rating ); ADD_VLC_META_STRING( 8, Date ); ADD_VLC_META_STRING( 9, Setting ); ADD_VLC_META_STRING( 10, URL ); ADD_VLC_META_STRING( 11, Language ); ADD_VLC_META_STRING( 12, NowPlaying ); ADD_VLC_META_STRING( 13, Publisher ); ADD_VLC_META_STRING( 14, EncodedBy ); ADD_VLC_META_STRING( 15, ArtURL ); ADD_VLC_META_STRING( 16, TrackID ); vlc_mutex_lock( &p_input->lock ); if( p_input->p_meta ) ADD_META( 17, DBUS_TYPE_INT32, p_input->p_meta->i_status ); vlc_mutex_unlock( &p_input->lock ); ADD_VLC_META_STRING( 18, URI ); ADD_META( 19, DBUS_TYPE_INT64, i_length ); dbus_message_iter_close_container( args, &dict ); return VLC_SUCCESS;}#undef ADD_META#undef ADD_VLC_META_STRING/***************************************************************************** * MarshalStatus: Fill a DBusMessage with the current player status *****************************************************************************/static int MarshalStatus( intf_thread_t* p_intf, DBusMessageIter* args, bool lock ){ /* This is NOT the right way to do that, it would be better to sore the status information in p_sys and update it on change, thus avoiding a long lock */ DBusMessageIter status; dbus_int32_t i_state, i_random, i_repeat, i_loop; vlc_value_t val; playlist_t* p_playlist = NULL; input_thread_t* p_input = NULL; p_playlist = pl_Yield( p_intf ); if( lock ) PL_LOCK; i_state = 2; p_input = p_playlist->p_input; if( p_input ) { var_Get( p_input, "state", &val ); if( val.i_int >= END_S ) i_state = 2; else if( val.i_int == PAUSE_S ) i_state = 1; else if( val.i_int <= PLAYING_S ) i_state = 0; } i_random = var_CreateGetBool( p_playlist, "random" ); i_repeat = var_CreateGetBool( p_playlist, "repeat" ); i_loop = var_CreateGetBool( p_playlist, "loop" ); if( lock ) PL_UNLOCK; pl_Release( p_intf ); dbus_message_iter_open_container( args, DBUS_TYPE_STRUCT, NULL, &status ); dbus_message_iter_append_basic( &status, DBUS_TYPE_INT32, &i_state ); dbus_message_iter_append_basic( &status, DBUS_TYPE_INT32, &i_random ); dbus_message_iter_append_basic( &status, DBUS_TYPE_INT32, &i_repeat ); dbus_message_iter_append_basic( &status, DBUS_TYPE_INT32, &i_loop ); dbus_message_iter_close_container( args, &status ); return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -