[xiph-cvs] cvs commit: vorbis-tools/ogg123 buffer.c buffer.h callbacks.c http_transport.c ogg123.c ogg123.h

Stan Seibert volsung at xiph.org
Sat Jun 1 20:07:13 PDT 2002



volsung     02/06/01 20:07:12

  Modified:    ogg123   buffer.c buffer.h callbacks.c http_transport.c
                        ogg123.c ogg123.h
  Log:
  Rewrite of thread handling code to eliminate the need for thread
  cancellation.  Now we use ugly (but effective) flags to note that it's
  time to quit.  This should actually work properly on most platforms, and
  now we have the fringe benefit of being able to kill execution during
  prebuffering.

Revision  Changes    Path
1.17      +21 -12    vorbis-tools/ogg123/buffer.c

Index: buffer.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- buffer.c	2002/02/07 04:40:49	1.16
+++ buffer.c	2002/06/02 03:07:10	1.17
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: buffer.c,v 1.16 2002/02/07 04:40:49 segher Exp $
+ last mod: $Id: buffer.c,v 1.17 2002/06/02 03:07:10 volsung Exp $
 
  ********************************************************************/
 
@@ -28,6 +28,7 @@
 #include "compat.h"
 #include "buffer.h"
 #include "i18n.h"
+#include "ogg123.h"
 
 #define MIN(x,y)       ( (x) < (y) ? (x) : (y) )
 #define MIN3(x,y,z)    MIN(x,MIN(y,z))
@@ -48,7 +49,9 @@
 #define COND_WAIT(cond, mutex) { DEBUG("Unlocking %s and waiting on %s", #mutex, #cond); pthread_cond_wait(&(cond), &(mutex)); }
 #define COND_SIGNAL(cond) { DEBUG("Signalling %s", #cond); pthread_cond_signal(&(cond)); }
 
+extern signal_request_t sig_request;  /* Need access to global cancel flag */
 
+
 /* -------------------- Private Functions ------------------ */
 
 void buffer_init_vars (buf_t *buf)
@@ -58,7 +61,8 @@
   buf->paused = 0;
   buf->eos = 0;
   buf->abort_write = 0;
-  
+  buf->cancel_flag = 0;
+
   buf->curfill = 0;
   buf->start = 0;
   buf->position = 0;
@@ -196,7 +200,10 @@
   
   /* This test is safe since curfill will never decrease and eos will
      never be unset. */
