/***************************************************************************** * ItemChange: Playlist item change callback *****************************************************************************/ static void playlist_on_current_index_changed(vlc_playlist_t *playlist, ssize_t index, void *userdata) { VLC_UNUSED(index); intf_thread_t *intf = userdata; intf_sys_t *sys = intf->p_sys; sys->b_meta_read = false; vlc_player_t *player = vlc_playlist_GetPlayer(playlist); input_item_t *item = vlc_player_GetCurrentMedia(player); if (!item) return; if (vlc_player_GetVideoTrackCount(player)) { msg_Dbg(intf, "Not an audio-only input, not submitting"); return; } sys->time_total_pauses = 0; time(&sys->p_current_song.date); /* to be sent to last.fm */ sys->p_current_song.i_start = vlc_tick_now(); /* only used locally */ if (input_item_IsPreparsed(item)) ReadMetaData(intf); /* if the input item was not preparsed, we'll do it in player_on_state_changed() * callback, when "state" == VLC_PLAYER_STATE_PLAYING */ }
/* Enqueue an item for preparsing, and play it, if needed */ static void GoAndPreparse( playlist_t *p_playlist, int i_mode, playlist_item_t *p_item ) { playlist_private_t *sys = pl_priv(p_playlist); PL_ASSERT_LOCKED; if( (i_mode & PLAYLIST_GO ) ) { sys->request.b_request = true; sys->request.i_skip = 0; sys->request.p_item = p_item; if( sys->p_input != NULL ) input_Stop( sys->p_input ); vlc_cond_signal( &sys->signal ); } /* Preparse if no artist/album info, and hasn't been preparsed already and if user has some preparsing option (auto-preparse variable) enabled*/ char *psz_artist = input_item_GetArtist( p_item->p_input ); char *psz_album = input_item_GetAlbum( p_item->p_input ); if( sys->b_preparse && !input_item_IsPreparsed( p_item->p_input ) && (EMPTY_STR(psz_artist) || EMPTY_STR(psz_album)) ) libvlc_MetadataRequest( p_playlist->obj.libvlc, p_item->p_input, 0, -1, NULL ); free( psz_artist ); free( psz_album ); }
/* Enqueue an item for preparsing, and play it, if needed */ static void GoAndPreparse( playlist_t *p_playlist, int i_mode, playlist_item_t *p_item ) { PL_ASSERT_LOCKED; if( (i_mode & PLAYLIST_GO ) ) { pl_priv(p_playlist)->request.b_request = true; pl_priv(p_playlist)->request.i_skip = 0; pl_priv(p_playlist)->request.p_item = p_item; if( pl_priv(p_playlist)->p_input ) input_Stop( pl_priv(p_playlist)->p_input, true ); pl_priv(p_playlist)->request.i_status = PLAYLIST_RUNNING; vlc_cond_signal( &pl_priv(p_playlist)->signal ); } /* Preparse if no artist/album info, and hasn't been preparsed allready and if user has some preparsing option (auto-preparse variable) enabled*/ char *psz_artist = input_item_GetArtist( p_item->p_input ); char *psz_album = input_item_GetAlbum( p_item->p_input ); if( pl_priv(p_playlist)->b_auto_preparse && input_item_IsPreparsed( p_item->p_input ) == false && ( EMPTY_STR( psz_artist ) || ( EMPTY_STR( psz_album ) ) ) ) libvlc_MetaRequest( p_playlist->p_libvlc, p_item->p_input ); free( psz_artist ); free( psz_album ); }
/** * @brief Callback for input item preparser to directory monitor */ static void PreparseComplete( const vlc_event_t * p_event, void *p_data ) { int i_ret = VLC_SUCCESS; preparsed_item_t* p_itemobject = (preparsed_item_t*) p_data; monitoring_thread_t *p_mon = p_itemobject->p_mon; media_library_t *p_ml = (media_library_t *)p_mon->p_ml; input_item_t *p_input = (input_item_t*) p_event->p_obj; if( input_item_IsPreparsed( p_input ) ) { if( p_itemobject->b_update ) { //TODO: Perhaps we don't have to load everything? ml_media_t* p_media = GetMedia( p_ml, p_itemobject->i_update_id, ML_MEDIA_SPARSE, true ); CopyInputItemToMedia( p_media, p_input ); i_ret = UpdateMedia( p_ml, p_media ); ml_gc_decref( p_media ); } else i_ret = AddInputItem( p_ml, p_input ); } if( i_ret != VLC_SUCCESS ) msg_Dbg( p_mon, "Item could not be correctly added" " or updated during scan: %s", p_input->psz_uri ); QuerySimple( p_ml, "UPDATE media SET directory_id=%d, timestamp=%d " "WHERE id=%d", p_itemobject->i_dir_id, p_itemobject->i_mtime, GetMediaIdOfURI( p_ml, p_input->psz_uri ) ); vlc_event_detach( &p_input->event_manager, vlc_InputItemPreparsedChanged, PreparseComplete, p_itemobject ); vlc_gc_decref( p_input ); free( p_itemobject->psz_uri ); }
/** * This function preparses an item when needed. */ static void Preparse( playlist_t *p_playlist, input_item_t *p_item ) { vlc_mutex_lock( &p_item->lock ); int i_type = p_item->i_type; vlc_mutex_unlock( &p_item->lock ); if( i_type != ITEM_TYPE_FILE ) { input_item_SetPreparsed( p_item, true ); return; } stats_TimerStart( p_playlist, "Preparse run", STATS_TIMER_PREPARSE ); /* Do not preparse if it is already done (like by playing it) */ if( !input_item_IsPreparsed( p_item ) ) { input_Preparse( VLC_OBJECT(p_playlist), p_item ); input_item_SetPreparsed( p_item, true ); var_SetAddress( p_playlist, "item-change", p_item ); } stats_TimerStop( p_playlist, STATS_TIMER_PREPARSE ); }
/************************************************************************** * Get parsed status for media object. **************************************************************************/ int libvlc_media_is_parsed( libvlc_media_t * p_md ) { assert( p_md ); if( !p_md->p_input_item ) return false; return input_item_IsPreparsed( p_md->p_input_item ); }
/***************************************************************************** * ItemChange: Playlist item change callback *****************************************************************************/ static int ItemChange( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ) { input_thread_t *p_input; intf_thread_t *p_intf = ( intf_thread_t* ) p_data; intf_sys_t *p_sys = p_intf->p_sys; input_item_t *p_item; VLC_UNUSED( p_this ); VLC_UNUSED( psz_var ); VLC_UNUSED( oldval ); VLC_UNUSED( newval ); p_sys->b_state_cb = false; p_sys->b_meta_read = false; p_sys->b_submit = false; p_input = playlist_CurrentInput( pl_Get( p_intf ) ); if( !p_input || p_input->b_dead ) return VLC_SUCCESS; p_item = input_GetItem( p_input ); if( !p_item ) { vlc_object_release( p_input ); return VLC_SUCCESS; } if( var_CountChoices( p_input, "video-es" ) ) { msg_Dbg( p_this, "Not an audio-only input, not submitting"); vlc_object_release( p_input ); return VLC_SUCCESS; } p_sys->time_total_pauses = 0; time( &p_sys->p_current_song.date ); /* to be sent to last.fm */ p_sys->p_current_song.i_start = mdate(); /* only used locally */ var_AddCallback( p_input, "intf-event", PlayingChange, p_intf ); p_sys->b_state_cb = true; if( input_item_IsPreparsed( p_item ) ) ReadMetaData( p_intf ); /* if the input item was not preparsed, we'll do it in PlayingChange() * callback, when "state" == PLAYING_S */ vlc_object_release( p_input ); return VLC_SUCCESS; }
/************************************************************************** * Get duration of media object (in ms) **************************************************************************/ int64_t libvlc_media_get_duration( libvlc_media_t * p_md ) { assert( p_md ); if( !p_md->p_input_item ) { libvlc_printerr( "No input item" ); return -1; } if (!input_item_IsPreparsed( p_md->p_input_item )) return -1; return from_mtime(input_item_GetDuration( p_md->p_input_item )); }
/** * This function preparses an item when needed. */ static void Preparse( playlist_preparser_t *preparser, input_item_t *p_item, input_item_meta_request_option_t i_options ) { vlc_mutex_lock( &p_item->lock ); int i_type = p_item->i_type; bool b_net = p_item->b_net; vlc_mutex_unlock( &p_item->lock ); bool b_preparse = false; switch (i_type) { case ITEM_TYPE_FILE: case ITEM_TYPE_DIRECTORY: case ITEM_TYPE_PLAYLIST: case ITEM_TYPE_NODE: if (!b_net || i_options & META_REQUEST_OPTION_SCOPE_NETWORK) b_preparse = true; break; } /* Do not preparse if it is already done (like by playing it) */ if( b_preparse && !input_item_IsPreparsed( p_item ) ) { input_thread_t *input = input_CreatePreparser( preparser->object, p_item ); if( input == NULL ) return; var_AddCallback( input, "intf-event", InputEvent, &preparser->item_done ); if( input_Start( input ) == VLC_SUCCESS ) vlc_sem_wait( &preparser->item_done ); var_DelCallback( input, "intf-event", InputEvent, &preparser->item_done ); /* Normally, the input is already stopped since we waited for it. But * if the playlist preparser is being deleted, then the input might * still be running. Force it to stop. */ input_Stop( input ); input_Close( input ); var_SetAddress( preparser->object, "item-change", p_item ); } input_item_SetPreparsed( p_item, true ); input_item_SignalPreparseEnded( p_item ); }
/***************************************************************************** * TrackChange: callback on playlist "item-current" *****************************************************************************/ static int TrackChange( intf_thread_t *p_intf ) { intf_sys_t *p_sys = p_intf->p_sys; playlist_t *p_playlist = p_sys->p_playlist; input_thread_t *p_input = NULL; input_item_t *p_item = NULL; if( p_intf->p_sys->b_dead ) return VLC_SUCCESS; if( p_sys->p_input ) { var_DelCallback( p_sys->p_input, "intf-event", AllCallback, p_intf ); var_DelCallback( p_sys->p_input, "can-pause", AllCallback, p_intf ); var_DelCallback( p_sys->p_input, "can-seek", AllCallback, p_intf ); vlc_object_release( p_sys->p_input ); p_sys->p_input = NULL; } p_sys->b_meta_read = false; p_input = playlist_CurrentInput( p_playlist ); if( !p_input ) { return VLC_SUCCESS; } 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; p_sys->p_input = p_input; var_AddCallback( p_input, "intf-event", AllCallback, p_intf ); var_AddCallback( p_input, "can-pause", AllCallback, p_intf ); var_AddCallback( p_input, "can-seek", AllCallback, p_intf ); return VLC_SUCCESS; }
/***************************************************************************** * ItemChange: Playlist item change callback *****************************************************************************/ static int ItemChange(vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data) { input_thread_t *p_input; intf_thread_t *p_intf = (intf_thread_t*) p_data; intf_sys_t *p_sys = p_intf->p_sys; input_item_t *p_item; VLC_UNUSED(p_this); VLC_UNUSED(psz_var); VLC_UNUSED(oldval); VLC_UNUSED(newval); p_sys->b_state_cb = false; p_sys->b_meta_read = false; p_sys->b_submit = false; p_input = playlist_CurrentInput(pl_Get(p_intf)); if (!p_input || p_input->b_dead) return VLC_SUCCESS; p_item = input_GetItem(p_input); if (!p_item) { vlc_object_release(p_input); return VLC_SUCCESS; } p_sys->time_total_pauses = 0; time(&p_sys->p_current_item.date); /* to be sent to upstream */ p_sys->p_current_item.i_start = mdate(); /* used to calculate run * time as fallback */ var_AddCallback(p_input, "intf-event", PlayingChange, p_intf); p_sys->b_state_cb = true; if (input_item_IsPreparsed(p_item)) ReadMetaData(p_intf); vlc_object_release(p_input); return VLC_SUCCESS; }
/** * This function preparses an item when needed. */ static void Preparse( vlc_object_t *obj, input_item_t *p_item ) { vlc_mutex_lock( &p_item->lock ); int i_type = p_item->i_type; vlc_mutex_unlock( &p_item->lock ); if( i_type != ITEM_TYPE_FILE ) { input_item_SetPreparsed( p_item, true ); return; } /* Do not preparse if it is already done (like by playing it) */ if( !input_item_IsPreparsed( p_item ) ) { input_Preparse( obj, p_item ); input_item_SetPreparsed( p_item, true ); var_SetAddress( obj, "item-change", p_item ); } }
/***************************************************************************** * TrackChange: callback on playlist "item-current" *****************************************************************************/ static int TrackChange( intf_thread_t *p_intf ) { 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; if( p_intf->p_sys->b_dead ) return VLC_SUCCESS; p_sys->b_meta_read = false; p_playlist = pl_Hold( p_intf ); p_input = playlist_CurrentInput( p_playlist ); if( !p_input ) { pl_Release( p_intf ); return VLC_SUCCESS; } 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", AllCallback, p_intf ); vlc_object_release( p_input ); return VLC_SUCCESS; }
static int InputEvent( vlc_object_t* p_this, const char* var, vlc_value_t oldval, vlc_value_t val, void* p_data) { input_thread_t* const p_input = (input_thread_t*)p_this; intf_thread_t* const p_intf = (intf_thread_t*)p_data; intf_sys_t* const p_sys = p_intf->p_sys; if (!p_sys->cad_window) return VLC_SUCCESS; switch (val.i_int) { case INPUT_EVENT_ITEM_META: { input_item_t* p_item = input_GetItem(p_input); if (input_item_IsPreparsed(p_item)) { PostMessage(p_sys->cad_window, WM_USER, 0, IPC_TRACK_CHANGED_NOTIFICATION); } break; } case INPUT_EVENT_STATE: { const int input_state = var_GetInteger(p_input, "state"); const int state = input_state == PLAYING_S ? 1 : input_state == PAUSE_S ? 2 : 0; PostMessage(p_sys->cad_window, WM_USER, state, IPC_STATE_CHANGED_NOTIFICATION); break; } } return VLC_SUCCESS; }
static int vlclua_input_item_is_preparsed( lua_State *L ) { lua_pushboolean( L, input_item_IsPreparsed( vlclua_input_item_get_internal( L ) ) ); return 1; }