int vout_Snapshot( vout_thread_t *p_vout, picture_t *p_pic ) { image_handler_t *p_image = image_HandlerCreate( p_vout ); video_format_t fmt_in, fmt_out; char *psz_filename = NULL; vlc_value_t val, format; DIR *path; int i_ret; bool b_embedded_snapshot; int i_id = 0; /* */ val.psz_string = var_GetNonEmptyString( p_vout, "snapshot-path" ); /* Embedded snapshot : if snapshot-path == object:id */ if( val.psz_string && sscanf( val.psz_string, "object:%d", &i_id ) > 0 ) b_embedded_snapshot = true; else b_embedded_snapshot = false; /* */ memset( &fmt_in, 0, sizeof(video_format_t) ); fmt_in = p_vout->fmt_in; if( fmt_in.i_sar_num <= 0 || fmt_in.i_sar_den <= 0 ) { fmt_in.i_sar_num = fmt_in.i_sar_den = 1; } /* */ memset( &fmt_out, 0, sizeof(video_format_t) ); fmt_out.i_sar_num = fmt_out.i_sar_den = 1; fmt_out.i_chroma = b_embedded_snapshot ? VLC_FOURCC('p','n','g',' ') : 0; fmt_out.i_width = var_GetInteger( p_vout, "snapshot-width" ); fmt_out.i_height = var_GetInteger( p_vout, "snapshot-height" ); if( b_embedded_snapshot && fmt_out.i_width == 0 && fmt_out.i_height == 0 ) { /* If snapshot-width and/or snapshot height were not specified, use a default snapshot width of 320 */ fmt_out.i_width = 320; } if( fmt_out.i_height == 0 && fmt_out.i_width > 0 ) { fmt_out.i_height = fmt_in.i_height * fmt_out.i_width / fmt_in.i_width; const int i_height = fmt_out.i_height * fmt_in.i_sar_den / fmt_in.i_sar_num; if( i_height > 0 ) fmt_out.i_height = i_height; } else { if( fmt_out.i_width == 0 && fmt_out.i_height > 0 ) { fmt_out.i_width = fmt_in.i_width * fmt_out.i_height / fmt_in.i_height; } else { fmt_out.i_width = fmt_in.i_width; fmt_out.i_height = fmt_in.i_height; } const int i_width = fmt_out.i_width * fmt_in.i_sar_num / fmt_in.i_sar_den; if( i_width > 0 ) fmt_out.i_width = i_width; } /* Embedded snapshot create a snapshot_t* and store it in object(object-id)->p_private, then unlock and signal the waiting object. */ if( b_embedded_snapshot ) { vlc_object_t* p_dest; block_t *p_block; snapshot_t *p_snapshot; size_t i_size; /* Destination object-id is following object: */ p_dest = ( vlc_object_t* )vlc_object_get( i_id ); if( !p_dest ) { msg_Err( p_vout, "Cannot find calling object" ); image_HandlerDelete( p_image ); return VLC_EGENERIC; } /* Object must be locked. We will unlock it once we get the snapshot and written it to p_private */ p_dest->p_private = NULL; /* Save the snapshot to a memory zone */ p_block = image_Write( p_image, p_pic, &fmt_in, &fmt_out ); if( !p_block ) { msg_Err( p_vout, "Could not get snapshot" ); image_HandlerDelete( p_image ); vlc_object_signal( p_dest ); vlc_object_release( p_dest ); return VLC_EGENERIC; } /* Copy the p_block data to a snapshot structure */ /* FIXME: get the timestamp */ p_snapshot = malloc( sizeof( snapshot_t ) ); if( !p_snapshot ) { block_Release( p_block ); image_HandlerDelete( p_image ); vlc_object_signal( p_dest ); vlc_object_release( p_dest ); return VLC_ENOMEM; } i_size = p_block->i_buffer; p_snapshot->i_width = fmt_out.i_width; p_snapshot->i_height = fmt_out.i_height; p_snapshot->i_datasize = i_size; p_snapshot->date = p_block->i_pts; /* FIXME ?? */ p_snapshot->p_data = malloc( i_size ); if( !p_snapshot->p_data ) { block_Release( p_block ); free( p_snapshot ); image_HandlerDelete( p_image ); vlc_object_signal( p_dest ); vlc_object_release( p_dest ); return VLC_ENOMEM; } memcpy( p_snapshot->p_data, p_block->p_buffer, p_block->i_buffer ); p_dest->p_private = p_snapshot; block_Release( p_block ); /* Unlock the object */ vlc_object_signal( p_dest ); vlc_object_release( p_dest ); image_HandlerDelete( p_image ); return VLC_SUCCESS; } /* Get default directory if none provided */ if( !val.psz_string ) val.psz_string = VoutSnapshotGetDefaultDirectory( p_vout ); if( !val.psz_string ) { msg_Err( p_vout, "no path specified for snapshots" ); image_HandlerDelete( p_image ); return VLC_EGENERIC; } /* Get snapshot format, default being "png" */ format.psz_string = var_GetNonEmptyString( p_vout, "snapshot-format" ); if( !format.psz_string ) format.psz_string = strdup( "png" ); if( !format.psz_string ) { free( val.psz_string ); image_HandlerDelete( p_image ); return VLC_ENOMEM; } /* * Did the user specify a directory? If not, path = NULL. */ path = utf8_opendir ( (const char *)val.psz_string ); if( path != NULL ) { char *psz_prefix = var_GetNonEmptyString( p_vout, "snapshot-prefix" ); if( psz_prefix == NULL ) psz_prefix = strdup( "vlcsnap-" ); else { char *psz_tmp = str_format( p_vout, psz_prefix ); filename_sanitize( psz_tmp ); free( psz_prefix ); psz_prefix = psz_tmp; } closedir( path ); if( var_GetBool( p_vout, "snapshot-sequential" ) == true ) { int i_num = var_GetInteger( p_vout, "snapshot-num" ); struct stat st; do { free( psz_filename ); if( asprintf( &psz_filename, "%s" DIR_SEP "%s%05d.%s", val.psz_string, psz_prefix, i_num++, format.psz_string ) == -1 ) { msg_Err( p_vout, "could not create snapshot" ); image_HandlerDelete( p_image ); return VLC_EGENERIC; } } while( utf8_stat( psz_filename, &st ) == 0 ); var_SetInteger( p_vout, "snapshot-num", i_num ); } else { if( asprintf( &psz_filename, "%s" DIR_SEP "%s%u.%s", val.psz_string, psz_prefix, (unsigned int)(p_pic->date / 100000) & 0xFFFFFF, format.psz_string ) == -1 ) { msg_Err( p_vout, "could not create snapshot" ); image_HandlerDelete( p_image ); return VLC_EGENERIC; } } free( psz_prefix ); } else // The user specified a full path name (including file name) { psz_filename = str_format( p_vout, val.psz_string ); path_sanitize( psz_filename ); } free( val.psz_string ); free( format.psz_string ); /* Save the snapshot */ i_ret = image_WriteUrl( p_image, p_pic, &fmt_in, &fmt_out, psz_filename ); if( i_ret != VLC_SUCCESS ) { msg_Err( p_vout, "could not create snapshot %s", psz_filename ); free( psz_filename ); image_HandlerDelete( p_image ); return VLC_EGENERIC; } /* */ msg_Dbg( p_vout, "snapshot taken (%s)", psz_filename ); vout_OSDMessage( VLC_OBJECT( p_vout ), DEFAULT_CHAN, "%s", psz_filename ); free( psz_filename ); /* */ if( var_GetBool( p_vout, "snapshot-preview" ) ) { if( VoutSnapshotPip( p_vout, p_image, p_pic, &fmt_in ) ) msg_Warn( p_vout, "Failed to display snapshot" ); } image_HandlerDelete( p_image ); return VLC_SUCCESS; }
/***************************************************************************** * PrefsPanel class definition. *****************************************************************************/ PrefsPanel::PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf, PrefsDialog *_p_prefs_dialog, int i_object_id, char *psz_section, char *psz_help ) { module_config_t *p_item; module_t *p_module = NULL; /* Initializations */ p_intf = _p_intf; p_prefs_dialog = _p_prefs_dialog; b_advanced = VLC_TRUE; if( i_object_id == PLUGIN_ID || i_object_id == GENERAL_ID || i_object_id == CAPABILITY_ID ) { label = CreateWindow( _T("STATIC"), _FROMMB(psz_section), WS_CHILD | WS_VISIBLE | SS_LEFT, 5, 10 + (15 + 10), 200, 15, parent, NULL, hInst, NULL ); config_window = NULL; } else { /* Get a pointer to the module */ p_module = (module_t *)vlc_object_get( p_intf, i_object_id ); if( p_module->i_object_type != VLC_OBJECT_MODULE ) { /* 0OOoo something went really bad */ return; } /* Enumerate config options and add corresponding config boxes * (submodules don't have config options, they are stored in the * parent module) */ if( p_module->b_submodule ) p_item = ((module_t *)p_module->p_parent)->p_config; else p_item = p_module->p_config; /* Find the category if it has been specified */ if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY ) { while( !(p_item->i_type == CONFIG_HINT_CATEGORY) || strcmp( psz_section, p_item->psz_text ) ) { if( p_item->i_type == CONFIG_HINT_END ) break; p_item++; } } /* Add a head title to the panel */ label = CreateWindow( _T("STATIC"), _FROMMB(psz_section ? p_item->psz_text : p_module->psz_longname), WS_CHILD | WS_VISIBLE | SS_LEFT, 5, 10 + (15 + 10), 250, 15, parent, NULL, hInst, NULL ); WNDCLASS wc; memset( &wc, 0, sizeof(wc) ); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC) _p_prefs_dialog->BaseWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = 0; wc.hCursor = 0; wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = _T("PrefsPanelClass"); RegisterClass(&wc); RECT rc; GetWindowRect( parent, &rc); config_window = CreateWindow( _T("PrefsPanelClass"), _T("config_window"), WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER, 5, 10 + 2*(15 + 10), rc.right - 5 - 7, 105, parent, NULL, hInst, (void *) _p_prefs_dialog ); int y_pos = 5; if( p_item ) do { /* If a category has been specified, check we finished the job */ if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY && strcmp( psz_section, p_item->psz_text ) ) break; ConfigControl *control = CreateConfigControl( VLC_OBJECT(p_intf), p_item, config_window, hInst, &y_pos ); /* Don't add items that were not recognized */ if( control == NULL ) continue; /* Add the config data to our array so we can keep a trace of it */ config_array.push_back( control ); } while( p_item->i_type != CONFIG_HINT_END && p_item++ ); GetWindowRect( config_window, &rc); maxvalue = y_pos - (rc.bottom - rc.top) + 5; oldvalue = 0; SetScrollRange( config_window, SB_VERT, 0, maxvalue, TRUE ); } }
/***************************************************************************** * DumpCommand: print the current vlc structure ***************************************************************************** * This function prints either an ASCII tree showing the connections between * vlc objects, and additional information such as their refcount, thread ID, * etc. (command "tree"), or the same data as a simple list (command "list"). *****************************************************************************/ static int DumpCommand( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ) { if( *psz_cmd == 't' ) { char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1]; vlc_object_t *p_object; if( *newval.psz_string ) { p_object = vlc_object_get( p_this, atoi(newval.psz_string) ); if( !p_object ) { return VLC_ENOOBJ; } } else { p_object = p_this->p_vlc ? VLC_OBJECT(p_this->p_vlc) : p_this; } vlc_mutex_lock( &structure_lock ); psz_foo[0] = '|'; DumpStructure( p_object, 0, psz_foo ); vlc_mutex_unlock( &structure_lock ); if( *newval.psz_string ) { vlc_object_release( p_this ); } } else if( *psz_cmd == 'l' ) { vlc_object_t **pp_current, **pp_end; vlc_mutex_lock( &structure_lock ); pp_current = p_this->p_libvlc->pp_objects; pp_end = pp_current + p_this->p_libvlc->i_objects; for( ; pp_current < pp_end ; pp_current++ ) { if( (*pp_current)->b_attached ) { PrintObject( *pp_current, "" ); } else { printf( " o %.8i %s (not attached)\n", (*pp_current)->i_object_id, (*pp_current)->psz_object_type ); } } vlc_mutex_unlock( &structure_lock ); } return VLC_SUCCESS; }
/***************************************************************************** * Stress: perform various stress tests *****************************************************************************/ static int Stress( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ) { vlc_object_t **pp_objects; mtime_t start; char ** ppsz_name; char * psz_blob; int i, i_level; if( *newval.psz_string ) { i_level = atoi( newval.psz_string ); if( i_level <= 0 ) { i_level = 1; } else if( i_level > 200 ) { /* It becomes quite dangerous above 150 */ i_level = 200; } } else { i_level = 10; } /* Allocate required data */ ppsz_name = malloc( MAXVAR * i_level * sizeof(char*) ); psz_blob = malloc( 20 * MAXVAR * i_level * sizeof(char) ); for( i = 0; i < MAXVAR * i_level; i++ ) { ppsz_name[i] = psz_blob + 20 * i; } pp_objects = malloc( MAXOBJ * i_level * sizeof(void*) ); /* * Test #1: objects */ printf( "Test #1: objects\n" ); printf( " - creating %i objects\n", MAXOBJ * i_level ); start = mdate(); for( i = 0; i < MAXOBJ * i_level; i++ ) { pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC ); } printf( " - randomly looking up %i objects\n", MAXLOOK * i_level ); for( i = MAXLOOK * i_level; i--; ) { int id = (int) (MAXOBJ * i_level * 1.0 * rand() / (RAND_MAX)); vlc_object_get( p_this, pp_objects[id]->i_object_id ); vlc_object_release( p_this ); } printf( " - destroying the objects (LIFO)\n" ); for( i = MAXOBJ * i_level; i--; ) { vlc_object_destroy( pp_objects[i] ); } printf( "done (%fs).\n", (mdate() - start) / 1000000.0 ); /* * Test #2: integer variables */ printf( "Test #2: integer variables\n" ); printf( " - creating %i integer variables\n", MAXVAR * i_level ); start = mdate(); for( i = 0; i < MAXVAR * i_level; i++ ) { sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 ); var_Create( p_this, ppsz_name[i], VLC_VAR_INTEGER ); } printf( " - randomly assigning %i values\n", MAXSET * i_level ); for( i = 0; i < MAXSET * i_level; i++ ) { int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX)); var_Set( p_this, ppsz_name[v], (vlc_value_t)i ); } printf( " - destroying the variables\n" ); for( i = 0; i < MAXVAR * i_level; i++ ) { var_Destroy( p_this, ppsz_name[i] ); } printf( "done (%fs).\n", (mdate() - start) / 1000000.0 ); /* * Test #3: string variables */ printf( "Test #3: string variables\n" ); printf( " - creating %i string variables\n", MAXVAR * i_level ); start = mdate(); for( i = 0; i < MAXVAR * i_level; i++ ) { sprintf( ppsz_name[i], "foo-%04i-bar-%04x", i, i * 11 ); var_Create( p_this, ppsz_name[i], VLC_VAR_STRING ); } printf( " - randomly assigning %i values\n", MAXSET * i_level ); for( i = 0; i < MAXSET * i_level; i++ ) { int v = (int) (MAXVAR * i_level * 1.0 * rand() / (RAND_MAX)); var_Set( p_this, ppsz_name[v], (vlc_value_t)ppsz_name[v] ); } printf( " - destroying the variables\n" ); for( i = 0; i < MAXVAR * i_level; i++ ) { var_Destroy( p_this, ppsz_name[i] ); } printf( "done (%fs).\n", (mdate() - start) / 1000000.0 ); /* * Test #4: threads */ printf( "Test #4: threads\n" ); start = mdate(); printf( " - spawning %i threads that will each create %i objects\n", MAXTH * i_level, MAXOBJ/MAXTH ); for( i = 0; i < MAXTH * i_level; i++ ) { pp_objects[i] = vlc_object_create( p_this, VLC_OBJECT_GENERIC ); vlc_thread_create( pp_objects[i], "foo", Dummy, 0, VLC_TRUE ); } printf( " - killing the threads (LIFO)\n" ); for( i = MAXTH * i_level; i--; ) { pp_objects[i]->b_die = VLC_TRUE; vlc_thread_join( pp_objects[i] ); vlc_object_destroy( pp_objects[i] ); } printf( "done (%fs).\n", (mdate() - start) / 1000000.0 ); /* Free required data */ free( pp_objects ); free( psz_blob ); free( ppsz_name ); return VLC_SUCCESS; }