-  while ( !(buf->eos && buf->curfill == 0) ) {
+  while ( !(buf->eos && buf->curfill == 0)) {
+
+    if (buf->cancel_flag || sig_request.cancel)
+      break;
     
     DEBUG("Check for something to play");
     /* Block until we can play something */
@@ -208,12 +215,13 @@
       DEBUG("Waiting for more data to play.");
       COND_WAIT(buf->playback_cond, buf->mutex);
     }
-
+    
     DEBUG("Ready to play");
     
     UNLOCK_MUTEX(buf->mutex);
 
-    pthread_testcancel();
+    if (buf->cancel_flag || sig_request.cancel)
+      break;
 
     /* Don't need to lock buffer while running actions since position
        won't change.  We clear out any actions before we compute the
@@ -226,8 +234,6 @@
     /* Need to be locked while we check things. */
     write_amount = compute_dequeue_size(buf, buf->audio_chunk_size);
 
-    pthread_testcancel();
-
     UNLOCK_MUTEX(buf->mutex);
  
     /* No need to lock mutex here because the other thread will
@@ -481,10 +487,10 @@
 {
   DEBUG("Attempting to kill playback thread.");
 
-  /* End thread */
-  pthread_cancel (buf->thread);
+  /* Flag the cancellation */
+  buf->cancel_flag = 1;
   
-  /* Signal all the playback condition to wake stuff up */
+  /* Signal the playback condition to wake stuff up */
   COND_SIGNAL(buf->playback_cond);
 
   pthread_join(buf->thread, NULL);
@@ -518,6 +524,9 @@
   /* Put the data into the buffer as space is made available */
   while (nbytes > 0) {
 
+    if (buf->abort_write)
+      break;
+
     DEBUG("Obtaining lock on buffer");
     /* Block until we can read something */
     if (buf->curfill == 0 && buf->eos)
@@ -590,13 +599,13 @@
 
 void buffer_abort_write (buf_t *buf)
 {
-  DEBUG("buffer_mark_eos");
+  DEBUG("buffer_abort_write");
 
   pthread_cleanup_push(buffer_mutex_unlock, buf);
 
   LOCK_MUTEX(buf->mutex);
   buf->abort_write = 1;
-  COND_SIGNAL(buf->write_cond);
+  COND_SIGNAL(buf->playback_cond);
   UNLOCK_MUTEX(buf->mutex);  
 
   pthread_cleanup_pop(0);

<p><p>1.6       +3 -1      vorbis-tools/ogg123/buffer.h

Index: buffer.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- buffer.h	2001/12/20 00:24:54	1.5
+++ buffer.h	2002/06/02 03:07:10	1.6
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
  
- last mod: $Id: buffer.h,v 1.5 2001/12/20 00:24:54 volsung Exp $
+ last mod: $Id: buffer.h,v 1.6 2002/06/02 03:07:10 volsung Exp $
  
 ********************************************************************/
 
@@ -51,6 +51,8 @@
                              if possible */
   long prebuffer_size;    /* number of bytes to prebuffer */
   long size;              /* buffer size, for reference */
+
+  int cancel_flag;        /* When set, the playback thread should exit */
 
   /* ----- Everything after this point is protected by mutex ----- */
 

<p><p>1.6       +1 -12     vorbis-tools/ogg123/callbacks.c

Index: callbacks.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/callbacks.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- callbacks.c	2002/02/07 04:40:49	1.5
+++ callbacks.c	2002/06/02 03:07:11	1.6
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: callbacks.c,v 1.5 2002/02/07 04:40:49 segher Exp $
+ last mod: $Id: callbacks.c,v 1.6 2002/06/02 03:07:11 volsung Exp $
 
  ********************************************************************/
 
@@ -31,12 +31,8 @@
   audio_play_arg_t *play_arg = (audio_play_arg_t *) arg;
   int ret;
 
-  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-
   ret = audio_devices_write(play_arg->devices, ptr, nbytes);
 
-  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
-
   return ret ? nbytes : 0;
 }
 
@@ -46,11 +42,6 @@
   audio_device_t *current;
   ao_sample_format format;
 
-  /* We DO NOT want to get cancelled part way through this and have our
-     audio devices in an unknown state */
-  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-
-
   close_audio_devices (reopen_arg->devices);
   
   /* Record audio device settings and open the devices */
@@ -117,8 +108,6 @@
   /* Cleanup argument */
   free(reopen_arg->format);
   free(reopen_arg);
-  
-  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);  
 }
 
 

<p><p>1.10      +45 -51    vorbis-tools/ogg123/http_transport.c

Index: http_transport.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/http_transport.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- http_transport.c	2002/05/05 03:45:04	1.9
+++ http_transport.c	2002/06/02 03:07:11	1.10
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
  
- last mod: $Id: http_transport.c,v 1.9 2002/05/05 03:45:04 segher Exp $
+ last mod: $Id: http_transport.c,v 1.10 2002/06/02 03:07:11 volsung Exp $
  
 ********************************************************************/
 
@@ -26,6 +26,7 @@
 #include <curl/easy.h>
 #include <pthread.h>
 
+#include "ogg123.h"
 #include "transport.h"
 #include "buffer.h"
 #include "status.h"
@@ -35,24 +36,21 @@
 #define INPUT_BUFFER_SIZE 32768
 
 extern stat_format_t *stat_format;  /* Bad hack!  Will fix after RC3! */
+extern signal_request_t sig_request;  /* Need access to global cancel flag */
 
 typedef struct http_private_t {
+  int cancel_flag;
+
   buf_t *buf;
   
   pthread_t curl_thread;
 
   CURL *curl_handle;
   char error[CURL_ERROR_SIZE];
-  data_source_stats_t stats;
-} http_private_t;
 
-
-typedef struct curl_thread_arg_t {
-  buf_t *buf;
   data_source_t *data_source;
-  http_private_t *http_private;
-  CURL *curl_handle;
-} curl_thread_arg_t;
+  data_source_stats_t stats;
+} http_private_t;
 
 
 transport_t http_transport;  /* Forward declaration */
