static int WindowOpen( vout_window_t *pWnd, const vout_window_cfg_t *cfg ) { if( cfg->type != VOUT_WINDOW_TYPE_INVALID ) { #ifdef X11_SKINS if( cfg->type != VOUT_WINDOW_TYPE_XID ) #else if( cfg->type != VOUT_WINDOW_TYPE_HWND ) #endif return VLC_EGENERIC; } vout_window_sys_t* sys; vlc_mutex_lock( &skin_load.mutex ); intf_thread_t *pIntf = skin_load.intf; if( pIntf ) vlc_object_hold( pIntf ); vlc_mutex_unlock( &skin_load.mutex ); if( pIntf == NULL ) return VLC_EGENERIC; if( !var_InheritBool( pIntf, "skinned-video") || cfg->is_standalone ) { vlc_object_release( pIntf ); return VLC_EGENERIC; } sys = (vout_window_sys_t*)calloc( 1, sizeof( *sys ) ); if( !sys ) { vlc_object_release( pIntf ); return VLC_ENOMEM; } pWnd->sys = sys; pWnd->sys->cfg = *cfg; pWnd->sys->pIntf = pIntf; #ifdef X11_SKINS pWnd->type = VOUT_WINDOW_TYPE_XID; #else pWnd->type = VOUT_WINDOW_TYPE_HWND; #endif pWnd->control = WindowControl; // force execution in the skins2 thread context CmdExecuteBlock* cmd = new CmdExecuteBlock( pIntf, VLC_OBJECT( pWnd ), WindowOpenLocal ); CmdExecuteBlock::executeWait( CmdGenericPtr( cmd ) ); #ifdef X11_SKINS pWnd->display.x11 = NULL; if( !pWnd->handle.xid ) #else if( !pWnd->handle.hwnd ) #endif { free( sys ); vlc_object_release( pIntf ); return VLC_EGENERIC; } return VLC_SUCCESS; }
/** * Create and start an interface. * * @param playlist playlist and parent object for the interface * @param chain configuration chain string * @return VLC_SUCCESS or an error code */ int intf_Create( playlist_t *playlist, const char *chain ) { /* Allocate structure */ intf_thread_t *p_intf = vlc_custom_create( playlist, sizeof( *p_intf ), "interface" ); if( unlikely(p_intf == NULL) ) return VLC_ENOMEM; /* Variable used for interface spawning */ vlc_value_t val, text; var_Create( p_intf, "intf-add", VLC_VAR_STRING | VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND ); text.psz_string = _("Add Interface"); var_Change( p_intf, "intf-add", VLC_VAR_SETTEXT, &text, NULL ); #if !defined(_WIN32) && defined(HAVE_ISATTY) if( isatty( 0 ) ) #endif { val.psz_string = (char *)"rc,none"; text.psz_string = (char *)_("Console"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); } val.psz_string = (char *)"telnet,none"; text.psz_string = (char *)_("Telnet"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = (char *)"http,none"; text.psz_string = (char *)_("Web"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = (char *)"logger,none"; text.psz_string = (char *)_("Debug logging"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); val.psz_string = (char *)"gestures,none"; text.psz_string = (char *)_("Mouse Gestures"); var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text ); var_AddCallback( p_intf, "intf-add", AddIntfCallback, playlist ); /* Choose the best module */ char *module; p_intf->p_cfg = NULL; free( config_ChainCreate( &module, &p_intf->p_cfg, chain ) ); p_intf->p_module = module_need( p_intf, "interface", module, true ); free(module); if( p_intf->p_module == NULL ) { msg_Err( p_intf, "no suitable interface module" ); goto error; } vlc_mutex_lock( &lock ); p_intf->p_next = pl_priv( playlist )->interface; pl_priv( playlist )->interface = p_intf; vlc_mutex_unlock( &lock ); return VLC_SUCCESS; error: if( p_intf->p_module ) module_unneed( p_intf, p_intf->p_module ); config_ChainDestroy( p_intf->p_cfg ); vlc_object_release( p_intf ); return VLC_EGENERIC; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to chose. *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_KATE ) { return VLC_EGENERIC; } msg_Dbg( p_dec, "kate: OpenDecoder"); /* Set callbacks */ p_dec->pf_decode_sub = (subpicture_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) DecodeBlock; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL ) return VLC_ENOMEM; vlc_mutex_init( &p_sys->lock ); p_sys->i_refcount = 0; DecSysHold( p_sys ); /* init of p_sys */ #ifdef ENABLE_PACKETIZER p_sys->b_packetizer = false; #endif p_sys->b_ready = false; p_sys->i_pts = 0; p_sys->i_max_stop = VLC_TS_INVALID; kate_comment_init( &p_sys->kc ); kate_info_init( &p_sys->ki ); p_sys->i_num_headers = 0; p_sys->i_headers = 0; /* retrieve options */ p_sys->b_formatted = var_CreateGetBool( p_dec, "kate-formatted" ); vlc_mutex_lock( &kate_decoder_list_mutex ); #ifdef HAVE_TIGER p_sys->b_use_tiger = var_CreateGetBool( p_dec, "kate-use-tiger" ); p_sys->p_tr = NULL; p_sys->last_render_ts = 0; /* get initial value of configuration */ p_sys->i_tiger_default_font_color = GetTigerColor( p_dec, "kate-tiger-default-font" ); p_sys->i_tiger_default_background_color = GetTigerColor( p_dec, "kate-tiger-default-background" ); p_sys->e_tiger_default_font_effect = GetTigerInteger( p_dec, "kate-tiger-default-font-effect" ); p_sys->f_tiger_default_font_effect_strength = GetTigerFloat( p_dec, "kate-tiger-default-font-effect-strength" ); p_sys->psz_tiger_default_font_desc = GetTigerString( p_dec, "kate-tiger-default-font-desc" ); p_sys->f_tiger_quality = GetTigerFloat( p_dec, "kate-tiger-quality" ); if( p_sys->b_use_tiger ) { int i_ret = tiger_renderer_create( &p_sys->p_tr ); if( i_ret < 0 ) { msg_Warn ( p_dec, "Failed to create Tiger renderer, falling back to basic rendering" ); p_sys->p_tr = NULL; p_sys->b_use_tiger = false; } CHECK_TIGER_RET( tiger_renderer_set_surface_clear_color( p_sys->p_tr, 1, 0, 0, 0, 0 ) ); UpdateTigerFontEffect( p_dec ); UpdateTigerFontColor( p_dec ); UpdateTigerBackgroundColor( p_dec ); UpdateTigerQuality( p_dec ); UpdateTigerFontDesc( p_dec ); } #else p_sys->b_use_tiger = false; #endif es_format_Init( &p_dec->fmt_out, SPU_ES, 0 ); /* add the decoder to the global list */ decoder_t **list = realloc( kate_decoder_list, (kate_decoder_list_size+1) * sizeof( *list )); if( list ) { list[ kate_decoder_list_size++ ] = p_dec; kate_decoder_list = list; } vlc_mutex_unlock( &kate_decoder_list_mutex ); return VLC_SUCCESS; }
static int vlclua_input_metas_internal( lua_State *L, input_item_t *p_item ) { if( !p_item ) { lua_pushnil( L ); return 1; } lua_newtable( L ); char *psz_name; const char *psz_meta; psz_name = input_item_GetName( p_item ); lua_pushstring( L, psz_name ); lua_setfield( L, -2, "filename" ); free( psz_name ); #define PUSH_META( n, m ) \ psz_meta = vlc_meta_Get( p_item->p_meta, vlc_meta_ ## n ); \ lua_pushstring( L, psz_meta ); \ lua_setfield( L, -2, m ) vlc_mutex_lock(&p_item->lock); if (p_item->p_meta) { PUSH_META( Title, "title" ); PUSH_META( Artist, "artist" ); PUSH_META( Genre, "genre" ); PUSH_META( Copyright, "copyright" ); PUSH_META( Album, "album" ); PUSH_META( TrackNumber, "track_number" ); PUSH_META( Description, "description" ); PUSH_META( Rating, "rating" ); PUSH_META( Date, "date" ); PUSH_META( Setting, "setting" ); PUSH_META( URL, "url" ); PUSH_META( Language, "language" ); PUSH_META( NowPlaying, "now_playing" ); PUSH_META( Publisher, "publisher" ); PUSH_META( EncodedBy, "encoded_by" ); PUSH_META( ArtworkURL, "artwork_url" ); PUSH_META( TrackID, "track_id" ); PUSH_META( TrackTotal, "track_total" ); #undef PUSH_META char **names = vlc_meta_CopyExtraNames(p_item->p_meta); for(int i = 0; names[i]; i++) { const char *meta = vlc_meta_GetExtra(p_item->p_meta, names[i]); lua_pushstring( L, meta ); lua_setfield( L, -2, names[i] ); free(names[i]); } free(names); } vlc_mutex_unlock(&p_item->lock); return 1; }
/***************************************************************************** * aout_Restart : re-open the output device and rebuild the input and output * pipelines ***************************************************************************** * This function is used whenever the parameters of the output plug-in are * changed (eg. selecting S/PDIF or PCM). *****************************************************************************/ static int aout_Restart( aout_instance_t * p_aout ) { int i; bool b_error = 0; aout_lock_mixer( p_aout ); if ( p_aout->i_nb_inputs == 0 ) { aout_unlock_mixer( p_aout ); msg_Err( p_aout, "no decoder thread" ); return -1; } for ( i = 0; i < p_aout->i_nb_inputs; i++ ) { aout_lock_input( p_aout, p_aout->pp_inputs[i] ); aout_lock_input_fifos( p_aout ); aout_InputDelete( p_aout, p_aout->pp_inputs[i] ); aout_unlock_input_fifos( p_aout ); } /* Lock all inputs. */ aout_lock_input_fifos( p_aout ); aout_MixerDelete( p_aout ); /* Re-open the output plug-in. */ aout_OutputDelete( p_aout ); if ( aout_OutputNew( p_aout, &p_aout->pp_inputs[0]->input ) == -1 ) { /* Release all locks and report the error. */ for ( i = 0; i < p_aout->i_nb_inputs; i++ ) { vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock ); } aout_unlock_input_fifos( p_aout ); aout_unlock_mixer( p_aout ); return -1; } if ( aout_MixerNew( p_aout ) == -1 ) { aout_OutputDelete( p_aout ); for ( i = 0; i < p_aout->i_nb_inputs; i++ ) { vlc_mutex_unlock( &p_aout->pp_inputs[i]->lock ); } aout_unlock_input_fifos( p_aout ); aout_unlock_mixer( p_aout ); return -1; } /* Re-open all inputs. */ for ( i = 0; i < p_aout->i_nb_inputs; i++ ) { aout_input_t * p_input = p_aout->pp_inputs[i]; b_error |= aout_InputNew( p_aout, p_input, &p_input->request_vout ); p_input->b_changed = 1; aout_unlock_input( p_aout, p_input ); } aout_unlock_input_fifos( p_aout ); aout_unlock_mixer( p_aout ); return b_error; }
void input_item_SetEpg( input_item_t *p_item, const vlc_epg_t *p_update ) { vlc_mutex_lock( &p_item->lock ); /* */ vlc_epg_t *p_epg = NULL; for( int i = 0; i < p_item->i_epg; i++ ) { vlc_epg_t *p_tmp = p_item->pp_epg[i]; if( (p_tmp->psz_name == NULL) != (p_update->psz_name == NULL) ) continue; if( p_tmp->psz_name && p_update->psz_name && strcmp(p_tmp->psz_name, p_update->psz_name) ) continue; p_epg = p_tmp; break; } /* */ if( !p_epg ) { p_epg = vlc_epg_New( p_update->psz_name ); if( p_epg ) TAB_APPEND( p_item->i_epg, p_item->pp_epg, p_epg ); } if( p_epg ) vlc_epg_Merge( p_epg, p_update ); vlc_mutex_unlock( &p_item->lock ); if( !p_epg ) return; #ifdef EPG_DEBUG char *psz_epg; if( asprintf( &psz_epg, "EPG %s", p_epg->psz_name ? p_epg->psz_name : "unknown" ) < 0 ) goto signal; input_item_DelInfo( p_item, psz_epg, NULL ); vlc_mutex_lock( &p_item->lock ); for( int i = 0; i < p_epg->i_event; i++ ) { const vlc_epg_event_t *p_evt = p_epg->pp_event[i]; time_t t_start = (time_t)p_evt->i_start; struct tm tm_start; char psz_start[128]; localtime_r( &t_start, &tm_start ); snprintf( psz_start, sizeof(psz_start), "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d", 1900 + tm_start.tm_year, 1 + tm_start.tm_mon, tm_start.tm_mday, tm_start.tm_hour, tm_start.tm_min, tm_start.tm_sec ); if( p_evt->psz_short_description || p_evt->psz_description ) InputItemAddInfo( p_item, psz_epg, psz_start, "%s (%2.2d:%2.2d) - %s %s", p_evt->psz_name, p_evt->i_duration/60/60, (p_evt->i_duration/60)%60, p_evt->psz_short_description ? p_evt->psz_short_description : "" , p_evt->psz_description ? p_evt->psz_description : "" ); else InputItemAddInfo( p_item, psz_epg, psz_start, "%s (%2.2d:%2.2d)", p_evt->psz_name, p_evt->i_duration/60/60, (p_evt->i_duration/60)%60 ); } vlc_mutex_unlock( &p_item->lock ); free( psz_epg ); signal: #endif if( p_epg->i_event > 0 ) { vlc_event_t event = { .type = vlc_InputItemInfoChanged, }; vlc_event_send( &p_item->event_manager, &event ); }
static block_t * DoWork( filter_t * p_filter, block_t * p_in_buf ) { int i_samples = p_in_buf->i_nb_samples; int i_channels = aout_FormatNbChannels( &p_filter->fmt_in.audio ); float *pf_buf = (float*)p_in_buf->p_buffer; /* Current parameters */ filter_sys_t *p_sys = p_filter->p_sys; /* Fetch the configurable parameters */ vlc_mutex_lock( &p_sys->lock ); float f_rms_peak = p_sys->f_rms_peak; /* RMS/peak */ float f_attack = p_sys->f_attack; /* Attack time (ms) */ float f_release = p_sys->f_release; /* Release time (ms) */ float f_threshold = p_sys->f_threshold; /* Threshold level (dB) */ float f_ratio = p_sys->f_ratio; /* Ratio (n:1) */ float f_knee = p_sys->f_knee; /* Knee radius (dB) */ float f_makeup_gain = p_sys->f_makeup_gain; /* Makeup gain (dB) */ vlc_mutex_unlock( &p_sys->lock ); /* Fetch the internal parameters */ float f_amp = p_sys->f_amp; float *pf_as = p_sys->pf_as; float f_env = p_sys->f_env; float f_env_peak = p_sys->f_env_peak; float f_env_rms = p_sys->f_env_rms; float f_gain = p_sys->f_gain; float f_gain_out = p_sys->f_gain_out; rms_env *p_rms = &p_sys->rms; float f_sum = p_sys->f_sum; lookahead *p_la = &p_sys->la; /* Prepare other compressor parameters */ float f_ga = f_attack < 2.0f ? 0.0f : pf_as[Round( f_attack * 0.001f * ( A_TBL - 1 ) )]; float f_gr = pf_as[Round( f_release * 0.001f * ( A_TBL - 1 ) )]; float f_rs = ( f_ratio - 1.0f ) / f_ratio; float f_mug = Db2Lin( f_makeup_gain, p_sys ); float f_knee_min = Db2Lin( f_threshold - f_knee, p_sys ); float f_knee_max = Db2Lin( f_threshold + f_knee, p_sys ); float f_ef_a = f_ga * 0.25f; float f_ef_ai = 1.0f - f_ef_a; /* Process the current buffer */ for( int i = 0; i < i_samples; i++ ) { float f_lev_in_old, f_lev_in_new; /* Now, compress the pre-equalized audio (ported from sc4_1882 * plugin with a few modifications) */ /* Fetch the old delayed buffer value */ f_lev_in_old = p_la->p_buf[p_la->i_pos].f_lev_in; /* Find the peak value of current sample. This becomes the new delayed * buffer value that replaces the old one in the lookahead array */ f_lev_in_new = fabs( pf_buf[0] ); for( int i_chan = 1; i_chan < i_channels; i_chan++ ) { f_lev_in_new = Max( f_lev_in_new, fabs( pf_buf[i_chan] ) ); } p_la->p_buf[p_la->i_pos].f_lev_in = f_lev_in_new; /* Add the square of the peak value to a running sum */ f_sum += f_lev_in_new * f_lev_in_new; /* Update the RMS envelope */ if( f_amp > f_env_rms ) { f_env_rms = f_env_rms * f_ga + f_amp * ( 1.0f - f_ga ); } else { f_env_rms = f_env_rms * f_gr + f_amp * ( 1.0f - f_gr ); } RoundToZero( &f_env_rms ); /* Update the peak envelope */ if( f_lev_in_old > f_env_peak ) { f_env_peak = f_env_peak * f_ga + f_lev_in_old * ( 1.0f - f_ga ); } else { f_env_peak = f_env_peak * f_gr + f_lev_in_old * ( 1.0f - f_gr ); } RoundToZero( &f_env_peak ); /* Process the RMS value and update the output gain every 4 samples */ if( ( p_sys->i_count++ & 3 ) == 3 ) { /* Process the RMS value by placing in the mean square value, and * reset the running sum */ f_amp = RmsEnvProcess( p_rms, f_sum * 0.25f ); f_sum = 0.0f; if( cover_isnan( f_env_rms ) ) // sunqueen modify { /* This can happen sometimes, but I don't know why. */ f_env_rms = 0.0f; } /* Find the superposition of the RMS and peak envelopes */ f_env = LIN_INTERP( f_rms_peak, f_env_rms, f_env_peak ); /* Update the output gain */ if( f_env <= f_knee_min ) { /* Gain below the knee (and below the threshold) */ f_gain_out = 1.0f; } else if( f_env < f_knee_max ) { /* Gain within the knee */ const float f_x = -( f_threshold - f_knee - Lin2Db( f_env, p_sys ) ) / f_knee; f_gain_out = Db2Lin( -f_knee * f_rs * f_x * f_x * 0.25f, p_sys ); } else { /* Gain above the knee (and above the threshold) */ f_gain_out = Db2Lin( ( f_threshold - Lin2Db( f_env, p_sys ) ) * f_rs, p_sys ); } } /* Find the total gain */ f_gain = f_gain * f_ef_a + f_gain_out * f_ef_ai; /* Write the resulting buffer to the output */ BufferProcess( pf_buf, i_channels, f_gain, f_mug, p_la ); pf_buf += i_channels; } /* Update the internal parameters */ p_sys->f_sum = f_sum; p_sys->f_amp = f_amp; p_sys->f_gain = f_gain; p_sys->f_gain_out = f_gain_out; p_sys->f_env = f_env; p_sys->f_env_rms = f_env_rms; p_sys->f_env_peak = f_env_peak; return p_in_buf; }
/***************************************************************************** * Decode: *****************************************************************************/ static int Decode( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; subpicture_t *p_spu = NULL; video_format_t fmt; bool b_cached = false; vbi_page p_page; if( p_block == NULL ) /* No Drain */ return VLCDEC_SUCCESS; if( p_block->i_buffer > 0 && ( ( p_block->p_buffer[0] >= 0x10 && p_block->p_buffer[0] <= 0x1f ) || ( p_block->p_buffer[0] >= 0x99 && p_block->p_buffer[0] <= 0x9b ) ) ) { vbi_sliced *p_sliced = p_sys->p_vbi_sliced; unsigned int i_lines = 0; p_block->i_buffer--; p_block->p_buffer++; while( p_block->i_buffer >= 2 ) { int i_id = p_block->p_buffer[0]; unsigned i_size = p_block->p_buffer[1]; if( 2 + i_size > p_block->i_buffer ) break; if( ( i_id == 0x02 || i_id == 0x03 ) && i_size >= 44 && i_lines < MAX_SLICES ) { if(p_block->p_buffer[3] == 0xE4 ) /* framing_code */ { unsigned line_offset = p_block->p_buffer[2] & 0x1f; unsigned field_parity = p_block->p_buffer[2] & 0x20; p_sliced[i_lines].id = VBI_SLICED_TELETEXT_B; if( line_offset > 0 ) p_sliced[i_lines].line = line_offset + (field_parity ? 0 : 313); else p_sliced[i_lines].line = 0; for( int i = 0; i < 42; i++ ) p_sliced[i_lines].data[i] = vbi_rev8( p_block->p_buffer[4 + i] ); i_lines++; } } p_block->i_buffer -= 2 + i_size; p_block->p_buffer += 2 + i_size; } if( i_lines > 0 ) vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, 0 ); } /* */ vlc_mutex_lock( &p_sys->lock ); if( p_sys->i_wanted_page == 0 ) { vlc_mutex_unlock( &p_sys->lock ); block_Release( p_block ); return VLCDEC_SUCCESS; } const int i_align = p_sys->i_align; const unsigned int i_wanted_page = p_sys->i_wanted_page; const unsigned int i_wanted_subpage = p_sys->i_wanted_subpage; const bool b_opaque = p_sys->b_opaque; const unsigned int i_level = p_sys->i_level > 3 ? 3 : p_sys->i_level; vlc_mutex_unlock( &p_sys->lock ); /* Try to see if the page we want is in the cache yet */ memset( &p_page, 0, sizeof(vbi_page) ); b_cached = vbi_fetch_vt_page( p_sys->p_vbi_dec, &p_page, vbi_dec2bcd( i_wanted_page ), i_wanted_subpage, level_zvbi_values[i_level], 25, true ); if( i_wanted_page == p_sys->i_last_page && !p_sys->b_update ) goto error; if( !b_cached ) { if( p_sys->b_text && p_sys->i_last_page != i_wanted_page ) { /* We need to reset the subtitle */ p_spu = Subpicture( p_dec, &fmt, true, p_page.columns, p_page.rows, i_align, p_block->i_pts ); if( !p_spu ) goto error; subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->region.p_segments = text_segment_New(""); p_sys->b_update = true; p_sys->i_last_page = i_wanted_page; goto exit; } goto error; } p_sys->b_update = false; p_sys->i_last_page = i_wanted_page; #ifdef ZVBI_DEBUG msg_Dbg( p_dec, "we now have page: %d ready for display", i_wanted_page ); #endif /* Ignore transparent rows at the beginning and end */ int i_first_row = get_first_visible_row( p_page.text, p_page.rows, p_page.columns ); int i_num_rows; if ( i_first_row < 0 ) { i_first_row = p_page.rows - 1; i_num_rows = 0; } else { i_num_rows = get_last_visible_row( p_page.text, p_page.rows, p_page.columns ) - i_first_row + 1; } #ifdef ZVBI_DEBUG msg_Dbg( p_dec, "After top and tail of page we have rows %i-%i of %i", i_first_row + 1, i_first_row + i_num_rows, p_page.rows ); #endif /* If there is a page or sub to render, then we do that here */ /* Create the subpicture unit */ p_spu = Subpicture( p_dec, &fmt, p_sys->b_text, p_page.columns, i_num_rows, i_align, p_block->i_pts ); if( !p_spu ) goto error; if( p_sys->b_text ) { unsigned int i_textsize = 7000; int i_total,offset; char p_text[i_textsize+1]; i_total = vbi_print_page_region( &p_page, p_text, i_textsize, "UTF-8", 0, 0, 0, i_first_row, p_page.columns, i_num_rows ); for( offset=1; offset<i_total && isspace( p_text[i_total-offset ] ); offset++) p_text[i_total-offset] = '\0'; i_total -= offset; offset=0; while( offset < i_total && isspace( p_text[offset] ) ) offset++; subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->region.p_segments = text_segment_New( &p_text[offset] ); if( p_spu_sys->region.p_segments && b_opaque ) { p_spu_sys->region.p_segments->style = text_style_Create( STYLE_NO_DEFAULTS ); if( p_spu_sys->region.p_segments->style ) { /* Set text background */ p_spu_sys->region.p_segments->style->i_style_flags = STYLE_BACKGROUND; p_spu_sys->region.p_segments->style->i_features |= STYLE_HAS_FLAGS; } } p_spu_sys->region.inner_align = i_align; p_spu_sys->region.flags = UPDT_REGION_IGNORE_BACKGROUND; #ifdef ZVBI_DEBUG msg_Info( p_dec, "page %x-%x(%d)\n\"%s\"", p_page.pgno, p_page.subno, i_total, &p_text[offset] ); #endif } else { picture_t *p_pic = p_spu->p_region->p_picture; /* ZVBI is stupid enough to assume pitch == width */ p_pic->p->i_pitch = 4 * fmt.i_width; /* Maintain subtitle postion */ p_spu->p_region->i_y = i_first_row*10; p_spu->i_original_picture_width = p_page.columns*12; p_spu->i_original_picture_height = p_page.rows*10; vbi_draw_vt_page_region( &p_page, ZVBI_PIXFMT_RGBA32, p_spu->p_region->p_picture->p->p_pixels, -1, 0, i_first_row, p_page.columns, i_num_rows, 1, 1); vlc_mutex_lock( &p_sys->lock ); memcpy( p_sys->nav_link, &p_page.nav_link, sizeof( p_sys->nav_link )) ; vlc_mutex_unlock( &p_sys->lock ); OpaquePage( p_pic, &p_page, &fmt, b_opaque, i_first_row * p_page.columns ); } exit: vbi_unref_page( &p_page ); block_Release( p_block ); if( p_spu ) decoder_QueueSub( p_dec, p_spu ); return VLCDEC_SUCCESS; error: vbi_unref_page( &p_page ); block_Release( p_block ); return VLCDEC_SUCCESS; }
/** * This function initializes SDL vout method. */ static int Open(vlc_object_t *object) { vout_display_t *vd = (vout_display_t *)object; vout_display_sys_t *sys; #if !defined(_WIN32) && !defined(__OS2__) if (!vlc_xlib_init (object)) return VLC_EGENERIC; #endif /* XXX: check for conflicts with the SDL audio output */ vlc_mutex_lock(&sdl_lock); /* Check if SDL video module has been initialized */ if (SDL_WasInit(SDL_INIT_VIDEO) != 0) { vlc_mutex_unlock(&sdl_lock); return VLC_EGENERIC; } vd->sys = sys = calloc(1, sizeof(*sys)); if (!sys) { vlc_mutex_unlock(&sdl_lock); return VLC_ENOMEM; } /* */ int sdl_flags = SDL_INIT_VIDEO; #ifndef _WIN32 /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/ sdl_flags |= SDL_INIT_EVENTTHREAD; #endif /* In debug mode you may want vlc to dump a core instead of staying stuck */ sdl_flags |= SDL_INIT_NOPARACHUTE; /* Initialize library */ if (SDL_Init(sdl_flags) < 0) { vlc_mutex_unlock(&sdl_lock); msg_Err(vd, "cannot initialize SDL (%s)", SDL_GetError()); free(sys); return VLC_EGENERIC; } vlc_mutex_unlock(&sdl_lock); /* Translate keys into unicode */ SDL_EnableUNICODE(1); /* Get the desktop resolution */ /* FIXME: SDL has a problem with virtual desktop */ sys->desktop_width = SDL_GetVideoInfo()->current_w; sys->desktop_height = SDL_GetVideoInfo()->current_h; /* */ video_format_t fmt; video_format_ApplyRotation(&fmt, &vd->fmt); /* */ vout_display_info_t info = vd->info; /* Set main window's size */ int display_width; int display_height; if (vd->cfg->is_fullscreen) { display_width = sys->desktop_width; display_height = sys->desktop_height; } else { display_width = vd->cfg->display.width; display_height = vd->cfg->display.height; } /* Initialize flags and cursor */ sys->display_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF; sys->display_flags |= vd->cfg->is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE; sys->display_bpp = SDL_VideoModeOK(display_width, display_height, 16, sys->display_flags); if (sys->display_bpp == 0) { msg_Err(vd, "no video mode available"); goto error; } vout_display_DeleteWindow(vd, NULL); sys->display = SDL_SetVideoMode(display_width, display_height, sys->display_bpp, sys->display_flags); if (!sys->display) { msg_Err(vd, "cannot set video mode"); goto error; } /* We keep the surface locked forever */ SDL_LockSurface(sys->display); /* */ vlc_fourcc_t forced_chroma = 0; char *psz_chroma = var_InheritString(vd, "sdl-chroma"); if (psz_chroma) { forced_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_chroma); if (forced_chroma) msg_Dbg(vd, "Forcing chroma to 0x%.8x (%4.4s)", forced_chroma, (const char*)&forced_chroma); free(psz_chroma); } /* Try to open an overlay if requested */ sys->overlay = NULL; const bool is_overlay = var_InheritBool(vd, "overlay"); if (is_overlay) { static const struct { vlc_fourcc_t vlc; uint32_t sdl; } vlc_to_sdl[] = { { VLC_CODEC_YV12, SDL_YV12_OVERLAY }, { VLC_CODEC_I420, SDL_IYUV_OVERLAY }, { VLC_CODEC_YUYV, SDL_YUY2_OVERLAY }, { VLC_CODEC_UYVY, SDL_UYVY_OVERLAY }, { VLC_CODEC_YVYU, SDL_YVYU_OVERLAY }, { 0, 0 } }; const vlc_fourcc_t forced_chromas[] = { forced_chroma, 0 }; const vlc_fourcc_t *fallback_chromas = vlc_fourcc_GetYUVFallback(fmt.i_chroma); const vlc_fourcc_t *chromas = forced_chroma ? forced_chromas : fallback_chromas; for (int pass = forced_chroma ? 1 : 0; pass < 2 && !sys->overlay; pass++) { for (int i = 0; chromas[i] != 0; i++) { const vlc_fourcc_t vlc = chromas[i]; uint32_t sdl = 0; for (int j = 0; vlc_to_sdl[j].vlc != 0 && !sdl; j++) { if (vlc_to_sdl[j].vlc == vlc) sdl = vlc_to_sdl[j].sdl; } if (!sdl) continue; sys->overlay = SDL_CreateYUVOverlay(fmt.i_width, fmt.i_height, sdl, sys->display); if (sys->overlay && !sys->overlay->hw_overlay && pass == 0) { /* Ignore non hardware overlay surface in first pass */ SDL_FreeYUVOverlay(sys->overlay); sys->overlay = NULL; } if (sys->overlay) { /* We keep the surface locked forever */ SDL_LockYUVOverlay(sys->overlay); fmt.i_chroma = vlc; sys->is_uv_swapped = vlc_fourcc_AreUVPlanesSwapped(fmt.i_chroma, vd->fmt.i_chroma); if (sys->is_uv_swapped) fmt.i_chroma = vd->fmt.i_chroma; break; } } } } else { msg_Warn(vd, "SDL overlay disabled by the user"); } /* */ vout_display_cfg_t place_cfg = *vd->cfg; place_cfg.display.width = display_width; place_cfg.display.height = display_height; vout_display_PlacePicture(&sys->place, &vd->source, &place_cfg, !sys->overlay); /* If no overlay, fallback to software output */ if (!sys->overlay) { /* */ switch (sys->display->format->BitsPerPixel) { case 8: fmt.i_chroma = VLC_CODEC_RGB8; break; case 15: fmt.i_chroma = VLC_CODEC_RGB15; break; case 16: fmt.i_chroma = VLC_CODEC_RGB16; break; case 24: fmt.i_chroma = VLC_CODEC_RGB24; break; case 32: fmt.i_chroma = VLC_CODEC_RGB32; break; default: msg_Err(vd, "unknown screen depth %i", sys->display->format->BitsPerPixel); goto error; } /* All we have is an RGB image with square pixels */ fmt.i_width = display_width; fmt.i_height = display_height; fmt.i_rmask = sys->display->format->Rmask; fmt.i_gmask = sys->display->format->Gmask; fmt.i_bmask = sys->display->format->Bmask; info.has_pictures_invalid = true; } if (vd->cfg->display.title) SDL_WM_SetCaption(vd->cfg->display.title, vd->cfg->display.title); else if (!sys->overlay) SDL_WM_SetCaption(VOUT_TITLE " (software RGB SDL output)", VOUT_TITLE " (software RGB SDL output)"); else if (sys->overlay->hw_overlay) SDL_WM_SetCaption(VOUT_TITLE " (hardware YUV SDL output)", VOUT_TITLE " (hardware YUV SDL output)"); else SDL_WM_SetCaption(VOUT_TITLE " (software YUV SDL output)", VOUT_TITLE " (software YUV SDL output)"); /* Setup events */ SDL_EventState(SDL_KEYUP, SDL_IGNORE); /* ignore keys up */ /* Setup vout_display now that everything is fine */ vd->fmt = fmt; vd->info = info; vd->pool = Pool; vd->prepare = NULL; vd->display = PictureDisplay; vd->control = Control; vd->manage = Manage; /* */ vout_display_SendEventDisplaySize(vd, display_width, display_height, vd->cfg->is_fullscreen); return VLC_SUCCESS; error: msg_Err(vd, "cannot set up SDL (%s)", SDL_GetError()); if (sys->display) { SDL_UnlockSurface(sys->display); SDL_FreeSurface(sys->display); } vlc_mutex_lock(&sdl_lock); SDL_QuitSubSystem(SDL_INIT_VIDEO); vlc_mutex_unlock(&sdl_lock); free(sys); return VLC_EGENERIC; }
void EventThreadUseOverlay( event_thread_t *p_event, bool b_used ) { vlc_mutex_lock( &p_event->lock ); p_event->use_overlay = b_used; vlc_mutex_unlock( &p_event->lock ); }
/***************************************************************************** * WinVoutEventProc: This is the window event processing function. ***************************************************************************** * On Windows, when you create a window you have to attach an event processing * function to it. The aim of this function is to manage "Queued Messages" and * "Nonqueued Messages". * Queued Messages are those picked up and retransmitted by vout_Manage * (using the GetMessage and DispatchMessage functions). * Nonqueued Messages are those that Windows will send directly to this * procedure (like WM_DESTROY, WM_WINDOWPOSCHANGED...) *****************************************************************************/ static long FAR PASCAL WinVoutEventProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { event_thread_t *p_event; if( message == WM_CREATE ) { /* Store vd for future use */ p_event = (event_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams; SetWindowLongPtr( hwnd, GWLP_USERDATA, (LONG_PTR)p_event ); return TRUE; } else { LONG_PTR p_user_data = GetWindowLongPtr( hwnd, GWLP_USERDATA ); p_event = (event_thread_t *)p_user_data; if( !p_event ) { /* Hmmm mozilla does manage somehow to save the pointer to our * windowproc and still calls it after the vout has been closed. */ return DefWindowProc(hwnd, message, wParam, lParam); } } vout_display_t *vd = p_event->vd; #if 0 if( message == WM_SETCURSOR ) { msg_Err(vd, "WM_SETCURSOR: %d (t2)", p_event->is_cursor_hidden); SetCursor( p_event->is_cursor_hidden ? p_event->cursor_empty : p_event->cursor_arrow ); return 1; } #endif if( message == WM_CAPTURECHANGED ) { for( int button = 0; p_event->button_pressed; button++ ) { unsigned m = 1 << button; if( p_event->button_pressed & m ) vout_display_SendEventMouseReleased( p_event->vd, button ); p_event->button_pressed &= ~m; } p_event->button_pressed = 0; return 0; } if( hwnd == p_event->hvideownd ) { #ifdef MODULE_NAME_IS_directdraw vlc_mutex_lock( &p_event->lock ); const bool use_overlay = p_event->use_overlay; vlc_mutex_unlock( &p_event->lock ); #endif switch( message ) { #ifdef MODULE_NAME_IS_directdraw case WM_ERASEBKGND: /* For overlay, we need to erase background */ return !use_overlay ? 1 : DefWindowProc(hwnd, message, wParam, lParam); case WM_PAINT: /* ** For overlay, DefWindowProc() will erase dirty regions ** with colorkey. ** For non-overlay, vout will paint the whole window at ** regular interval, therefore dirty regions can be ignored ** to minimize repaint. */ if( !use_overlay ) { ValidateRect(hwnd, NULL); } // fall through to default #else /* ** For OpenGL and Direct3D, vout will update the whole ** window at regular interval, therefore dirty region ** can be ignored to minimize repaint. */ case WM_ERASEBKGND: /* nothing to erase */ return 1; case WM_PAINT: /* nothing to repaint */ ValidateRect(hwnd, NULL); // fall through #endif default: return DefWindowProc(hwnd, message, wParam, lParam); } } switch( message ) { case WM_WINDOWPOSCHANGED: vlc_mutex_lock( &p_event->lock ); p_event->has_moved = true; vlc_mutex_unlock( &p_event->lock ); return 0; /* the user wants to close the window */ case WM_CLOSE: vout_display_SendEventClose(vd); return 0; /* the window has been closed so shut down everything now */ case WM_DESTROY: msg_Dbg( vd, "WinProc WM_DESTROY" ); /* just destroy the window */ PostQuitMessage( 0 ); return 0; case WM_SYSCOMMAND: switch (wParam) { case IDM_TOGGLE_ON_TOP: /* toggle the "on top" status */ { msg_Dbg(vd, "WinProc WM_SYSCOMMAND: IDM_TOGGLE_ON_TOP"); HMENU hMenu = GetSystemMenu(vd->sys->hwnd, FALSE); vout_display_SendWindowState(vd, (GetMenuState(hMenu, IDM_TOGGLE_ON_TOP, MF_BYCOMMAND) & MF_CHECKED) ? VOUT_WINDOW_STATE_NORMAL : VOUT_WINDOW_STATE_ABOVE); return 0; } default: break; } break; case WM_PAINT: case WM_NCPAINT: case WM_ERASEBKGND: return DefWindowProc(hwnd, message, wParam, lParam); case WM_KILLFOCUS: return 0; case WM_SETFOCUS: return 0; case WM_GESTURE: return DecodeGesture( VLC_OBJECT(vd), p_event->p_gesture, hwnd, message, wParam, lParam ); default: //msg_Dbg( vd, "WinProc WM Default %i", message ); break; } /* Let windows handle the message */ return DefWindowProc(hwnd, message, wParam, lParam); }
/***************************************************************************** * EventThread: Create video window & handle its messages ***************************************************************************** * This function creates a video window and then enters an infinite loop * that handles the messages sent to that window. * The main goal of this thread is to isolate the Win32 PeekMessage function * because this one can block for a long time. *****************************************************************************/ static void *EventThread( void *p_this ) { event_thread_t *p_event = (event_thread_t *)p_this; vout_display_t *vd = p_event->vd; MSG msg; POINT old_mouse_pos = {0,0}, mouse_pos; int canc = vlc_savecancel (); bool b_mouse_support = var_InheritBool( p_event->vd, "mouse-events" ); bool b_key_support = var_InheritBool( p_event->vd, "keyboard-events" ); vlc_mutex_lock( &p_event->lock ); /* Create a window for the video */ /* Creating a window under Windows also initializes the thread's event * message queue */ if( Win32VoutCreateWindow( p_event ) ) p_event->b_error = true; p_event->b_ready = true; vlc_cond_signal( &p_event->wait ); const bool b_error = p_event->b_error; vlc_mutex_unlock( &p_event->lock ); if( b_error ) { vlc_restorecancel( canc ); return NULL; } /* Prevent monitor from powering off */ if (var_GetBool(vd, "disable-screensaver")) SetThreadExecutionState( ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED | ES_CONTINUOUS ); /* Main loop */ /* GetMessage will sleep if there's no message in the queue */ for( ;; ) { vout_display_place_t place; video_format_t source; if( !GetMessage( &msg, 0, 0, 0 ) ) { vlc_mutex_lock( &p_event->lock ); p_event->b_done = true; vlc_mutex_unlock( &p_event->lock ); break; } /* Check if we are asked to exit */ vlc_mutex_lock( &p_event->lock ); const bool b_done = p_event->b_done; vlc_mutex_unlock( &p_event->lock ); if( b_done ) break; if( !b_mouse_support && isMouseEvent( msg.message ) ) continue; if( !b_key_support && isKeyEvent( msg.message ) ) continue; /* Handle mouse state */ if( msg.message == WM_MOUSEMOVE || msg.message == WM_NCMOUSEMOVE ) { GetCursorPos( &mouse_pos ); /* FIXME, why this >2 limits ? */ if( (abs(mouse_pos.x - old_mouse_pos.x) > 2 || (abs(mouse_pos.y - old_mouse_pos.y)) > 2 ) ) { old_mouse_pos = mouse_pos; UpdateCursor( p_event, true ); } } else if( isMouseEvent( msg.message ) ) { UpdateCursor( p_event, true ); } else if( msg.message == WM_VLC_HIDE_MOUSE ) { UpdateCursor( p_event, false ); } /* */ switch( msg.message ) { case WM_MOUSEMOVE: vlc_mutex_lock( &p_event->lock ); place = p_event->place; source = p_event->source; vlc_mutex_unlock( &p_event->lock ); if( place.width > 0 && place.height > 0 ) { if( msg.hwnd == p_event->hvideownd ) { /* Child window */ place.x = 0; place.y = 0; } const int x = source.i_x_offset + (int64_t)(GET_X_LPARAM(msg.lParam) - place.x) * source.i_width / place.width; const int y = source.i_y_offset + (int64_t)(GET_Y_LPARAM(msg.lParam) - place.y) * source.i_height / place.height; vout_display_SendEventMouseMoved(vd, x, y); } break; case WM_NCMOUSEMOVE: break; case WM_VLC_HIDE_MOUSE: break; case WM_LBUTTONDOWN: MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_LEFT ); break; case WM_LBUTTONUP: MouseReleased( p_event, MOUSE_BUTTON_LEFT ); break; case WM_LBUTTONDBLCLK: vout_display_SendEventMouseDoubleClick(vd); break; case WM_MBUTTONDOWN: MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_CENTER ); break; case WM_MBUTTONUP: MouseReleased( p_event, MOUSE_BUTTON_CENTER ); break; case WM_RBUTTONDOWN: MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_RIGHT ); break; case WM_RBUTTONUP: MouseReleased( p_event, MOUSE_BUTTON_RIGHT ); break; case WM_KEYDOWN: case WM_SYSKEYDOWN: { /* The key events are first processed here and not translated * into WM_CHAR events because we need to know the status of the * modifier keys. */ int i_key = Win32VoutConvertKey( msg.wParam ); if( !i_key ) { /* This appears to be a "normal" (ascii) key */ i_key = tolower( (unsigned char)MapVirtualKey( msg.wParam, 2 ) ); } if( i_key ) { if( GetKeyState(VK_CONTROL) & 0x8000 ) { i_key |= KEY_MODIFIER_CTRL; } if( GetKeyState(VK_SHIFT) & 0x8000 ) { i_key |= KEY_MODIFIER_SHIFT; } if( GetKeyState(VK_MENU) & 0x8000 ) { i_key |= KEY_MODIFIER_ALT; } vout_display_SendEventKey(vd, i_key); } break; } case WM_MOUSEWHEEL: { int i_key; if( GET_WHEEL_DELTA_WPARAM( msg.wParam ) > 0 ) { i_key = KEY_MOUSEWHEELUP; } else { i_key = KEY_MOUSEWHEELDOWN; } if( i_key ) { if( GetKeyState(VK_CONTROL) & 0x8000 ) { i_key |= KEY_MODIFIER_CTRL; } if( GetKeyState(VK_SHIFT) & 0x8000 ) { i_key |= KEY_MODIFIER_SHIFT; } if( GetKeyState(VK_MENU) & 0x8000 ) { i_key |= KEY_MODIFIER_ALT; } vout_display_SendEventKey(vd, i_key); } break; } case WM_VLC_CHANGE_TEXT: { vlc_mutex_lock( &p_event->lock ); wchar_t *pwz_title = NULL; if( p_event->psz_title ) { const size_t i_length = strlen(p_event->psz_title); pwz_title = (wchar_t *)malloc( 2 * (i_length + 1) ); // sunqueen modify if( pwz_title ) { mbstowcs( pwz_title, p_event->psz_title, 2 * i_length ); pwz_title[i_length] = 0; } } vlc_mutex_unlock( &p_event->lock ); if( pwz_title ) { SetWindowTextW( p_event->hwnd, pwz_title ); if( p_event->hfswnd ) SetWindowTextW( p_event->hfswnd, pwz_title ); free( pwz_title ); } break; } default: /* Messages we don't handle directly are dispatched to the * window procedure */ TranslateMessage(&msg); DispatchMessage(&msg); break; } /* End Switch */ } /* End Main loop */ /* Check for WM_QUIT if we created the window */ if( !p_event->hparent && msg.message == WM_QUIT ) { msg_Warn( vd, "WM_QUIT... should not happen!!" ); p_event->hwnd = NULL; /* Window already destroyed */ } msg_Dbg( vd, "Win32 Vout EventThread terminating" ); Win32VoutCloseWindow( p_event ); vlc_restorecancel(canc); return NULL; }
static picture_t *FilterPacked( filter_t *p_filter, picture_t *p_pic ) { picture_t *p_outpic; filter_sys_t *p_sys = p_filter->p_sys; vlc_mutex_lock( &p_sys->lock ); int i_simthres = p_sys->i_simthres; int i_satthres = p_sys->i_satthres; int i_color = p_sys->i_color; vlc_mutex_unlock( &p_sys->lock ); if( !p_pic ) return NULL; p_outpic = filter_NewPicture( p_filter ); if( !p_outpic ) { picture_Release( p_pic ); return NULL; } int i_y_offset, i_u_offset, i_v_offset; int i_ret = GetPackedYuvOffsets( p_filter->fmt_in.video.i_chroma, &i_y_offset, &i_u_offset, &i_v_offset ); if( i_ret == VLC_EGENERIC ) { picture_Release( p_pic ); return NULL; } /* * Copy Y and do the U and V planes */ int refu, refv, reflength; GetReference( &refu, &refv, &reflength, i_color ); for( int y = 0; y < p_pic->p->i_visible_lines; y++ ) { uint8_t *p_src = &p_pic->p->p_pixels[y * p_pic->p->i_pitch]; uint8_t *p_dst = &p_outpic->p->p_pixels[y * p_outpic->p->i_pitch]; for( int x = 0; x < p_pic->p->i_visible_pitch / 4; x++ ) { p_dst[i_y_offset + 0] = p_src[i_y_offset + 0]; p_dst[i_y_offset + 2] = p_src[i_y_offset + 2]; if( IsSimilar( p_src[i_u_offset] - 0x80, p_src[i_v_offset] - 0x80, refu, refv, reflength, i_satthres, i_simthres ) ) { p_dst[i_u_offset] = p_src[i_u_offset]; p_dst[i_v_offset] = p_src[i_v_offset]; } else { p_dst[i_u_offset] = 0x80; p_dst[i_v_offset] = 0x80; } p_dst += 4; p_src += 4; } } return CopyInfoAndRelease( p_outpic, p_pic ); }
//--------------------------------------------------------------------------- // Open: initialize interface //--------------------------------------------------------------------------- static int Open( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; // Allocate instance and initialize some members p_intf->p_sys = (intf_sys_t *) calloc( 1, sizeof( intf_sys_t ) ); if( p_intf->p_sys == NULL ) return VLC_ENOMEM; p_intf->p_sys->p_input = NULL; p_intf->p_sys->p_playlist = pl_Get( p_intf ); // Initialize "singleton" objects p_intf->p_sys->p_logger = NULL; p_intf->p_sys->p_queue = NULL; p_intf->p_sys->p_dialogs = NULL; p_intf->p_sys->p_interpreter = NULL; p_intf->p_sys->p_osFactory = NULL; p_intf->p_sys->p_osLoop = NULL; p_intf->p_sys->p_varManager = NULL; p_intf->p_sys->p_voutManager = NULL; p_intf->p_sys->p_vlcProc = NULL; p_intf->p_sys->p_repository = NULL; // No theme yet p_intf->p_sys->p_theme = NULL; vlc_mutex_init( &p_intf->p_sys->init_lock ); vlc_cond_init( &p_intf->p_sys->init_wait ); vlc_mutex_lock( &p_intf->p_sys->init_lock ); p_intf->p_sys->b_error = false; p_intf->p_sys->b_ready = false; if( vlc_clone( &p_intf->p_sys->thread, Run, p_intf, VLC_THREAD_PRIORITY_LOW ) ) { vlc_mutex_unlock( &p_intf->p_sys->init_lock ); vlc_cond_destroy( &p_intf->p_sys->init_wait ); vlc_mutex_destroy( &p_intf->p_sys->init_lock ); free( p_intf->p_sys ); return VLC_EGENERIC; } while( !p_intf->p_sys->b_ready ) vlc_cond_wait( &p_intf->p_sys->init_wait, &p_intf->p_sys->init_lock ); vlc_mutex_unlock( &p_intf->p_sys->init_lock ); if( p_intf->p_sys->b_error ) { vlc_join( p_intf->p_sys->thread, NULL ); vlc_mutex_destroy( &p_intf->p_sys->init_lock ); vlc_cond_destroy( &p_intf->p_sys->init_wait ); free( p_intf->p_sys ); return VLC_EGENERIC; } vlc_mutex_lock( &skin_load.mutex ); skin_load.intf = p_intf; vlc_mutex_unlock( &skin_load.mutex ); return VLC_SUCCESS; }
/***************************************************************************** * aout_InputPlay : play a buffer ***************************************************************************** * This function must be entered with the input lock. *****************************************************************************/ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input, aout_buffer_t * p_buffer ) { mtime_t start_date; if( p_input->b_restart ) { aout_fifo_t fifo, dummy_fifo; byte_t *p_first_byte_to_mix; vlc_mutex_lock( &p_aout->mixer_lock ); /* A little trick to avoid loosing our input fifo */ aout_FifoInit( p_aout, &dummy_fifo, p_aout->mixer.mixer.i_rate ); p_first_byte_to_mix = p_input->p_first_byte_to_mix; fifo = p_input->fifo; p_input->fifo = dummy_fifo; aout_InputDelete( p_aout, p_input ); aout_InputNew( p_aout, p_input ); p_input->p_first_byte_to_mix = p_first_byte_to_mix; p_input->fifo = fifo; vlc_mutex_unlock( &p_aout->mixer_lock ); } /* We don't care if someone changes the start date behind our back after * this. We'll deal with that when pushing the buffer, and compensate * with the next incoming buffer. */ vlc_mutex_lock( &p_aout->input_fifos_lock ); start_date = aout_FifoNextStart( p_aout, &p_input->fifo ); vlc_mutex_unlock( &p_aout->input_fifos_lock ); if ( start_date != 0 && start_date < mdate() ) { /* The decoder is _very_ late. This can only happen if the user * pauses the stream (or if the decoder is buggy, which cannot * happen :). */ msg_Warn( p_aout, "computed PTS is out of range ("I64Fd"), " "clearing out", mdate() - start_date ); vlc_mutex_lock( &p_aout->input_fifos_lock ); aout_FifoSet( p_aout, &p_input->fifo, 0 ); p_input->p_first_byte_to_mix = NULL; vlc_mutex_unlock( &p_aout->input_fifos_lock ); if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) msg_Warn( p_aout, "timing screwed, stopping resampling" ); p_input->i_resampling_type = AOUT_RESAMPLING_NONE; if ( p_input->i_nb_resamplers != 0 ) { p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; p_input->pp_resamplers[0]->b_continuity = VLC_FALSE; } start_date = 0; if( p_input->p_input_thread ) { stats_UpdateInteger( p_input->p_input_thread, STATS_LOST_ABUFFERS, 1, NULL ); } } if ( p_buffer->start_date < mdate() + AOUT_MIN_PREPARE_TIME ) { /* The decoder gives us f*cked up PTS. It's its business, but we * can't present it anyway, so drop the buffer. */ msg_Warn( p_aout, "PTS is out of range ("I64Fd"), dropping buffer", mdate() - p_buffer->start_date ); if( p_input->p_input_thread ) { stats_UpdateInteger( p_input->p_input_thread, STATS_LOST_ABUFFERS, 1, NULL ); } aout_BufferFree( p_buffer ); p_input->i_resampling_type = AOUT_RESAMPLING_NONE; if ( p_input->i_nb_resamplers != 0 ) { p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; p_input->pp_resamplers[0]->b_continuity = VLC_FALSE; } return 0; } /* If the audio drift is too big then it's not worth trying to resample * the audio. */ if ( start_date != 0 && ( start_date < p_buffer->start_date - 3 * AOUT_PTS_TOLERANCE ) ) { msg_Warn( p_aout, "audio drift is too big ("I64Fd"), clearing out", start_date - p_buffer->start_date ); vlc_mutex_lock( &p_aout->input_fifos_lock ); aout_FifoSet( p_aout, &p_input->fifo, 0 ); p_input->p_first_byte_to_mix = NULL; vlc_mutex_unlock( &p_aout->input_fifos_lock ); if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) msg_Warn( p_aout, "timing screwed, stopping resampling" ); p_input->i_resampling_type = AOUT_RESAMPLING_NONE; if ( p_input->i_nb_resamplers != 0 ) { p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; p_input->pp_resamplers[0]->b_continuity = VLC_FALSE; } start_date = 0; } else if ( start_date != 0 && ( start_date > p_buffer->start_date + 3 * AOUT_PTS_TOLERANCE ) ) { msg_Warn( p_aout, "audio drift is too big ("I64Fd"), dropping buffer", start_date - p_buffer->start_date ); aout_BufferFree( p_buffer ); if( p_input->p_input_thread ) { stats_UpdateInteger( p_input->p_input_thread, STATS_LOST_ABUFFERS, 1, NULL ); } return 0; } if ( start_date == 0 ) start_date = p_buffer->start_date; /* Run pre-filters. */ aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters, &p_buffer ); /* Run the resampler if needed. * We first need to calculate the output rate of this resampler. */ if ( ( p_input->i_resampling_type == AOUT_RESAMPLING_NONE ) && ( start_date < p_buffer->start_date - AOUT_PTS_TOLERANCE || start_date > p_buffer->start_date + AOUT_PTS_TOLERANCE ) && p_input->i_nb_resamplers > 0 ) { /* Can happen in several circumstances : * 1. A problem at the input (clock drift) * 2. A small pause triggered by the user * 3. Some delay in the output stage, causing a loss of lip * synchronization * Solution : resample the buffer to avoid a scratch. */ mtime_t drift = p_buffer->start_date - start_date; p_input->i_resamp_start_date = mdate(); p_input->i_resamp_start_drift = (int)drift; if ( drift > 0 ) p_input->i_resampling_type = AOUT_RESAMPLING_DOWN; else p_input->i_resampling_type = AOUT_RESAMPLING_UP; msg_Warn( p_aout, "buffer is "I64Fd" %s, triggering %ssampling", drift > 0 ? drift : -drift, drift > 0 ? "in advance" : "late", drift > 0 ? "down" : "up"); } if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE ) { /* Resampling has been triggered previously (because of dates * mismatch). We want the resampling to happen progressively so * it isn't too audible to the listener. */ if( p_input->i_resampling_type == AOUT_RESAMPLING_UP ) { p_input->pp_resamplers[0]->input.i_rate += 2; /* Hz */ } else { p_input->pp_resamplers[0]->input.i_rate -= 2; /* Hz */ } /* Check if everything is back to normal, in which case we can stop the * resampling */ if( p_input->pp_resamplers[0]->input.i_rate == p_input->input.i_rate ) { p_input->i_resampling_type = AOUT_RESAMPLING_NONE; msg_Warn( p_aout, "resampling stopped after "I64Fi" usec " "(drift: "I64Fi")", mdate() - p_input->i_resamp_start_date, p_buffer->start_date - start_date); } else if( abs( (int)(p_buffer->start_date - start_date) ) < abs( p_input->i_resamp_start_drift ) / 2 ) { /* if we reduced the drift from half, then it is time to switch * back the resampling direction. */ if( p_input->i_resampling_type == AOUT_RESAMPLING_UP ) p_input->i_resampling_type = AOUT_RESAMPLING_DOWN; else p_input->i_resampling_type = AOUT_RESAMPLING_UP; p_input->i_resamp_start_drift = 0; } else if( p_input->i_resamp_start_drift && ( abs( (int)(p_buffer->start_date - start_date) ) > abs( p_input->i_resamp_start_drift ) * 3 / 2 ) ) { /* If the drift is increasing and not decreasing, than something * is bad. We'd better stop the resampling right now. */ msg_Warn( p_aout, "timing screwed, stopping resampling" ); p_input->i_resampling_type = AOUT_RESAMPLING_NONE; p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate; } } /* Adding the start date will be managed by aout_FifoPush(). */ p_buffer->end_date = start_date + (p_buffer->end_date - p_buffer->start_date); p_buffer->start_date = start_date; /* Actually run the resampler now. */ if ( p_input->i_nb_resamplers > 0 ) { aout_FiltersPlay( p_aout, p_input->pp_resamplers, p_input->i_nb_resamplers, &p_buffer ); } vlc_mutex_lock( &p_aout->input_fifos_lock ); aout_FifoPush( p_aout, &p_input->fifo, p_buffer ); vlc_mutex_unlock( &p_aout->input_fifos_lock ); return 0; }
/** * Filter a picture */ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic ) { filter_sys_t *p_sys = p_filter->p_sys; picture_t *p_outpic = filter_NewPicture( p_filter ); if( !p_outpic ) { picture_Release( p_pic ); return NULL; } /* */ vlc_mutex_lock( &p_sys->lock ); if( p_sys->b_change ) { p_sys->i_rows = p_sys->change.i_rows; p_sys->i_cols = p_sys->change.i_cols; p_sys->b_blackslot = p_sys->change.b_blackslot; p_sys->b_change = false; Shuffle( p_sys ); } vlc_mutex_unlock( &p_sys->lock ); /* */ const int i_rows = p_sys->i_rows; const int i_cols = p_sys->i_cols; /* */ for( int i_plane = 0; i_plane < p_outpic->i_planes; i_plane++ ) { const plane_t *p_in = &p_pic->p[i_plane]; const int i_pitch = p_in->i_pitch; plane_t *p_out = &p_outpic->p[i_plane]; for( int i = 0; i < i_cols * i_rows; i++ ) { int i_col = i % i_cols; int i_row = i / i_cols; int i_ocol = p_sys->pi_order[i] % i_cols; int i_orow = p_sys->pi_order[i] / i_cols; int i_last_row = i_row + 1; i_orow *= p_in->i_lines / i_rows; i_row *= p_in->i_lines / i_rows; i_last_row *= p_in->i_lines / i_rows; if( p_sys->b_blackslot && p_sys->b_finished && i == p_sys->i_selected ) { uint8_t color = ( i_plane == Y_PLANE ? 0x0 : 0x80 ); for( ; i_row < i_last_row; i_row++, i_orow++ ) { memset( p_out->p_pixels + i_row * i_pitch + i_col * i_pitch / i_cols, color, i_pitch / i_cols ); } } else { for( ; i_row < i_last_row; i_row++, i_orow++ ) { memcpy( p_out->p_pixels + i_row * i_pitch + i_col * i_pitch / i_cols, p_in->p_pixels + i_orow * i_pitch + i_ocol * i_pitch / i_cols, i_pitch / i_cols ); } } } } if( p_sys->i_selected != -1 && !p_sys->b_blackslot ) { const plane_t *p_in = &p_pic->p[Y_PLANE]; const int i_pitch = p_in->i_pitch; plane_t *p_out = &p_outpic->p[Y_PLANE]; int i_col = p_sys->i_selected % i_cols; int i_row = p_sys->i_selected / i_cols; int i_last_row = i_row + 1; i_row *= p_in->i_lines / i_rows; i_last_row *= p_in->i_lines / i_rows; memset( p_out->p_pixels + i_row * i_pitch + i_col * i_pitch / i_cols, 0xff, i_pitch / i_cols ); for( ; i_row < i_last_row; i_row++ ) { p_out->p_pixels[ i_row * i_pitch + i_col * i_pitch / i_cols ] = 0xff; p_out->p_pixels[ i_row * i_pitch + (i_col+1) * i_pitch / i_cols - 1 ] = 0xff; } i_row--; memset( p_out->p_pixels + i_row * i_pitch + i_col * i_pitch / i_cols, 0xff, i_pitch / i_cols ); } if( p_sys->b_finished ) { plane_t *p_out = &p_outpic->p[Y_PLANE]; for( int i = 0; i < SHUFFLE_HEIGHT; i++ ) { for( int j = 0; j < SHUFFLE_WIDTH; j++ ) { if( shuffle_button[i][j] == '.' ) p_out->p_pixels[ i * p_out->i_pitch + j ] = 0xff; } } } return CopyInfoAndRelease( p_outpic, p_pic ); }
void input_item_SetURI( input_item_t *p_i, const char *psz_uri ) { assert( psz_uri ); #ifndef NDEBUG if( !strstr( psz_uri, "://" ) || strchr( psz_uri, ' ' ) || strchr( psz_uri, '"' ) ) fprintf( stderr, "Warning: %s(\"%s\"): file path instead of URL.\n", __func__, psz_uri ); #endif vlc_mutex_lock( &p_i->lock ); free( p_i->psz_uri ); p_i->psz_uri = strdup( psz_uri ); p_i->i_type = GuessType( p_i, &p_i->b_net ); if( p_i->psz_name ) ; else if( p_i->i_type == ITEM_TYPE_FILE || p_i->i_type == ITEM_TYPE_DIRECTORY ) { const char *psz_filename = strrchr( p_i->psz_uri, '/' ); if( psz_filename && *psz_filename == '/' ) psz_filename++; if( psz_filename && *psz_filename ) p_i->psz_name = strdup( psz_filename ); /* Make the name more readable */ if( p_i->psz_name ) { decode_URI( p_i->psz_name ); EnsureUTF8( p_i->psz_name ); } } else { /* Strip login and password from title */ int r; vlc_url_t url; vlc_UrlParse( &url, psz_uri, 0 ); if( url.psz_protocol ) { if( url.i_port > 0 ) r=asprintf( &p_i->psz_name, "%s://%s:%d%s", url.psz_protocol, url.psz_host, url.i_port, url.psz_path ? url.psz_path : "" ); else r=asprintf( &p_i->psz_name, "%s://%s%s", url.psz_protocol, url.psz_host ? url.psz_host : "", url.psz_path ? url.psz_path : "" ); } else { if( url.i_port > 0 ) r=asprintf( &p_i->psz_name, "%s:%d%s", url.psz_host, url.i_port, url.psz_path ? url.psz_path : "" ); else r=asprintf( &p_i->psz_name, "%s%s", url.psz_host, url.psz_path ? url.psz_path : "" ); } vlc_UrlClean( &url ); if( -1==r ) p_i->psz_name=NULL; /* recover from undefined value */ } vlc_mutex_unlock( &p_i->lock ); }
/***************************************************************************** * Decode: *****************************************************************************/ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; subpicture_t *p_spu = NULL; video_format_t fmt; bool b_cached = false; vbi_page p_page; if( (pp_block == NULL) || (*pp_block == NULL) ) return NULL; p_block = *pp_block; *pp_block = NULL; if( p_block->i_buffer > 0 && ( ( p_block->p_buffer[0] >= 0x10 && p_block->p_buffer[0] <= 0x1f ) || ( p_block->p_buffer[0] >= 0x99 && p_block->p_buffer[0] <= 0x9b ) ) ) { vbi_sliced *p_sliced = p_sys->p_vbi_sliced; unsigned int i_lines = 0; p_block->i_buffer--; p_block->p_buffer++; while( p_block->i_buffer >= 2 ) { int i_id = p_block->p_buffer[0]; unsigned i_size = p_block->p_buffer[1]; if( 2 + i_size > p_block->i_buffer ) break; if( ( i_id == 0x02 || i_id == 0x03 ) && i_size >= 44 && i_lines < MAX_SLICES ) { unsigned line_offset = p_block->p_buffer[2] & 0x1f; unsigned field_parity = p_block->p_buffer[2] & 0x20; p_sliced[i_lines].id = VBI_SLICED_TELETEXT_B; if( line_offset > 0 ) p_sliced[i_lines].line = line_offset + (field_parity ? 0 : 313); else p_sliced[i_lines].line = 0; for( int i = 0; i < 42; i++ ) p_sliced[i_lines].data[i] = vbi_rev8( p_block->p_buffer[4 + i] ); i_lines++; } p_block->i_buffer -= 2 + i_size; p_block->p_buffer += 2 + i_size; } if( i_lines > 0 ) vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, 0 ); } /* */ vlc_mutex_lock( &p_sys->lock ); const int i_align = p_sys->i_align; const unsigned int i_wanted_page = p_sys->i_wanted_page; const unsigned int i_wanted_subpage = p_sys->i_wanted_subpage; const bool b_opaque = p_sys->b_opaque; vlc_mutex_unlock( &p_sys->lock ); /* Try to see if the page we want is in the cache yet */ memset( &p_page, 0, sizeof(vbi_page) ); b_cached = vbi_fetch_vt_page( p_sys->p_vbi_dec, &p_page, vbi_dec2bcd( i_wanted_page ), i_wanted_subpage, VBI_WST_LEVEL_3p5, 25, true ); if( i_wanted_page == p_sys->i_last_page && !p_sys->b_update ) goto error; if( !b_cached ) { if( p_sys->i_last_page != i_wanted_page ) { /* We need to reset the subtitle */ p_spu = Subpicture( p_dec, &fmt, true, p_page.columns, p_page.rows, i_align, p_block->i_pts ); if( !p_spu ) goto error; subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->text = strdup(""); p_sys->b_update = true; p_sys->i_last_page = i_wanted_page; goto exit; } goto error; } p_sys->b_update = false; p_sys->i_last_page = i_wanted_page; #ifdef ZVBI_DEBUG msg_Dbg( p_dec, "we now have page: %d ready for display", i_wanted_page ); #endif /* Ignore transparent rows at the beginning and end */ int i_first_row = get_first_visible_row( p_page.text, p_page.rows, p_page.columns ); if ( i_first_row < 0 ) goto error; int i_num_rows = get_last_visible_row( p_page.text, p_page.rows, p_page.columns ) - i_first_row + 1; #ifdef ZVBI_DEBUG msg_Dbg( p_dec, "After top and tail of page we have rows %i-%i of %i", i_first_row + 1, i_first_row + i_num_rows, p_page.rows ); #endif /* If there is a page or sub to render, then we do that here */ /* Create the subpicture unit */ p_spu = Subpicture( p_dec, &fmt, p_sys->b_text, p_page.columns, i_num_rows, i_align, p_block->i_pts ); if( !p_spu ) goto error; if( p_sys->b_text ) { unsigned int i_textsize = 7000; int i_total,offset; char p_text[i_textsize+1]; i_total = vbi_print_page_region( &p_page, p_text, i_textsize, "UTF-8", 0, 0, 0, i_first_row, p_page.columns, i_num_rows ); for( offset=1; offset<i_total && isspace( p_text[i_total-offset ] ); offset++) p_text[i_total-offset] = '\0'; i_total -= offset; offset=0; while( offset < i_total && isspace( p_text[offset] ) ) offset++; subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->text = strdup( &p_text[offset] ); p_spu_sys->align = i_align; p_spu_sys->i_font_height_percent = 5; p_spu_sys->renderbg = b_opaque; #ifdef ZVBI_DEBUG msg_Info( p_dec, "page %x-%x(%d)\n\"%s\"", p_page.pgno, p_page.subno, i_total, &p_text[offset] ); #endif } else { picture_t *p_pic = p_spu->p_region->p_picture; /* ZVBI is stupid enough to assume pitch == width */ p_pic->p->i_pitch = 4 * fmt.i_width; /* Maintain subtitle postion */ p_spu->p_region->i_y = i_first_row*10; p_spu->i_original_picture_width = p_page.columns*12; p_spu->i_original_picture_height = p_page.rows*10; vbi_draw_vt_page_region( &p_page, ZVBI_PIXFMT_RGBA32, p_spu->p_region->p_picture->p->p_pixels, -1, 0, i_first_row, p_page.columns, i_num_rows, 1, 1); vlc_mutex_lock( &p_sys->lock ); memcpy( p_sys->nav_link, &p_page.nav_link, sizeof( p_sys->nav_link )) ; vlc_mutex_unlock( &p_sys->lock ); OpaquePage( p_pic, p_page, fmt, b_opaque, i_first_row * p_page.columns ); } exit: vbi_unref_page( &p_page ); block_Release( p_block ); return p_spu; error: vbi_unref_page( &p_page ); if( p_spu != NULL ) { decoder_DeleteSubpicture( p_dec, p_spu ); p_spu = NULL; } block_Release( p_block ); return NULL; }
/**************************************************************************** * Filter: the whole thing **************************************************************************** * This function outputs subpictures at regular time intervals. ****************************************************************************/ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) { filter_sys_t *p_sys = p_filter->p_sys; subpicture_t *p_spu; video_format_t fmt; subpicture_region_t *p_region; int i_feed, i_item; rss_feed_t *p_feed; memset( &fmt, 0, sizeof(video_format_t) ); vlc_mutex_lock( &p_sys->lock ); /* Check if the feeds have been fetched and that we have some feeds */ /* TODO: check that we have items for each feeds */ if( !p_sys->b_fetched && p_sys->i_feeds > 0 ) { vlc_mutex_unlock( &p_sys->lock ); return NULL; } if( p_sys->last_date + ( p_sys->i_cur_char == 0 && p_sys->i_cur_item == ( p_sys->i_title == scroll_title ? -1 : 0 ) ? 5 : 1 ) /* ( ... ? 5 : 1 ) means "wait 5 times more for the 1st char" */ * p_sys->i_speed > date ) { vlc_mutex_unlock( &p_sys->lock ); return NULL; } p_sys->last_date = date; p_sys->i_cur_char++; if( p_sys->i_cur_item == -1 ? p_sys->p_feeds[p_sys->i_cur_feed].psz_title[p_sys->i_cur_char] == 0 : p_sys->p_feeds[p_sys->i_cur_feed].p_items[p_sys->i_cur_item].psz_title[p_sys->i_cur_char] == 0 ) { p_sys->i_cur_char = 0; p_sys->i_cur_item++; if( p_sys->i_cur_item >= p_sys->p_feeds[p_sys->i_cur_feed].i_items ) { if( p_sys->i_title == scroll_title ) p_sys->i_cur_item = -1; else p_sys->i_cur_item = 0; p_sys->i_cur_feed = (p_sys->i_cur_feed + 1)%p_sys->i_feeds; } } p_spu = filter_NewSubpicture( p_filter ); if( !p_spu ) { vlc_mutex_unlock( &p_sys->lock ); return NULL; } fmt.i_chroma = VLC_CODEC_TEXT; p_spu->p_region = subpicture_region_New( &fmt ); if( !p_spu->p_region ) { p_filter->pf_sub_buffer_del( p_filter, p_spu ); vlc_mutex_unlock( &p_sys->lock ); return NULL; } /* Generate the string that will be displayed. This string is supposed to be p_sys->i_length characters long. */ i_item = p_sys->i_cur_item; i_feed = p_sys->i_cur_feed; p_feed = &p_sys->p_feeds[i_feed]; if( ( p_feed->p_pic && p_sys->i_title == default_title ) || p_sys->i_title == hide_title ) { /* Don't display the feed's title if we have an image */ _snprintf( p_sys->psz_marquee, p_sys->i_length, "%s", p_sys->p_feeds[i_feed].p_items[i_item].psz_title +p_sys->i_cur_char ); // sunqueen modify } else if( ( !p_feed->p_pic && p_sys->i_title == default_title ) || p_sys->i_title == prepend_title ) { _snprintf( p_sys->psz_marquee, p_sys->i_length, "%s : %s", p_sys->p_feeds[i_feed].psz_title, p_sys->p_feeds[i_feed].p_items[i_item].psz_title +p_sys->i_cur_char ); // sunqueen modify } else /* scrolling title */ { if( i_item == -1 ) _snprintf( p_sys->psz_marquee, p_sys->i_length, "%s : %s", p_sys->p_feeds[i_feed].psz_title + p_sys->i_cur_char, p_sys->p_feeds[i_feed].p_items[i_item+1].psz_title ); // sunqueen modify else _snprintf( p_sys->psz_marquee, p_sys->i_length, "%s", p_sys->p_feeds[i_feed].p_items[i_item].psz_title +p_sys->i_cur_char ); // sunqueen modify } while( strlen( p_sys->psz_marquee ) < (unsigned int)p_sys->i_length ) { i_item++; if( i_item == p_sys->p_feeds[i_feed].i_items ) break; _snprintf( strchr( p_sys->psz_marquee, 0 ), p_sys->i_length - strlen( p_sys->psz_marquee ), " - %s", p_sys->p_feeds[i_feed].p_items[i_item].psz_title ); // sunqueen modify } /* Calls to snprintf might split multibyte UTF8 chars ... * which freetype doesn't like. */ { char *a = strdup( p_sys->psz_marquee ); char *a2 = a; char *b = p_sys->psz_marquee; EnsureUTF8( p_sys->psz_marquee ); /* we want to use ' ' instead of '?' for erroneous chars */ while( *b != '\0' ) { if( *b != *a ) *b = ' '; b++;a++; } free( a2 ); } p_spu->p_region->psz_text = strdup(p_sys->psz_marquee); if( p_sys->p_style->i_font_size > 0 ) p_spu->p_region->fmt.i_visible_height = p_sys->p_style->i_font_size; p_spu->i_start = date; p_spu->i_stop = 0; p_spu->b_ephemer = true; /* where to locate the string: */ if( p_sys->i_pos < 0 ) { /* set to an absolute xy */ p_spu->p_region->i_align = SUBPICTURE_ALIGN_LEFT | SUBPICTURE_ALIGN_TOP; p_spu->b_absolute = true; } else { /* set to one of the 9 relative locations */ p_spu->p_region->i_align = p_sys->i_pos; p_spu->b_absolute = false; } p_spu->p_region->i_x = p_sys->i_xoff; p_spu->p_region->i_y = p_sys->i_yoff; p_spu->p_region->p_style = text_style_Duplicate( p_sys->p_style ); if( p_feed->p_pic ) { /* Display the feed's image */ picture_t *p_pic = p_feed->p_pic; video_format_t fmt_out; memset( &fmt_out, 0, sizeof(video_format_t) ); fmt_out.i_chroma = VLC_CODEC_YUVA; fmt_out.i_sar_num = fmt_out.i_sar_den = 1; fmt_out.i_width = fmt_out.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch; fmt_out.i_height = fmt_out.i_visible_height = p_pic->p[Y_PLANE].i_visible_lines; p_region = subpicture_region_New( &fmt_out ); if( !p_region ) { msg_Err( p_filter, "cannot allocate SPU region" ); } else { p_region->i_x = p_spu->p_region->i_x; p_region->i_y = p_spu->p_region->i_y; /* FIXME the copy is probably not needed anymore */ picture_Copy( p_region->p_picture, p_pic ); p_spu->p_region->p_next = p_region; /* Offset text to display right next to the image */ p_spu->p_region->i_x += fmt_out.i_visible_width; } } vlc_mutex_unlock( &p_sys->lock ); return p_spu; }
/************************************************************************** * libvlc_media_list_retain (Public) * * Increase an object refcount. **************************************************************************/ void libvlc_media_list_retain( libvlc_media_list_t * p_mlist ) { vlc_mutex_lock( &p_mlist->refcount_lock ); p_mlist->i_refcount++; vlc_mutex_unlock( &p_mlist->refcount_lock ); }
static int Retrieve( addons_finder_t *p_finder, addon_entry_t *p_entry ) { vlc_mutex_lock( &p_entry->lock ); if ( !p_entry->psz_archive_uri ) { vlc_mutex_unlock( &p_entry->lock ); return VLC_EGENERIC; } char *psz_archive_uri = strdup( p_entry->psz_archive_uri ); vlc_mutex_unlock( &p_entry->lock ); if ( !psz_archive_uri ) return VLC_ENOMEM; /* get archive and parse manifest */ stream_t *p_stream; if ( psz_archive_uri[0] == '/' ) { /* Relative path */ char *psz_uri; if ( ! asprintf( &psz_uri, ADDONS_REPO_SCHEMEHOST"%s", psz_archive_uri ) ) { free( psz_archive_uri ); return VLC_ENOMEM; } p_stream = vlc_stream_NewURL_ND( p_finder, psz_uri ); free( psz_uri ); } else { p_stream = vlc_stream_NewURL_ND( p_finder, psz_archive_uri ); } msg_Dbg( p_finder, "downloading archive %s", psz_archive_uri ); free ( psz_archive_uri ); if ( !p_stream ) return VLC_EGENERIC; /* In case of pf_ reuse */ if ( p_finder->p_sys->psz_tempfile ) { vlc_unlink( p_finder->p_sys->psz_tempfile ); FREENULL( p_finder->p_sys->psz_tempfile ); } p_finder->p_sys->psz_tempfile = tempnam( NULL, "vlp" ); if ( !p_finder->p_sys->psz_tempfile ) { msg_Err( p_finder, "Can't create temp storage file" ); vlc_stream_Delete( p_stream ); return VLC_EGENERIC; } int fd = vlc_open( p_finder->p_sys->psz_tempfile, O_WRONLY | O_CREAT | O_EXCL, 0600 ); if( fd == -1 ) { msg_Err( p_finder, "Failed to open addon temp storage file" ); FREENULL(p_finder->p_sys->psz_tempfile); vlc_stream_Delete( p_stream ); return VLC_EGENERIC; } char buffer[1<<10]; ssize_t i_read = 0; int i_ret = VLC_SUCCESS; while ( ( i_read = vlc_stream_Read( p_stream, &buffer, 1<<10 ) ) > 0 ) { if ( write( fd, buffer, i_read ) != i_read ) { msg_Err( p_finder, "Failed to write to Addon file" ); i_ret = VLC_EGENERIC; break; } } vlc_close( fd ); vlc_stream_Delete( p_stream ); if (i_ret) return i_ret; msg_Dbg( p_finder, "Reading manifest from %s", p_finder->p_sys->psz_tempfile ); char *psz_tempfileuri = vlc_path2uri( p_finder->p_sys->psz_tempfile, NULL ); if ( !psz_tempfileuri ) return VLC_ENOMEM; char *psz_manifest_uri; if ( asprintf( &psz_manifest_uri, "%s#!/manifest.xml", psz_tempfileuri ) < 1 ) { free( psz_tempfileuri ); return VLC_ENOMEM; } p_stream = vlc_stream_NewMRL( p_finder, psz_manifest_uri ); free( psz_manifest_uri ); if ( !p_stream ) { free( psz_tempfileuri ); return VLC_EGENERIC; } vlc_mutex_lock( &p_entry->lock ); i_ret = ( ParseManifest( p_finder, p_entry, psz_tempfileuri, p_stream ) > 0 ) ? VLC_SUCCESS : VLC_EGENERIC; vlc_mutex_unlock( &p_entry->lock ); free( psz_tempfileuri ); vlc_stream_Delete( p_stream ); return i_ret; }
/************************************************************************** * libvlc_media_list_unlock (Public) * * The lock must be held in access operations **************************************************************************/ void libvlc_media_list_unlock( libvlc_media_list_t * p_mlist ) { vlc_mutex_unlock( &p_mlist->object_lock ); }
static int ControlReopenDevice(vout_display_t *vd) { vout_display_sys_t *sys = vd->sys; if (!sys->use_desktop) { /* Save non-desktop state */ sys->desktop_save.is_fullscreen = vd->cfg->is_fullscreen; sys->desktop_save.is_on_top = sys->is_on_top; WINDOWPLACEMENT wp = { /*.length =*/ sizeof(wp), }; // sunqueen modify GetWindowPlacement(sys->hparent ? sys->hparent : sys->hwnd, &wp); sys->desktop_save.win = wp.rcNormalPosition; } /* */ Direct3DClose(vd); EventThreadStop(sys->event); /* */ vlc_mutex_lock(&sys->lock); sys->use_desktop = sys->desktop_requested; sys->ch_desktop = false; vlc_mutex_unlock(&sys->lock); /* */ event_cfg_t cfg; memset(&cfg, 0, sizeof(cfg)); cfg.use_desktop = sys->use_desktop; if (!sys->use_desktop) { cfg.win.type = VOUT_WINDOW_TYPE_HWND; cfg.win.x = sys->desktop_save.win.left; cfg.win.y = sys->desktop_save.win.top; cfg.win.width = sys->desktop_save.win.right - sys->desktop_save.win.left; cfg.win.height = sys->desktop_save.win.bottom - sys->desktop_save.win.top; } event_hwnd_t hwnd; if (EventThreadStart(sys->event, &hwnd, &cfg)) { msg_Err(vd, "Failed to restart event thread"); return VLC_EGENERIC; } sys->parent_window = hwnd.parent_window; sys->hparent = hwnd.hparent; sys->hwnd = hwnd.hwnd; sys->hvideownd = hwnd.hvideownd; sys->hfswnd = hwnd.hfswnd; SetRectEmpty(&sys->rect_parent); /* */ video_format_t fmt; if (Direct3DOpen(vd, &fmt)) { CommonClean(vd); msg_Err(vd, "Failed to reopen device"); return VLC_EGENERIC; } vd->fmt = fmt; sys->is_first_display = true; if (sys->use_desktop) { /* Disable fullscreen/on_top while using desktop */ if (sys->desktop_save.is_fullscreen) vout_display_SendEventFullscreen(vd, false); if (sys->desktop_save.is_on_top) vout_display_SendWindowState(vd, VOUT_WINDOW_STATE_NORMAL); } else { /* Restore fullscreen/on_top */ if (sys->desktop_save.is_fullscreen) vout_display_SendEventFullscreen(vd, true); if (sys->desktop_save.is_on_top) vout_display_SendWindowState(vd, VOUT_WINDOW_STATE_ABOVE); } return VLC_SUCCESS; }
int GetInputMeta( input_item_t* p_input, DBusMessageIter *args ) { DBusMessageIter dict, dict_entry, variant; /** The duration of the track can be expressed in second, milli-seconds and µ-seconds */ dbus_int64_t i_mtime = input_item_GetDuration( p_input ); dbus_uint32_t i_time = i_mtime / 1000000; dbus_int64_t i_length = i_mtime / 1000; char *psz_trackid; if( -1 == asprintf( &psz_trackid, MPRIS_TRACKID_FORMAT, p_input->i_id ) ) return VLC_ENOMEM; const char* ppsz_meta_items[] = { "mpris:trackid", "xesam:url", "xesam:title", "xesam:artist", "xesam:album", "xesam:tracknumber", "vlc:time", "mpris:length", "xesam:genre", "xesam:userRating", "xesam:contentCreated", "mpris:artUrl", "mb:trackId", "vlc:audio-bitrate", "vlc:audio-samplerate", "vlc:video-bitrate", "vlc:audio-codec", "vlc:copyright", "xesam:comment", "vlc:encodedby", "language", "vlc:length", "vlc:nowplaying", "vlc:publisher", "vlc:setting", "status", "vlc:url", "vlc:video-codec" }; dbus_message_iter_open_container( args, DBUS_TYPE_ARRAY, "{sv}", &dict ); ADD_META( 0, DBUS_TYPE_OBJECT_PATH, psz_trackid ); ADD_VLC_META_STRING( 1, URI ); ADD_VLC_META_STRING( 2, Title ); ADD_VLC_META_STRING( 3, Artist ); ADD_VLC_META_STRING( 4, Album ); ADD_VLC_META_STRING( 5, TrackNum ); ADD_META( 6, DBUS_TYPE_UINT32, i_time ); ADD_META( 7, DBUS_TYPE_INT64, i_mtime ); ADD_VLC_META_STRING( 8, Genre ); ADD_VLC_META_STRING( 9, Rating ); ADD_VLC_META_STRING( 10, Date ); ADD_VLC_META_STRING( 11, ArtURL ); ADD_VLC_META_STRING( 12, TrackID ); ADD_VLC_META_STRING( 17, Copyright ); ADD_VLC_META_STRING( 18, Description ); ADD_VLC_META_STRING( 19, EncodedBy ); ADD_VLC_META_STRING( 20, Language ); ADD_META( 21, DBUS_TYPE_INT64, i_length ); ADD_VLC_META_STRING( 22, NowPlaying ); ADD_VLC_META_STRING( 23, Publisher ); ADD_VLC_META_STRING( 24, Setting ); ADD_VLC_META_STRING( 25, URL ); free( psz_trackid ); vlc_mutex_lock( &p_input->lock ); if( p_input->p_meta ) { int i_status = vlc_meta_GetStatus( p_input->p_meta ); ADD_META( 23, DBUS_TYPE_INT32, i_status ); } vlc_mutex_unlock( &p_input->lock ); dbus_message_iter_close_container( args, &dict ); return VLC_SUCCESS; }
static int WriteCatalog( addons_storage_t *p_storage, addon_entry_t **pp_entries, int i_entries ) { addon_entry_t *p_entry; char *psz_file; char *psz_file_tmp; char *psz_tempstring; char *psz_userdir = config_GetUserDir( VLC_DATA_DIR ); if ( !psz_userdir ) return VLC_ENOMEM; if ( asprintf( &psz_file, "%s%s", psz_userdir, ADDONS_CATALOG ) < 1 ) { free( psz_userdir ); return VLC_ENOMEM; } free( psz_userdir ); if ( asprintf( &psz_file_tmp, "%s.tmp", psz_file ) < 1 ) { free( psz_file ); return VLC_ENOMEM; } char *psz_path = strdup( psz_file ); if ( !psz_path ) { free( psz_file ); free( psz_file_tmp ); return VLC_ENOMEM; } char *psz_buf = strrchr( psz_path, DIR_SEP_CHAR ); if( psz_buf ) { *++psz_buf = '\0'; /* ensure directory exists */ if( !EMPTY_STR( psz_path ) ) recursive_mkdir( VLC_OBJECT(p_storage), psz_path ); } free( psz_path ); FILE *p_catalog = vlc_fopen( psz_file_tmp, "wt" ); if ( !p_catalog ) { free( psz_file ); free( psz_file_tmp ); return VLC_EGENERIC; } /* write XML header */ fprintf( p_catalog, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); fprintf( p_catalog, "<videolan xmlns=\"http://videolan.org/ns/vlc/addons/1.0\">\n" ); fprintf( p_catalog, "\t<addons>\n" ); for ( int i=0; i<i_entries; i++ ) { p_entry = pp_entries[i]; vlc_mutex_lock( &p_entry->lock ); psz_tempstring = NULL; if ( ( p_entry->e_state != ADDON_INSTALLED ) || !( p_entry->e_flags & ADDON_MANAGEABLE ) ) { vlc_mutex_unlock( &p_entry->lock ); continue; } if ( p_entry->psz_source_module ) psz_tempstring = convert_xml_special_chars( p_entry->psz_source_module ); char *psz_uuid = addons_uuid_to_psz( ( const addon_uuid_t * ) & p_entry->uuid ); fprintf( p_catalog, "\t\t<addon source=\"%s\" type=\"%s\" id=\"%s\" " "downloads=\"%ld\" score=\"%d\"", ( psz_tempstring ) ? psz_tempstring : "", getTypePsz( p_entry->e_type ), psz_uuid, p_entry->i_downloads, p_entry->i_score ); free( psz_uuid ); free( psz_tempstring ); WRITE_WITH_ENTITIES( " version=\"%s\"", p_entry->psz_version ) fprintf( p_catalog, ">\n" ); WRITE_WITH_ENTITIES( "\t\t\t<name>%s</name>\n", p_entry->psz_name ) WRITE_WITH_ENTITIES( "\t\t\t<summary>%s</summary>\n", p_entry->psz_summary ) if ( p_entry->psz_description ) { psz_tempstring = p_entry->psz_description; /* FIXME: do real escaping */ while( ( psz_tempstring = strstr( psz_tempstring, "]]>" ) ) ) *psz_tempstring = ' '; fprintf( p_catalog, "\t\t\t<description><![CDATA[%s]]></description>\n", p_entry->psz_description ); } WRITE_WITH_ENTITIES( "\t\t\t<image>%s</image>\n", p_entry->psz_image_data ) WRITE_WITH_ENTITIES( "\t\t\t<archive>%s</archive>\n", p_entry->psz_archive_uri ) fprintf( p_catalog, "\t\t\t<authorship>\n" ); WRITE_WITH_ENTITIES( "\t\t\t\t<creator>%s</creator>\n", p_entry->psz_author ) WRITE_WITH_ENTITIES( "\t\t\t\t<sourceurl>%s</sourceurl>\n", p_entry->psz_source_uri ) fprintf( p_catalog, "\t\t\t</authorship>\n" ); FOREACH_ARRAY( addon_file_t *p_file, p_entry->files ) psz_tempstring = convert_xml_special_chars( p_file->psz_filename ); fprintf( p_catalog, "\t\t\t<resource type=\"%s\">%s</resource>\n", getTypePsz( p_file->e_filetype ), psz_tempstring ); free( psz_tempstring ); FOREACH_END(); fprintf( p_catalog, "\t\t</addon>\n" ); vlc_mutex_unlock( &p_entry->lock ); } fprintf( p_catalog, "\t</addons>\n" ); fprintf( p_catalog, "</videolan>\n" ); fclose( p_catalog ); int i_ret = vlc_rename( psz_file_tmp, psz_file ); free( psz_file ); free( psz_file_tmp ); if( i_ret == -1 ) { msg_Err( p_storage, "could not rename temp catalog: %s", vlc_strerror_c(errno) ); return VLC_EGENERIC; } return VLC_SUCCESS; }
static void Run ( intf_thread_t *p_intf ) { intf_sys_t *p_sys = p_intf->p_sys; mtime_t i_last_run = mdate(); for( ;; ) { int canc = vlc_savecancel(); vlc_mutex_lock( &p_sys->lock ); int i_watches = vlc_array_count( p_sys->p_watches ); struct pollfd fds[i_watches]; memset(fds, 0, sizeof fds); int i_fds = GetPollFds( p_intf, fds ); mtime_t i_now = mdate(), i_loop_interval = i_now - i_last_run; int i_next_timeout = UpdateTimeouts( p_intf, i_loop_interval ); i_last_run = i_now; vlc_mutex_unlock( &p_sys->lock ); /* thread cancellation is allowed while the main loop sleeps */ vlc_restorecancel( canc ); int i_pollres = poll( fds, i_fds, i_next_timeout ); canc = vlc_savecancel(); if( -1 == i_pollres ) { /* XXX: What should we do when poll() fails ? */ msg_Err( p_intf, "poll() failed: %m" ); vlc_restorecancel( canc ); continue; } /* Was the main loop woken up manually ? */ if( 0 < i_pollres && ( fds[0].revents & POLLIN ) ) { char buf; (void)read( fds[0].fd, &buf, 1 ); } /* We need to lock the mutex while building lists of events, * timeouts and watches to process but we can't keep the lock while * processing them, or else we risk a deadlock: * * The signal functions could lock mutex X while p_events is locked; * While some other function in vlc (playlist) might lock mutex X * and then set a variable which would call AllCallback(), which itself * needs to lock p_events to add a new event. */ vlc_mutex_lock( &p_intf->p_sys->lock ); /* Get the list of timeouts to process */ unsigned int i_timeouts = vlc_array_count( p_sys->p_timeouts ); DBusTimeout *p_timeouts[i_timeouts]; for( unsigned int i = 0; i < i_timeouts; i++ ) { p_timeouts[i] = vlc_array_item_at_index( p_sys->p_timeouts, i ); } /* Get the list of watches to process */ i_watches = vlc_array_count( p_sys->p_watches ); DBusWatch *p_watches[i_watches]; for( int i = 0; i < i_watches; i++ ) { p_watches[i] = vlc_array_item_at_index( p_sys->p_watches, i ); } /* Get the list of events to process */ int i_events = vlc_array_count( p_intf->p_sys->p_events ); callback_info_t* p_info[i_events]; for( int i = i_events - 1; i >= 0; i-- ) { p_info[i] = vlc_array_item_at_index( p_intf->p_sys->p_events, i ); vlc_array_remove( p_intf->p_sys->p_events, i ); } /* now we can release the lock and process what's pending */ vlc_mutex_unlock( &p_intf->p_sys->lock ); ProcessEvents( p_intf, p_info, i_events ); ProcessWatches( p_intf, p_watches, i_watches, fds, i_fds ); ProcessTimeouts( p_intf, p_timeouts, i_timeouts ); DispatchDBusMessages( p_intf ); vlc_restorecancel( canc ); } }
void vlc_media_tree_Unlock(vlc_media_tree_t *tree) { media_tree_private_t *priv = mt_priv(tree); vlc_mutex_unlock(&priv->lock); }
// Get all the callbacks static int AllCallback( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ) { (void)p_this; (void)oldval; intf_thread_t *p_intf = (intf_thread_t*)p_data; callback_info_t *info = calloc( 1, sizeof( callback_info_t ) ); if( !info ) return VLC_ENOMEM; vlc_mutex_lock( &p_intf->p_sys->lock ); // Wich event is it ? if( !strcmp( "item-current", psz_var ) ) info->signal = SIGNAL_ITEM_CURRENT; else if( !strcmp( "volume", psz_var ) ) info->signal = SIGNAL_VOLUME_CHANGE; else if( !strcmp( "mute", psz_var ) ) info->signal = SIGNAL_VOLUME_MUTED; else if( !strcmp( "intf-change", psz_var ) ) info->signal = SIGNAL_INTF_CHANGE; else if( !strcmp( "playlist-item-append", psz_var ) ) { info->signal = SIGNAL_PLAYLIST_ITEM_APPEND; info->i_node = ((playlist_add_t*)newval.p_address)->i_node; } else if( !strcmp( "playlist-item-deleted", psz_var ) ) info->signal = SIGNAL_PLAYLIST_ITEM_DELETED; else if( !strcmp( "random", psz_var ) ) info->signal = SIGNAL_RANDOM; else if( !strcmp( "fullscreen", psz_var ) ) info->signal = SIGNAL_FULLSCREEN; else if( !strcmp( "repeat", psz_var ) ) info->signal = SIGNAL_REPEAT; else if( !strcmp( "loop", psz_var ) ) info->signal = SIGNAL_LOOP; else if( !strcmp( "intf-event", psz_var ) ) { int i_res = InputIntfEventCallback( p_intf, (input_thread_t*) p_this, newval.i_int, info ); if( VLC_SUCCESS != i_res ) { vlc_mutex_unlock( &p_intf->p_sys->lock ); free( info ); return i_res; } } else if( !strcmp( "can-seek", psz_var ) ) info->signal = SIGNAL_CAN_SEEK; else if( !strcmp( "can-pause", psz_var ) ) info->signal = SIGNAL_CAN_PAUSE; else assert(0); // Append the event vlc_array_append( p_intf->p_sys->p_events, info ); vlc_mutex_unlock( &p_intf->p_sys->lock ); wakeup_main_loop( p_intf ); return VLC_SUCCESS; }
/***************************************************************************** * Decode: *****************************************************************************/ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; subpicture_t *p_spu = NULL; video_format_t fmt; bool b_cached = false; vbi_page p_page; if( (pp_block == NULL) || (*pp_block == NULL) ) return NULL; p_block = *pp_block; *pp_block = NULL; if( p_block->i_buffer > 0 && ( ( p_block->p_buffer[0] >= 0x10 && p_block->p_buffer[0] <= 0x1f ) || ( p_block->p_buffer[0] >= 0x99 && p_block->p_buffer[0] <= 0x9b ) ) ) { vbi_sliced *p_sliced = p_sys->p_vbi_sliced; unsigned int i_lines = 0; p_block->i_buffer--; p_block->p_buffer++; while( p_block->i_buffer >= 2 ) { int i_id = p_block->p_buffer[0]; unsigned i_size = p_block->p_buffer[1]; if( 2 + i_size > p_block->i_buffer ) break; if( ( i_id == 0x02 || i_id == 0x03 ) && i_size >= 44 && i_lines < MAX_SLICES ) { unsigned line_offset = p_block->p_buffer[2] & 0x1f; unsigned field_parity = p_block->p_buffer[2] & 0x20; p_sliced[i_lines].id = VBI_SLICED_TELETEXT_B; if( line_offset > 0 ) p_sliced[i_lines].line = line_offset + (field_parity ? 0 : 313); else p_sliced[i_lines].line = 0; for( int i = 0; i < 42; i++ ) p_sliced[i_lines].data[i] = vbi_rev8( p_block->p_buffer[4 + i] ); i_lines++; } p_block->i_buffer -= 2 + i_size; p_block->p_buffer += 2 + i_size; } if( i_lines > 0 ) vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, (double)p_block->i_pts / 1000000 ); } /* */ vlc_mutex_lock( &p_sys->lock ); const int i_align = p_sys->i_align; const unsigned int i_wanted_page = p_sys->i_wanted_page; const unsigned int i_wanted_subpage = p_sys->i_wanted_subpage; const bool b_opaque = p_sys->b_opaque; vlc_mutex_unlock( &p_sys->lock ); /* Try to see if the page we want is in the cache yet */ memset( &p_page, 0, sizeof(vbi_page) ); b_cached = vbi_fetch_vt_page( p_sys->p_vbi_dec, &p_page, vbi_dec2bcd( i_wanted_page ), i_wanted_subpage, VBI_WST_LEVEL_3p5, 25, true ); if( i_wanted_page == p_sys->i_last_page && !p_sys->b_update ) goto error; if( !b_cached ) { if( p_sys->i_last_page != i_wanted_page ) { /* We need to reset the subtitle */ p_spu = Subpicture( p_dec, &fmt, true, p_page.columns, p_page.rows, i_align, p_block->i_pts ); if( !p_spu ) goto error; p_spu->p_region->psz_text = strdup(""); p_sys->b_update = true; p_sys->i_last_page = i_wanted_page; goto exit; } goto error; } p_sys->b_update = false; p_sys->i_last_page = i_wanted_page; #ifdef ZVBI_DEBUG msg_Dbg( p_dec, "we now have page: %d ready for display", i_wanted_page ); #endif /* If there is a page or sub to render, then we do that here */ /* Create the subpicture unit */ p_spu = Subpicture( p_dec, &fmt, p_sys->b_text, p_page.columns, p_page.rows, i_align, p_block->i_pts ); if( !p_spu ) goto error; if( p_sys->b_text ) { unsigned int i_textsize = 7000; int i_total; char p_text[i_textsize+1]; i_total = vbi_print_page_region( &p_page, p_text, i_textsize, "UTF-8", 0, 0, 0, 0, p_page.columns, p_page.rows ); p_text[i_total] = '\0'; /* Strip off the pagenumber */ if( i_total <= 40 ) goto error; p_spu->p_region->psz_text = strdup( &p_text[8] ); #ifdef ZVBI_DEBUG msg_Info( p_dec, "page %x-%x(%d)\n%s", p_page.pgno, p_page.subno, i_total, p_text ); #endif } else { picture_t *p_pic = p_spu->p_region->p_picture; /* ZVBI is stupid enough to assume pitch == width */ p_pic->p->i_pitch = 4 * fmt.i_width; vbi_draw_vt_page( &p_page, ZVBI_PIXFMT_RGBA32, p_spu->p_region->p_picture->p->p_pixels, 1, 1 ); vlc_mutex_lock( &p_sys->lock ); memcpy( p_sys->nav_link, &p_page.nav_link, sizeof( p_sys->nav_link )) ; vlc_mutex_unlock( &p_sys->lock ); OpaquePage( p_pic, p_page, fmt, b_opaque ); } exit: vbi_unref_page( &p_page ); block_Release( p_block ); return p_spu; error: vbi_unref_page( &p_page ); if( p_spu != NULL ) { decoder_DeleteSubpicture( p_dec, p_spu ); p_spu = NULL; } block_Release( p_block ); return NULL; }
//--------------------------------------------------------------------------- // Run: main loop //--------------------------------------------------------------------------- static void *Run( void * p_obj ) { int canc = vlc_savecancel(); intf_thread_t *p_intf = (intf_thread_t *)p_obj; bool b_error = false; char *skin_last = NULL; ThemeLoader *pLoader = NULL; OSLoop *loop = NULL; vlc_mutex_lock( &p_intf->p_sys->init_lock ); // Initialize singletons if( OSFactory::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot initialize OSFactory" ); b_error = true; goto end; } if( AsyncQueue::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot initialize AsyncQueue" ); b_error = true; goto end; } if( Interpreter::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate Interpreter" ); b_error = true; goto end; } if( VarManager::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate VarManager" ); b_error = true; goto end; } if( VlcProc::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot initialize VLCProc" ); b_error = true; goto end; } if( VoutManager::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate VoutManager" ); b_error = true; goto end; } if( ArtManager::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate ArtManager" ); b_error = true; goto end; } if( ThemeRepository::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate ThemeRepository" ); b_error = true; goto end; } if( Dialogs::instance( p_intf ) == NULL ) { msg_Err( p_intf, "cannot instantiate qt4 dialogs provider" ); b_error = true; goto end; } // Load a theme skin_last = config_GetPsz( p_intf, "skins2-last" ); pLoader = new ThemeLoader( p_intf ); if( !skin_last || !pLoader->load( skin_last ) ) { // No skins (not even the default one). let's quit CmdQuit *pCmd = new CmdQuit( p_intf ); AsyncQueue *pQueue = AsyncQueue::instance( p_intf ); pQueue->push( CmdGenericPtr( pCmd ) ); msg_Err( p_intf, "no skins found : exiting"); } delete pLoader; free( skin_last ); // Get the instance of OSLoop loop = OSFactory::instance( p_intf )->getOSLoop(); // Signal the main thread this thread is now ready p_intf->p_sys->b_error = false; p_intf->p_sys->b_ready = true; vlc_cond_signal( &p_intf->p_sys->init_wait ); vlc_mutex_unlock( &p_intf->p_sys->init_lock ); // Enter the main event loop loop->run(); // Destroy OSLoop OSFactory::instance( p_intf )->destroyOSLoop(); // save and delete the theme if( p_intf->p_sys->p_theme ) { p_intf->p_sys->p_theme->saveConfig(); delete p_intf->p_sys->p_theme; p_intf->p_sys->p_theme = NULL; msg_Dbg( p_intf, "current theme deleted" ); } // save config file config_SaveConfigFile( p_intf ); end: // Destroy "singleton" objects Dialogs::destroy( p_intf ); ThemeRepository::destroy( p_intf ); ArtManager::destroy( p_intf ); VoutManager::destroy( p_intf ); VlcProc::destroy( p_intf ); VarManager::destroy( p_intf ); Interpreter::destroy( p_intf ); AsyncQueue::destroy( p_intf ); OSFactory::destroy( p_intf ); if( b_error ) { p_intf->p_sys->b_error = true; p_intf->p_sys->b_ready = true; vlc_cond_signal( &p_intf->p_sys->init_wait ); vlc_mutex_unlock( &p_intf->p_sys->init_lock ); } vlc_restorecancel(canc); return NULL; }