static void test_dictionary_validity (vlc_dictionary_t * p_dict, const char ** our_keys, int size ) { /* Test values and keys now */ char ** keys = vlc_dictionary_all_keys( p_dict ); int i, j; assert( keys ); for( j = 0; keys[j]; j++ ) { bool found = false; for( i = 0; i < size; i++ ) { if(!strcmp( keys[j], our_keys[i] )) { found = true; break; } } free( keys[j] ); assert( found ); } free( keys ); for( i = 0; i < size; i++ ) assert( vlc_dictionary_value_for_key( p_dict, our_keys[i] ) == (void*)i ); }
vlc_family_t *Win32_GetFallbacks( filter_t *p_filter, const char *psz_family, uni_char_t codepoint ) { vlc_family_t *p_family = NULL; vlc_family_t *p_fallbacks = NULL; filter_sys_t *p_sys = p_filter->p_sys; char *psz_uniscribe = NULL; char *psz_lc = ToLower( psz_family ); if( unlikely( !psz_lc ) ) return NULL; p_fallbacks = vlc_dictionary_value_for_key( &p_sys->fallback_map, psz_lc ); if( p_fallbacks ) p_family = SearchFallbacks( p_filter, p_fallbacks, codepoint ); /* * If the fallback list of psz_family has no family which contains the requested * codepoint, try UniscribeFallback(). If it returns a valid family which does * contain that codepoint, add the new family to the fallback list to speed up * later searches. */ if( !p_family ) { psz_uniscribe = UniscribeFallback( psz_lc, codepoint ); if( !psz_uniscribe ) goto done; const vlc_family_t *p_uniscribe = Win32_GetFamily( p_filter, psz_uniscribe ); if( !p_uniscribe || !p_uniscribe->p_fonts ) goto done; FT_Face p_face = GetFace( p_filter, p_uniscribe->p_fonts ); if( !p_face || !FT_Get_Char_Index( p_face, codepoint ) ) goto done; p_family = NewFamily( p_filter, psz_uniscribe, NULL, NULL, NULL ); if( unlikely( !p_family ) ) goto done; p_family->p_fonts = p_uniscribe->p_fonts; if( p_fallbacks ) AppendFamily( &p_fallbacks, p_family ); else vlc_dictionary_insert( &p_sys->fallback_map, psz_lc, p_family ); } done: free( psz_lc ); free( psz_uniscribe ); return p_family; }
/** * Merging meta */ void vlc_meta_Merge( vlc_meta_t *dst, const vlc_meta_t *src ) { char **ppsz_all_keys; int i; if( !dst || !src ) return; for( i = 0; i < VLC_META_TYPE_COUNT; i++ ) { if( src->ppsz_meta[i] ) { free( dst->ppsz_meta[i] ); dst->ppsz_meta[i] = strdup( src->ppsz_meta[i] ); } } /* XXX: If speed up are needed, it is possible */ ppsz_all_keys = vlc_dictionary_all_keys( &src->extra_tags ); for( i = 0; ppsz_all_keys && ppsz_all_keys[i]; i++ ) { /* Always try to remove the previous value */ vlc_dictionary_remove_value_for_key( &dst->extra_tags, ppsz_all_keys[i], vlc_meta_FreeExtraKey, NULL ); void *p_value = vlc_dictionary_value_for_key( &src->extra_tags, ppsz_all_keys[i] ); vlc_dictionary_insert( &dst->extra_tags, ppsz_all_keys[i], strdup( (const char*)p_value ) ); free( ppsz_all_keys[i] ); } free( ppsz_all_keys ); }
void vlc_meta_AddExtra( vlc_meta_t *m, const char *psz_name, const char *psz_value ) { char *psz_oldvalue = (char *)vlc_dictionary_value_for_key( &m->extra_tags, psz_name ); if( psz_oldvalue != kVLCDictionaryNotFound ) vlc_dictionary_remove_value_for_key( &m->extra_tags, psz_name, vlc_meta_FreeExtraKey, NULL ); vlc_dictionary_insert( &m->extra_tags, psz_name, strdup(psz_value) ); }
static int vlc_sd_probe_Open( vlc_object_t *obj ) { vlc_dictionary_t name_d; char **ppsz_dir_list; if( vlclua_dir_list( "sd", &ppsz_dir_list ) ) return VLC_ENOMEM; vlc_dictionary_init( &name_d, 32 ); for( char **ppsz_dir = ppsz_dir_list; *ppsz_dir; ppsz_dir++ ) { char **ppsz_filelist; int i_files = vlc_scandir( *ppsz_dir, &ppsz_filelist, file_select, file_compare ); if( i_files < 1 ) continue; for( char **ppsz_file = ppsz_filelist; ppsz_file < ppsz_filelist + i_files; ppsz_file++ ) { char *temp = strchr( *ppsz_file, '.' ); if( temp ) *temp = '\0'; if( vlc_dictionary_value_for_key( &name_d, *ppsz_file ) == kVLCDictionaryNotFound ) vlc_dictionary_insert( &name_d, *ppsz_file, &name_d ); free( *ppsz_file ); } free( ppsz_filelist ); } vlclua_dir_list_free( ppsz_dir_list ); int r = VLC_PROBE_CONTINUE; char **names = vlc_dictionary_all_keys( &name_d ); if( names != NULL ) { for( char **name = names; *name; ++name ) { r = vlclua_probe_sd( obj, *name ); if( r != VLC_PROBE_CONTINUE ) break; } for( char **name = names; *name; ++name ) free( *name ); free( names ); } vlc_dictionary_clear( &name_d, NULL, NULL ); return r; }
vlc_family_t *NewFamily( filter_t *p_filter, const char *psz_family, vlc_family_t **pp_list, vlc_dictionary_t *p_dict, const char *psz_key ) { filter_sys_t *p_sys = p_filter->p_sys; vlc_family_t *p_family = NULL; p_family = calloc( 1, sizeof( *p_family ) ); char *psz_name; if( psz_family && *psz_family ) psz_name = ToLower( psz_family ); else if( asprintf( &psz_name, FB_NAME"-%02d", p_sys->i_fallback_counter++ ) < 0 ) psz_name = NULL; char *psz_lc = NULL; if( likely( psz_name ) ) { if( !psz_key ) psz_lc = strdup( psz_name ); else psz_lc = ToLower( psz_key ); } if( unlikely( !p_family || !psz_name || !psz_lc ) ) { free( p_family ); free( psz_name ); free( psz_lc ); return NULL; } p_family->psz_name = psz_name; if( pp_list ) AppendFamily( pp_list, p_family ); if( p_dict ) { vlc_family_t *p_root = vlc_dictionary_value_for_key( p_dict, psz_lc ); if( p_root ) AppendFamily( &p_root, p_family ); else vlc_dictionary_insert( p_dict, psz_lc, p_family ); } free( psz_lc ); return p_family; }
static void services_discovery_item_added( services_discovery_t *sd, input_item_t *parent, input_item_t *p_item, const char *psz_cat ) { libvlc_media_t * p_md; libvlc_media_discoverer_t *p_mdis = sd->owner.sys; libvlc_media_list_t * p_mlist = p_mdis->p_mlist; p_md = libvlc_media_new_from_input_item( p_mdis->p_libvlc_instance, p_item ); if( parent != NULL ) { /* Flatten items list for now. TODO: tree support. */ } else /* If we have a category, that mean we have to group the items having * that category in a media_list. */ if( psz_cat ) { p_mlist = vlc_dictionary_value_for_key( &p_mdis->catname_to_submedialist, psz_cat ); if( p_mlist == kVLCDictionaryNotFound ) { libvlc_media_t * p_catmd; p_catmd = libvlc_media_new_as_node( p_mdis->p_libvlc_instance, psz_cat ); p_mlist = libvlc_media_subitems( p_catmd ); p_mlist->b_read_only = true; /* Insert the newly created mlist in our dictionary */ vlc_dictionary_insert( &p_mdis->catname_to_submedialist, psz_cat, p_mlist ); /* Insert the md into the root list */ libvlc_media_list_lock( p_mdis->p_mlist ); libvlc_media_list_internal_add_media( p_mdis->p_mlist, p_catmd ); libvlc_media_list_unlock( p_mdis->p_mlist ); /* We don't release the mlist cause the dictionary * doesn't retain the object. But we release the md. */ libvlc_media_release( p_catmd ); } } libvlc_media_list_lock( p_mlist ); libvlc_media_list_internal_add_media( p_mlist, p_md ); libvlc_media_list_unlock( p_mlist ); libvlc_media_release( p_md ); }
void DumpDictionary( filter_t *p_filter, const vlc_dictionary_t *p_dict, bool b_dump_fonts, int i_max_families ) { char **ppsz_keys = vlc_dictionary_all_keys( p_dict ); for( int i = 0; ppsz_keys[ i ]; ++i ) { vlc_family_t *p_family = vlc_dictionary_value_for_key( p_dict, ppsz_keys[ i ] ); msg_Dbg( p_filter, "Key: %s", ppsz_keys[ i ] ); if( p_family ) DumpFamily( p_filter, p_family, b_dump_fonts, i_max_families ); free( ppsz_keys[ i ] ); } free( ppsz_keys ); }
/************************************************************************** * release (Public) **************************************************************************/ void libvlc_media_discoverer_release( libvlc_media_discoverer_t * p_mdis ) { int i; vlc_event_detach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemAdded, services_discovery_item_added, p_mdis ); vlc_event_detach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemRemoved, services_discovery_item_removed, p_mdis ); vlc_event_detach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryStarted, services_discovery_started, p_mdis ); vlc_event_detach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryEnded, services_discovery_ended, p_mdis ); vlc_event_detach( services_discovery_EventManager( p_mdis->p_sd ), vlc_ServicesDiscoveryItemRemoveAll, services_discovery_removeall, p_mdis ); libvlc_media_list_release( p_mdis->p_mlist ); if( p_mdis->running ) vlc_sd_Stop( p_mdis->p_sd ); vlc_sd_Destroy( p_mdis->p_sd ); /* Free catname_to_submedialist and all the mlist */ char ** all_keys = vlc_dictionary_all_keys( &p_mdis->catname_to_submedialist ); for( i = 0; all_keys[i]; i++ ) { libvlc_media_list_t * p_catmlist = vlc_dictionary_value_for_key( &p_mdis->catname_to_submedialist, all_keys[i] ); libvlc_media_list_release( p_catmlist ); free( all_keys[i] ); } free( all_keys ); vlc_dictionary_clear( &p_mdis->catname_to_submedialist, NULL, NULL ); libvlc_event_manager_release( p_mdis->p_event_manager ); libvlc_release( p_mdis->p_libvlc_instance ); free( p_mdis ); }
const vlc_family_t *Android_GetFamily( filter_t *p_filter, const char *psz_family ) { filter_sys_t *p_sys = p_filter->p_sys; char *psz_lc = ToLower( psz_family ); if( unlikely( !psz_lc ) ) return NULL; vlc_family_t *p_family = vlc_dictionary_value_for_key( &p_sys->family_map, psz_lc ); free( psz_lc ); if( p_family == kVLCDictionaryNotFound ) return NULL; return p_family; }
static void services_discovery_item_added( const vlc_event_t * p_event, void * user_data ) { input_item_t * p_item = p_event->u.services_discovery_item_added.p_new_item; const char * psz_cat = p_event->u.services_discovery_item_added.psz_category; libvlc_media_t * p_md; libvlc_media_discoverer_t * p_mdis = user_data; libvlc_media_list_t * p_mlist = p_mdis->p_mlist; p_md = libvlc_media_new_from_input_item( p_mdis->p_libvlc_instance, p_item, NULL ); /* If we have a category, that mean we have to group the items having * that category in a media_list. */ if( psz_cat ) { p_mlist = vlc_dictionary_value_for_key( &p_mdis->catname_to_submedialist, psz_cat ); if( p_mlist == kVLCDictionaryNotFound ) { libvlc_media_t * p_catmd; p_catmd = libvlc_media_new_as_node( p_mdis->p_libvlc_instance, psz_cat, NULL ); p_mlist = libvlc_media_subitems( p_catmd, NULL ); p_mlist->b_read_only = true; /* Insert the newly created mlist in our dictionary */ vlc_dictionary_insert( &p_mdis->catname_to_submedialist, psz_cat, p_mlist ); /* Insert the md into the root list */ libvlc_media_list_lock( p_mdis->p_mlist ); _libvlc_media_list_add_media( p_mdis->p_mlist, p_catmd, NULL ); libvlc_media_list_unlock( p_mdis->p_mlist ); /* We don't release the mlist cause the dictionary * doesn't retain the object. But we release the md. */ libvlc_media_release( p_catmd ); } } else { libvlc_media_list_lock( p_mlist ); _libvlc_media_list_add_media( p_mlist, p_md, NULL ); libvlc_media_list_unlock( p_mlist ); } }
/***************************************************************************** * browser_callback *****************************************************************************/ static void browse_callback( AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata ) { VLC_UNUSED(b); VLC_UNUSED(flags); services_discovery_t *p_sd = ( services_discovery_t* )userdata; services_discovery_sys_t *p_sys = p_sd->p_sys; if( event == AVAHI_BROWSER_NEW ) { if( avahi_service_resolver_new( p_sys->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, userdata ) == NULL ) { msg_Err( p_sd, "failed to resolve service '%s': %s", name, avahi_strerror( avahi_client_errno( p_sys->client ) ) ); } } else if( name ) { /** \todo Store the input id and search it, rather than searching the items */ input_item_t *p_item; p_item = vlc_dictionary_value_for_key( &p_sys->services_name_to_input_item, name ); if( !p_item ) msg_Err( p_sd, "failed to find service '%s' in playlist", name ); else { services_discovery_RemoveItem( p_sd, p_item ); vlc_dictionary_remove_value_for_key( &p_sys->services_name_to_input_item, name, NULL, NULL ); } } }
vlc_family_t *Android_GetFallbacks( filter_t *p_filter, const char *psz_family, uni_char_t codepoint ) { VLC_UNUSED( codepoint ); vlc_family_t *p_fallbacks = NULL; filter_sys_t *p_sys = p_filter->p_sys; char *psz_lc = ToLower( psz_family ); if( unlikely( !psz_lc ) ) return NULL; p_fallbacks = vlc_dictionary_value_for_key( &p_sys->fallback_map, psz_lc ); free( psz_lc ); if( p_fallbacks == kVLCDictionaryNotFound ) return NULL; return p_fallbacks; }
/************************************************************************** * release (Public) **************************************************************************/ void libvlc_media_discoverer_release( libvlc_media_discoverer_t * p_mdis ) { int i; libvlc_media_list_release( p_mdis->p_mlist ); services_discovery_Destroy( p_mdis->p_sd ); /* Free catname_to_submedialist and all the mlist */ char ** all_keys = vlc_dictionary_all_keys( &p_mdis->catname_to_submedialist ); for( i = 0; all_keys[i]; i++ ) { libvlc_media_list_t * p_catmlist = vlc_dictionary_value_for_key( &p_mdis->catname_to_submedialist, all_keys[i] ); libvlc_media_list_release( p_catmlist ); free( all_keys[i] ); } free( all_keys ); vlc_dictionary_clear( &p_mdis->catname_to_submedialist ); free( p_mdis ); }
const vlc_family_t *Win32_GetFamily( filter_t *p_filter, const char *psz_family ) { filter_sys_t *p_sys = p_filter->p_sys; char *psz_lc = ToLower( psz_family ); if( unlikely( !psz_lc ) ) return NULL; vlc_family_t *p_family = vlc_dictionary_value_for_key( &p_sys->family_map, psz_lc ); free( psz_lc ); if( p_family ) return p_family; p_family = NewFamily( p_filter, psz_family, &p_sys->p_families, &p_sys->family_map, psz_family ); if( unlikely( !p_family ) ) return NULL; LOGFONT lf; lf.lfCharSet = DEFAULT_CHARSET; LPTSTR psz_fbuffer = ToT( psz_family ); _tcsncpy( (LPTSTR)&lf.lfFaceName, psz_fbuffer, LF_FACESIZE ); free( psz_fbuffer ); /* */ HDC hDC = GetDC( NULL ); EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)&EnumFontCallback, (LPARAM)p_family, 0); ReleaseDC(NULL, hDC); return p_family; }
/***************************************************************************** * PrintMsg: output a standard message item to stderr ***************************************************************************** * Print a message to stderr, with colour formatting if needed. *****************************************************************************/ static void PrintMsg ( vlc_object_t * p_this, msg_item_t * p_item ) { # define COL(x) "\033[" #x ";1m" # define RED COL(31) # define GREEN COL(32) # define YELLOW COL(33) # define WHITE COL(0) # define GRAY "\033[0m" #ifdef UNDER_CE int i_dummy; #endif static const char ppsz_type[4][9] = { "", " error", " warning", " debug" }; static const char ppsz_color[4][8] = { WHITE, RED, YELLOW, GRAY }; const char *psz_object; libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc); int i_type = p_item->i_type; switch( i_type ) { case VLC_MSG_ERR: if( priv->i_verbose < 0 ) return; break; case VLC_MSG_INFO: if( priv->i_verbose < 0 ) return; break; case VLC_MSG_WARN: if( priv->i_verbose < 1 ) return; break; case VLC_MSG_DBG: if( priv->i_verbose < 2 ) return; break; } psz_object = p_item->psz_object_type; void * val = vlc_dictionary_value_for_key( &priv->msg_enabled_objects, p_item->psz_module ); if( val == kObjectPrintingDisabled ) return; if( val == kObjectPrintingEnabled ) /* Allowed */; else { val = vlc_dictionary_value_for_key( &priv->msg_enabled_objects, psz_object ); if( val == kObjectPrintingDisabled ) return; if( val == kObjectPrintingEnabled ) /* Allowed */; else if( !priv->msg_all_objects_enabled ) return; } #ifdef UNDER_CE # define CE_WRITE(str) WriteFile( QUEUE.logfile, \ str, strlen(str), &i_dummy, NULL ); CE_WRITE( p_item->psz_module ); CE_WRITE( " " ); CE_WRITE( psz_object ); CE_WRITE( ppsz_type[i_type] ); CE_WRITE( ": " ); CE_WRITE( p_item->psz_msg ); CE_WRITE( "\r\n" ); FlushFileBuffers( QUEUE.logfile ); #else int canc = vlc_savecancel (); /* Send the message to stderr */ utf8_fprintf( stderr, "[%s%p%s] %s%s%s %s%s: %s%s%s\n", priv->b_color ? GREEN : "", (void *)p_item->i_object_id, priv->b_color ? GRAY : "", p_item->psz_header ? p_item->psz_header : "", p_item->psz_header ? " " : "", p_item->psz_module, psz_object, ppsz_type[i_type], priv->b_color ? ppsz_color[i_type] : "", p_item->psz_msg, priv->b_color ? GRAY : "" ); # if defined(WIN32) fflush( stderr ); # endif vlc_restorecancel (canc); #endif }
const char * vlc_meta_GetExtra( const vlc_meta_t *m, const char *psz_name ) { return (char *)vlc_dictionary_value_for_key(&m->extra_tags, psz_name); }
/***************************************************************************** * PrintMsg: output a standard message item to stderr ***************************************************************************** * Print a message to stderr, with colour formatting if needed. *****************************************************************************/ static void PrintMsg ( vlc_object_t * p_this, msg_item_t * p_item ) { # define COL(x) "\033[" #x ";1m" # define RED COL(31) # define GREEN COL(32) # define YELLOW COL(33) # define WHITE COL(0) # define GRAY "\033[0m" static const char ppsz_type[4][9] = { "", " error", " warning", " debug" }; static const char ppsz_color[4][8] = { WHITE, RED, YELLOW, GRAY }; const char *psz_object; libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc); msg_bank_t *bank = priv->msg_bank; int i_type = p_item->i_type; switch( i_type ) { case VLC_MSG_ERR: if( priv->i_verbose < 0 ) return; break; case VLC_MSG_INFO: if( priv->i_verbose < 0 ) return; break; case VLC_MSG_WARN: if( priv->i_verbose < 1 ) return; break; case VLC_MSG_DBG: if( priv->i_verbose < 2 ) return; break; } psz_object = p_item->psz_object_type; void * val = vlc_dictionary_value_for_key (&bank->enabled_objects, p_item->psz_module); if( val == kObjectPrintingDisabled ) return; if( val == kObjectPrintingEnabled ) /* Allowed */; else { val = vlc_dictionary_value_for_key (&bank->enabled_objects, psz_object); if( val == kObjectPrintingDisabled ) return; if( val == kObjectPrintingEnabled ) /* Allowed */; else if( !bank->all_objects_enabled ) return; } int canc = vlc_savecancel (); /* Send the message to stderr */ utf8_fprintf( stderr, "[%s%p%s] %s%s%s %s%s: %s%s%s\n", priv->b_color ? GREEN : "", (void *)p_item->i_object_id, priv->b_color ? GRAY : "", p_item->psz_header ? p_item->psz_header : "", p_item->psz_header ? " " : "", p_item->psz_module, psz_object, ppsz_type[i_type], priv->b_color ? ppsz_color[i_type] : "", p_item->psz_msg, priv->b_color ? GRAY : "" ); #ifdef WIN32 fflush( stderr ); #endif vlc_restorecancel (canc); }
static FT_Face LoadFace( filter_t *p_filter, const char *psz_fontfile, int i_idx, const text_style_t *p_style ) { filter_sys_t *p_sys = p_filter->p_sys; char *psz_key = NULL; int i_font_size = ConvertToLiveSize( p_filter, p_style ); int i_font_width = p_style->i_style_flags & STYLE_HALFWIDTH ? i_font_size / 2 : i_font_size; if( asprintf( &psz_key, "%s - %d - %d - %d", psz_fontfile, i_idx, i_font_size, i_font_width ) < 0 ) return NULL; FT_Face p_face = vlc_dictionary_value_for_key( &p_sys->face_map, psz_key ); if( p_face != kVLCDictionaryNotFound ) goto done; if( psz_fontfile[0] == ':' && psz_fontfile[1] == '/' ) { int i_attach = atoi( psz_fontfile + 2 ); if( i_attach < 0 || i_attach >= p_sys->i_font_attachments ) { msg_Err( p_filter, "LoadFace: Invalid font attachment index" ); p_face = NULL; } else { input_attachment_t *p_attach = p_sys->pp_font_attachments[ i_attach ]; if( FT_New_Memory_Face( p_sys->p_library, p_attach->p_data, p_attach->i_data, i_idx, &p_face ) ) p_face = NULL; } } else if( FT_New_Face( p_sys->p_library, psz_fontfile, i_idx, &p_face ) ) { msg_Err( p_filter, "LoadFace: Error creating face for %s", psz_key ); p_face = NULL; } if( !p_face ) goto done; if( FT_Select_Charmap( p_face, ft_encoding_unicode ) ) { /* We've loaded a font face which is unhelpful for actually * rendering text - fallback to the default one. */ msg_Err( p_filter, "LoadFace: Error selecting charmap for %s", psz_key ); FT_Done_Face( p_face ); p_face = NULL; goto done; } if( FT_Set_Pixel_Sizes( p_face, i_font_width, i_font_size ) ) { msg_Err( p_filter, "LoadFace: Failed to set font size for %s", psz_key ); FT_Done_Face( p_face ); p_face = NULL; goto done; } vlc_dictionary_insert( &p_sys->face_map, psz_key, p_face ); done: free( psz_key ); return p_face; }
char* Generic_Select( filter_t *p_filter, const char* psz_family, bool b_bold, bool b_italic, int *i_idx, uni_char_t codepoint ) { filter_sys_t *p_sys = p_filter->p_sys; const vlc_family_t *p_family = NULL; vlc_family_t *p_fallbacks = NULL; if( codepoint ) { /* * Try regular face of the same family first. * It usually has the best coverage. */ const vlc_family_t *p_temp = p_sys->pf_get_family( p_filter, psz_family ); if( p_temp && p_temp->p_fonts ) { FT_Face p_face = GetFace( p_filter, p_temp->p_fonts ); if( p_face && FT_Get_Char_Index( p_face, codepoint ) ) p_family = p_temp; } /* Try font attachments */ if( !p_family ) { p_fallbacks = vlc_dictionary_value_for_key( &p_sys->fallback_map, FB_LIST_ATTACHMENTS ); if( p_fallbacks ) p_family = SearchFallbacks( p_filter, p_fallbacks, codepoint ); } /* Try system fallbacks */ if( !p_family ) { p_fallbacks = p_sys->pf_get_fallbacks( p_filter, psz_family, codepoint ); if( p_fallbacks ) p_family = SearchFallbacks( p_filter, p_fallbacks, codepoint ); } /* Try the default fallback list, if any */ if( !p_family ) { p_fallbacks = vlc_dictionary_value_for_key( &p_sys->fallback_map, FB_LIST_DEFAULT ); if( p_fallbacks ) p_family = SearchFallbacks( p_filter, p_fallbacks, codepoint ); } if( !p_family ) return NULL; } if( !p_family ) p_family = p_sys->pf_get_family( p_filter, psz_family ); vlc_font_t *p_font; if( p_family && ( p_font = GetBestFont( p_filter, p_family, b_bold, b_italic, codepoint ) ) ) { *i_idx = p_font->i_index; return strdup( p_font->psz_fontfile ); } return File_Select( SYSTEM_DEFAULT_FONT_FILE ); }
const vlc_family_t *FontConfig_GetFamily( filter_t *p_filter, const char *psz_family ) { filter_sys_t *p_sys = p_filter->p_sys; char *psz_lc = ToLower( psz_family ); if( unlikely( !psz_lc ) ) return NULL; vlc_family_t *p_family = vlc_dictionary_value_for_key( &p_sys->family_map, psz_lc ); if( p_family != kVLCDictionaryNotFound ) { free( psz_lc ); return p_family; } p_family = NewFamily( p_filter, psz_lc, &p_sys->p_families, &p_sys->family_map, psz_lc ); free( psz_lc ); if( !p_family ) return NULL; bool b_bold, b_italic; for( int i = 0; i < 4; ++i ) { switch( i ) { case 0: b_bold = false; b_italic = false; break; case 1: b_bold = true; b_italic = false; break; case 2: b_bold = false; b_italic = true; break; case 3: b_bold = true; b_italic = true; break; } int i_index = 0; FcResult result = FcResultMatch; FcPattern *pat, *p_pat; FcChar8* val_s; FcBool val_b; char *psz_fontfile = NULL; FcConfig* config = NULL; /* Create a pattern and fill it */ pat = FcPatternCreate(); if (!pat) continue; /* */ FcPatternAddString( pat, FC_FAMILY, (const FcChar8*) psz_family ); FcPatternAddBool( pat, FC_OUTLINE, FcTrue ); FcPatternAddInteger( pat, FC_SLANT, b_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN ); FcPatternAddInteger( pat, FC_WEIGHT, b_bold ? FC_WEIGHT_EXTRABOLD : FC_WEIGHT_NORMAL ); /* */ FcDefaultSubstitute( pat ); if( !FcConfigSubstitute( config, pat, FcMatchPattern ) ) { FcPatternDestroy( pat ); continue; } /* Find the best font for the pattern, destroy the pattern */ p_pat = FcFontMatch( config, pat, &result ); FcPatternDestroy( pat ); if( !p_pat || result == FcResultNoMatch ) continue; /* Check the new pattern */ if( ( FcResultMatch != FcPatternGetBool( p_pat, FC_OUTLINE, 0, &val_b ) ) || ( val_b != FcTrue ) ) { FcPatternDestroy( p_pat ); continue; } if( FcResultMatch != FcPatternGetInteger( p_pat, FC_INDEX, 0, &i_index ) ) { i_index = 0; } if( FcResultMatch != FcPatternGetString( p_pat, FC_FAMILY, 0, &val_s ) ) { FcPatternDestroy( p_pat ); continue; } if( FcResultMatch == FcPatternGetString( p_pat, FC_FILE, 0, &val_s ) ) psz_fontfile = strdup( (const char*)val_s ); FcPatternDestroy( p_pat ); if( !psz_fontfile ) continue; NewFont( psz_fontfile, i_index, b_bold, b_italic, p_family ); } return p_family; }
static FT_Face LoadFace( filter_t *p_filter, const char *psz_fontfile, int i_idx, const text_style_t *p_style ) { filter_sys_t *p_sys = p_filter->p_sys; char *psz_key = NULL; int i_font_size = ConvertToLiveSize( p_filter, p_style ); int i_font_width = p_style->i_style_flags & STYLE_HALFWIDTH ? i_font_size / 2 : i_font_size; if( asprintf( &psz_key, "%s - %d - %d - %d", psz_fontfile, i_idx, i_font_size, i_font_width ) < 0 ) return NULL; FT_Face p_face = vlc_dictionary_value_for_key( &p_sys->face_map, psz_key ); if( p_face != NULL ) goto done; if( psz_fontfile[0] == ':' && psz_fontfile[1] == '/' ) { int i_attach = atoi( psz_fontfile + 2 ); if( i_attach < 0 || i_attach >= p_sys->i_font_attachments ) msg_Err( p_filter, "LoadFace: Invalid font attachment index" ); else { input_attachment_t *p_attach = p_sys->pp_font_attachments[ i_attach ]; if( FT_New_Memory_Face( p_sys->p_library, p_attach->p_data, p_attach->i_data, i_idx, &p_face ) ) msg_Err( p_filter, "LoadFace: Error creating face for %s", psz_key ); } } #if defined( _WIN32 ) else if( !memcmp( psz_fontfile, ":dw/", 4 ) ) { int i_index = atoi( psz_fontfile + 4 ); FT_Stream p_stream; if( DWrite_GetFontStream( p_filter, i_index, &p_stream ) != VLC_SUCCESS ) msg_Err( p_filter, "LoadFace: Invalid font stream index" ); else { FT_Open_Args args = {0}; args.flags = FT_OPEN_STREAM; args.stream = p_stream; if( FT_Open_Face( p_sys->p_library, &args, i_idx, &p_face ) ) msg_Err( p_filter, "LoadFace: Error creating face for %s", psz_key ); } } #endif else if( FT_New_Face( p_sys->p_library, psz_fontfile, i_idx, &p_face ) ) msg_Err( p_filter, "LoadFace: Error creating face for %s", psz_key ); if( !p_face ) goto done; if( FT_Select_Charmap( p_face, ft_encoding_unicode ) ) { /* We've loaded a font face which is unhelpful for actually * rendering text - fallback to the default one. */ msg_Err( p_filter, "LoadFace: Error selecting charmap for %s", psz_key ); FT_Done_Face( p_face ); p_face = NULL; goto done; } if( FT_Set_Pixel_Sizes( p_face, i_font_width, i_font_size ) ) { msg_Err( p_filter, "LoadFace: Failed to set font size for %s", psz_key ); FT_Done_Face( p_face ); p_face = NULL; goto done; } vlc_dictionary_insert( &p_sys->face_map, psz_key, p_face ); done: free( psz_key ); return p_face; }
/** * Add a message to a queue * * This function provides basic functionnalities to other msg_* functions. * It adds a message to a queue (after having printed all stored messages if it * is full). If the message can't be converted to string in memory, it issues * a warning. */ void msg_GenericVa (vlc_object_t *p_this, int i_type, const char *psz_module, const char *psz_format, va_list _args) { char * psz_str = NULL; /* formatted message string */ va_list args; assert (p_this); if( p_this->i_flags & OBJECT_FLAGS_QUIET || (p_this->i_flags & OBJECT_FLAGS_NODBG && i_type == VLC_MSG_DBG) ) return; msg_bank_t *bank = libvlc_bank (p_this->p_libvlc); locale_t locale = uselocale (bank->locale); #ifndef __GLIBC__ /* Expand %m to strerror(errno) - only once */ char buf[strlen( psz_format ) + 2001], *ptr; strcpy( buf, psz_format ); ptr = (char*)buf; psz_format = (const char*) buf; for( ;; ) { ptr = strchr( ptr, '%' ); if( ptr == NULL ) break; if( ptr[1] == 'm' ) { char errbuf[2001]; size_t errlen; #ifndef WIN32 strerror_r( errno, errbuf, 1001 ); #else int sockerr = WSAGetLastError( ); if( sockerr ) { strncpy( errbuf, net_strerror( sockerr ), 1001 ); WSASetLastError( sockerr ); } if ((sockerr == 0) || (strcmp ("Unknown network stack error", errbuf) == 0)) strncpy( errbuf, strerror( errno ), 1001 ); #endif errbuf[1000] = 0; /* Escape '%' from the error string */ for( char *percent = strchr( errbuf, '%' ); percent != NULL; percent = strchr( percent + 2, '%' ) ) { memmove( percent + 1, percent, strlen( percent ) + 1 ); } errlen = strlen( errbuf ); memmove( ptr + errlen, ptr + 2, strlen( ptr + 2 ) + 1 ); memcpy( ptr, errbuf, errlen ); break; /* Only once, so we don't overflow */ } /* Looks for conversion specifier... */ do ptr++; while( *ptr && ( strchr( "diouxXeEfFgGaAcspn%", *ptr ) == NULL ) ); if( *ptr ) ptr++; /* ...and skip it */ } #endif /* Convert message to string */ vlc_va_copy( args, _args ); if( vasprintf( &psz_str, psz_format, args ) == -1 ) psz_str = NULL; va_end( args ); if( psz_str == NULL ) { int canc = vlc_savecancel (); /* Do not print half of a message... */ #ifdef __GLIBC__ fprintf( stderr, "main warning: can't store message (%m): " ); #else char psz_err[1001]; #ifndef WIN32 /* we're not using GLIBC, so we are sure that the error description * will be stored in the buffer we provide to strerror_r() */ strerror_r( errno, psz_err, 1001 ); #else strncpy( psz_err, strerror( errno ), 1001 ); #endif psz_err[1000] = '\0'; fprintf( stderr, "main warning: can't store message (%s): ", psz_err ); #endif vlc_va_copy( args, _args ); /* We should use utf8_vfprintf - but it calls malloc()... */ vfprintf( stderr, psz_format, args ); va_end( args ); fputs( "\n", stderr ); vlc_restorecancel (canc); uselocale (locale); return; } uselocale (locale); /* Fill message information fields */ msg_item_t msg; msg.i_type = i_type; msg.i_object_id = (uintptr_t)p_this; msg.psz_object_type = p_this->psz_object_type; msg.psz_module = psz_module; msg.psz_msg = psz_str; msg.psz_header = NULL; for (vlc_object_t *o = p_this; o != NULL; o = o->p_parent) if (o->psz_header != NULL) { msg.psz_header = o->psz_header; break; } PrintMsg( p_this, &msg ); vlc_rwlock_rdlock (&bank->lock); for (int i = 0; i < bank->i_sub; i++) { msg_subscription_t *sub = bank->pp_sub[i]; libvlc_priv_t *priv = libvlc_priv( sub->instance ); msg_bank_t *bank = priv->msg_bank; void *val = vlc_dictionary_value_for_key( &bank->enabled_objects, msg.psz_module ); if( val == kObjectPrintingDisabled ) continue; if( val != kObjectPrintingEnabled ) /*if not allowed */ { val = vlc_dictionary_value_for_key( &bank->enabled_objects, msg.psz_object_type ); if( val == kObjectPrintingDisabled ) continue; if( val == kObjectPrintingEnabled ); /* Allowed */ else if( !bank->all_objects_enabled ) continue; } switch( msg.i_type ) { case VLC_MSG_INFO: case VLC_MSG_ERR: if( sub->verbosity < 0 ) continue; break; case VLC_MSG_WARN: if( sub->verbosity < 1 ) continue; break; case VLC_MSG_DBG: if( sub->verbosity < 2 ) continue; break; } sub->func (sub->opaque, &msg); } vlc_rwlock_unlock (&bank->lock); free (msg.psz_msg); }
static int Android_ParseFamily( filter_t *p_filter, xml_reader_t *p_xml ) { filter_sys_t *p_sys = p_filter->p_sys; vlc_dictionary_t *p_dict = &p_sys->family_map; vlc_family_t *p_family = NULL; char *psz_lc = NULL; int i_counter = 0; bool b_bold = false; bool b_italic = false; const char *p_node = NULL; int i_type = 0; while( ( i_type = xml_ReaderNextNode( p_xml, &p_node ) ) > 0 ) { switch( i_type ) { case XML_READER_STARTELEM: /* * Multiple names can reference the same family in Android. When * the first name is encountered we set p_family to the vlc_family_t * in the master list matching this name, and if no such family * exists we create a new one and add it to the master list. * If the master list does contain a family with that name it's one * of the font attachments, and the family will end up having embedded * fonts and system fonts. */ if( !strcasecmp( "name", p_node ) ) { i_type = xml_ReaderNextNode( p_xml, &p_node ); if( i_type != XML_READER_TEXT || !p_node || !*p_node ) { msg_Warn( p_filter, "Android_ParseFamily: empty name" ); continue; } psz_lc = ToLower( p_node ); if( unlikely( !psz_lc ) ) return VLC_ENOMEM; if( !p_family ) { p_family = vlc_dictionary_value_for_key( p_dict, psz_lc ); if( p_family == kVLCDictionaryNotFound ) { p_family = NewFamily( p_filter, psz_lc, &p_sys->p_families, NULL, NULL ); if( unlikely( !p_family ) ) { free( psz_lc ); return VLC_ENOMEM; } } } if( vlc_dictionary_value_for_key( p_dict, psz_lc ) == kVLCDictionaryNotFound ) vlc_dictionary_insert( p_dict, psz_lc, p_family ); free( psz_lc ); } /* * If p_family has not been set by the time we encounter the first file, * it means this family has no name, and should be used only as a fallback. * We create a new family for it in the master list with the name "fallback-xx" * and later add it to the "default" fallback list. */ else if( !strcasecmp( "file", p_node ) ) { i_type = xml_ReaderNextNode( p_xml, &p_node ); if( i_type != XML_READER_TEXT || !p_node || !*p_node ) { ++i_counter; continue; } if( !p_family ) p_family = NewFamily( p_filter, NULL, &p_sys->p_families, &p_sys->family_map, NULL ); if( unlikely( !p_family ) ) return VLC_ENOMEM; switch( i_counter ) { case 0: b_bold = false; b_italic = false; break; case 1: b_bold = true; b_italic = false; break; case 2: b_bold = false; b_italic = true; break; case 3: b_bold = true; b_italic = true; break; default: msg_Warn( p_filter, "Android_ParseFamily: too many files" ); return VLC_EGENERIC; } char *psz_fontfile = NULL; if( asprintf( &psz_fontfile, "%s/%s", ANDROID_FONT_PATH, p_node ) < 0 || !NewFont( psz_fontfile, 0, b_bold, b_italic, p_family ) ) return VLC_ENOMEM; ++i_counter; } break; case XML_READER_ENDELEM: if( !strcasecmp( "family", p_node ) ) { if( !p_family ) { msg_Warn( p_filter, "Android_ParseFamily: empty family" ); return VLC_EGENERIC; } /* * If the family name has "fallback" in it, add it to the * "default" fallback list. */ if( strcasestr( p_family->psz_name, FB_NAME ) ) { vlc_family_t *p_fallback = NewFamily( p_filter, p_family->psz_name, NULL, &p_sys->fallback_map, FB_LIST_DEFAULT ); if( unlikely( !p_fallback ) ) return VLC_ENOMEM; p_fallback->p_fonts = p_family->p_fonts; } return VLC_SUCCESS; } break; } } msg_Warn( p_filter, "Android_ParseFamily: Corrupt font configuration file" ); return VLC_EGENERIC; }
vlc_family_t *FontConfig_GetFallbacks( filter_t *p_filter, const char *psz_family, uni_char_t codepoint ) { VLC_UNUSED( codepoint ); vlc_family_t *p_family = NULL; filter_sys_t *p_sys = p_filter->p_sys; char *psz_lc = ToLower( psz_family ); if( unlikely( !psz_lc ) ) return NULL; p_family = vlc_dictionary_value_for_key( &p_sys->fallback_map, psz_lc ); if( p_family != kVLCDictionaryNotFound ) { free( psz_lc ); return p_family; } else p_family = NULL; const char *psz_last_name = ""; FcPattern *p_pattern = FcPatternCreate(); FcValue family; family.type = FcTypeString; family.u.s = ( const FcChar8* ) psz_family; FcPatternAdd( p_pattern, FC_FAMILY, family, FcFalse ); if( FcConfigSubstitute( NULL, p_pattern, FcMatchPattern ) == FcTrue ) { FcDefaultSubstitute( p_pattern ); FcResult result; FcFontSet* p_font_set = FcFontSort( NULL, p_pattern, FcTrue, NULL, &result ); if( p_font_set ) { for( int i = 0; i < p_font_set->nfont; ++i ) { char* psz_name = NULL; FcPatternGetString( p_font_set->fonts[i], FC_FAMILY, 0, ( FcChar8** )( &psz_name ) ); /* Avoid duplicate family names */ if( strcasecmp( psz_last_name, psz_name ) ) { vlc_family_t *p_temp = NewFamily( p_filter, psz_name, &p_family, NULL, NULL ); if( unlikely( !p_temp ) ) { FcFontSetDestroy( p_font_set ); FcPatternDestroy( p_pattern ); if( p_family ) FreeFamilies( p_family, NULL ); free( psz_lc ); return NULL; } psz_last_name = p_temp->psz_name; } } FcFontSetDestroy( p_font_set ); } } FcPatternDestroy( p_pattern ); if( p_family ) vlc_dictionary_insert( &p_sys->fallback_map, psz_lc, p_family ); free( psz_lc ); return p_family; }
/***************************************************************************** * PrintMsg: output a standard message item to stderr ***************************************************************************** * Print a message to stderr, with colour formatting if needed. *****************************************************************************/ static void PrintMsg ( vlc_object_t *p_this, const msg_item_t *p_item ) { # define COL(x,y) "\033[" #x ";" #y "m" # define RED COL(31,1) # define GREEN COL(32,1) # define YELLOW COL(0,33) # define WHITE COL(0,1) # define GRAY "\033[0m" static const char msgtype[4][9] = { "", " error", " warning", " debug" }; static const char msgcolor[4][8] = { WHITE, RED, YELLOW, GRAY }; libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc); int type = p_item->i_type; if (priv->i_verbose < 0 || priv->i_verbose < (type - VLC_MSG_ERR)) return; const char *objtype = p_item->psz_object_type; msg_bank_t *bank = priv->msg_bank; void * val = vlc_dictionary_value_for_key (&bank->enabled_objects, p_item->psz_module); if( val == kObjectPrintingDisabled ) return; if( val == kObjectPrintingEnabled ) /* Allowed */; else { val = vlc_dictionary_value_for_key (&bank->enabled_objects, objtype); if( val == kObjectPrintingDisabled ) return; if( val == kObjectPrintingEnabled ) /* Allowed */; else if( !bank->all_objects_enabled ) return; } /* Send the message to stderr */ FILE *stream = stderr; int canc = vlc_savecancel (); flockfile (stream); fprintf (stream, priv->b_color ? "["GREEN"%p"GRAY"] " : "[%p] ", (void *)p_item->i_object_id); if (p_item->psz_header != NULL) utf8_fprintf (stream, "[%s] ", p_item->psz_header); utf8_fprintf (stream, "%s %s%s: ", p_item->psz_module, objtype, msgtype[type]); if (priv->b_color) fputs (msgcolor[type], stream); fputs (p_item->psz_msg, stream); if (priv->b_color) fputs (GRAY, stream); putc_unlocked ('\n', stream); #if defined (WIN32) || defined (__OS2__) fflush (stream); #endif funlockfile (stream); #ifdef ANDROID int level[] = {ANDROID_LOG_INFO, ANDROID_LOG_ERROR, ANDROID_LOG_WARN, ANDROID_LOG_DEBUG}; __android_log_print( level[p_item->i_type], "faplayer", p_item->psz_header ? "[%p][%s] %s %s: %s" : "[%p]%s%s %s: %s", (void *) p_item->i_object_id, p_item->psz_header ? p_item->psz_header : "", p_item->psz_module, p_item->psz_object_type, p_item->psz_msg ); #endif vlc_restorecancel (canc); }