XMMS2
|
00001 00002 #include "xmms/xmms_log.h" 00003 #include "xmms/xmms_medialib.h" 00004 #include "xmmspriv/xmms_ringbuf.h" 00005 #include "xmmspriv/xmms_xform.h" 00006 00007 /* 00008 - producer: 00009 want_buffer -> buffering 00010 want_seek -> seeked 00011 want_stop -> stopped 00012 00013 - consumer: 00014 * -> want_seek 00015 wait until state == seek_done 00016 seek_done -> want_buffer 00017 00018 * -> want_stop 00019 wait until state == is_stopped 00020 00021 */ 00022 typedef enum xmms_buffer_state_E { 00023 STATE_WANT_BUFFER, 00024 STATE_BUFFERING, 00025 STATE_WANT_SEEK, 00026 STATE_SEEK_DONE, 00027 STATE_WANT_STOP, 00028 STATE_IS_STOPPED 00029 } xmms_buffer_state_t; 00030 00031 typedef struct xmms_ringbuf_priv_St { 00032 GThread *thread; 00033 00034 xmms_ringbuf_t *buffer; 00035 GMutex *buffer_lock; 00036 00037 xmms_buffer_state_t state; 00038 GCond *state_cond; 00039 GMutex *state_lock; 00040 } xmms_ringbuf_priv_t; 00041 00042 static xmms_xform_plugin_t *ringbuf_plugin; 00043 00044 static gpointer xmms_ringbuf_xform_thread (gpointer data); 00045 00046 static gboolean 00047 xmms_ringbuf_plugin_init (xmms_xform_t *xform) 00048 { 00049 xmms_ringbuf_priv_t *priv; 00050 00051 priv = g_new0 (xmms_ringbuf_priv_t, 1); 00052 00053 xmms_xform_private_data_set (xform, priv); 00054 00055 priv->buffer = xmms_ringbuf_new (4096*8); 00056 priv->buffer_lock = g_mutex_new (); 00057 priv->state = STATE_WANT_BUFFER; 00058 priv->state_cond = g_cond_new (); 00059 priv->state_lock = g_mutex_new (); 00060 priv->thread = g_thread_create (xmms_ringbuf_xform_thread, xform, TRUE, NULL); 00061 00062 xmms_xform_outdata_type_copy (xform); 00063 00064 return TRUE; 00065 } 00066 00067 static void 00068 xmms_ringbuf_plugin_destroy (xmms_xform_t *xform) 00069 { 00070 xmms_ringbuf_priv_t *priv; 00071 priv = xmms_xform_private_data_get (xform); 00072 00073 g_mutex_lock (priv->state_lock); 00074 xmms_ringbuf_clear (priv->buffer); 00075 while (priv->state != STATE_IS_STOPPED) { 00076 priv->state = STATE_WANT_STOP; 00077 g_cond_wait (priv->state_cond, priv->state_lock); 00078 } 00079 g_mutex_unlock (priv->state_lock); 00080 00081 g_thread_join (priv->thread); 00082 00083 XMMS_DBG ("Ringbuf destroyed!"); 00084 } 00085 00086 static gint 00087 xmms_ringbuf_plugin_read (xmms_xform_t *xform, void *buffer, gint len, xmms_error_t *error) 00088 { 00089 xmms_ringbuf_priv_t *priv; 00090 priv = xmms_xform_private_data_get (xform); 00091 00092 return xmms_ringbuf_read_wait (priv->buffer, buffer, len, priv->buffer_lock); 00093 } 00094 00095 00096 static gboolean 00097 xmms_ringbuf_plugin_setup (xmms_xform_plugin_t *xform_plugin) 00098 { 00099 xmms_xform_methods_t methods; 00100 00101 XMMS_XFORM_METHODS_INIT (methods); 00102 methods.init = xmms_ringbuf_plugin_init; 00103 methods.destroy = xmms_ringbuf_plugin_destroy; 00104 methods.read = xmms_ringbuf_plugin_read; 00105 /* 00106 methods.seek 00107 */ 00108 00109 xmms_xform_plugin_methods_set (xform_plugin, &methods); 00110 00111 ringbuf_plugin = xform_plugin; 00112 00113 return TRUE; 00114 } 00115 00116 static xmms_xform_t * 00117 xmms_ringbuf_xform_new (xmms_xform_t *prev, xmms_medialib_entry_t entry, GList *gt) 00118 { 00119 xmms_xform_t *xform; 00120 00121 xform = xmms_xform_new (ringbuf_plugin, prev, entry, gt); 00122 00123 return xform; 00124 } 00125 00126 static void 00127 fill (xmms_xform_t *xform, xmms_ringbuf_priv_t *priv) 00128 { 00129 xmms_error_t err; 00130 char buf[4096]; 00131 int res; 00132 00133 res = xmms_xform_read (xform, buf, sizeof (buf), &err); 00134 if (res > 0) { 00135 xmms_ringbuf_write_wait (priv->buffer, buf, res, priv->buffer_lock); 00136 } else if (res == -1) { 00137 /* XXX copy error */ 00138 g_mutex_lock (priv->state_lock); 00139 priv->state = STATE_WANT_STOP; 00140 } else { 00141 xmms_ringbuf_set_eos (priv->buffer, TRUE); 00142 priv->state = STATE_WANT_STOP; 00143 } 00144 } 00145 00146 static gpointer 00147 xmms_ringbuf_xform_thread (gpointer data) 00148 { 00149 xmms_xform_t *xform = (xmms_xform_t *)data; 00150 xmms_ringbuf_priv_t *priv; 00151 00152 priv = xmms_xform_private_data_get (xform); 00153 00154 g_mutex_lock (priv->state_lock); 00155 while (priv->state != STATE_WANT_STOP) { 00156 if (priv->state == STATE_WANT_BUFFER) { 00157 priv->state = STATE_BUFFERING; 00158 g_cond_signal (priv->state_cond); 00159 while (priv->state == STATE_BUFFERING) { 00160 g_mutex_unlock (priv->state_lock); 00161 fill (xform, priv); 00162 g_mutex_lock (priv->state_lock); 00163 } 00164 } else if (priv->state == STATE_WANT_SEEK) { 00165 /** **/ 00166 priv->state = STATE_SEEK_DONE; 00167 g_cond_signal (priv->state_cond); 00168 while (priv->state == STATE_SEEK_DONE) { 00169 g_cond_wait (priv->state_cond, priv->state_lock); 00170 } 00171 } 00172 XMMS_DBG ("thread: state: %d", priv->state); 00173 } 00174 priv->state = STATE_IS_STOPPED; 00175 g_cond_signal (priv->state_cond); 00176 g_mutex_unlock (priv->state_lock); 00177 00178 return NULL; 00179 } 00180 00181 XMMS_XFORM_BUILTIN (ringbuf, 00182 "Ringbuffer", 00183 XMMS_VERSION, 00184 "Buffer", 00185 xmms_ringbuf_plugin_setup);