1 /*****************************************************************************
2 * preparser.c: Preparser thread.
3 *****************************************************************************
4 * Copyright © 1999-2009 VLC authors and VideoLAN
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Clément Stenac <zorglub@videolan.org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
28 #include <vlc_common.h>
29 #include <vlc_playlist.h>
33 #include "preparser.h"
34 #include "../input/input_interface.h"
37 /*****************************************************************************
38 * Structures/definitions
39 *****************************************************************************/
40 struct playlist_preparser_t
43 playlist_fetcher_t
*p_fetcher
;
48 input_item_t
**pp_waiting
;
54 static void *Thread( void * );
56 /*****************************************************************************
58 *****************************************************************************/
59 playlist_preparser_t
*playlist_preparser_New( vlc_object_t
*parent
,
60 playlist_fetcher_t
*p_fetcher
)
62 playlist_preparser_t
*p_preparser
= malloc( sizeof(*p_preparser
) );
66 p_preparser
->object
= parent
;
67 p_preparser
->p_fetcher
= p_fetcher
;
68 vlc_mutex_init( &p_preparser
->lock
);
69 vlc_cond_init( &p_preparser
->wait
);
70 p_preparser
->b_live
= false;
71 p_preparser
->i_art_policy
= var_InheritInteger( parent
, "album-art" );
72 p_preparser
->i_waiting
= 0;
73 p_preparser
->pp_waiting
= NULL
;
78 void playlist_preparser_Push( playlist_preparser_t
*p_preparser
, input_item_t
*p_item
)
80 vlc_gc_incref( p_item
);
82 vlc_mutex_lock( &p_preparser
->lock
);
83 INSERT_ELEM( p_preparser
->pp_waiting
, p_preparser
->i_waiting
,
84 p_preparser
->i_waiting
, p_item
);
85 if( !p_preparser
->b_live
)
87 if( vlc_clone_detach( NULL
, Thread
, p_preparser
,
88 VLC_THREAD_PRIORITY_LOW
) )
89 msg_Warn( p_preparser
->object
, "cannot spawn pre-parser thread" );
91 p_preparser
->b_live
= true;
93 vlc_mutex_unlock( &p_preparser
->lock
);
96 void playlist_preparser_Delete( playlist_preparser_t
*p_preparser
)
98 vlc_mutex_lock( &p_preparser
->lock
);
99 /* Remove pending item to speed up preparser thread exit */
100 while( p_preparser
->i_waiting
> 0 )
102 vlc_gc_decref( p_preparser
->pp_waiting
[0] );
103 REMOVE_ELEM( p_preparser
->pp_waiting
, p_preparser
->i_waiting
, 0 );
106 while( p_preparser
->b_live
)
107 vlc_cond_wait( &p_preparser
->wait
, &p_preparser
->lock
);
108 vlc_mutex_unlock( &p_preparser
->lock
);
110 /* Destroy the item preparser */
111 vlc_cond_destroy( &p_preparser
->wait
);
112 vlc_mutex_destroy( &p_preparser
->lock
);
116 /*****************************************************************************
118 *****************************************************************************/
120 * This function preparses an item when needed.
122 static void Preparse( vlc_object_t
*obj
, input_item_t
*p_item
)
124 vlc_mutex_lock( &p_item
->lock
);
125 int i_type
= p_item
->i_type
;
126 vlc_mutex_unlock( &p_item
->lock
);
128 if( i_type
!= ITEM_TYPE_FILE
)
130 input_item_SetPreparsed( p_item
, true );
134 /* Do not preparse if it is already done (like by playing it) */
135 if( !input_item_IsPreparsed( p_item
) )
137 input_Preparse( obj
, p_item
);
138 input_item_SetPreparsed( p_item
, true );
140 var_SetAddress( obj
, "item-change", p_item
);
145 * This function ask the fetcher object to fetch the art when needed
147 static void Art( playlist_preparser_t
*p_preparser
, input_item_t
*p_item
)
149 vlc_object_t
*obj
= p_preparser
->object
;
150 playlist_fetcher_t
*p_fetcher
= p_preparser
->p_fetcher
;
152 bool b_fetch
= false;
153 /* If we haven't retrieved enough meta, add to secondary queue
154 * which will run the "meta fetchers".
155 * This only checks for meta, not for art
156 * \todo don't do this for things we won't get meta for, like vids
159 vlc_mutex_lock( &p_item
->lock
);
162 const char *psz_arturl
= vlc_meta_Get( p_item
->p_meta
, vlc_meta_ArtworkURL
);
163 const char *psz_name
= vlc_meta_Get( p_item
->p_meta
, vlc_meta_Title
);
165 if( p_preparser
->i_art_policy
== ALBUM_ART_ALL
&&
167 ( strncmp( psz_arturl
, "file://", 7 ) &&
168 strncmp( psz_arturl
, "attachment://", 13 ) ) ) )
170 msg_Dbg( obj
, "meta ok for %s, need to fetch art",
171 psz_name
? psz_name
: "(null)" );
176 msg_Dbg( obj
, "no fetch required for %s (art currently %s)",
177 psz_name
? psz_name
: "(null)",
178 psz_arturl
? psz_arturl
: "(null)" );
181 vlc_mutex_unlock( &p_item
->lock
);
183 if( b_fetch
&& p_fetcher
)
184 playlist_fetcher_Push( p_fetcher
, p_item
);
188 * This function does the preparsing and issues the art fetching requests
190 static void *Thread( void *data
)
192 playlist_preparser_t
*p_preparser
= data
;
193 vlc_object_t
*obj
= p_preparser
->object
;
197 input_item_t
*p_current
;
200 vlc_mutex_lock( &p_preparser
->lock
);
201 if( p_preparser
->i_waiting
> 0 )
203 p_current
= p_preparser
->pp_waiting
[0];
204 REMOVE_ELEM( p_preparser
->pp_waiting
, p_preparser
->i_waiting
, 0 );
209 p_preparser
->b_live
= false;
210 vlc_cond_signal( &p_preparser
->wait
);
212 vlc_mutex_unlock( &p_preparser
->lock
);
217 Preparse( obj
, p_current
);
219 Art( p_preparser
, p_current
);
220 vlc_gc_decref(p_current
);