/************************************************************************** * new (Public) * * Init an object. **************************************************************************/ libvlc_media_discoverer_t * libvlc_media_discoverer_new_from_name( libvlc_instance_t * p_inst, const char * psz_name, libvlc_exception_t * p_e ) { libvlc_media_discoverer_t * p_mdis; p_mdis = malloc(sizeof(libvlc_media_discoverer_t)); if( !p_mdis ) { libvlc_exception_raise( p_e, "Not enough memory" ); return NULL; } p_mdis->p_libvlc_instance = p_inst; p_mdis->p_mlist = libvlc_media_list_new( p_inst, NULL ); p_mdis->p_mlist->b_read_only = true; p_mdis->running = false; vlc_dictionary_init( &p_mdis->catname_to_submedialist, 0 ); p_mdis->p_event_manager = libvlc_event_manager_new( p_mdis, p_inst, NULL ); libvlc_event_manager_register_event_type( p_mdis->p_event_manager, libvlc_MediaDiscovererStarted, NULL ); libvlc_event_manager_register_event_type( p_mdis->p_event_manager, libvlc_MediaDiscovererEnded, NULL ); p_mdis->p_sd = services_discovery_Create( (vlc_object_t*)p_inst->p_libvlc_int, psz_name ); if( !p_mdis->p_sd ) { libvlc_exception_raise( p_e, "Can't find the services_discovery module named '%s'", psz_name ); libvlc_media_list_release( p_mdis->p_mlist ); free( p_mdis ); return NULL; } vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemAdded, services_discovery_item_added, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemRemoved, services_discovery_item_removed, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryStarted, services_discovery_started, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryEnded, services_discovery_ended, p_mdis ); services_discovery_Start( p_mdis->p_sd ); /* Here we go */ return p_mdis; }
int playlist_MLLoad( playlist_t *p_playlist ) { input_item_t *p_input; char *psz_datadir = config_GetUserDir( VLC_DATA_DIR ); if( !psz_datadir ) /* XXX: This should never happen */ { msg_Err( p_playlist, "no data directory, cannot load media library") ; return VLC_EGENERIC; } char *psz_file; if( asprintf( &psz_file, "%s" DIR_SEP "ml.xspf", psz_datadir ) == -1 ) psz_file = NULL; free( psz_datadir ); if( psz_file == NULL ) return VLC_ENOMEM; /* loosy check for media library file */ struct stat st; if( vlc_stat( psz_file, &st ) ) { free( psz_file ); return VLC_EGENERIC; } char *psz_uri = make_URI( psz_file, "file/xspf-open" ); free( psz_file ); if( psz_uri == NULL ) return VLC_ENOMEM; const char *const options[1] = { "meta-file", }; /* that option has to be cleaned in input_item_subitem_tree_added() */ /* vlc_gc_decref() in the same function */ p_input = input_item_NewExt( p_playlist, psz_uri, _("Media Library"), 1, options, VLC_INPUT_OPTION_TRUSTED, -1 ); free( psz_uri ); if( p_input == NULL ) return VLC_EGENERIC; PL_LOCK; if( p_playlist->p_media_library->p_input ) vlc_gc_decref( p_playlist->p_media_library->p_input ); p_playlist->p_media_library->p_input = p_input; vlc_event_attach( &p_input->event_manager, vlc_InputItemSubItemTreeAdded, input_item_subitem_tree_added, p_playlist ); pl_priv(p_playlist)->b_doing_ml = true; PL_UNLOCK; stats_TimerStart( p_playlist, "ML Load", STATS_TIMER_ML_LOAD ); input_Read( p_playlist, p_input ); stats_TimerStop( p_playlist,STATS_TIMER_ML_LOAD ); PL_LOCK; pl_priv(p_playlist)->b_doing_ml = false; PL_UNLOCK; vlc_event_detach( &p_input->event_manager, vlc_InputItemSubItemTreeAdded, input_item_subitem_tree_added, p_playlist ); return VLC_SUCCESS; }
/************************************************************************** * new (Public) * * Init an object. **************************************************************************/ libvlc_media_discoverer_t * libvlc_media_discoverer_new_from_name( libvlc_instance_t * p_inst, const char * psz_name ) { libvlc_media_discoverer_t * p_mdis; p_mdis = malloc(sizeof(libvlc_media_discoverer_t)); if( unlikely(!p_mdis) ) { libvlc_printerr( "Not enough memory" ); return NULL; } p_mdis->p_libvlc_instance = p_inst; p_mdis->p_mlist = libvlc_media_list_new( p_inst ); p_mdis->p_mlist->b_read_only = true; p_mdis->running = false; vlc_dictionary_init( &p_mdis->catname_to_submedialist, 0 ); p_mdis->p_event_manager = libvlc_event_manager_new( p_mdis, p_inst ); if( unlikely(p_mdis->p_event_manager == NULL) ) { free( p_mdis ); return NULL; } libvlc_event_manager_register_event_type( p_mdis->p_event_manager, libvlc_MediaDiscovererStarted ); libvlc_event_manager_register_event_type( p_mdis->p_event_manager, libvlc_MediaDiscovererEnded ); p_mdis->p_sd = vlc_sd_Create( (vlc_object_t*)p_inst->p_libvlc_int, psz_name ); if( unlikely(p_mdis->p_sd == NULL) ) { libvlc_printerr( "%s: no such discovery module found", psz_name ); libvlc_media_list_release( p_mdis->p_mlist ); libvlc_event_manager_release( p_mdis->p_event_manager ); free( p_mdis ); return NULL; } vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemAdded, services_discovery_item_added, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemRemoved, services_discovery_item_removed, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryStarted, services_discovery_started, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryEnded, services_discovery_ended, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemRemoveAll, services_discovery_removeall, p_mdis ); /* Here we go */ if( !vlc_sd_Start( p_mdis->p_sd ) ) { libvlc_printerr( "%s: internal module error", p_mdis->p_sd->psz_name ); libvlc_media_list_release( p_mdis->p_mlist ); libvlc_event_manager_release( p_mdis->p_event_manager ); free( p_mdis ); return NULL; } return p_mdis; }
/** * @brief Scan files in a particular directory */ static void ScanFiles( monitoring_thread_t *p_mon, int i_dir_id, bool b_recursive, stat_list_t *stparent ) { int i_rows, i_cols, i_dir_content, i, i_mon_rows, i_mon_cols; char **ppsz_monitored_files; char **pp_results, *psz_dir; char **pp_dir_content; bool *pb_processed; input_item_t *p_input; struct stat s_stat; media_library_t *p_ml = (media_library_t *)p_mon->p_ml; Query( p_ml, &pp_results, &i_rows, &i_cols, "SELECT uri AS directory_uri FROM directories WHERE id = '%d'", i_dir_id ); if( i_rows < 1 ) { msg_Dbg( p_mon, "query returned no directory for dir_id: %d (%s:%d)", i_dir_id, __FILE__, __LINE__ ); return; } psz_dir = strdup( pp_results[1] ); FreeSQLResult( p_ml, pp_results ); struct stat_list_t stself; if( vlc_stat( psz_dir, &stself.st ) == -1 ) { msg_Err( p_ml, "Cannot stat `%s': %m", psz_dir ); free( psz_dir ); return; } #ifndef WIN32 for( stat_list_t *stats = stparent; stats != NULL; stats = stats->parent ) { if( ( stself.st.st_ino == stats->st.st_ino ) && ( stself.st.st_dev == stats->st.st_dev ) ) { msg_Warn( p_ml, "Ignoring infinitely recursive directory `%s'", psz_dir ); free( psz_dir ); return; } } #else /* Windows has st_dev (driver letter - 'A'), but it zeroes st_ino, * so that the test above will always incorrectly succeed. * Besides, Windows does not have dirfd(). */ #endif stself.parent = stparent; QuerySimple( p_ml, "UPDATE directories SET timestamp=%d WHERE id = %d", stself.st.st_mtime, i_dir_id ); Query( p_ml, &ppsz_monitored_files, &i_mon_rows, &i_mon_cols, "SELECT id AS media_id, timestamp AS media_ts, uri AS media_uri " "FROM media WHERE directory_id = %d", i_dir_id ); pb_processed = malloc(sizeof(bool) * i_mon_rows); for( i = 0; i < i_mon_rows ; i++) pb_processed[i] = false; i_dir_content = vlc_scandir( psz_dir, &pp_dir_content, NULL, Sort ); if( i_dir_content == -1 ) { msg_Err( p_mon, "Cannot read `%s': %m", psz_dir ); free( pb_processed ); free( psz_dir ); return; } else if( i_dir_content == 0 ) { msg_Dbg( p_mon, "Nothing in directory `%s'", psz_dir ); free( pb_processed ); free( psz_dir ); return; } for( i = 0; i < i_dir_content; i++ ) { const char *psz_entry = pp_dir_content[i]; if( psz_entry[0] != '.' ) { /* 7 is the size of "file://" */ char psz_uri[strlen(psz_dir) + strlen(psz_entry) + 2 + 7]; sprintf( psz_uri, "%s/%s", psz_dir, psz_entry ); if( vlc_stat( psz_uri, &s_stat ) == -1 ) { msg_Err( p_mon, "%s: %m", psz_uri ); free( pb_processed ); free( psz_dir ); return; } if( S_ISREG( s_stat.st_mode ) ) { const char *psz_dot = strrchr( psz_uri, '.' ); if( psz_dot++ && *psz_dot ) { int i_is_media = 0; for( int a = 0; ppsz_MediaExtensions[a]; a++ ) { if( !strcasecmp( psz_dot, ppsz_MediaExtensions[a] ) ) { i_is_media = 1; break; } } if( !i_is_media ) { msg_Dbg( p_mon, "ignoring file %s", psz_uri ); continue; } } char * psz_tmp = encode_URI_component( psz_uri ); char * psz_encoded_uri = ( char * )calloc( strlen( psz_tmp ) + 9, 1 ); strcpy( psz_encoded_uri, "file:///" ); strcat( psz_encoded_uri, psz_tmp ); free( psz_tmp ); /* Check if given media is already in DB and it has been updated */ bool b_skip = false; bool b_update = false; int j = 1; for( j = 1; j <= i_mon_rows; j++ ) { if( strcasecmp( ppsz_monitored_files[ j * i_mon_cols + 2 ], psz_encoded_uri ) != 0 ) continue; b_update = true; pb_processed[ j - 1 ] = true; if( atoi( ppsz_monitored_files[ j * i_mon_cols + 1 ] ) < s_stat.st_mtime ) { b_skip = false; break; } else { b_skip = true; break; } } msg_Dbg( p_ml , "Checking if %s is in DB. Found: %d", psz_encoded_uri, b_skip? 1 : 0 ); if( b_skip ) continue; p_input = input_item_New( psz_encoded_uri, psz_entry ); playlist_t* p_pl = pl_Get( p_mon ); preparsed_item_t* p_itemobject; p_itemobject = malloc( sizeof( preparsed_item_t ) ); p_itemobject->i_dir_id = i_dir_id; p_itemobject->psz_uri = psz_encoded_uri; p_itemobject->i_mtime = s_stat.st_mtime; p_itemobject->p_mon = p_mon; p_itemobject->b_update = b_update; p_itemobject->i_update_id = b_update ? atoi( ppsz_monitored_files[ j * i_mon_cols + 0 ] ) : 0 ; vlc_event_manager_t *p_em = &p_input->event_manager; vlc_event_attach( p_em, vlc_InputItemPreparsedChanged, PreparseComplete, p_itemobject ); playlist_PreparseEnqueue( p_pl, p_input ); } else if( S_ISDIR( s_stat.st_mode ) && b_recursive ) { Query( p_ml, &pp_results, &i_rows, &i_cols, "SELECT id AS directory_id FROM directories " "WHERE uri=%Q", psz_uri ); FreeSQLResult( p_ml, pp_results ); if( i_rows <= 0 ) { msg_Dbg( p_mon, "New directory `%s' in dir of id %d", psz_uri, i_dir_id ); QuerySimple( p_ml, "INSERT INTO directories (uri, timestamp, " "recursive) VALUES(%Q, 0, 1)", psz_uri ); // We get the id of the directory we've just added Query( p_ml, &pp_results, &i_rows, &i_cols, "SELECT id AS directory_id FROM directories WHERE uri=%Q", psz_uri ); if( i_rows <= 0 ) { msg_Err( p_mon, "Directory `%s' was not sucessfully" " added to the database", psz_uri ); FreeSQLResult( p_ml, pp_results ); continue; } ScanFiles( p_mon, atoi( pp_results[1] ), b_recursive, &stself ); FreeSQLResult( p_ml, pp_results ); } } } } vlc_array_t* delete_ids = vlc_array_new(); for( i = 0; i < i_mon_rows; i++ ) { if( !pb_processed[i] ) { /* This file doesn't exist anymore. Let's...urm...delete it. */ ml_element_t* find = ( ml_element_t* ) calloc( 1, sizeof( ml_element_t ) ); find->criteria = ML_ID; find->value.i = atoi( ppsz_monitored_files[ (i + 1) * i_mon_cols ] ); vlc_array_append( delete_ids, find ); } } /* Delete the unfound media */ if( Delete( p_ml, delete_ids ) != VLC_SUCCESS ) msg_Dbg( p_ml, "Something went wrong in multi delete" ); for( i = 0; i < vlc_array_count( delete_ids ); i++ ) { free( vlc_array_item_at_index( delete_ids, i ) ); } vlc_array_destroy( delete_ids ); FreeSQLResult( p_ml, ppsz_monitored_files ); for( i = 0; i < i_dir_content; i++ ) free( pp_dir_content[i] ); free( pp_dir_content ); free( psz_dir ); free( pb_processed ); }
int playlist_MLLoad( playlist_t *p_playlist ) { char *psz_datadir; char *psz_uri = NULL; input_item_t *p_input; if( !config_GetInt( p_playlist, "media-library") ) return VLC_SUCCESS; psz_datadir = config_GetUserDir( VLC_DATA_DIR ); if( !psz_datadir ) /* XXX: This should never happen */ { msg_Err( p_playlist, "no data directory, cannot load media library") ; return VLC_EGENERIC; } if( asprintf( &psz_uri, "%s" DIR_SEP "ml.xspf", psz_datadir ) != -1 ) { /* loosy check for media library file */ struct stat st; int ret = utf8_stat( psz_uri , &st ); free( psz_uri ); if( ret ) { free( psz_datadir ); return VLC_EGENERIC; } } psz_uri = make_URI( psz_datadir ); free( psz_datadir ); psz_datadir = psz_uri; if( psz_datadir == NULL ) return VLC_EGENERIC; /* Force XSPF demux (psz_datadir was a path, now it is a file URI) */ if( asprintf( &psz_uri, "file/xspf-open%s/ml.xspf", psz_datadir+4 ) == -1 ) psz_uri = NULL; free( psz_datadir ); psz_datadir = NULL; if( psz_uri == NULL ) return VLC_ENOMEM; const char *const options[1] = { "meta-file", }; /* that option has to be cleaned in input_item_subitem_added() */ /* vlc_gc_decref() in the same function */ p_input = input_item_NewExt( p_playlist, psz_uri, _("Media Library"), 1, options, VLC_INPUT_OPTION_TRUSTED, -1 ); free( psz_uri ); if( p_input == NULL ) return VLC_EGENERIC; PL_LOCK; if( p_playlist->p_ml_onelevel->p_input ) vlc_gc_decref( p_playlist->p_ml_onelevel->p_input ); if( p_playlist->p_ml_category->p_input ) vlc_gc_decref( p_playlist->p_ml_category->p_input ); p_playlist->p_ml_onelevel->p_input = p_playlist->p_ml_category->p_input = p_input; /* We save the input at two different place, incref */ vlc_gc_incref( p_input ); vlc_gc_incref( p_input ); vlc_event_attach( &p_input->event_manager, vlc_InputItemSubItemAdded, input_item_subitem_added, p_playlist ); pl_priv(p_playlist)->b_doing_ml = true; PL_UNLOCK; stats_TimerStart( p_playlist, "ML Load", STATS_TIMER_ML_LOAD ); input_Read( p_playlist, p_input ); stats_TimerStop( p_playlist,STATS_TIMER_ML_LOAD ); PL_LOCK; pl_priv(p_playlist)->b_doing_ml = false; PL_UNLOCK; vlc_event_detach( &p_input->event_manager, vlc_InputItemSubItemAdded, input_item_subitem_added, p_playlist ); vlc_gc_decref( p_input ); return VLC_SUCCESS; }
int playlist_ServicesDiscoveryAdd( playlist_t *p_playlist, const char *psz_modules ) { const char *psz_parser = psz_modules ?psz_modules: ""; int retval = VLC_SUCCESS; for (;;) { struct playlist_services_discovery_support_t * p_sds; playlist_item_t * p_cat; playlist_item_t * p_one; while( *psz_parser == ' ' || *psz_parser == ':' || *psz_parser == ',' ) psz_parser++; if( *psz_parser == '\0' ) break; const char *psz_next = strchr( psz_parser, ':' ); if( psz_next == NULL ) psz_next = psz_parser + strlen( psz_parser ); char psz_plugin[psz_next - psz_parser + 1]; memcpy (psz_plugin, psz_parser, sizeof (psz_plugin) - 1); psz_plugin[sizeof (psz_plugin) - 1] = '\0'; psz_parser = psz_next; /* Perform the addition */ msg_Dbg( p_playlist, "Add services_discovery %s", psz_plugin ); services_discovery_t *p_sd; p_sd = services_discovery_Create( (vlc_object_t*)p_playlist, psz_plugin ); if( !p_sd ) continue; char * psz = services_discovery_GetLocalizedName( p_sd ); assert( psz ); PL_LOCK; playlist_NodesPairCreate( p_playlist, psz, &p_cat, &p_one, false ); PL_UNLOCK; free( psz ); vlc_event_attach( services_discovery_EventManager( p_sd ), vlc_ServicesDiscoveryItemAdded, playlist_sd_item_added, p_one ); vlc_event_attach( services_discovery_EventManager( p_sd ), vlc_ServicesDiscoveryItemAdded, playlist_sd_item_added, p_cat ); vlc_event_attach( services_discovery_EventManager( p_sd ), vlc_ServicesDiscoveryItemRemoved, playlist_sd_item_removed, p_one ); vlc_event_attach( services_discovery_EventManager( p_sd ), vlc_ServicesDiscoveryItemRemoved, playlist_sd_item_removed, p_cat ); services_discovery_Start( p_sd ); /* Free in playlist_ServicesDiscoveryRemove */ p_sds = malloc( sizeof(struct playlist_services_discovery_support_t) ); if( !p_sds ) return VLC_ENOMEM; /* We want tree-view for service directory */ p_one->p_input->b_prefers_tree = true; p_sds->p_sd = p_sd; p_sds->p_one = p_one; p_sds->p_cat = p_cat; PL_LOCK; TAB_APPEND( p_playlist->i_sds, p_playlist->pp_sds, p_sds ); PL_UNLOCK; } return retval; }
void RendererDialog::setVisible(bool visible) { QVLCDialog::setVisible(visible); if (visible) { /* SD subnodes */ char **ppsz_longnames; char **ppsz_names; if( vlc_rd_get_names( THEPL, &ppsz_names, &ppsz_longnames ) != VLC_SUCCESS ) return; char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames; for( ; *ppsz_name; ppsz_name++, ppsz_longname++ ) { /* TODO launch all discovery services for renderers */ msg_Dbg( p_intf, "starting renderer discovery service %s", *ppsz_longname ); if ( p_rd == NULL ) { p_rd = vlc_rd_new( VLC_OBJECT(p_intf), *ppsz_name ); if( !p_rd ) msg_Err( p_intf, "Could not start renderer discovery services" ); } break; } free( ppsz_names ); free( ppsz_longnames ); if ( p_rd != NULL ) { int row = -1; char *psz_renderer = var_InheritString( THEPL, "sout" ); if ( psz_renderer != NULL ) { for ( row = 0 ; row < ui.receiversListWidget->count(); row++ ) { RendererItem *rowItem = reinterpret_cast<RendererItem*>( ui.receiversListWidget->item( row ) ); if ( rowItem->isItemSout( psz_renderer, false ) ) break; } if ( row == ui.receiversListWidget->count() ) row = -1; free( psz_renderer ); } ui.receiversListWidget->setCurrentRow( row ); if ( !b_rd_started ) { vlc_event_manager_t *em = vlc_rd_event_manager( p_rd ); vlc_event_attach( em, vlc_RendererDiscoveryItemAdded, renderer_event_received, this ); vlc_event_attach( em, vlc_RendererDiscoveryItemRemoved, renderer_event_received, this ); b_rd_started = vlc_rd_start( p_rd ) == VLC_SUCCESS; if ( !b_rd_started ) { vlc_event_detach( em, vlc_RendererDiscoveryItemAdded, renderer_event_received, this); vlc_event_detach( em, vlc_RendererDiscoveryItemRemoved, renderer_event_received, this); } } } } else { if ( p_rd != NULL ) { if ( b_rd_started ) { vlc_event_manager_t *em = vlc_rd_event_manager( p_rd ); vlc_event_detach( em, vlc_RendererDiscoveryItemAdded, renderer_event_received, this); vlc_event_detach( em, vlc_RendererDiscoveryItemRemoved, renderer_event_received, this); vlc_rd_stop( p_rd ); b_rd_started = false; } } ui.receiversListWidget->clear(); } }
/************************************************************************** * new (Public) **************************************************************************/ libvlc_media_discoverer_t * libvlc_media_discoverer_new( libvlc_instance_t * p_inst, const char * psz_name ) { /* podcast SD is a hack and only works with custom playlist callbacks. */ if( !strncasecmp( psz_name, "podcast", 7 ) ) return NULL; libvlc_media_discoverer_t *p_mdis = malloc(sizeof(*p_mdis)); if( unlikely(!p_mdis) ) { libvlc_printerr( "Not enough memory" ); return NULL; } p_mdis->p_libvlc_instance = p_inst; p_mdis->p_mlist = libvlc_media_list_new( p_inst ); p_mdis->p_mlist->b_read_only = true; p_mdis->running = false; vlc_dictionary_init( &p_mdis->catname_to_submedialist, 0 ); p_mdis->p_event_manager = libvlc_event_manager_new( p_mdis ); if( unlikely(p_mdis->p_event_manager == NULL) ) { free( p_mdis ); return NULL; } p_mdis->p_sd = vlc_sd_Create( (vlc_object_t*)p_inst->p_libvlc_int, psz_name ); if( unlikely(p_mdis->p_sd == NULL) ) { libvlc_printerr( "%s: no such discovery module found", psz_name ); libvlc_media_list_release( p_mdis->p_mlist ); libvlc_event_manager_release( p_mdis->p_event_manager ); free( p_mdis ); return NULL; } vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemAdded, services_discovery_item_added, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemRemoved, services_discovery_item_removed, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryStarted, services_discovery_started, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryEnded, services_discovery_ended, p_mdis ); vlc_event_attach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemRemoveAll, services_discovery_removeall, p_mdis ); libvlc_retain( p_inst ); return p_mdis; }