Fetcher: use nornal thread API
authorRémi Denis-Courmont <rdenis@simphalempin.com>
Sun, 14 Sep 2008 10:12:26 +0000 (13:12 +0300)
committerRémi Denis-Courmont <rdenis@simphalempin.com>
Sun, 14 Sep 2008 10:12:26 +0000 (13:12 +0300)
src/input/meta.c
src/playlist/control.c
src/playlist/engine.c
src/playlist/playlist_internal.h
src/playlist/thread.c

index 3420e7c..e966d4b 100644 (file)
@@ -99,7 +99,7 @@ int input_ArtFind( playlist_t *p_playlist, input_item_t *p_item )
     /* If we already checked this album in this session, skip */
     if( psz_artist && psz_album )
     {
-        FOREACH_ARRAY( playlist_album_t album, pl_priv(p_playlist)->p_fetcher->albums )
+        FOREACH_ARRAY( playlist_album_t album, pl_priv(p_playlist)->fetcher.albums )
             if( !strcmp( album.psz_artist, psz_artist ) &&
                 !strcmp( album.psz_album, psz_album ) )
             {
@@ -179,7 +179,7 @@ int input_ArtFind( playlist_t *p_playlist, input_item_t *p_item )
         a.psz_album = psz_album;
         a.psz_arturl = input_item_GetArtURL( p_item );
         a.b_found = (i_ret == VLC_EGENERIC ? false : true );
-        ARRAY_APPEND( pl_priv(p_playlist)->p_fetcher->albums, a );
+        ARRAY_APPEND( pl_priv(p_playlist)->fetcher.albums, a );
     }
     else
     {
index 3eb2d29..6f97817 100644 (file)
@@ -219,19 +219,15 @@ int playlist_PreparseEnqueueItem( playlist_t *p_playlist,
 int playlist_AskForArtEnqueue( playlist_t *p_playlist,
                                input_item_t *p_item )
 {
-    playlist_fetcher_t *p_fetcher = pl_priv(p_playlist)->p_fetcher;
-    vlc_object_lock( p_fetcher );
-    if( !vlc_object_alive( p_fetcher ) )
-    {
-        vlc_object_unlock( p_fetcher );
-        return VLC_EGENERIC;
-    }
+    playlist_fetcher_t *p_fetcher = &pl_priv(p_playlist)->fetcher;
 
     vlc_gc_incref( p_item );
+
+    vlc_mutex_lock( &p_fetcher->lock );
     INSERT_ELEM( p_fetcher->pp_waiting, p_fetcher->i_waiting,
                  p_fetcher->i_waiting, p_item );
-    vlc_object_signal_unlocked( p_fetcher );
-    vlc_object_unlock( p_fetcher );
+    vlc_cond_signal( &p_fetcher->wait );
+    vlc_mutex_unlock( &p_fetcher->lock );
     return VLC_SUCCESS;
 }
 
@@ -534,8 +530,7 @@ int playlist_PlayItem( playlist_t *p_playlist, playlist_item_t *p_item )
     }
     free( psz_uri );
 
-    if( pl_priv(p_playlist)->p_fetcher &&
-        pl_priv(p_playlist)->p_fetcher->i_art_policy == ALBUM_ART_WHEN_PLAYED )
+    if( pl_priv(p_playlist)->fetcher.i_art_policy == ALBUM_ART_WHEN_PLAYED )
     {
         bool b_has_art;
 
index 7e04935..a7be733 100644 (file)
@@ -176,9 +176,9 @@ playlist_t * playlist_Create( vlc_object_t *p_parent )
 static void playlist_Destructor( vlc_object_t * p_this )
 {
     playlist_t * p_playlist = (playlist_t *)p_this;
-    playlist_preparse_t *p_preparse = &pl_priv(p_playlist)->preparse;
 
     /* Destroy the item preparser */
+    playlist_preparse_t *p_preparse = &pl_priv(p_playlist)->preparse;
     if (p_preparse->up)
     {
         vlc_cancel (p_preparse->thread);
@@ -193,10 +193,20 @@ static void playlist_Destructor( vlc_object_t * p_this )
     vlc_mutex_destroy (&p_preparse->lock);
 
     /* Destroy the item meta-infos fetcher */
-    if( pl_priv(p_playlist)->p_fetcher )
+    playlist_fetcher_t *p_fetcher = &pl_priv(p_playlist)->fetcher;
+    if (p_fetcher->up)
     {
-        vlc_object_release( pl_priv(p_playlist)->p_fetcher );
+        vlc_cancel (p_fetcher->thread);
+        vlc_join (p_fetcher->thread, NULL);
+    }
+    while (p_fetcher->i_waiting > 0)
+    {   /* Any left-over unparsed item? */
+        vlc_gc_decref (p_fetcher->pp_waiting[0]);
+        REMOVE_ELEM (p_fetcher->pp_waiting, p_fetcher->i_waiting, 0);
     }
+    vlc_cond_destroy (&p_fetcher->wait);
+    vlc_mutex_destroy (&p_fetcher->lock);
+
     msg_Dbg( p_this, "Destroyed" );
 }
 
@@ -530,9 +540,6 @@ void playlist_LastLoop( playlist_t *p_playlist )
     playlist_ServicesDiscoveryKillAll( p_playlist );
     playlist_MLDump( p_playlist );
 
-    vlc_object_kill( pl_priv(p_playlist)->p_fetcher );
-    vlc_thread_join( pl_priv(p_playlist)->p_fetcher );
-
     PL_LOCK;
 
     /* Release the current node */
@@ -571,7 +578,6 @@ void *playlist_PreparseLoop( void *data )
     playlist_preparse_t *p_preparse = data;
     playlist_t *p_playlist = &((playlist_private_t *)(((char *)p_preparse)
              - offsetof(playlist_private_t, preparse)))->public_data;
-    int i_activity;
 
     for( ;; )
     {
@@ -615,21 +621,16 @@ void *playlist_PreparseLoop( void *data )
              */
             char *psz_arturl = input_item_GetArtURL( p_current );
             char *psz_name = input_item_GetName( p_current );
-            playlist_fetcher_t *p_fetcher = pl_priv(p_playlist)->p_fetcher;
+            playlist_fetcher_t *p_fetcher = &pl_priv(p_playlist)->fetcher;
             if( p_fetcher->i_art_policy == ALBUM_ART_ALL &&
                 ( !psz_arturl || strncmp( psz_arturl, "file://", 7 ) ) )
             {
                 PL_DEBUG("meta ok for %s, need to fetch art", psz_name );
-                vlc_object_lock( p_fetcher );
-                if( vlc_object_alive( p_fetcher ) )
-                {
-                    INSERT_ELEM( p_fetcher->pp_waiting, p_fetcher->i_waiting,
-                                 p_fetcher->i_waiting, p_current);
-                    vlc_object_signal_unlocked( p_fetcher );
-                }
-                else
-                    vlc_gc_decref( p_current );
-                vlc_object_unlock( p_fetcher );
+                vlc_mutex_lock( &p_fetcher->lock );
+                INSERT_ELEM( p_fetcher->pp_waiting, p_fetcher->i_waiting,
+                             p_fetcher->i_waiting, p_current);
+                vlc_cond_signal( &p_fetcher->wait );
+                vlc_mutex_unlock( &p_fetcher->lock );
             }
             else
             {
@@ -643,7 +644,7 @@ void *playlist_PreparseLoop( void *data )
             vlc_restorecancel( canc );
         }
 
-        i_activity = var_GetInteger( p_playlist, "activity" );
+        int i_activity = var_GetInteger( p_playlist, "activity" );
         if( i_activity < 0 ) i_activity = 0;
         /* Sleep at least 1ms */
         msleep( (i_activity+1) * 1000 );
@@ -656,36 +657,38 @@ void *playlist_PreparseLoop( void *data )
 /**
  * Fetcher loop
  *
- * Main loop for secondary preparser queue
- * \param p_obj items to preparse
- * \return nothing
+ * \return never
  */
-void playlist_FetcherLoop( playlist_fetcher_t *p_obj )
+void *playlist_FetcherLoop( void *data )
 {
-    playlist_t *p_playlist = (playlist_t *)p_obj->p_parent;
-    input_item_t *p_item;
-    int i_activity;
-
-    vlc_object_lock( p_obj );
+    playlist_fetcher_t *p_fetcher = data;
+    playlist_t *p_playlist = &((playlist_private_t *)(((char *)p_fetcher)
+             - offsetof(playlist_private_t, fetcher)))->public_data;
 
-    while( vlc_object_alive( p_obj ) )
+    for( ;; )
     {
-        if( p_obj->i_waiting == 0 )
-        {
-            vlc_object_wait( p_obj );
-            continue;
-        }
+        input_item_t *p_item;
+
+        vlc_mutex_lock( &p_fetcher->lock );
+        mutex_cleanup_push( &p_fetcher->lock );
+
+        while( p_fetcher->i_waiting == 0 )
+            vlc_cond_wait( &p_fetcher->wait, &p_fetcher->lock );
 
-        p_item = p_obj->pp_waiting[0];
-        REMOVE_ELEM( p_obj->pp_waiting, p_obj->i_waiting, 0 );
-        vlc_object_unlock( p_obj );
+        p_item = p_fetcher->pp_waiting[0];
+        REMOVE_ELEM( p_fetcher->pp_waiting, p_fetcher->i_waiting, 0 );
+        vlc_cleanup_run( );
+
+        int canc = vlc_savecancel();
         if( p_item )
         {
             int i_ret;
 
-            /* Check if it is not yet preparsed and if so wait for it (at most 0.5s)
+            /* Check if it is not yet preparsed and if so wait for it
+             * (at most 0.5s)
              * (This can happen if we fetch art on play)
-             * FIXME this doesn't work if we need to fetch meta before art ... */
+             * FIXME this doesn't work if we need to fetch meta before art...
+             */
             for( i_ret = 0; i_ret < 10 && !input_item_IsPreparsed( p_item ); i_ret++ )
             {
                 bool b_break;
@@ -723,22 +726,16 @@ void playlist_FetcherLoop( playlist_fetcher_t *p_obj )
             }
             vlc_gc_decref( p_item );
         }
-        vlc_object_lock( p_obj );
-        i_activity = var_GetInteger( p_playlist, "activity" );
+        vlc_restorecancel( canc );
+
+        int i_activity = var_GetInteger( p_playlist, "activity" );
         if( i_activity < 0 ) i_activity = 0;
-        vlc_object_unlock( p_obj );
         /* Sleep at least 1ms */
         msleep( (i_activity+1) * 1000 );
-        vlc_object_lock( p_obj );
-    }
-
-    while( p_obj->i_waiting > 0 )
-    {
-        vlc_gc_decref( p_obj->pp_waiting[0] );
-        REMOVE_ELEM( p_obj->pp_waiting, p_obj->i_waiting, 0 );
     }
 
-    vlc_object_unlock( p_obj );
+    assert( 0 );
+    return NULL;
 }
 
 static void VariablesInit( playlist_t *p_playlist )
index 1d0d2ee..86b93f4 100644 (file)
@@ -49,11 +49,13 @@ typedef struct playlist_preparse_t
 
 typedef struct playlist_fetcher_t
 {
-    VLC_COMMON_MEMBERS
+    vlc_thread_t    thread;
     vlc_mutex_t     lock;
+    vlc_cond_t      wait;
     int             i_art_policy;
     int             i_waiting;
     input_item_t    **pp_waiting;
+    bool            up;
 
     DECL_ARRAY(playlist_album_t) albums;
 } playlist_fetcher_t;
@@ -62,7 +64,7 @@ typedef struct playlist_private_t
 {
     playlist_t           public_data;
     playlist_preparse_t  preparse; /**< Preparser data */
-    playlist_fetcher_t   *p_fetcher; /**< Meta and art fetcher object */
+    playlist_fetcher_t   fetcher; /**< Meta and art fetcher data */
     sout_instance_t      *p_sout; /**< Kept sout instance */
 } playlist_private_t;
 
@@ -86,7 +88,7 @@ playlist_t *playlist_Create   ( vlc_object_t * );
 void playlist_MainLoop( playlist_t * );
 void playlist_LastLoop( playlist_t * );
 void *playlist_PreparseLoop( void * );
-void playlist_FetcherLoop( playlist_fetcher_t * );
+void *playlist_FetcherLoop( void * );
 
 void ResetCurrentlyPlaying( playlist_t *, bool, playlist_item_t * );
 
index 3701d48..d030a1d 100644 (file)
@@ -36,8 +36,6 @@
  * Local prototypes
  *****************************************************************************/
 static void* RunControlThread   ( vlc_object_t * );
-static void* RunFetcher         ( vlc_object_t * );
-static void FetcherDestructor   ( vlc_object_t * );
 
 /*****************************************************************************
  * Main functions for the global thread
@@ -73,30 +71,21 @@ void __playlist_ThreadCreate( vlc_object_t *p_parent )
     p_preparse->up = true;
 
     // Secondary Preparse
-    static const char fname[] = "fetcher";
-    playlist_fetcher_t *p_fetcher =
-    pl_priv(p_playlist)->p_fetcher =
-        vlc_custom_create( p_playlist, sizeof( playlist_fetcher_t ),
-                           VLC_OBJECT_GENERIC, fname );
-    if( !p_fetcher )
-    {
-        msg_Err( p_playlist, "unable to create secondary preparser" );
-        vlc_object_release( p_playlist );
-        return;
-    }
+    playlist_fetcher_t *p_fetcher = &pl_priv(p_playlist)->fetcher;
+    vlc_mutex_init (&p_fetcher->lock);
+    vlc_cond_init (&p_fetcher->wait);
     p_fetcher->i_waiting = 0;
     p_fetcher->pp_waiting = NULL;
     p_fetcher->i_art_policy = var_CreateGetInteger( p_playlist, "album-art" );
 
-    vlc_object_set_destructor( p_fetcher, FetcherDestructor );
-    vlc_object_attach( p_fetcher, p_playlist );
-    if( vlc_thread_create( p_fetcher, "fetcher", RunFetcher,
-                           VLC_THREAD_PRIORITY_LOW, false ) )
+    if( vlc_clone( &p_fetcher->thread, playlist_FetcherLoop, p_fetcher,
+                   VLC_THREAD_PRIORITY_LOW ) )
     {
         msg_Err( p_playlist, "cannot spawn secondary preparse thread" );
-        vlc_object_release( p_fetcher );
+        p_fetcher->up = false;
         return;
     }
+    p_fetcher->up = true;
 
     // Start the thread
     if( vlc_thread_create( p_playlist, "playlist", RunControlThread,
@@ -151,19 +140,3 @@ static void* RunControlThread ( vlc_object_t *p_this )
     vlc_restorecancel (canc);
     return NULL;
 }
-
-static void* RunFetcher( vlc_object_t *p_this )
-{
-    playlist_fetcher_t *p_obj = (playlist_fetcher_t *)p_this;
-    int canc = vlc_savecancel ();
-    playlist_FetcherLoop( p_obj );
-    vlc_restorecancel (canc);
-    return NULL;
-}
-
-static void FetcherDestructor( vlc_object_t * p_this )
-{
-    playlist_fetcher_t * p_fetcher = (playlist_fetcher_t *)p_this;
-    free( p_fetcher->pp_waiting );
-    msg_Dbg( p_this, "Destroyed" );
-}