]> git.sesse.net Git - vlc/commitdiff
Add a input_Read function that reads a stream in blocking or non-blocking mode and...
authorClément Stenac <zorglub@videolan.org>
Wed, 9 Nov 2005 13:44:49 +0000 (13:44 +0000)
committerClément Stenac <zorglub@videolan.org>
Wed, 9 Nov 2005 13:44:49 +0000 (13:44 +0000)
Still needs to be exported, but needs some thinking for pause/stop handling

include/vlc_input.h
include/vlc_symbols.h
src/input/input.c
src/libvlc.c
src/playlist/playlist.c
src/playlist/view.c

index 09f2218553aa03545719653f95b1d389d5a2b12f..8901de1dca3887cd1ec09575a299b14bdd316bff 100644 (file)
@@ -411,6 +411,9 @@ struct input_thread_t
 VLC_EXPORT( input_thread_t *, __input_CreateThread, ( vlc_object_t *, input_item_t * ) );
 #define input_Preparse(a,b) __input_Preparse(VLC_OBJECT(a),b)
 VLC_EXPORT( int, __input_Preparse, ( vlc_object_t *, input_item_t * ) );
+
+#define input_Read(a,b,c) __input_Read(VLC_OBJECT(a),b, c)
+VLC_EXPORT( void, __input_Read, ( vlc_object_t *, input_item_t *, vlc_bool_t ) );
 VLC_EXPORT( void,             input_StopThread,     ( input_thread_t * ) );
 VLC_EXPORT( void,             input_DestroyThread,  ( input_thread_t * ) );
 
index 0ab41c3881771aeafedcd8827af3ddb6fc838102..7e95f605018e7c0d3eb266949a621268b2d7c1d0 100644 (file)
@@ -263,6 +263,7 @@ int net_Printf (vlc_object_t *p_this, int fd, v_socket_t *, const char *psz_fmt,
 int __vlc_thread_set_priority (vlc_object_t *, char *, int, int);
 int ACL_LoadFile (vlc_acl_t *p_acl, const char *path);
 void input_StopThread (input_thread_t *);
+void __input_Read (vlc_object_t *, input_item_t *, vlc_bool_t);
 intf_thread_t * __intf_Create (vlc_object_t *, const char *);
 void aout_ChannelReorder (uint8_t *, int, int, const int *, int);
 int __var_DelCallback (vlc_object_t *, const char *, vlc_callback_t, void *);
@@ -847,6 +848,7 @@ struct module_symbols_t
     int (*osd_ShowTextAbsolute_inner) (spu_t *, int, char *, text_style_t *, int, int, int, mtime_t, mtime_t);
     char * (*config_GetUserDir_inner) (void);
     char * (*FromUTF32_inner) (const wchar_t *);
+    void (*__input_Read_inner) (vlc_object_t *, input_item_t *, vlc_bool_t);
 };
 #  if defined (__PLUGIN__)
 #  define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner
@@ -1256,6 +1258,7 @@ struct module_symbols_t
 #  define osd_ShowTextAbsolute (p_symbols)->osd_ShowTextAbsolute_inner
 #  define config_GetUserDir (p_symbols)->config_GetUserDir_inner
 #  define FromUTF32 (p_symbols)->FromUTF32_inner
+#  define __input_Read (p_symbols)->__input_Read_inner
 #  elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__)
 /******************************************************************
  * STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access.
@@ -1668,6 +1671,7 @@ struct module_symbols_t
     ((p_symbols)->osd_ShowTextAbsolute_inner) = osd_ShowTextAbsolute; \
     ((p_symbols)->config_GetUserDir_inner) = config_GetUserDir; \
     ((p_symbols)->FromUTF32_inner) = FromUTF32; \
+    ((p_symbols)->__input_Read_inner) = __input_Read; \
     (p_symbols)->net_ConvertIPv4_deprecated = NULL; \
 
 #  endif /* __PLUGIN__ */