@@ -61,11 +59,15 @@
 
 size_t write_callback (void *ptr, size_t size, size_t nmemb, void *arg)
 {
-  buf_t *buf = arg;
+  http_private_t *myarg = arg;
+
+  if (myarg->cancel_flag || sig_request.cancel)
+    return 0;
 
-  buffer_submit_data(buf, ptr, size*nmemb);
+  buffer_submit_data(myarg->buf, ptr, size*nmemb);
 
-  pthread_testcancel();
+  if (myarg->cancel_flag || sig_request.cancel)
+    return 0;
 
   return size * nmemb;
 }
@@ -73,28 +75,35 @@
 int progress_callback (void *arg, size_t dltotal, size_t dlnow,
                        size_t ultotal, size_t ulnow)
 {
-  data_source_t *source = arg;
+  http_private_t *myarg = arg;
   print_statistics_arg_t *pstats_arg;
+  data_source_t *source = myarg->data_source;
 
+  if (myarg->cancel_flag || sig_request.cancel)
+    return -1;
+
   pstats_arg = new_print_statistics_arg(stat_format,
                                         source->transport->statistics(source),
                                         NULL);
 
   print_statistics_action(NULL, pstats_arg);
 
+  if (myarg->cancel_flag || sig_request.cancel)
+    return -1;
+
   return 0;
 }
 
 
 /* -------------------------- Private functions --------------------- */
 
-void set_curl_opts (CURL *handle, buf_t *buf, char *url, data_source_t *source)
+void set_curl_opts (http_private_t *private)
 {
-  http_private_t *private = (http_private_t *) source;
+  CURL *handle = private->curl_handle;
 
-  curl_easy_setopt(handle, CURLOPT_FILE, buf);
+  curl_easy_setopt(handle, CURLOPT_FILE, private);
   curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback);
-  curl_easy_setopt(handle, CURLOPT_URL, url);
+  curl_easy_setopt(handle, CURLOPT_URL, private->data_source->source_string);
   /*
   if (inputOpts.ProxyPort)
     curl_easy_setopt(handle, CURLOPT_PROXYPORT, inputOpts.ProxyPort);
@@ -106,34 +115,15 @@
   curl_easy_setopt(handle, CURLOPT_MUTE, 1);
   curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, private->error);
   curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, progress_callback);
-  curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, source);
+  curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, private);
   curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 0);
   curl_easy_setopt(handle, CURLOPT_USERAGENT, "ogg123 "VERSION);
 }
 
 
-curl_thread_arg_t *new_curl_thread_arg (buf_t *buf, data_source_t *data_source,
-					CURL *curl_handle)
-{
-  curl_thread_arg_t *arg;
-
-  if ( (arg = malloc(sizeof(curl_thread_arg_t))) == NULL ) {
-    status_error(_("Error: Out of memory in new_curl_thread_arg().\n"));
-    exit(1);
-  }  
-  
-  arg->buf = buf;
-  arg->data_source = data_source;
-  arg->http_private = data_source->private;
-  arg->curl_handle = curl_handle;
-
-  return arg;
-}
-
-
 void *curl_thread_func (void *arg)
 {
-  curl_thread_arg_t *myarg = (curl_thread_arg_t *) arg;
+  http_private_t *myarg = (http_private_t *) arg;
   CURLcode ret;
   sigset_t set;
 
@@ -147,16 +137,18 @@
 
   ret = curl_easy_perform((CURL *) myarg->curl_handle);
 
+  if (myarg->cancel_flag || sig_request.cancel) {
+    buffer_abort_write(myarg->buf);
+    ret = 0;  // "error" was on purpose
+  } else
+    buffer_mark_eos(myarg->buf);
+
   if (ret != 0)
-    status_error(myarg->http_private->error);
-    
-  buffer_mark_eos(myarg->buf);
+    status_error(myarg->error);
 
   curl_easy_cleanup(myarg->curl_handle);
   myarg->curl_handle = 0;
 
-  free(arg);
-
   return (void *) ret;
 }
 
@@ -200,10 +192,11 @@
     }
 
     private->curl_handle = NULL;
-
+    private->data_source = source;
     private->stats.transfer_rate = 0;
     private->stats.bytes_read = 0;
     private->stats.input_buffer_used = 0;
+    private->cancel_flag = 0;
 
   } else {
     fprintf(stderr, _("Error: Out of memory.\n"));
@@ -211,17 +204,15 @@
   }
 
   /* Open URL */
