Commit 9d8ceda6 authored by Laurent Aimar's avatar Laurent Aimar

- Added support for embeded cover. Demuxer just need to fill psz_arturl meta

field to "attachment://NAME" where NAME is an attachment filename
(returned by DEMUX_GET_ATTACHMENTS)
- Lock input_item_t every time we access p_meta fields (there is still a problem
as playlist code does not always do so...).
- Do not preparse item we have already played.
- Wait that the current playing item is meta parsed before fetching its cover.
parent 054e07f0
...@@ -478,10 +478,12 @@ static void EsOutProgramSelect( es_out_t *out, es_out_pgrm_t *p_pgrm ) ...@@ -478,10 +478,12 @@ static void EsOutProgramSelect( es_out_t *out, es_out_pgrm_t *p_pgrm )
} }
/* Update now playing */ /* Update now playing */
vlc_mutex_lock( &p_input->p->input.p_item->lock );
vlc_meta_SetNowPlaying( p_input->p->input.p_item->p_meta, vlc_meta_SetNowPlaying( p_input->p->input.p_item->p_meta,
p_pgrm->psz_now_playing ); p_pgrm->psz_now_playing );
vlc_meta_SetPublisher( p_input->p->input.p_item->p_meta, vlc_meta_SetPublisher( p_input->p->input.p_item->p_meta,
p_pgrm->psz_publisher ); p_pgrm->psz_publisher );
vlc_mutex_unlock( &p_input->p->input.p_item->lock );
var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE ); var_SetBool( p_sys->p_input, "intf-change", VLC_TRUE );
} }
...@@ -658,7 +660,11 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta ) ...@@ -658,7 +660,11 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta )
if( psz_provider ) if( psz_provider )
{ {
if( p_sys->p_pgrm == p_pgrm ) if( p_sys->p_pgrm == p_pgrm )
{
vlc_mutex_lock( &p_input->p->input.p_item->lock );
vlc_meta_SetPublisher( p_input->p->input.p_item->p_meta, psz_provider ); vlc_meta_SetPublisher( p_input->p->input.p_item->p_meta, psz_provider );
vlc_mutex_unlock( &p_input->p->input.p_item->lock );
}
input_Control( p_input, INPUT_ADD_INFO, psz_cat, _(VLC_META_PUBLISHER), psz_provider ); input_Control( p_input, INPUT_ADD_INFO, psz_cat, _(VLC_META_PUBLISHER), psz_provider );
} }
for( i = 0; i < p_meta->i_extra; i++ ) for( i = 0; i < p_meta->i_extra; i++ )
...@@ -666,20 +672,6 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta ) ...@@ -666,20 +672,6 @@ static void EsOutProgramMeta( es_out_t *out, int i_group, vlc_meta_t *p_meta )
free( psz_cat ); free( psz_cat );
} }
#define TAB_INSERT_CAST( cast, count, tab, p, index ) do { \
if( (count) > 0 ) \
(tab) = cast realloc( tab, sizeof( void ** ) * ( (count) + 1 ) ); \
else \
(tab) = cast malloc( sizeof( void ** ) ); \
if( (count) - (index) > 0 ) \
memmove( (void**)(tab) + (index) + 1, \
(void**)(tab) + (index), \
((count) - (index)) * sizeof(*(tab)) );\
(tab)[(index)] = (p); \
(count)++; \
} while(0)
#define TAB_INSERT( count, tab, p, index ) TAB_INSERT_CAST( , count, tab, p, index )
static void vlc_epg_Merge( vlc_epg_t *p_dst, const vlc_epg_t *p_src ) static void vlc_epg_Merge( vlc_epg_t *p_dst, const vlc_epg_t *p_src )
{ {
...@@ -785,20 +777,19 @@ static void EsOutProgramEpg( es_out_t *out, int i_group, vlc_epg_t *p_epg ) ...@@ -785,20 +777,19 @@ static void EsOutProgramEpg( es_out_t *out, int i_group, vlc_epg_t *p_epg )
if( p_pgrm->psz_now_playing ) if( p_pgrm->psz_now_playing )
free( p_pgrm->psz_now_playing ); free( p_pgrm->psz_now_playing );
p_pgrm->psz_now_playing = NULL; p_pgrm->psz_now_playing = NULL;
if( p_epg->p_current && p_epg->p_current->psz_name && *p_epg->p_current->psz_name ) if( p_epg->p_current && p_epg->p_current->psz_name && *p_epg->p_current->psz_name )
{
p_pgrm->psz_now_playing = strdup( p_epg->p_current->psz_name ); p_pgrm->psz_now_playing = strdup( p_epg->p_current->psz_name );
if( p_pgrm == p_sys->p_pgrm )
vlc_meta_SetNowPlaying( p_input->p->input.p_item->p_meta, p_pgrm->psz_now_playing ); vlc_mutex_lock( &p_input->p->input.p_item->lock );
if( p_pgrm == p_sys->p_pgrm )
vlc_meta_SetNowPlaying( p_input->p->input.p_item->p_meta, p_pgrm->psz_now_playing );
vlc_mutex_unlock( &p_input->p->input.p_item->lock );
if( p_pgrm->psz_now_playing )
input_Control( p_input, INPUT_ADD_INFO, psz_cat, _(VLC_META_NOW_PLAYING), p_pgrm->psz_now_playing ); input_Control( p_input, INPUT_ADD_INFO, psz_cat, _(VLC_META_NOW_PLAYING), p_pgrm->psz_now_playing );
}
else else
{
if( p_pgrm == p_sys->p_pgrm )
vlc_meta_SetNowPlaying( p_input->p->input.p_item->p_meta, NULL );
input_Control( p_input, INPUT_DEL_INFO, psz_cat, _(VLC_META_NOW_PLAYING) ); input_Control( p_input, INPUT_DEL_INFO, psz_cat, _(VLC_META_NOW_PLAYING) );
}
free( psz_cat ); free( psz_cat );
} }
......
...@@ -65,7 +65,6 @@ static vlc_bool_t Control( input_thread_t *, int, vlc_value_t ); ...@@ -65,7 +65,6 @@ static vlc_bool_t Control( input_thread_t *, int, vlc_value_t );
static int UpdateFromAccess( input_thread_t * ); static int UpdateFromAccess( input_thread_t * );
static int UpdateFromDemux( input_thread_t * ); static int UpdateFromDemux( input_thread_t * );
static int UpdateMeta( input_thread_t * );
static void UpdateItemLength( input_thread_t *, int64_t i_length ); static void UpdateItemLength( input_thread_t *, int64_t i_length );
...@@ -75,11 +74,14 @@ static input_source_t *InputSourceNew( input_thread_t *); ...@@ -75,11 +74,14 @@ static input_source_t *InputSourceNew( input_thread_t *);
static int InputSourceInit( input_thread_t *, input_source_t *, static int InputSourceInit( input_thread_t *, input_source_t *,
const char *, const char *psz_forced_demux ); const char *, const char *psz_forced_demux );
static void InputSourceClean( input_source_t * ); static void InputSourceClean( input_source_t * );
/* TODO */
//static void InputGetAttachments( input_thread_t *, input_source_t * );
static void SlaveDemux( input_thread_t *p_input ); static void SlaveDemux( input_thread_t *p_input );
static void SlaveSeek( input_thread_t *p_input ); static void SlaveSeek( input_thread_t *p_input );
static void InputMetaUser( input_thread_t *p_input ); static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta );
static void InputUpdateMeta( input_thread_t *p_input, vlc_meta_t *p_meta );
static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item, vlc_bool_t * ); static sout_instance_t *SoutFind( vlc_object_t *p_parent, input_item_t *p_item, vlc_bool_t * );
static void SoutKeep( sout_instance_t * ); static void SoutKeep( sout_instance_t * );
...@@ -152,7 +154,6 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, ...@@ -152,7 +154,6 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
p_input->p->i_rate = INPUT_RATE_DEFAULT; p_input->p->i_rate = INPUT_RATE_DEFAULT;
TAB_INIT( p_input->p->i_bookmark, p_input->p->bookmark ); TAB_INIT( p_input->p->i_bookmark, p_input->p->bookmark );
TAB_INIT( p_input->p->i_attachment, p_input->p->attachment ); TAB_INIT( p_input->p->i_attachment, p_input->p->attachment );
p_input->p->p_meta = NULL;
p_input->p->p_es_out = NULL; p_input->p->p_es_out = NULL;
p_input->p->p_sout = NULL; p_input->p->p_sout = NULL;
p_input->p->b_sout_keep = VLC_FALSE; p_input->p->b_sout_keep = VLC_FALSE;
...@@ -172,15 +173,13 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, ...@@ -172,15 +173,13 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
p_input->p->input.b_eof = VLC_FALSE; p_input->p->input.b_eof = VLC_FALSE;
p_input->p->input.i_cr_average = 0; p_input->p->input.i_cr_average = 0;
vlc_mutex_lock( &p_item->lock );
if( !p_input->p->input.p_item->p_meta ) if( !p_input->p->input.p_item->p_meta )
p_input->p->input.p_item->p_meta = vlc_meta_New(); p_input->p->input.p_item->p_meta = vlc_meta_New();
if( !p_item->p_stats ) if( !p_item->p_stats )
{ p_item->p_stats = stats_NewInputStats( p_input );
p_item->p_stats = (input_stats_t*)malloc( sizeof( input_stats_t ) ); vlc_mutex_unlock( &p_item->lock );
vlc_mutex_init( p_input, &p_item->p_stats->lock );
stats_ReinitInputStats( p_item->p_stats );
}
/* No slave */ /* No slave */
p_input->p->i_slave = 0; p_input->p->i_slave = 0;
...@@ -254,7 +253,9 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, ...@@ -254,7 +253,9 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
/* Remove 'Now playing' info as it is probably outdated */ /* Remove 'Now playing' info as it is probably outdated */
input_Control( p_input, INPUT_DEL_INFO, _(VLC_META_INFO_CAT), VLC_META_NOW_PLAYING ); input_Control( p_input, INPUT_DEL_INFO, _(VLC_META_INFO_CAT), VLC_META_NOW_PLAYING );
vlc_mutex_lock( &p_item->lock );
vlc_meta_SetNowPlaying( p_item->p_meta, NULL ); vlc_meta_SetNowPlaying( p_item->p_meta, NULL );
vlc_mutex_unlock( &p_item->lock );
/* */ /* */
if( p_input->b_preparsing ) if( p_input->b_preparsing )
...@@ -898,7 +899,6 @@ static int Init( input_thread_t * p_input ) ...@@ -898,7 +899,6 @@ static int Init( input_thread_t * p_input )
{ {
var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL ); var_Change( p_input, "length", VLC_VAR_SETVALUE, &val, NULL );
UpdateItemLength( p_input, val.i_time ); UpdateItemLength( p_input, val.i_time );
p_input->p->input.p_item->i_duration = val.i_time;
} }
/* Start title/chapter */ /* Start title/chapter */
...@@ -1120,9 +1120,10 @@ static int Init( input_thread_t * p_input ) ...@@ -1120,9 +1120,10 @@ static int Init( input_thread_t * p_input )
} }
} }
p_meta = p_input->p->input.p_item->p_meta; p_meta = vlc_meta_New();
/* Get meta data from users */ /* Get meta data from users */
InputMetaUser( p_input ); InputMetaUser( p_input, p_meta );
/* Get meta data from master input */ /* Get meta data from master input */
demux2_Control( p_input->p->input.p_demux, DEMUX_GET_META, p_meta ); demux2_Control( p_input->p->input.p_demux, DEMUX_GET_META, p_meta );
...@@ -1146,7 +1147,7 @@ static int Init( input_thread_t * p_input ) ...@@ -1146,7 +1147,7 @@ static int Init( input_thread_t * p_input )
} }
} }
UpdateMeta( p_input ); InputUpdateMeta( p_input, p_meta );
if( !p_input->b_preparsing ) if( !p_input->b_preparsing )
{ {
...@@ -1846,7 +1847,7 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type, ...@@ -1846,7 +1847,7 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type,
if( !InputSourceInit( p_input, slave, val.psz_string, NULL ) ) if( !InputSourceInit( p_input, slave, val.psz_string, NULL ) )
{ {
vlc_meta_t *p_meta = p_input->p->input.p_item->p_meta; vlc_meta_t *p_meta;
int64_t i_time; int64_t i_time;
/* Add the slave */ /* Add the slave */
...@@ -1872,10 +1873,11 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type, ...@@ -1872,10 +1873,11 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type,
} }
/* Get meta (access and demux) */ /* Get meta (access and demux) */
p_meta = vlc_meta_New();
access2_Control( slave->p_access, ACCESS_GET_META, access2_Control( slave->p_access, ACCESS_GET_META,
p_meta ); p_meta );
demux2_Control( slave->p_demux, DEMUX_GET_META, p_meta ); demux2_Control( slave->p_demux, DEMUX_GET_META, p_meta );
UpdateMeta( p_input ); InputUpdateMeta( p_input, p_meta );
TAB_APPEND( p_input->p->i_slave, p_input->p->slave, slave ); TAB_APPEND( p_input->p->i_slave, p_input->p->slave, slave );
} }
...@@ -1980,9 +1982,9 @@ static int UpdateFromAccess( input_thread_t *p_input ) ...@@ -1980,9 +1982,9 @@ static int UpdateFromAccess( input_thread_t *p_input )
if( p_access->info.i_update & INPUT_UPDATE_META ) if( p_access->info.i_update & INPUT_UPDATE_META )
{ {
/* TODO maybe multi - access ? */ /* TODO maybe multi - access ? */
vlc_meta_t *p_meta = p_input->p->input.p_item->p_meta; vlc_meta_t *p_meta = vlc_meta_New();
access2_Control( p_input->p->input.p_access,ACCESS_GET_META, p_meta ); access2_Control( p_input->p->input.p_access,ACCESS_GET_META, p_meta );
UpdateMeta( p_input ); InputUpdateMeta( p_input, p_meta );
var_SetBool( p_input, "item-change", p_input->p->input.p_item->i_id ); var_SetBool( p_input, "item-change", p_input->p->input.p_item->i_id );
p_access->info.i_update &= ~INPUT_UPDATE_META; p_access->info.i_update &= ~INPUT_UPDATE_META;
} }
...@@ -2016,23 +2018,6 @@ static int UpdateFromAccess( input_thread_t *p_input ) ...@@ -2016,23 +2018,6 @@ static int UpdateFromAccess( input_thread_t *p_input )
return 1; return 1;
} }
/*****************************************************************************
* UpdateMeta:
*****************************************************************************/
static int UpdateMeta( input_thread_t *p_input )
{
vlc_meta_t *p_meta = p_input->p->input.p_item->p_meta;
if( !p_meta )
return VLC_SUCCESS;
if( p_meta->psz_title && !p_input->p->input.p_item->b_fixed_name )
input_Control( p_input, INPUT_SET_NAME, p_meta->psz_title );
/** \todo handle sout meta */
return VLC_SUCCESS;
}
/***************************************************************************** /*****************************************************************************
* UpdateItemLength: * UpdateItemLength:
*****************************************************************************/ *****************************************************************************/
...@@ -2327,8 +2312,9 @@ static int InputSourceInit( input_thread_t *p_input, ...@@ -2327,8 +2312,9 @@ static int InputSourceInit( input_thread_t *p_input,
in->b_title_demux = VLC_TRUE; in->b_title_demux = VLC_TRUE;
} }
} }
/* get attachment */ /* get attachment
if( !p_input->b_preparsing ) * FIXME improve for b_preparsing: move it after GET_META and check psz_arturl */
if( 1 || !p_input->b_preparsing )
{ {
int i_attachment; int i_attachment;
input_attachment_t **attachment; input_attachment_t **attachment;
...@@ -2472,9 +2458,8 @@ static void SlaveSeek( input_thread_t *p_input ) ...@@ -2472,9 +2458,8 @@ static void SlaveSeek( input_thread_t *p_input )
/***************************************************************************** /*****************************************************************************
* InputMetaUser: * InputMetaUser:
*****************************************************************************/ *****************************************************************************/
static void InputMetaUser( input_thread_t *p_input ) static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta )
{ {
vlc_meta_t *p_meta = p_input->p->input.p_item->p_meta;
vlc_value_t val; vlc_value_t val;
if( !p_meta ) return; if( !p_meta ) return;
...@@ -2498,6 +2483,60 @@ static void InputMetaUser( input_thread_t *p_input ) ...@@ -2498,6 +2483,60 @@ static void InputMetaUser( input_thread_t *p_input )
#undef GET_META #undef GET_META
} }
/*****************************************************************************
* InputUpdateMeta: merge p_item meta data with p_meta taking care of
* arturl and locking issue.
*****************************************************************************/
static void InputUpdateMeta( input_thread_t *p_input, vlc_meta_t *p_meta )
{
input_item_t *p_item = p_input->p->input.p_item;
char *psz_title = NULL;
if( !p_meta )
return;
vlc_mutex_lock( &p_item->lock );
if( p_meta->psz_title && !p_item->b_fixed_name )
psz_title = strdup( p_meta->psz_title );
if( p_item->p_meta )
{
char *psz_arturl = p_item->p_meta->psz_arturl;
p_item->p_meta->psz_arturl = NULL;
vlc_meta_Merge( p_item->p_meta, p_meta );
if( psz_arturl && *psz_arturl )
vlc_meta_SetArtURL( p_item->p_meta, psz_arturl );
vlc_meta_Delete( p_meta );
}
else
{
p_item->p_meta = p_meta;
}
if( p_item->p_meta->psz_arturl && !strncmp( p_item->p_meta->psz_arturl, "attachment://", strlen("attachment") ) )
{
/* Don't look for art cover if sout
* XXX It can change when sout has meta data support */
if( p_input->p->p_sout && !p_input->b_preparsing )
vlc_meta_SetArtURL( p_item->p_meta, "" );
else
input_ExtractAttachmentAndCacheArt( p_input );
}
p_item->p_meta->i_status |= ITEM_PREPARSED;
vlc_mutex_unlock( &p_item->lock );
if( psz_title )
{
input_Control( p_input, INPUT_SET_NAME, psz_title );
free( psz_title );
}
/** \todo handle sout meta */
}
/***************************************************************************** /*****************************************************************************
* MRLSplit: parse the access, demux and url part of the * MRLSplit: parse the access, demux and url part of the
* Media Resource Locator. * Media Resource Locator.
...@@ -2524,8 +2563,6 @@ void MRLSplit( vlc_object_t *p_input, char *psz_dup, ...@@ -2524,8 +2563,6 @@ void MRLSplit( vlc_object_t *p_input, char *psz_dup,
psz_path = psz_dup; psz_path = psz_dup;
} }
else else
#else
(void)p_input;
#endif #endif
if( psz ) if( psz )
......
...@@ -91,9 +91,6 @@ struct input_thread_private_t ...@@ -91,9 +91,6 @@ struct input_thread_private_t
int i_attachment; int i_attachment;
input_attachment_t **attachment; input_attachment_t **attachment;
/* Global meta datas FIXME move to input_item_t ? */
vlc_meta_t *p_meta;
/* Output */ /* Output */
es_out_t *p_es_out; es_out_t *p_es_out;
sout_instance_t *p_sout; /* XXX Move it to es_out ? */ sout_instance_t *p_sout; /* XXX Move it to es_out ? */
...@@ -131,7 +128,8 @@ struct input_thread_private_t ...@@ -131,7 +128,8 @@ struct input_thread_private_t
int i_control; int i_control;
struct struct
{ {
/* XXX: val isn't duplicated so it won't works with string */ /* XXX for string value you have to allocate it before calling
* input_ControlPush */
int i_type; int i_type;
vlc_value_t val; vlc_value_t val;
} control[INPUT_CONTROL_FIFO_SIZE]; } control[INPUT_CONTROL_FIFO_SIZE];
...@@ -225,10 +223,16 @@ vlc_bool_t input_MetaSatisfied ( playlist_t*, input_item_t*, ...@@ -225,10 +223,16 @@ vlc_bool_t input_MetaSatisfied ( playlist_t*, input_item_t*,
uint32_t*, uint32_t* ); uint32_t*, uint32_t* );
int input_DownloadAndCacheArt ( playlist_t *, input_item_t * ); int input_DownloadAndCacheArt ( playlist_t *, input_item_t * );
/* Becarefull; p_item lock HAS to be taken */
void input_ExtractAttachmentAndCacheArt( input_thread_t *p_input );
/*************************************************************************** /***************************************************************************
* Internal prototypes * Internal prototypes
***************************************************************************/ ***************************************************************************/
/* misc/stats.c */
input_stats_t *stats_NewInputStats( input_thread_t *p_input );
/* input.c */ /* input.c */
#define input_CreateThreadExtended(a,b,c,d) __input_CreateThreadExtended(VLC_OBJECT(a),b,c,d) #define input_CreateThreadExtended(a,b,c,d) __input_CreateThreadExtended(VLC_OBJECT(a),b,c,d)
input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, sout_instance_t * ); input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, sout_instance_t * );
......
...@@ -35,7 +35,10 @@ ...@@ -35,7 +35,10 @@
# include <sys/stat.h> # include <sys/stat.h>
#endif #endif
int input_FindArtInCache( playlist_t *p_playlist, input_item_t *p_item ); // FIXME be sure to not touch p_meta without lock on p_item
#define input_FindArtInCache(a,b) __input_FindArtInCache(VLC_OBJECT(a),b)
static int __input_FindArtInCache( vlc_object_t *, input_item_t *p_item );
vlc_bool_t input_MetaSatisfied( playlist_t *p_playlist, input_item_t *p_item, vlc_bool_t input_MetaSatisfied( playlist_t *p_playlist, input_item_t *p_item,
uint32_t *pi_mandatory, uint32_t *pi_optional ) uint32_t *pi_mandatory, uint32_t *pi_optional )
...@@ -100,6 +103,7 @@ int input_ArtFind( playlist_t *p_playlist, input_item_t *p_item ) ...@@ -100,6 +103,7 @@ int input_ArtFind( playlist_t *p_playlist, input_item_t *p_item )
{ {
msg_Dbg( p_playlist, " %s - %s has already been searched", msg_Dbg( p_playlist, " %s - %s has already been searched",
p_item->p_meta->psz_artist, p_item->p_meta->psz_album ); p_item->p_meta->psz_artist, p_item->p_meta->psz_album );
/* TODO-fenrir if we cache art filename too, we can go faster */
if( album.b_found ) if( album.b_found )
{ {
/* Actually get URL from cache */ /* Actually get URL from cache */
...@@ -107,7 +111,9 @@ int input_ArtFind( playlist_t *p_playlist, input_item_t *p_item ) ...@@ -107,7 +111,9 @@ int input_ArtFind( playlist_t *p_playlist, input_item_t *p_item )
return 0; return 0;
} }
else else
{
return VLC_EGENERIC; return VLC_EGENERIC;
}
} }
FOREACH_END(); FOREACH_END();
...@@ -144,7 +150,56 @@ int input_ArtFind( playlist_t *p_playlist, input_item_t *p_item ) ...@@ -144,7 +150,56 @@ int input_ArtFind( playlist_t *p_playlist, input_item_t *p_item )
#ifndef MAX_PATH #ifndef MAX_PATH
# define MAX_PATH 250 # define MAX_PATH 250
#endif #endif
int input_FindArtInCache( playlist_t *p_playlist, input_item_t *p_item ) #define ArtCacheCreateName( a,b,c,d,e) __ArtCacheCreateName(VLC_OBJECT(a),b,c,d,e)
static void __ArtCacheCreateName( vlc_object_t *p_obj,
char psz_filename[MAX_PATH+1],
const char *psz_artist, const char *psz_album,
const char *psz_extension )
{
snprintf( psz_filename, MAX_PATH,
"file://%s" DIR_SEP CONFIG_DIR DIR_SEP "art"
DIR_SEP "%s" DIR_SEP "%s" DIR_SEP "art%s",
p_obj->p_libvlc->psz_homedir,
psz_artist, psz_album, psz_extension ? psz_extension : "" );
}
#define ArtCacheCreatePath(a,b,c) __ArtCacheCreatePath(VLC_OBJECT(a),b,c)
static void __ArtCacheCreatePath( vlc_object_t *p_obj,
const char *psz_artist, const char *psz_album )
{
char psz_dir[MAX_PATH+1];
snprintf( psz_dir, MAX_PATH, "%s" DIR_SEP CONFIG_DIR,
p_obj->p_libvlc->psz_homedir );
utf8_mkdir( psz_dir );
snprintf( psz_dir, MAX_PATH, "%s" DIR_SEP CONFIG_DIR DIR_SEP "art",
p_obj->p_libvlc->psz_homedir );
utf8_mkdir( psz_dir );
snprintf( psz_dir, MAX_PATH, "%s" DIR_SEP CONFIG_DIR DIR_SEP
"art" DIR_SEP "%s",
p_obj->p_libvlc->psz_homedir, psz_artist );
utf8_mkdir( psz_dir );
snprintf( psz_dir, MAX_PATH, "%s" DIR_SEP CONFIG_DIR DIR_SEP
"art" DIR_SEP "%s" DIR_SEP "%s",
p_obj->p_libvlc->psz_homedir,
psz_artist, psz_album );
utf8_mkdir( psz_dir );
}
static char *ArtCacheCreateString( const char *psz )
{
char *dup = strdup(psz);
int i;
/* Doesn't create a filename with invalid characters
* TODO: several filesystems forbid several characters: list them all
*/
for( i = 0; dup[i] != '\0'; i++ )
{
if( dup[i] == '/' )
dup[i] = ' ';
}
return dup;
}
static int __input_FindArtInCache( vlc_object_t *p_obj, input_item_t *p_item )
{ {
char *psz_artist; char *psz_artist;
char *psz_album; char *psz_album;
...@@ -160,11 +215,7 @@ int input_FindArtInCache( playlist_t *p_playlist, input_item_t *p_item ) ...@@ -160,11 +215,7 @@ int input_FindArtInCache( playlist_t *p_playlist, input_item_t *p_item )
for( i = 0; i < 5; i++ ) for( i = 0; i < 5; i++ )
{ {
snprintf( psz_filename, MAX_PATH, ArtCacheCreateName( p_obj, psz_filename, psz_artist, psz_album, ppsz_type[i] );
"file://%s" DIR_SEP CONFIG_DIR DIR_SEP "art"
DIR_SEP "%s" DIR_SEP "%s" DIR_SEP "art%s",
p_playlist->p_libvlc->psz_homedir,
psz_artist, psz_album, ppsz_type[i] );
/* Check if file exists */ /* Check if file exists */
if( utf8_stat( psz_filename+7, &a ) == 0 ) if( utf8_stat( psz_filename+7, &a ) == 0 )
...@@ -184,68 +235,41 @@ int input_DownloadAndCacheArt( playlist_t *p_playlist, input_item_t *p_item ) ...@@ -184,68 +235,41 @@ int input_DownloadAndCacheArt( playlist_t *p_playlist, input_item_t *p_item )
{ {
int i_status = VLC_EGENERIC; int i_status = VLC_EGENERIC;
stream_t *p_stream; stream_t *p_stream;
char psz_filename[MAX_PATH+1], psz_dir[MAX_PATH+1]; char psz_filename[MAX_PATH+1];
char *psz_artist = NULL; char *psz_artist = NULL;
char *psz_album = NULL; char *psz_album = NULL;
char *psz_type; char *psz_type;
unsigned int i;
if( p_item->p_meta->psz_artist ) if( p_item->p_meta->psz_artist )
psz_artist = strdup( p_item->p_meta->psz_artist ); psz_artist = ArtCacheCreateString( p_item->p_meta->psz_artist );
if( p_item->p_meta->psz_album ) if( p_item->p_meta->psz_album )
psz_album = strdup( p_item->p_meta->psz_album ); psz_album = ArtCacheCreateString( p_item->p_meta->psz_album );
assert( p_item->p_meta && !EMPTY_STR(p_item->p_meta->psz_arturl) ); assert( p_item->p_meta && !EMPTY_STR(p_item->p_meta->psz_arturl) );
/* FIXME: use an alternate saving filename scheme if we don't have /* FIXME: use an alternate saving filename scheme if we don't have
* the artist or album name */ * the artist or album name */
if( !p_item->p_meta->psz_artist || !p_item->p_meta->psz_album ) if( !psz_artist || !psz_album )
{ {
free( psz_artist ); if( psz_artist ) free( psz_artist );
free( psz_album ); if( psz_album ) free( psz_album );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* Doesn't create a filename with invalid characters
* TODO: several filesystems forbid several characters: list them all
*/
for( i = 0 ; i < strlen( psz_artist ) ; i++ )
if( psz_artist[i] == '/' )
psz_artist[i] = ' ';
for( i = 0 ; i < strlen( psz_album ) ; i++ )
if( psz_album[i] == '/' )
psz_album[i] = ' ';
psz_type = strrchr( p_item->p_meta->psz_arturl, '.' ); psz_type = strrchr( p_item->p_meta->psz_arturl, '.' );
/* Todo: get a helper to do this */ /* */
snprintf( psz_filename, MAX_PATH, ArtCacheCreateName( p_playlist, psz_filename, psz_artist, psz_album, psz_type );
"file://%s" DIR_SEP CONFIG_DIR DIR_SEP "art"
DIR_SEP "%s" DIR_SEP "%s" DIR_SEP "art%s",
p_playlist->p_libvlc->psz_homedir,
psz_artist, psz_album, psz_type );
snprintf( psz_dir, MAX_PATH, "%s" DIR_SEP CONFIG_DIR, /* */
p_playlist->p_libvlc->psz_homedir ); ArtCacheCreatePath( p_playlist, psz_artist, psz_album );
utf8_mkdir( psz_dir );
snprintf( psz_dir, MAX_PATH, "%s" DIR_SEP CONFIG_DIR DIR_SEP "art", /* */
p_playlist->p_libvlc->psz_homedir ); free( psz_artist );
utf8_mkdir( psz_dir ); free( psz_album );
snprintf( psz_dir, MAX_PATH, "%s" DIR_SEP CONFIG_DIR DIR_SEP
"art" DIR_SEP "%s",
p_playlist->p_libvlc->psz_homedir, psz_artist );
utf8_mkdir( psz_dir );
snprintf( psz_dir, MAX_PATH, "%s" DIR_SEP CONFIG_DIR DIR_SEP
"art" DIR_SEP "%s" DIR_SEP "%s",
p_playlist->p_libvlc->psz_homedir,
psz_artist, psz_album );
utf8_mkdir( psz_dir );
if( !strncmp( p_item->p_meta->psz_arturl , "APIC", 4 ) ) if( !strncmp( p_item->p_meta->psz_arturl , "APIC", 4 ) )
{ {
msg_Warn( p_playlist, "APIC fetch not supported yet" ); msg_Warn( p_playlist, "APIC fetch not supported yet" );
free( psz_artist );
free( psz_album );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
...@@ -277,11 +301,95 @@ int input_DownloadAndCacheArt( playlist_t *p_playlist, input_item_t *p_item ) ...@@ -277,11 +301,95 @@ int input_DownloadAndCacheArt( playlist_t *p_playlist, input_item_t *p_item )
p_item->p_meta->psz_arturl = strdup( psz_filename ); p_item->p_meta->psz_arturl = strdup( psz_filename );
i_status = VLC_SUCCESS; i_status = VLC_SUCCESS;
} }
free( psz_artist );
free( psz_album );
return i_status; return i_status;
} }
void input_ExtractAttachmentAndCacheArt( input_thread_t *p_input )
{
input_item_t *p_item = p_input->p->input.p_item;
char *psz_arturl;
char *psz_artist = NULL;
char *psz_album = NULL;
char *psz_type = NULL;
char psz_filename[MAX_PATH+1];
FILE *f;
input_attachment_t *p_attachment;
struct stat s;
int i_idx;
/* TODO-fenrir merge input_ArtFind with download and make it set the flags FETCH
* and then set it here to to be faster */
assert( p_item->p_meta );
psz_arturl = p_item->p_meta->psz_arturl;
if( !psz_arturl || strncmp( psz_arturl, "attachment://", strlen("attachment://") ) )
{
msg_Err( p_input, "internal input error with input_ExtractAttachmentAndCacheArt" );
return;
}
p_item->p_meta->psz_arturl = NULL;
if( p_item->p_meta->i_status & ITEM_ART_FETCHED )
{