/***************************************************************************** * ModuleConfigControl implementation *****************************************************************************/ ModuleConfigControl::ModuleConfigControl( vlc_object_t *p_this, module_config_t *p_item, HWND parent, HINSTANCE hInst, int * py_pos ) : ConfigControl( p_this, p_item, parent, hInst ) { module_t **p_list; module_t *p_parser; label = CreateWindow( _T("STATIC"), _FROMMB(p_item->psz_text), WS_CHILD | WS_VISIBLE | SS_LEFT, 5, *py_pos, 200, 15, parent, NULL, hInst, NULL ); *py_pos += 15 + 10; combo = CreateWindow( _T("COMBOBOX"), _T(""), WS_CHILD | WS_VISIBLE | CBS_AUTOHSCROLL | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL, 20, *py_pos, 180, 5*15 + 6, parent, NULL, hInst, NULL); *py_pos += 15 + 10; /* build a list of available modules */ p_list = module_list_get( NULL ); ComboBox_AddString( combo, _T("Default") ); ComboBox_SetItemData( combo, 0, (void *)NULL ); ComboBox_SetCurSel( combo, 0 ); //ComboBox_SetText( combo, _T("Default") ); for( size_t i_index = 0; p_list[i_index]; i_index++ ) { p_parser = p_list[i_index]; if( module_provides( p_parser, p_item->psz_type ) ) { ComboBox_AddString( combo, _FROMMB(module_GetLongName( p_parser ) )); ComboBox_SetItemData( combo, i_index, (void *) module_get_object( p_parser ) ); if( p_item->value.psz && !strcmp( p_item->value.psz, module_get_object( p_parser )) ) { ComboBox_SetCurSel( combo, i_index ); //ComboBox_SetText( combo, _FROMMB( module_GetLongName(p_parser)) ); } } } module_list_free( p_list ); }
/***************************************** * Get the list of available audio outputs *****************************************/ libvlc_audio_output_t * libvlc_audio_output_list_get( libvlc_instance_t *p_instance, libvlc_exception_t *p_e ) { VLC_UNUSED( p_instance ); libvlc_audio_output_t *p_list = NULL, *p_actual = NULL, *p_previous = NULL; module_t **module_list = module_list_get( NULL ); for (size_t i = 0; module_list[i]; i++) { module_t *p_module = module_list[i]; if( module_provides( p_module, "audio output" ) ) { if( p_actual == NULL) { p_actual = ( libvlc_audio_output_t * ) malloc( sizeof( libvlc_audio_output_t ) ); if( p_actual == NULL ) { libvlc_exception_raise( p_e ); libvlc_printerr( "Not enough memory" ); libvlc_audio_output_list_release( p_list ); module_list_free( module_list ); return NULL; } if( p_list == NULL ) { p_list = p_actual; p_previous = p_actual; } } p_actual->psz_name = strdup( module_get_object( p_module ) ); p_actual->psz_description = strdup( module_get_name( p_module, true ) ); p_actual->p_next = NULL; if( p_previous != p_actual ) /* not first item */ p_previous->p_next = p_actual; p_previous = p_actual; p_actual = p_actual->p_next; } } module_list_free( module_list ); return p_list; }
static libvlc_module_description_t *module_description_list_get( libvlc_instance_t *p_instance, const char *capability ) { libvlc_module_description_t *p_list = NULL, *p_actual = NULL, *p_previous = NULL; size_t count; module_t **module_list = module_list_get( &count ); for (size_t i = 0; i < count; i++) { module_t *p_module = module_list[i]; if ( !module_provides( p_module, capability ) ) continue; p_actual = ( libvlc_module_description_t * ) malloc( sizeof( libvlc_module_description_t ) ); if ( p_actual == NULL ) { libvlc_printerr( "Not enough memory" ); libvlc_module_description_list_release( p_list ); module_list_free( module_list ); return NULL; } if ( p_list == NULL ) p_list = p_actual; const char* name = module_get_object( p_module ); const char* shortname = module_get_name( p_module, false ); const char* longname = module_get_name( p_module, true ); const char* help = module_get_help( p_module ); p_actual->psz_name = name ? strdup( name ) : NULL; p_actual->psz_shortname = shortname ? strdup( shortname ) : NULL; p_actual->psz_longname = longname ? strdup( longname ) : NULL; p_actual->psz_help = help ? strdup( help ) : NULL; p_actual->p_next = NULL; if ( p_previous ) p_previous->p_next = p_actual; p_previous = p_actual; } module_list_free( module_list ); VLC_UNUSED( p_instance ); return p_list; }
/***************************************** * Get the list of available audio outputs *****************************************/ libvlc_audio_output_t * libvlc_audio_output_list_get( libvlc_instance_t *p_instance ) { size_t count; module_t **module_list = module_list_get( &count ); libvlc_audio_output_t *list = NULL; for (size_t i = 0; i < count; i++) { module_t *module = module_list[i]; if( !module_provides( module, "audio output" ) ) continue; libvlc_audio_output_t *item = malloc( sizeof( *item ) ); if( unlikely(item == NULL) ) { error: libvlc_printerr( "Not enough memory" ); libvlc_audio_output_list_release( list ); list = NULL; break; } item->psz_name = strdup( module_get_object( module ) ); item->psz_description = strdup( module_get_name( module, true ) ); if( unlikely(item->psz_name == NULL || item->psz_description == NULL) ) { free( item->psz_name ); free( item->psz_description ); free( item ); goto error; } item->p_next = list; list = item; } module_list_free( module_list ); VLC_UNUSED( p_instance ); return list; }
/** * Finds and instantiates the best module of a certain type. * All candidates modules having the specified capability and name will be * sorted in decreasing order of priority. Then the probe callback will be * invoked for each module, until it succeeds (returns 0), or all candidate * module failed to initialize. * * The probe callback first parameter is the address of the module entry point. * Further parameters are passed as an argument list; it corresponds to the * variable arguments passed to this function. This scheme is meant to * support arbitrary prototypes for the module entry point. * * \param p_this VLC object * \param psz_capability capability, i.e. class of module * \param psz_name name name of the module asked, if any * \param b_strict if true, do not fallback to plugin with a different name * but the same capability * \param probe module probe callback * \return the module or NULL in case of a failure */ module_t *vlc_module_load(vlc_object_t *p_this, const char *psz_capability, const char *psz_name, bool b_strict, vlc_activate_t probe, ...) { int i_shortcuts = 0; char *psz_shortcuts = NULL, *psz_var = NULL, *psz_alias = NULL; bool b_force_backup = p_this->b_force; /* Deal with variables */ if( psz_name && psz_name[0] == '$' ) { psz_name = psz_var = var_CreateGetString( p_this, psz_name + 1 ); } /* Count how many different shortcuts were asked for */ if( psz_name && *psz_name ) { char *psz_parser, *psz_last_shortcut; /* If the user wants none, give him none. */ if( !strcmp( psz_name, "none" ) ) { free( psz_var ); return NULL; } i_shortcuts++; psz_parser = psz_shortcuts = psz_last_shortcut = strdup( psz_name ); while( ( psz_parser = strchr( psz_parser, ',' ) ) ) { *psz_parser = '\0'; i_shortcuts++; psz_last_shortcut = ++psz_parser; } /* Check if the user wants to override the "strict" mode */ if( psz_last_shortcut ) { if( !strcmp(psz_last_shortcut, "none") ) { b_strict = true; i_shortcuts--; } else if( !strcmp(psz_last_shortcut, "any") ) { b_strict = false; i_shortcuts--; } } } /* Sort the modules and test them */ size_t total, match = 0; module_t **p_all = module_list_get (&total); module_list_t *p_list = xmalloc( total * sizeof( module_list_t ) ); /* Parse the module list for capabilities and probe each of them */ for (size_t i = 0; i < total; i++) { module_t *p_module = p_all[i]; int i_shortcut_bonus = 0; /* Test that this module can do what we need */ if( !module_provides( p_module, psz_capability ) ) continue; /* If we required a shortcut, check this plugin provides it. */ if( i_shortcuts > 0 ) { const char *name = psz_shortcuts; for( unsigned i_short = i_shortcuts; i_short > 0; i_short-- ) { for( unsigned i = 0; i < p_module->i_shortcuts; i++ ) { char *c; if( ( c = strchr( name, '@' ) ) ? !strncasecmp( name, p_module->pp_shortcuts[i], c-name ) : !strcasecmp( name, p_module->pp_shortcuts[i] ) ) { /* Found it */ if( c && c[1] ) psz_alias = c+1; i_shortcut_bonus = i_short * 10000; goto found_shortcut; } } /* Go to the next shortcut... This is so lame! */ name += strlen( name ) + 1; } /* If we are in "strict" mode and we couldn't * find the module in the list of provided shortcuts, * then kick the bastard out of here!!! */ if( b_strict ) continue; } /* Trash <= 0 scored plugins (they can only be selected by shortcut) */ if( p_module->i_score <= 0 ) continue; found_shortcut: /* Store this new module */ p_list[match].p_module = p_module; p_list[match].i_score = p_module->i_score + i_shortcut_bonus; p_list[match].b_force = i_shortcut_bonus && b_strict; match++; } /* We can release the list, interesting modules are held */ module_list_free (p_all); if( match == 0 ) { msg_Dbg( p_this, "no %s module matched \"%s\"", psz_capability, (psz_name && *psz_name) ? psz_name : "any" ); return NULL; // shortcut } /* Sort candidates by descending score */ qsort (p_list, match, sizeof (p_list[0]), modulecmp); msg_Dbg( p_this, "looking for %s module: %zu candidate%s", psz_capability, match, match == 1 ? "" : "s" ); /* Parse the linked list and use the first successful module */ module_t *p_module = NULL; va_list args; va_start(args, probe); for (size_t i = 0; (i < match) && (p_module == NULL); i++) { module_t *p_cand = p_list[i].p_module; if (module_Map (p_this, p_cand)) continue; p_this->b_force = p_list[i].b_force; int ret; if (likely(p_cand->pf_activate != NULL)) { va_list ap; va_copy(ap, args); ret = probe(p_cand->pf_activate, ap); va_end(ap); } else ret = VLC_SUCCESS; switch (ret) { case VLC_SUCCESS: /* good module! */ p_module = p_cand; break; case VLC_ETIMEOUT: /* good module, but aborted */ break; default: /* bad module */ continue; } } va_end (args); free( p_list ); p_this->b_force = b_force_backup; if( p_module != NULL ) { msg_Dbg( p_this, "using %s module \"%s\"", psz_capability, module_get_object(p_module) ); vlc_object_set_name( p_this, psz_alias ? psz_alias : module_get_object(p_module) ); } else msg_Dbg( p_this, "no %s module matching \"%s\" could be loaded", psz_capability, (psz_name && *psz_name) ? psz_name : "any" ); free( psz_shortcuts ); free( psz_var ); /* Don't forget that the module is still locked */ return p_module; }
void vout_EnableFilter( vout_thread_t *p_vout, const char *psz_name, bool b_add, bool b_setconfig ) { char *psz_parser; char *psz_string; const char *psz_filter_type; module_t *p_obj = module_find( psz_name ); if( !p_obj ) { msg_Err( p_vout, "Unable to find filter module \"%s\".", psz_name ); return; } if( module_provides( p_obj, "video filter2" ) ) { psz_filter_type = "video-filter"; } else if( module_provides( p_obj, "sub source" ) ) { psz_filter_type = "sub-source"; } else if( module_provides( p_obj, "sub filter" ) ) { psz_filter_type = "sub-filter"; } else { msg_Err( p_vout, "Unknown video filter type." ); return; } psz_string = var_GetString( p_vout, psz_filter_type ); /* Todo : Use some generic chain manipulation functions */ if( !psz_string ) psz_string = strdup(""); psz_parser = strstr( psz_string, psz_name ); if( b_add ) { if( !psz_parser ) { psz_parser = psz_string; if( asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s", psz_string, psz_name ) == -1 ) { free( psz_parser ); return; } free( psz_parser ); } else return; } else { if( psz_parser ) { memmove( psz_parser, psz_parser + strlen(psz_name) + (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ), strlen(psz_parser + strlen(psz_name)) + 1 ); /* Remove trailing : : */ if( *(psz_string+strlen(psz_string ) -1 ) == ':' ) { *(psz_string+strlen(psz_string ) -1 ) = '\0'; } } else { free( psz_string ); return; } } if( b_setconfig ) { config_PutPsz( p_vout, psz_filter_type, psz_string ); } var_SetString( p_vout, psz_filter_type, psz_string ); free( psz_string ); }
void vout_EnableFilter( vout_thread_t *p_vout, char *psz_name, bool b_add, bool b_setconfig ) { char *psz_parser; char *psz_string; const char *psz_filter_type; /* FIXME temporary hack */ const char *psz_module_name = psz_name; if( !strcmp( psz_name, "magnify" ) || !strcmp( psz_name, "puzzle" ) || !strcmp( psz_name, "logo" ) || !strcmp( psz_name, "wall" ) || !strcmp( psz_name, "clone" ) ) psz_module_name = "video_filter_wrapper"; module_t *p_obj = module_find( psz_module_name ); if( !p_obj ) { msg_Err( p_vout, "Unable to find filter module \"%s\".", psz_name ); return; } if( module_provides( p_obj, "video filter" ) ) { psz_filter_type = "vout-filter"; } else if( module_provides( p_obj, "video filter2" ) ) { psz_filter_type = "video-filter"; } else if( module_provides( p_obj, "sub filter" ) ) { psz_filter_type = "sub-filter"; } else { module_release( p_obj ); msg_Err( p_vout, "Unknown video filter type." ); return; } module_release( p_obj ); if( !strcmp( psz_filter_type, "sub-filter") ) psz_string = var_GetString( vout_GetSpu( p_vout ), psz_filter_type ); else psz_string = var_GetString( p_vout, psz_filter_type ); /* Todo : Use some generic chain manipulation functions */ if( !psz_string ) psz_string = strdup(""); psz_parser = strstr( psz_string, psz_name ); if( b_add ) { if( !psz_parser ) { psz_parser = psz_string; if( asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s", psz_string, psz_name ) == -1 ) { free( psz_parser ); return; } free( psz_parser ); } else return; } else { if( psz_parser ) { memmove( psz_parser, psz_parser + strlen(psz_name) + (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ), strlen(psz_parser + strlen(psz_name)) + 1 ); /* Remove trailing : : */ if( *(psz_string+strlen(psz_string ) -1 ) == ':' ) { *(psz_string+strlen(psz_string ) -1 ) = '\0'; } } else { free( psz_string ); return; } } if( b_setconfig ) { if( !strcmp( psz_filter_type, "sub-filter") ) config_PutPsz( vout_GetSpu( p_vout ), psz_filter_type, psz_string ); else config_PutPsz( p_vout, psz_filter_type, psz_string ); } if( !strcmp( psz_filter_type, "sub-filter") ) var_SetString( vout_GetSpu( p_vout ), psz_filter_type, psz_string ); else var_SetString( p_vout, psz_filter_type, psz_string ); free( psz_string ); }