preparser.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:7k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * preparse.c: Preparser thread.
  3.  *****************************************************************************
  4.  * Copyright © 1999-2009 the VideoLAN team
  5.  * $Id: 74b3961f475a75e0e3dd8c345d1e81815c058c76 $
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *          Clément Stenac <zorglub@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  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 General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. #ifdef HAVE_CONFIG_H
  25. # include "config.h"
  26. #endif
  27. #include <vlc_common.h>
  28. #include <vlc_playlist.h>
  29. #include "art.h"
  30. #include "fetcher.h"
  31. #include "preparser.h"
  32. #include "../input/input_interface.h"
  33. /*****************************************************************************
  34.  * Structures/definitions
  35.  *****************************************************************************/
  36. struct playlist_preparser_t
  37. {
  38.     playlist_t          *p_playlist;
  39.     playlist_fetcher_t  *p_fetcher;
  40.     vlc_thread_t    thread;
  41.     vlc_mutex_t     lock;
  42.     vlc_cond_t      wait;
  43.     input_item_t  **pp_waiting;
  44.     int             i_waiting;
  45.     int             i_art_policy;
  46. };
  47. static void *Thread( void * );
  48. /*****************************************************************************
  49.  * Public functions
  50.  *****************************************************************************/
  51. playlist_preparser_t *playlist_preparser_New( playlist_t *p_playlist, playlist_fetcher_t *p_fetcher )
  52. {
  53.     playlist_preparser_t *p_preparser = malloc( sizeof(*p_preparser) );
  54.     if( !p_preparser )
  55.         return NULL;
  56.     p_preparser->p_playlist = p_playlist;
  57.     p_preparser->p_fetcher = p_fetcher;
  58.     vlc_mutex_init( &p_preparser->lock );
  59.     vlc_cond_init( &p_preparser->wait );
  60.     p_preparser->i_art_policy = var_GetInteger( p_playlist, "album-art" );
  61.     p_preparser->i_waiting = 0;
  62.     p_preparser->pp_waiting = NULL;
  63.     if( vlc_clone( &p_preparser->thread, Thread, p_preparser,
  64.                    VLC_THREAD_PRIORITY_LOW ) )
  65.     {
  66.         msg_Err( p_playlist, "cannot spawn preparse thread" );
  67.         free( p_preparser );
  68.         return NULL;
  69.     }
  70.     return p_preparser;
  71. }
  72. void playlist_preparser_Push( playlist_preparser_t *p_preparser, input_item_t *p_item )
  73. {
  74.     vlc_gc_incref( p_item );
  75.     vlc_mutex_lock( &p_preparser->lock );
  76.     INSERT_ELEM( p_preparser->pp_waiting, p_preparser->i_waiting,
  77.                  p_preparser->i_waiting, p_item );
  78.     vlc_cond_signal( &p_preparser->wait );
  79.     vlc_mutex_unlock( &p_preparser->lock );
  80. }
  81. void playlist_preparser_Delete( playlist_preparser_t *p_preparser )
  82. {
  83.     /* Destroy the item preparser */
  84.     vlc_cancel( p_preparser->thread );
  85.     vlc_join( p_preparser->thread, NULL );
  86.     while( p_preparser->i_waiting > 0 )
  87.     {   /* Any left-over unparsed item? */
  88.         vlc_gc_decref( p_preparser->pp_waiting[0] );
  89.         REMOVE_ELEM( p_preparser->pp_waiting, p_preparser->i_waiting, 0 );
  90.     }
  91.     vlc_cond_destroy( &p_preparser->wait );
  92.     vlc_mutex_destroy( &p_preparser->lock );
  93.     free( p_preparser );
  94. }
  95. /*****************************************************************************
  96.  * Privates functions
  97.  *****************************************************************************/
  98. /**
  99.  * This function preparses an item when needed.
  100.  */
  101. static void Preparse( playlist_t *p_playlist, input_item_t *p_item )
  102. {
  103.     vlc_mutex_lock( &p_item->lock );
  104.     int i_type = p_item->i_type;
  105.     vlc_mutex_unlock( &p_item->lock );
  106.     if( i_type != ITEM_TYPE_FILE )
  107.         return;
  108.     stats_TimerStart( p_playlist, "Preparse run", STATS_TIMER_PREPARSE );
  109.     /* Do not preparse if it is already done (like by playing it) */
  110.     if( !input_item_IsPreparsed( p_item ) )
  111.     {
  112.         input_Preparse( VLC_OBJECT(p_playlist), p_item );
  113.         input_item_SetPreparsed( p_item, true );
  114.         var_SetInteger( p_playlist, "item-change", p_item->i_id );
  115.     }
  116.     stats_TimerStop( p_playlist, STATS_TIMER_PREPARSE );
  117. }
  118. /**
  119.  * This function ask the fetcher object to fetch the art when needed
  120.  */
  121. static void Art( playlist_preparser_t *p_preparser, input_item_t *p_item )
  122. {
  123.     playlist_t *p_playlist = p_preparser->p_playlist;
  124.     playlist_fetcher_t *p_fetcher = p_preparser->p_fetcher;
  125.     bool b_fetch = false;
  126.     /* If we haven't retrieved enough meta, add to secondary queue
  127.      * which will run the "meta fetchers".
  128.      * This only checks for meta, not for art
  129.      * todo don't do this for things we won't get meta for, like vids
  130.      */
  131.     vlc_mutex_lock( &p_item->lock );
  132.     if( p_item->p_meta )
  133.     {
  134.         const char *psz_arturl = vlc_meta_Get( p_item->p_meta, vlc_meta_ArtworkURL );
  135.         const char *psz_name = vlc_meta_Get( p_item->p_meta, vlc_meta_Title );
  136.         if( p_preparser->i_art_policy == ALBUM_ART_ALL &&
  137.             ( !psz_arturl || strncmp( psz_arturl, "file://", 7 ) ) )
  138.         {
  139.             msg_Dbg( p_playlist, "meta ok for %s, need to fetch art", psz_name );
  140.             b_fetch = true;
  141.         }
  142.         else
  143.         {
  144.             msg_Dbg( p_playlist, "no fetch required for %s (art currently %s)",
  145.                      psz_name, psz_arturl );
  146.         }
  147.     }
  148.     vlc_mutex_unlock( &p_item->lock );
  149.     if( b_fetch && p_fetcher )
  150.         playlist_fetcher_Push( p_fetcher, p_item );
  151. }
  152. /**
  153.  * This function does the preparsing and issues the art fetching requests
  154.  */
  155. static void *Thread( void *data )
  156. {
  157.     playlist_preparser_t *p_preparser = data;
  158.     playlist_t *p_playlist = p_preparser->p_playlist;
  159.     for( ;; )
  160.     {
  161.         input_item_t *p_current;
  162.         /* Be sure to be cancellable before our queue is empty */
  163.         vlc_testcancel();
  164.         /* */
  165.         vlc_mutex_lock( &p_preparser->lock );
  166.         mutex_cleanup_push( &p_preparser->lock );
  167.         while( p_preparser->i_waiting == 0 )
  168.             vlc_cond_wait( &p_preparser->wait, &p_preparser->lock );
  169.         p_current = p_preparser->pp_waiting[0];
  170.         REMOVE_ELEM( p_preparser->pp_waiting, p_preparser->i_waiting, 0 );
  171.         vlc_cleanup_run( );
  172.         if( !p_current )
  173.             continue;
  174.         int canc = vlc_savecancel();
  175.         Preparse( p_playlist, p_current );
  176.         Art( p_preparser, p_current );
  177.         vlc_restorecancel( canc );
  178.         /* */
  179.         int i_activity = var_GetInteger( p_playlist, "activity" );
  180.         if( i_activity < 0 )
  181.             i_activity = 0;
  182.         /* Sleep at least 1ms */
  183.         msleep( (i_activity+1) * 1000 );
  184.     }
  185.     return NULL;
  186. }