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
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00107
00108
00109 xmms_xform_plugin_methods_set (xform_plugin, &methods);
00110
00111 ringbuf_plugin = xform_plugin;
00112
00113 return TRUE;
00114 }
00115
00116 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
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);