XMMS2
ringbuf_xform.c
Go to the documentation of this file.
1
2#include "xmms/xmms_log.h"
6
7/*
8 - producer:
9 want_buffer -> buffering
10 want_seek -> seeked
11 want_stop -> stopped
12
13 - consumer:
14 * -> want_seek
15 wait until state == seek_done
16 seek_done -> want_buffer
17
18 * -> want_stop
19 wait until state == is_stopped
20
21*/
22typedef enum xmms_buffer_state_E {
30
31typedef struct xmms_ringbuf_priv_St {
32 GThread *thread;
33
34 xmms_ringbuf_t *buffer;
35 GMutex *buffer_lock;
36
38 GCond *state_cond;
39 GMutex *state_lock;
41
42static xmms_xform_plugin_t *ringbuf_plugin;
43
44static gpointer xmms_ringbuf_xform_thread (gpointer data);
45
46static gboolean
47xmms_ringbuf_plugin_init (xmms_xform_t *xform)
48{
50
51 priv = g_new0 (xmms_ringbuf_priv_t, 1);
52
53 xmms_xform_private_data_set (xform, priv);
54
55 priv->buffer = xmms_ringbuf_new (4096*8);
56 priv->buffer_lock = g_mutex_new ();
57 priv->state = STATE_WANT_BUFFER;
58 priv->state_cond = g_cond_new ();
59 priv->state_lock = g_mutex_new ();
60 priv->thread = g_thread_create (xmms_ringbuf_xform_thread, xform, TRUE, NULL);
61
63
64 return TRUE;
65}
66
67static void
68xmms_ringbuf_plugin_destroy (xmms_xform_t *xform)
69{
71 priv = xmms_xform_private_data_get (xform);
72
73 g_mutex_lock (priv->state_lock);
74 xmms_ringbuf_clear (priv->buffer);
75 while (priv->state != STATE_IS_STOPPED) {
76 priv->state = STATE_WANT_STOP;
77 g_cond_wait (priv->state_cond, priv->state_lock);
78 }
79 g_mutex_unlock (priv->state_lock);
80
81 g_thread_join (priv->thread);
82
83 XMMS_DBG ("Ringbuf destroyed!");
84}
85
86static gint
87xmms_ringbuf_plugin_read (xmms_xform_t *xform, void *buffer, gint len, xmms_error_t *error)
88{
90 priv = xmms_xform_private_data_get (xform);
91
92 return xmms_ringbuf_read_wait (priv->buffer, buffer, len, priv->buffer_lock);
93}
94
95
96static gboolean
97xmms_ringbuf_plugin_setup (xmms_xform_plugin_t *xform_plugin)
98{
100
101 XMMS_XFORM_METHODS_INIT (methods);
102 methods.init = xmms_ringbuf_plugin_init;
103 methods.destroy = xmms_ringbuf_plugin_destroy;
104 methods.read = xmms_ringbuf_plugin_read;
105 /*
106 methods.seek
107 */
108
109 xmms_xform_plugin_methods_set (xform_plugin, &methods);
110
111 ringbuf_plugin = xform_plugin;
112
113 return TRUE;
114}
115
116static xmms_xform_t *
117xmms_ringbuf_xform_new (xmms_xform_t *prev, xmms_medialib_entry_t entry, GList *gt)
118{
119 xmms_xform_t *xform;
120
121 xform = xmms_xform_new (ringbuf_plugin, prev, entry, gt);
122
123 return xform;
124}
125
126static void
127fill (xmms_xform_t *xform, xmms_ringbuf_priv_t *priv)
128{
129 xmms_error_t err;
130 char buf[4096];
131 int res;
132
133 res = xmms_xform_read (xform, buf, sizeof (buf), &err);
134 if (res > 0) {
135 xmms_ringbuf_write_wait (priv->buffer, buf, res, priv->buffer_lock);
136 } else if (res == -1) {
137 /* XXX copy error */
138 g_mutex_lock (priv->state_lock);
139 priv->state = STATE_WANT_STOP;
140 } else {
141 xmms_ringbuf_set_eos (priv->buffer, TRUE);
142 priv->state = STATE_WANT_STOP;
143 }
144}
145
146static gpointer
147xmms_ringbuf_xform_thread (gpointer data)
148{
149 xmms_xform_t *xform = (xmms_xform_t *)data;
151
152 priv = xmms_xform_private_data_get (xform);
153
154 g_mutex_lock (priv->state_lock);
155 while (priv->state != STATE_WANT_STOP) {
156 if (priv->state == STATE_WANT_BUFFER) {
157 priv->state = STATE_BUFFERING;
158 g_cond_signal (priv->state_cond);
159 while (priv->state == STATE_BUFFERING) {
160 g_mutex_unlock (priv->state_lock);
161 fill (xform, priv);
162 g_mutex_lock (priv->state_lock);
163 }
164 } else if (priv->state == STATE_WANT_SEEK) {
165 /** **/
166 priv->state = STATE_SEEK_DONE;
167 g_cond_signal (priv->state_cond);
168 while (priv->state == STATE_SEEK_DONE) {
169 g_cond_wait (priv->state_cond, priv->state_lock);
170 }
171 }
172 XMMS_DBG ("thread: state: %d", priv->state);
173 }
174 priv->state = STATE_IS_STOPPED;
175 g_cond_signal (priv->state_cond);
176 g_mutex_unlock (priv->state_lock);
177
178 return NULL;
179}
180
182 "Ringbuffer",
183 XMMS_VERSION,
184 "Buffer",
185 xmms_ringbuf_plugin_setup);
guint xmms_ringbuf_write_wait(xmms_ringbuf_t *ringbuf, gconstpointer data, guint len, GMutex *mtx)
Same as xmms_ringbuf_write but blocks until there is enough free space.
Definition: ringbuf.c:353
void xmms_ringbuf_set_eos(xmms_ringbuf_t *ringbuf, gboolean eos)
Set EOS flag on ringbuffer.
Definition: ringbuf.c:427
void xmms_ringbuf_clear(xmms_ringbuf_t *ringbuf)
Clear the ringbuffers data.
Definition: ringbuf.c:121
xmms_ringbuf_t * xmms_ringbuf_new(guint size)
Allocate a new ringbuffer.
Definition: ringbuf.c:74
guint xmms_ringbuf_read_wait(xmms_ringbuf_t *ringbuf, gpointer data, guint len, GMutex *mtx)
Same as xmms_ringbuf_read but blocks until you have all the data you want.
Definition: ringbuf.c:265
void xmms_xform_private_data_set(xmms_xform_t *xform, gpointer data)
Set private data for this xform.
Definition: xform.c:430
struct xmms_xform_plugin_St xmms_xform_plugin_t
Xform plugin.
gpointer xmms_xform_private_data_get(xmms_xform_t *xform)
Get private data for this xform.
Definition: xform.c:424
struct xmms_xform_St xmms_xform_t
gint xmms_xform_read(xmms_xform_t *xform, gpointer buf, gint siz, xmms_error_t *err)
Read data from previous xform.
Definition: xform.c:1113
void xmms_xform_plugin_methods_set(xmms_xform_plugin_t *plugin, xmms_xform_methods_t *methods)
Should be called once from the plugin's setupfunc.
Definition: xform_plugin.c:53
void xmms_xform_outdata_type_copy(xmms_xform_t *xform)
Definition: xform.c:452
#define XMMS_XFORM_METHODS_INIT(m)
enum xmms_buffer_state_E xmms_buffer_state_t
xmms_buffer_state_E
Definition: ringbuf_xform.c:22
@ STATE_WANT_BUFFER
Definition: ringbuf_xform.c:23
@ STATE_BUFFERING
Definition: ringbuf_xform.c:24
@ STATE_WANT_STOP
Definition: ringbuf_xform.c:27
@ STATE_SEEK_DONE
Definition: ringbuf_xform.c:26
@ STATE_WANT_SEEK
Definition: ringbuf_xform.c:25
@ STATE_IS_STOPPED
Definition: ringbuf_xform.c:28
struct xmms_ringbuf_priv_St xmms_ringbuf_priv_t
Methods provided by an xform plugin.
gboolean(* init)(xmms_xform_t *)
Initialisation method.
void(* destroy)(xmms_xform_t *)
Destruction method.
gint(* read)(xmms_xform_t *, gpointer, gint, xmms_error_t *)
Read method.
xmms_xform_t * xmms_xform_new(xmms_xform_plugin_t *plugin, xmms_xform_t *prev, xmms_medialib_entry_t entry, GList *goal_hints)
Definition: xform.c:375
#define XMMS_DBG(fmt,...)
Definition: xmms_log.h:32
G_BEGIN_DECLS typedef gint32 xmms_medialib_entry_t
Definition: xmms_medialib.h:86
G_BEGIN_DECLS struct xmms_error_St xmms_error_t
struct xmms_ringbuf_St xmms_ringbuf_t
Definition: xmms_ringbuf.h:25
#define XMMS_XFORM_BUILTIN(shname, name, ver, desc, setupfunc)
Definition: xmms_xform.h:53