static void ArtCacheGetDirPath( char *psz_dir, const char *psz_title, const char *psz_artist, const char *psz_album ) { char *psz_cachedir = config_GetCacheDir(); if( !EMPTY_STR(psz_artist) && !EMPTY_STR(psz_album) ) { char *psz_album_sanitized = filename_sanitize( psz_album ); char *psz_artist_sanitized = filename_sanitize( psz_artist ); snprintf( psz_dir, PATH_MAX, "%s" DIR_SEP "art" DIR_SEP "artistalbum" DIR_SEP "%s" DIR_SEP "%s", psz_cachedir, psz_artist_sanitized, psz_album_sanitized ); free( psz_album_sanitized ); free( psz_artist_sanitized ); } else { char * psz_title_sanitized = filename_sanitize( psz_title ); snprintf( psz_dir, PATH_MAX, "%s" DIR_SEP "art" DIR_SEP "title" DIR_SEP "%s", psz_cachedir, psz_title_sanitized ); free( psz_title_sanitized ); } free( psz_cachedir ); }
static char* ArtCacheGetDirPath( const char *psz_arturl, const char *psz_artist, const char *psz_album, const char *psz_title ) { char *psz_dir; char *psz_cachedir = config_GetUserDir(VLC_CACHE_DIR); if( !EMPTY_STR(psz_artist) && !EMPTY_STR(psz_album) ) { char *psz_album_sanitized = strdup( psz_album ); filename_sanitize( psz_album_sanitized ); char *psz_artist_sanitized = strdup( psz_artist ); filename_sanitize( psz_artist_sanitized ); if( asprintf( &psz_dir, "%s" DIR_SEP "art" DIR_SEP "artistalbum" DIR_SEP "%s" DIR_SEP "%s", psz_cachedir, psz_artist_sanitized, psz_album_sanitized ) == -1 ) psz_dir = NULL; free( psz_album_sanitized ); free( psz_artist_sanitized ); } else { /* If artist or album are missing, cache by art download URL. * If the URL is an attachment://, add the title to the cache name. * It will be md5 hashed to form a valid cache filename. * We assume that psz_arturl is always the download URL and not the * already hashed filename. * (We should never need to call this function if art has already been * downloaded anyway). */ struct md5_s md5; InitMD5( &md5 ); AddMD5( &md5, psz_arturl, strlen( psz_arturl ) ); if( !strncmp( psz_arturl, "attachment://", 13 ) ) AddMD5( &md5, psz_title, strlen( psz_title ) ); EndMD5( &md5 ); char * psz_arturl_sanitized = psz_md5_hash( &md5 ); if( asprintf( &psz_dir, "%s" DIR_SEP "art" DIR_SEP "arturl" DIR_SEP "%s", psz_cachedir, psz_arturl_sanitized ) == -1 ) psz_dir = NULL; free( psz_arturl_sanitized ); } free( psz_cachedir ); return psz_dir; }
static char *ArtCacheName( input_item_t *p_item, const char *psz_type ) { char *psz_path = ArtCachePath( p_item ); if( !psz_path ) return NULL; ArtCacheCreateDir( psz_path ); char *psz_ext = filename_sanitize( psz_type ? psz_type : "" ); char *psz_filename; if( asprintf( &psz_filename, "%s" DIR_SEP "art%s", psz_path, psz_ext ) < 0 ) psz_filename = NULL; free( psz_ext ); free( psz_path ); return psz_filename; }
static char *ArtCacheName( input_item_t *p_item, const char *psz_type ) { char *psz_path = ArtCachePath( p_item ); char *psz_ext = strdup( psz_type ? psz_type : "" ); char *psz_filename = NULL; if( unlikely( !psz_path || !psz_ext ) ) goto end; ArtCacheCreateDir( psz_path ); filename_sanitize( psz_ext ); if( asprintf( &psz_filename, "%s" DIR_SEP "art%s", psz_path, psz_ext ) < 0 ) psz_filename = NULL; end: free( psz_ext ); free( psz_path ); return psz_filename; }
int vout_snapshot_SaveImage(char **name, int *sequential, const block_t *image, vout_thread_t *p_vout, const vout_snapshot_save_cfg_t *cfg) { /* */ char *filename; DIR *pathdir = vlc_opendir(cfg->path); input_thread_t *input = (input_thread_t*)p_vout->p->input; if (pathdir != NULL) { /* The use specified a directory path */ closedir(pathdir); /* */ char *prefix = NULL; if (cfg->prefix_fmt) prefix = str_format(input, cfg->prefix_fmt); if (prefix) filename_sanitize(prefix); else { prefix = strdup("vlcsnap-"); if (!prefix) goto error; } if (cfg->is_sequential) { for (int num = cfg->sequence; ; num++) { struct stat st; if (asprintf(&filename, "%s" DIR_SEP "%s%05d.%s", cfg->path, prefix, num, cfg->format) < 0) { free(prefix); goto error; } if (vlc_stat(filename, &st)) { *sequential = num; break; } free(filename); } } else { struct timespec ts; struct tm curtime; char buffer[128]; timespec_get(&ts, TIME_UTC); if (localtime_r(&ts.tv_sec, &curtime) == NULL) gmtime_r(&ts.tv_sec, &curtime); if (strftime(buffer, sizeof(buffer), "%Y-%m-%d-%Hh%Mm%Ss", &curtime) == 0) strcpy(buffer, "error"); if (asprintf(&filename, "%s" DIR_SEP "%s%s%03lu.%s", cfg->path, prefix, buffer, ts.tv_nsec / 1000000, cfg->format) < 0) filename = NULL; } free(prefix); } else { /* The user specified a full path name (including file name) */ filename = str_format(input, cfg->path); path_sanitize(filename); } if (!filename) goto error; /* Save the snapshot */ FILE *file = vlc_fopen(filename, "wb"); if (!file) { msg_Err(p_vout, "Failed to open '%s'", filename); free(filename); goto error; } if (fwrite(image->p_buffer, image->i_buffer, 1, file) != 1) { msg_Err(p_vout, "Failed to write to '%s'", filename); fclose(file); free(filename); goto error; } fclose(file); /* */ if (name) *name = filename; else free(filename); return VLC_SUCCESS; error: msg_Err(p_vout, "could not save snapshot"); return VLC_EGENERIC; }
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; }
int vout_snapshot_SaveImage(char **name, int *sequential, const block_t *image, vlc_object_t *object, const vout_snapshot_save_cfg_t *cfg) { /* */ char *filename; DIR *pathdir = vlc_opendir(cfg->path); if (pathdir != NULL) { /* The use specified a directory path */ closedir(pathdir); /* */ char *prefix = NULL; if (cfg->prefix_fmt) prefix = str_format(object, cfg->prefix_fmt); if (prefix) filename_sanitize(prefix); else { prefix = strdup("vlcsnap-"); if (!prefix) goto error; } if (cfg->is_sequential) { for (int num = cfg->sequence; ; num++) { struct stat st; if (asprintf(&filename, "%s" DIR_SEP "%s%05d.%s", cfg->path, prefix, num, cfg->format) < 0) { free(prefix); goto error; } if (vlc_stat(filename, &st)) { *sequential = num; break; } free(filename); } } else { struct tm curtime; time_t lcurtime = time(NULL) ; if (!localtime_r(&lcurtime, &curtime)) { const unsigned int id = (image->i_pts / 100000) & 0xFFFFFF; msg_Warn(object, "failed to get current time. Falling back to legacy snapshot naming"); if (asprintf(&filename, "%s" DIR_SEP "%s%u.%s", cfg->path, prefix, id, cfg->format) < 0) filename = NULL; } else { /* suffix with the last decimal digit in 10s of seconds resolution * FIXME gni ? */ const int id = (image->i_pts / (100*1000)) & 0xFF; char buffer[128]; if (!strftime(buffer, sizeof(buffer), "%Y-%m-%d-%Hh%Mm%Ss", &curtime)) strcpy(buffer, "error"); if (asprintf(&filename, "%s" DIR_SEP "%s%s%1u.%s", cfg->path, prefix, buffer, id, cfg->format) < 0) filename = NULL; } } free(prefix); } else { /* The user specified a full path name (including file name) */ filename = str_format(object, cfg->path); path_sanitize(filename); } if (!filename) goto error; /* Save the snapshot */ FILE *file = vlc_fopen(filename, "wb"); if (!file) { msg_Err(object, "Failed to open '%s'", filename); free(filename); goto error; } if (fwrite(image->p_buffer, image->i_buffer, 1, file) != 1) { msg_Err(object, "Failed to write to '%s'", filename); fclose(file); free(filename); goto error; } fclose(file); /* */ if (name) *name = filename; else free(filename); return VLC_SUCCESS; error: msg_Err(object, "could not save snapshot"); return VLC_EGENERIC; }