index 1c3001d098b7196af702151811765c0a0d05486d..2eb982744b7e2498be7fba42454b837034b55b66 100644 (file)
  * Local prototypes
  *****************************************************************************/
 static  int Run  ( input_thread_t *p_input );
+static  int RunAndClean  ( input_thread_t *p_input );
 
-static  int Init ( input_thread_t *p_input, vlc_bool_t b_quick );
-static void Error( input_thread_t *p_input );
-static void End  ( input_thread_t *p_input );
+static input_thread_t * Create  ( vlc_object_t *, input_item_t *, vlc_bool_t );
+static  int             Init    ( input_thread_t *p_input, vlc_bool_t b_quick );
+static void             Error   ( input_thread_t *p_input );
+static void             End     ( input_thread_t *p_input );
+static void             MainLoop( input_thread_t *p_input );
 
 static inline int ControlPopNoLock( input_thread_t *, int *, vlc_value_t * );
 static void       ControlReduce( input_thread_t * );
@@ -76,8 +79,6 @@ static void SlaveSeek( input_thread_t *p_input );
 static vlc_meta_t *InputMetaUser( input_thread_t *p_input );
 
 /*****************************************************************************
- * input_CreateThread: creates a new input thread
- *****************************************************************************
  * This function creates a new input, and returns a pointer
  * to its description. On error, it returns NULL.
  *
@@ -101,9 +102,8 @@ static vlc_meta_t *InputMetaUser( input_thread_t *p_input );
  * TODO explain when Callback is called
  * TODO complete this list (?)
  *****************************************************************************/
