summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <waker@users.sourceforge.net>2013-10-28 22:36:46 +0100
committerGravatar Alexey Yakovenko <waker@users.sourceforge.net>2013-10-28 22:36:46 +0100
commitd5bad39e15fae6770a84787823c56d066cee614a (patch)
tree09a026c46ce2f8420b148506f627a9dea12c3bf3 /plugins
parentbdd531322954ad92509c20a00c7372c893cdf412 (diff)
improved visualization API; improved scope
Diffstat (limited to 'plugins')
-rw-r--r--plugins/gtkui/widgets.c63
1 files changed, 60 insertions, 3 deletions
diff --git a/plugins/gtkui/widgets.c b/plugins/gtkui/widgets.c
index 88c0f8f7..e42601b6 100644
--- a/plugins/gtkui/widgets.c
+++ b/plugins/gtkui/widgets.c
@@ -134,6 +134,8 @@ typedef struct {
#if USE_OPENGL
GdkGLContext *glcontext;
#endif
+ float *samples;
+ int nsamples;
} w_scope_t;
typedef struct {
@@ -2233,6 +2235,7 @@ w_coverart_create (void) {
void
w_scope_destroy (ddb_gtkui_widget_t *w) {
w_scope_t *s = (w_scope_t *)w;
+ deadbeef->unregister_continuous_wavedata_listener (w);
if (s->drawtimer) {
g_source_remove (s->drawtimer);
s->drawtimer = 0;
@@ -2243,6 +2246,10 @@ w_scope_destroy (ddb_gtkui_widget_t *w) {
s->glcontext = NULL;
}
#endif
+ if (s->samples) {
+ free (s->samples);
+ s->samples = NULL;
+ }
}
gboolean
@@ -2252,11 +2259,27 @@ w_scope_draw_cb (void *data) {
return TRUE;
}
+static void
+scope_wavedata_listener (void *ctx, ddb_waveformat_t *fmt, const float *data, int in_samples) {
+ w_scope_t *w = ctx;
+ if (w->samples) {
+ // append
+ float ratio = (44100.f / fmt->samplerate);
+ int size = in_samples * ratio;
+
+ int sz = min (w->nsamples, size);
+ int n = w->nsamples-sz;
+
+ memmove (w->samples, w->samples + sz, n * sizeof (float));
+ float pos = 0;
+ for (int i = 0; i < sz && pos < in_samples; i++, pos += 1./ratio) {
+ w->samples[n + i] = data[(int)(pos * fmt->channels)];
+ }
+ }
+}
+
gboolean
scope_draw_cairo (GtkWidget *widget, cairo_t *cr, gpointer user_data) {
- ddb_waveformat_t fmt;
- float data[DDB_AUDIO_MEMORY_FRAMES];
- deadbeef->audio_get_waveform_data (DDB_AUDIO_WAVEFORM, data);
GtkAllocation a;
gtk_widget_get_allocation (widget, &a);
cairo_set_source_rgb (cr, 0, 0, 0);
@@ -2266,12 +2289,45 @@ scope_draw_cairo (GtkWidget *widget, cairo_t *cr, gpointer user_data) {
cairo_set_line_width (cr, 1);
cairo_set_source_rgb (cr, 1, 1, 1);
+ w_scope_t *w = user_data;
+
+ float spp = 1;
+ int nsamples = a.width / spp;
+ if (w->nsamples != nsamples) {
+ printf ("init\n");
+ float *oldsamples = w->samples;
+ int oldnsamples = w->nsamples;
+ w->samples = NULL;
+ w->nsamples = nsamples;
+ if (nsamples > 0) {
+ w->samples = malloc (sizeof (float) * nsamples);
+ memset (w->samples, 0, sizeof (float) * nsamples);
+ if (oldsamples) {
+ int n = min (oldnsamples, w->nsamples);
+ memcpy (w->samples + w->nsamples - n, oldsamples + oldnsamples - n, n * sizeof (float));
+ free (oldsamples);
+ }
+ }
+ else {
+ return FALSE;
+ }
+ }
+
+
+ float incr = a.width / (float)w->nsamples;
+ for (int i = 0; i < w->nsamples; i++) {
+ float s = w->samples[i];
+ cairo_line_to (cr, i, s * a.height/2 + a.height/2);
+ }
+
+#if 0
float incr = a.width / (float)DDB_AUDIO_MEMORY_FRAMES;
float pos = 0;
for (float x = 0; x < a.width && pos < DDB_AUDIO_MEMORY_FRAMES; x += incr, pos ++) {
float s = data[(int)pos];
cairo_line_to (cr, x, s * a.height/2 + a.height/2);
}
+#endif
cairo_stroke (cr);
return FALSE;
@@ -2398,6 +2454,7 @@ w_scope_create (void) {
#endif
g_signal_connect_after (G_OBJECT (w->drawarea), "realize", G_CALLBACK (scope_realize), w);
w_override_signals (w->base.widget, w);
+ deadbeef->register_continuous_wavedata_listener (w, scope_wavedata_listener);
return (ddb_gtkui_widget_t *)w;
}