-  private->curl_handle = curl_easy_init ();
+  private->curl_handle = curl_easy_init();
   if (private->curl_handle == NULL)
     goto fail;
 
-  set_curl_opts(private->curl_handle, private->buf, source_string, source);
+  set_curl_opts(private);
 
   /* Start thread */
-  if (pthread_create(&private->curl_thread, NULL, 
-		     curl_thread_func,
-		     new_curl_thread_arg(private->buf, source, 
-					 private->curl_handle)) != 0)
+  if (pthread_create(&private->curl_thread, NULL, curl_thread_func, 
+		     private) != 0)
     goto fail;
 
 
@@ -265,6 +256,9 @@
   http_private_t *private = source->private;
   int bytes_read;
 
+  if (private->cancel_flag || sig_request.cancel)
+    return 0;
+
   bytes_read = buffer_get_data(private->buf, ptr, size * nmemb);
 
   private->stats.bytes_read += bytes_read;
@@ -307,7 +301,7 @@
 {
   http_private_t *private = source->private;
 
-  pthread_cancel(private->curl_thread);
+  private->cancel_flag = 1;
   buffer_abort_write(private->buf);
   pthread_join(private->curl_thread, NULL);
 

<p><p>1.61      +14 -11    vorbis-tools/ogg123/ogg123.c

Index: ogg123.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -r1.60 -r1.61
--- ogg123.c	2002/01/26 11:06:37	1.60
+++ ogg123.c	2002/06/02 03:07:11	1.61
@@ -14,7 +14,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: ogg123.c,v 1.60 2002/01/26 11:06:37 segher Exp $
+ last mod: $Id: ogg123.c,v 1.61 2002/06/02 03:07:11 volsung Exp $
 
  ********************************************************************/
 
@@ -78,7 +78,7 @@
 
 
 /* Flags set by the signal handler to control the threads */
-signal_request_t sig_request = {0, 0, 0, 0};
+signal_request_t sig_request = {0, 0, 0, 0, 0};
 
 
 /* ------------------------------- signal handler ------------------------- */
@@ -101,6 +101,7 @@
     else
       sig_request.skipfile = 1;
 
+    sig_request.cancel = 1;
     sig_request.last_ctrl_c = now;
     break;
 
@@ -365,6 +366,11 @@
   int next_status = 0;
   static int status_interval = 0;
 
+  /* Reset all of the signal flags */
+  sig_request.cancel   = 0;
+  sig_request.skipfile = 0;
+  sig_request.exit     = 0;
+  sig_request.pause    = 0;
 
   /* Set preferred audio format (used by decoder) */
   new_audio_fmt.big_endian = ao_is_big_endian();
@@ -402,20 +408,17 @@
   if ( (decoder = format->init(source, &options, &new_audio_fmt, 
                                &decoder_callbacks,
                                decoder_callbacks_arg)) == NULL ) {
-    status_error(_("Error opening %s using the %s module."
-		 "  The file may be corrupted.\n"), source_string,
-		 format->name);
+
+    // We may have failed because of user command
+    if (!sig_request.cancel)
+      status_error(_("Error opening %s using the %s module."
+		     "  The file may be corrupted.\n"), source_string,
+		   format->name);
     return;
   }
 
   /* Decide which statistics are valid */
   select_stats(stat_format, &options, source, decoder, audio_buffer);
-
-
-  /* Reset all of the signal flags */
-  sig_request.skipfile = 0;
-  sig_request.exit     = 0;
-  sig_request.pause    = 0;
 
   /* Start the audio playback thread before we begin sending data */    
   if (audio_buffer != NULL) {

<p><p>1.13      +2 -1      vorbis-tools/ogg123/ogg123.h

Index: ogg123.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- ogg123.h	2001/12/24 15:58:03	1.12
+++ ogg123.h	2002/06/02 03:07:11	1.13
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: ogg123.h,v 1.12 2001/12/24 15:58:03 volsung Exp $
+ last mod: $Id: ogg123.h,v 1.13 2002/06/02 03:07:11 volsung Exp $
 
  ********************************************************************/
 
@@ -43,6 +43,7 @@
 } ogg123_options_t;
 
 typedef struct signal_request_t {
+  int cancel;
   int skipfile;
   int exit;
   int pause;

<p><p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list