-input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
-                                      input_item_t *p_item )
-
+static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
+                               vlc_bool_t b_quick )
 {
     input_thread_t *p_input;                        /* thread descriptor */
     vlc_value_t val;
@@ -172,62 +172,81 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
     input_ControlVarInit( p_input );
     p_input->input.i_cr_average = var_GetInteger( p_input, "cr-average" );
 
-    /* TODO */
-    var_Get( p_input, "bookmarks", &val );
-    if( val.psz_string )
-    {
-        /* FIXME: have a common cfg parsing routine used by sout and others */
-        char *psz_parser, *psz_start, *psz_end;
-        psz_parser = val.psz_string;
-        while( (psz_start = strchr( psz_parser, '{' ) ) )
-        {
-            seekpoint_t *p_seekpoint = vlc_seekpoint_New();
-            char backup;
-            psz_start++;
-            psz_end = strchr( psz_start, '}' );
-            if( !psz_end ) break;
-            psz_parser = psz_end + 1;
-            backup = *psz_parser;
-            *psz_parser = 0;
-            *psz_end = ',';
-
-            while( (psz_end = strchr( psz_start, ',' ) ) )
+    if( !b_quick )
+    {
+        var_Get( p_input, "bookmarks", &val );
+        if( val.psz_string )
+        {
+            /* FIXME: have a common cfg parsing routine used by sout and others */
+            char *psz_parser, *psz_start, *psz_end;
+            psz_parser = val.psz_string;
+            while( (psz_start = strchr( psz_parser, '{' ) ) )
             {
-                *psz_end = 0;
-                if( !strncmp( psz_start, "name=", 5 ) )
-                {
-                    p_seekpoint->psz_name = psz_start + 5;
-                }
-                else if( !strncmp( psz_start, "bytes=", 6 ) )
-                {
-                    p_seekpoint->i_byte_offset = atoll(psz_start + 6);
+                 seekpoint_t *p_seekpoint = vlc_seekpoint_New();
+                 char backup;
+                 psz_start++;
+                 psz_end = strchr( psz_start, '}' );
+                 if( !psz_end ) break;
+                 psz_parser = psz_end + 1;
+                 backup = *psz_parser;
+                 *psz_parser = 0;
+                 *psz_end = ',';
+                 while( (psz_end = strchr( psz_start, ',' ) ) )
+                 {
+                     *psz_end = 0;
+                     if( !strncmp( psz_start, "name=", 5 ) )
+                     {
+                         p_seekpoint->psz_name = psz_start + 5;
+                     }
+                     else if( !strncmp( psz_start, "bytes=", 6 ) )
+                     {
+                         p_seekpoint->i_byte_offset = atoll(psz_start + 6);
+                     }
+                     else if( !strncmp( psz_start, "time=", 5 ) )
+                     {
+                         p_seekpoint->i_time_offset = atoll(psz_start + 5) * 1000000;
+                     }
+                     psz_start = psz_end + 1;
                 }
-                else if( !strncmp( psz_start, "time=", 5 ) )
-                {
-                    p_seekpoint->i_time_offset = atoll(psz_start + 5) * 1000000;
-                }
-                psz_start = psz_end + 1;
+                msg_Dbg( p_input, "adding bookmark: %s, bytes="I64Fd", time="I64Fd,
+                                  p_seekpoint->psz_name, p_seekpoint->i_byte_offset,
+                                  p_seekpoint->i_time_offset );
+                input_Control( p_input, INPUT_ADD_BOOKMARK, p_seekpoint );
+                vlc_seekpoint_Delete( p_seekpoint );
+                *psz_parser = backup;
             }
-            msg_Dbg( p_input, "adding bookmark: %s, bytes="I64Fd", time="I64Fd,
-                     p_seekpoint->psz_name, p_seekpoint->i_byte_offset,
-                     p_seekpoint->i_time_offset );
-            input_Control( p_input, INPUT_ADD_BOOKMARK, p_seekpoint );
-            vlc_seekpoint_Delete( p_seekpoint );
-            *psz_parser = backup;
+            free( val.psz_string );
         }
-        free( val.psz_string );
     }
 
     /* Remove 'Now playing' info as it is probably outdated */
     input_Control( p_input, INPUT_DEL_INFO, _("Meta-information"),
-                   VLC_META_NOW_PLAYING );
+                    VLC_META_NOW_PLAYING );
 
+    return p_input;
+}
+
+/**
+ * Initialize an input thread and run it. You will need to monitor the thread to clean
+ * up after it is done
+ *
+ * \param p_parent a vlc_object
+ * \param p_item an input item
+ * \return a pointer to the spawned input thread
+ */
+input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
+                                      input_item_t *p_item )
+
+{
+    input_thread_t *p_input;                        /* thread descriptor */
+
+    p_input = Create( p_parent, p_item, VLC_FALSE );
     /* Now we can attach our new input */
     vlc_object_attach( p_input, p_parent );
 
     /* Create thread and wait for its readiness. */
     if( vlc_thread_create( p_input, "input", Run,
-                           VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
+                            VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
     {
         msg_Err( p_input, "cannot create input thread" );
         vlc_object_detach( p_input );
@@ -238,75 +257,55 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
     return p_input;
 }
 
-/*****************************************************************************
- * input_PreParse: Lightweight input for playlist item preparsing
- *****************************************************************************/
-int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
+
+/**
+ * Initialize an input thread and run it. This thread will clean after himself,
+ * you can forget about it. It can work either in blocking or non-blocking mode
+ *
+ * \param p_parent a vlc_object
+ * \param p_item an input item
+ * \param b_block should we block until read is finished ?
+ */
+void __input_Read( vlc_object_t *p_parent, input_item_t *p_item,
+                   vlc_bool_t b_block )
 {
     input_thread_t *p_input;                        /* thread descriptor */
-    int i;
 
-    /* Allocate descriptor */
-    p_input = vlc_object_create( p_parent, VLC_OBJECT_INPUT );
-    if( p_input == NULL )
+    p_input = Create( p_parent, p_item, VLC_FALSE );
+    /* Now we can attach our new input */
+    vlc_object_attach( p_input, p_parent );
+
+    if( b_block )
     {
-        msg_Err( p_parent, "out of memory" );
-        return VLC_EGENERIC;
+        RunAndClean( p_input );
     }
-
-    /* Init Common fields */
-    p_input->b_eof = VLC_FALSE;
-    p_input->b_can_pace_control = VLC_TRUE;
-    p_input->i_start = 0;
-    p_input->i_time  = 0;
-    p_input->i_stop  = 0;
-    p_input->i_title = 0;
-    p_input->title   = NULL;
-    p_input->i_title_offset = p_input->i_seekpoint_offset = 0;
-    p_input->i_state = INIT_S;
-    p_input->i_rate  = INPUT_RATE_DEFAULT;
-    p_input->i_bookmark = 0;
-    p_input->bookmark = NULL;
-    p_input->p_meta  = NULL;
-    p_input->p_es_out = NULL;
-    p_input->p_sout  = NULL;
-    p_input->b_out_pace_control = VLC_FALSE;
-    p_input->i_pts_delay = 0;
-
-    /* Init Input fields */
-    p_input->input.p_item = p_item;
-    p_input->input.p_access = NULL;
-    p_input->input.p_stream = NULL;
-    p_input->input.p_demux  = NULL;
-    p_input->input.b_title_demux = VLC_FALSE;
-    p_input->input.i_title  = 0;
-    p_input->input.title    = NULL;
-    p_input->input.i_title_offset = p_input->input.i_seekpoint_offset = 0;
-    p_input->input.b_can_pace_control = VLC_TRUE;
-    p_input->input.b_eof = VLC_FALSE;
-    p_input->input.i_cr_average = 0;
-
-    /* No slave */
-    p_input->i_slave = 0;
-    p_input->slave   = NULL;
-
-    /* Init control buffer */
-    vlc_mutex_init( p_input, &p_input->lock_control );
-    p_input->i_control = 0;
-
-    /* Parse input options */
-    vlc_mutex_lock( &p_item->lock );
-    for( i = 0; i < p_item->i_options; i++ )
+    else
     {
-        ParseOption( p_input, p_item->ppsz_options[i] );
+        if( vlc_thread_create( p_input, "input", RunAndClean,
+                               VLC_THREAD_PRIORITY_INPUT, VLC_TRUE ) )
+        {
+            msg_Err( p_input, "cannot create input thread" );
+            vlc_object_detach( p_input );
+            vlc_object_destroy( p_input );
+            return;
+        }
     }
-    vlc_mutex_unlock( &p_item->lock );
+}
 
-    /* Create Object Variables for private use only */
-    input_ConfigVarInit( p_input );
-    input_ControlVarInit( p_input );
+/**
+ * Initialize an input and initialize it to preparse the item
+ * This function is blocking. It will only accept to parse files
+ *
+ * \param p_parent a vlc_object_t
+ * \param p_item an input item
+ * \return VLC_SUCCESS or an error
+ */
+int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
+{
+    input_thread_t *p_input;                        /* thread descriptor */
 
-    p_input->input.i_cr_average = var_GetInteger( p_input, "cr-average" );
+    /* Allocate descriptor */
+    p_input = Create( p_parent, p_item, VLC_TRUE );
 
     /* Now we can attach our new input */
     vlc_object_attach( p_input, p_parent );
@@ -332,11 +331,11 @@ int __input_Preparse( vlc_object_t *p_parent, input_item_t *p_item )
     return VLC_SUCCESS;
 }
 
-/*****************************************************************************
- * input_StopThread: mark an input thread as zombie
- *****************************************************************************
- * This function should not return until the thread is effectively cancelled.
- *****************************************************************************/
+/**
+ * Request a running input thread to stop and die
+ *
+ * \param the input thread to stop
+ */
 void input_StopThread( input_thread_t *p_input )
 {
     vlc_list_t *p_list;
@@ -375,11 +374,12 @@ void input_StopThread( input_thread_t *p_input )
     input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
 }
 
-/*****************************************************************************
- * input_DestroyThread: mark an input thread as zombie
- *****************************************************************************
- * This function should not return until the thread is effectively cancelled.
- *****************************************************************************/
+/**
+ * Clean up a dead input thread
+ * This function does not return until the thread is effectively cancelled.
+ *
+ * \param the input thread to kill
+ */
 void input_DestroyThread( input_thread_t *p_input )
 {
     /* Join the thread */
@@ -394,16 +394,11 @@ void input_DestroyThread( input_thread_t *p_input )
 
 /*****************************************************************************
  * Run: main thread loop
- *****************************************************************************
- * Thread in charge of processing the network packets and demultiplexing.
- *
- * TODO:
- *  read subtitle support (XXX take care of spu-delay in the right way).
- *  multi-input support (XXX may be done with subs)
+ * This is the "normal" thread that spawns the input processing chain,
+ * reads the stream, cleans up and waits
  *****************************************************************************/
 static int Run( input_thread_t *p_input )
 {
-    int64_t i_intf_update = 0;
 
     /* Signal that the thread is launched */
     vlc_thread_ready( p_input );
@@ -421,7 +416,88 @@ static int Run( input_thread_t *p_input )
         return 0;
     }
 
-    /* Main loop */
+    MainLoop( p_input );
+
+    if( !p_input->b_eof && !p_input->b_error && p_input->input.b_eof )
+    {
+        /* We have finish to demux data but not to play them */
+        while( !p_input->b_die )
+        {
+            if( input_EsOutDecodersEmpty( p_input->p_es_out ) )
+                break;
+
+            msg_Dbg( p_input, "waiting decoder fifos to empty" );
+
+            msleep( INPUT_IDLE_SLEEP );
+        }
+
+        /* We have finished */
+        p_input->b_eof = VLC_TRUE;
+    }
+
+    /* Wait we are asked to die */
+    if( !p_input->b_die )
+    {
+        Error( p_input );
+    }
+
+    /* Clean up */
+    End( p_input );
+
+    return 0;
+}
+
+/*****************************************************************************
+ * RunAndClean: main thread loop
+ * This is the "just forget me" thread that spawns the input processing chain,
+ * reads the stream, cleans up and releases memory
+ *****************************************************************************/
+static int RunAndClean( input_thread_t *p_input )
+{
+    /* Signal that the thread is launched */
+    vlc_thread_ready( p_input );
+
+    if( Init( p_input, VLC_FALSE ) )
+    {
+        /* If we failed, just exit */
+        return 0;
+    }
+
+    MainLoop( p_input );
+
+    if( !p_input->b_eof && !p_input->b_error && p_input->input.b_eof )
+    {
+        /* We have finish to demux data but not to play them */
+        while( !p_input->b_die )
+        {
+            if( input_EsOutDecodersEmpty( p_input->p_es_out ) )
+                break;
+
+            msg_Dbg( p_input, "waiting decoder fifos to empty" );
+
+            msleep( INPUT_IDLE_SLEEP );
+        }
+        /* We have finished */
+        p_input->b_eof = VLC_TRUE;
+    }
+
+    /* Clean up */
+    End( p_input );
+
+    /* Release memory */
+    vlc_object_detach( p_input );
+    vlc_object_destroy( p_input );
+
+    return 0;
+}
+
+
+/*****************************************************************************
+ * Main loop: Fill buffers from access, and demux
+ *****************************************************************************/
+static void MainLoop( input_thread_t *p_input )
+{
+    int64_t i_intf_update = 0;
     while( !p_input->b_die && !p_input->b_error && !p_input->input.b_eof )
     {
         vlc_bool_t b_force_update = VLC_FALSE;
@@ -570,34 +646,6 @@ static int Run( input_thread_t *p_input )
             i_intf_update = mdate() + I64C(150000);
         }
     }
-
-    if( !p_input->b_eof && !p_input->b_error && p_input->input.b_eof )
-    {
-        /* We have finish to demux data but not to play them */
-        while( !p_input->b_die )
-        {
-            if( input_EsOutDecodersEmpty( p_input->p_es_out ) )
-                break;
-
-            msg_Dbg( p_input, "waiting decoder fifos to empty" );
-
-            msleep( INPUT_IDLE_SLEEP );
-        }
-
-        /* We have finished */
-        p_input->b_eof = VLC_TRUE;
-    }
-
-    /* Wait we are asked to die */
-    if( !p_input->b_die )
-    {
-        Error( p_input );
-    }
-
-    /* Clean up */
-    End( p_input );
-
-    return 0;
 }
 
 
index ec3efc268372db443824096552e5aac03c8381b0..2e22fa43395665479407e319e714733234c28788 100644 (file)
@@ -1219,7 +1219,7 @@ int VLC_AddTarget( int i_object, char const *psz_target,
 }
 
 /*****************************************************************************
- * VLC_Play: play
+ * VLC_Play: play the playlist
  *****************************************************************************/
 int VLC_Play( int i_object )
 {
index 8fc8c75de4c8a2b416e84f1b4c28597b4809f600..6e86f9445db89cea2bc3c8cb8051a413ed954c36 100644 (file)
@@ -37,7 +37,7 @@
 #define TITLE_ALL      N_( "All items, unsorted" )
 
 #undef PLAYLIST_PROFILE
-#undef PLAYLIST_DEBUG
+#define PLAYLIST_DEBUG 1
 
 /*****************************************************************************
  * Local prototypes
@@ -364,8 +364,8 @@ int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args )
         i_view = (int)va_arg( args,int );
         p_node = (playlist_item_t *)va_arg( args, playlist_item_t * );
         p_item = (playlist_item_t *)va_arg( args, playlist_item_t * );
-        if ( p_node == NULL || (p_item != NULL && p_item->input.psz_uri
-                                                         == NULL ))
+        if ( p_node == NULL ) //|| (p_item != NULL && p_item->input.psz_uri
+                                //                         == NULL ))
         {
             p_playlist->status.i_status = PLAYLIST_STOPPED;
             p_playlist->request.b_request = VLC_TRUE;
@@ -378,10 +378,8 @@ int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args )
         p_playlist->request.p_node = p_node;
         p_playlist->request.p_item = p_item;
 
-        /* If we select a node, play only it.
-         * If we select an item, continue */
-        if( p_playlist->request.p_item == NULL ||
-            ! p_playlist->request.p_node->i_flags & PLAYLIST_SKIP_FLAG )
+        /* Don't go further if the node doesn't want to */
+        if( ! p_playlist->request.p_node->i_flags & PLAYLIST_SKIP_FLAG )
         {
             p_playlist->b_go_next = VLC_FALSE;
         }
@@ -468,7 +466,7 @@ int playlist_vaControl( playlist_t * p_playlist, int i_query, va_list args )
         break;
 
     default:
-        msg_Err( p_playlist, "unimplemented playlist query" );
+        msg_Err( p_playlist, "unknown playlist query" );
         return VLC_EBADVAR;
         break;
     }
@@ -680,7 +678,6 @@ static void RunThread ( playlist_t *p_playlist )
              * Get the next item to play */
             p_item = NextItem( p_playlist );
 
-
             /* We must stop */
             if( p_item == NULL )
             {
@@ -899,7 +896,7 @@ static playlist_item_t * NextItem( playlist_t *p_playlist )
     /* TODO: use the "shuffled view" internally ? */
     /* Random case. This is an exception: if request, but request is skip +- 1
      * we don't go to next item but select a new random one. */
-    if( b_random && 
+    if( b_random &&
         ( !p_playlist->request.b_request ||
         ( p_playlist->request.b_request && ( p_playlist->request.p_item == NULL ||
           p_playlist->request.i_skip == 1 || p_playlist->request.i_skip == -1 ) ) ) )
index b963d083e1b0f4d48a2448e5fc7981a81ae26d81..3d8c2365e9da4ce2595b20b04a8942a587b9e025 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "vlc_playlist.h"
 
-#undef PLAYLIST_DEBUG
+#define PLAYLIST_DEBUG 1
 
 /************************************************************************
  * Local prototypes