diff options
author | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2012-06-01 20:21:08 +0000 |
---|---|---|
committer | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2012-06-01 20:21:08 +0000 |
commit | 70958d6e6d40802c0f6ac0ed55bf704fbe2c9fc3 (patch) | |
tree | cb73f0e4552b23eb988a8c3b12d442933f69113b | |
parent | f84862993fca45ffb3190d8e3ca0ae73ad4f2942 (diff) | |
download | 2012-violon-leds-70958d6e6d40802c0f6ac0ed55bf704fbe2c9fc3.tar.gz 2012-violon-leds-70958d6e6d40802c0f6ac0ed55bf704fbe2c9fc3.tar.bz2 2012-violon-leds-70958d6e6d40802c0f6ac0ed55bf704fbe2c9fc3.zip |
Ecriture du test5 : intégration de PulseAudio dans le code du test4.
Le squelette est là, l'initialisation du contexte pulse audio aussi.
Reste : ouvrir les flux, écrire le callback pulse qui récupère le niveau sonore (avec timing si possible) et qui appelle le callback applicatif du test5.c
git-svn-id: file:///var/svn/2012-violon-leds/trunk@9 6be1fa4d-33ac-4c33-becc-79fcb3794bb6
-rw-r--r-- | tests/test5/TOREAD | 2 | ||||
-rw-r--r-- | tests/test5/capture.c | 82 | ||||
-rw-r--r-- | tests/test5/capture.h | 9 | ||||
-rwxr-xr-x | tests/test5/compil.sh | 8 | ||||
-rw-r--r-- | tests/test5/compute.c | 42 | ||||
-rw-r--r-- | tests/test5/compute.h | 10 | ||||
-rw-r--r-- | tests/test5/gtkvumeter.c | 261 | ||||
-rw-r--r-- | tests/test5/gtkvumeter.h | 39 | ||||
-rw-r--r-- | tests/test5/old/test5.c | 187 | ||||
-rw-r--r-- | tests/test5/test5.c | 213 | ||||
-rw-r--r-- | tests/test5/win_main.c | 65 | ||||
-rw-r--r-- | tests/test5/win_main.h | 9 |
12 files changed, 759 insertions, 168 deletions
diff --git a/tests/test5/TOREAD b/tests/test5/TOREAD new file mode 100644 index 0000000..e84ab7e --- /dev/null +++ b/tests/test5/TOREAD @@ -0,0 +1,2 @@ +http://freedesktop.org/software/pulseaudio/doxygen/async.html#overv_sec + diff --git a/tests/test5/capture.c b/tests/test5/capture.c new file mode 100644 index 0000000..6bc5afe --- /dev/null +++ b/tests/test5/capture.c @@ -0,0 +1,82 @@ +#include "capture.h" +#include <pulse/pulseaudio.h> +#include <gtk/gtk.h> + +#define APP_TITLE "Test 5 lpo" +#define BUFSIZE 1024 + +pa_context *pa_ct=NULL; +capture_sound_level_cb_t *capture_sound_level_cb=NULL; + +int capture_init(pa_mainloop **m); +void context_state_callback(pa_context *c, void *userdata); + +void audio_thread(void *args) { + pa_mainloop *m; + int res, retval; + + capture_sound_level_cb=(capture_sound_level_cb_t *)args; + + res=capture_init(&m); + g_assert(res==0); + + res=pa_mainloop_run(m,&retval); + g_assert(res==0); + g_assert(retval==0); + +// pa_context_disconnect(pa_ct); + pa_mainloop_free(m); +} + +int capture_init(pa_mainloop **m) { + int res=0; + + *m=pa_mainloop_new(); + g_assert(*m); + + pa_ct = pa_context_new(pa_mainloop_get_api(*m), APP_TITLE); + g_assert(pa_ct); + + pa_context_set_state_callback(pa_ct, context_state_callback, NULL); + res=pa_context_connect(pa_ct, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); + + return res; +} + +void context_state_callback(pa_context *c, void *userdata) { + switch (pa_context_get_state(c)) { + case PA_CONTEXT_UNCONNECTED: + printf("PA_CONTEXT_UNCONNECTED\n"); + break; + case PA_CONTEXT_CONNECTING: + printf("PA_CONTEXT_CONNECTING\n"); + break; + case PA_CONTEXT_AUTHORIZING: + printf("PA_CONTEXT_AUTHORIZING\n"); + break; + case PA_CONTEXT_SETTING_NAME: + printf("PA_CONTEXT_SETTING_NAME\n"); + break; + case PA_CONTEXT_READY: + printf("PA_CONTEXT_READY\n"); + //g_assert(!stream); + + //if (device_name && mode == RECORD) + //pa_operation_unref(pa_context_get_source_info_by_name(c, device_name, context_get_source_info_callback, NULL)); + /*else if (device_name && mode == PLAYBACK) + pa_operation_unref(pa_context_get_sink_info_by_name(c, device_name, context_get_sink_info_callback, NULL)); + else + pa_operation_unref(pa_context_get_server_info(c, context_get_server_info_callback, NULL)); + */ + break; + + case PA_CONTEXT_FAILED: + printf("PA_CONTEXT_FAILED\n"); + break; + + case PA_CONTEXT_TERMINATED: + printf("PA_CONTEXT_TERMINATED\n"); + break; + } +} + diff --git a/tests/test5/capture.h b/tests/test5/capture.h new file mode 100644 index 0000000..2acbe09 --- /dev/null +++ b/tests/test5/capture.h @@ -0,0 +1,9 @@ +#ifndef CAPTURE_H +#define CAPTURE_H +#include <gtk/gtk.h> + +typedef void(* capture_sound_level_cb_t)(gint sound_level, void *userdata); + +void audio_thread(void *args); + +#endif /*CAPTURE_H*/ diff --git a/tests/test5/compil.sh b/tests/test5/compil.sh index 6ca9982..e69ee99 100755 --- a/tests/test5/compil.sh +++ b/tests/test5/compil.sh @@ -1,3 +1,7 @@ #!/bin/bash -ex -gcc -Wall -g -c test5.c $(pkg-config --cflags gtk+-2.0 libpulse libpulse-mainloop-glib) -gcc -Wall -o test5 test5.o $(pkg-config --libs gtk+-2.0 libpulse libpulse-mainloop-glib) +gcc -Wall -g -c gtkvumeter.c $(pkg-config --cflags gtk+-2.0) +gcc -Wall -g -c win_main.c $(pkg-config --cflags gtk+-2.0) +gcc -Wall -g -c compute.c $(pkg-config --cflags gtk+-2.0) +gcc -Wall -g -c capture.c $(pkg-config --cflags gtk+-2.0 libpulse) +gcc -Wall -g -c test5.c $(pkg-config --cflags gtk+-2.0 gthread-2.0 libpulse) +gcc -Wall -o test5 *.o $(pkg-config --libs gtk+-2.0 gthread-2.0 libpulse) diff --git a/tests/test5/compute.c b/tests/test5/compute.c new file mode 100644 index 0000000..11a7f81 --- /dev/null +++ b/tests/test5/compute.c @@ -0,0 +1,42 @@ +#include "compute.h" + +void audio2hsv_1(gint audio_level, gint *light_h, gint *light_s, gint *light_v) { + // Dummy code + *light_h=-audio_level; + *light_s=audio_level; + *light_v=65535; +} + + +void hsv2rgb(gint h, gint s, gint v, gint *r, gint *g, gint *b) { + /* + * Purpose: + * Convert HSV values to RGB values + * All values are in the range [0..65535] + */ + float F, M, N, K; + int I; + + if ( s == 0 ) { + /* + * Achromatic case, set level of grey + */ + *r = v; + *g = v; + *b = v; + } else { + I = (int) h/(65535/6); /* should be in the range 0..5 */ + F = h - I; /* fractional part */ + + M = v * (1 - s); + N = v * (1 - s * F); + K = v * (1 - s * (1 - F)); + + if (I == 0) { *r = v; *g = K; *b = M; } + if (I == 1) { *r = N; *g = v; *b = M; } + if (I == 2) { *r = M; *g = v; *b = K; } + if (I == 3) { *r = M; *g = N; *b = v; } + if (I == 4) { *r = K; *g = M; *b = v; } + if (I == 5) { *r = v; *g = M; *b = N; } + } +} diff --git a/tests/test5/compute.h b/tests/test5/compute.h new file mode 100644 index 0000000..2454e56 --- /dev/null +++ b/tests/test5/compute.h @@ -0,0 +1,10 @@ +#ifndef COMPUTE_H +#define COMPUTE_H + +#include <gtk/gtk.h> + +void audio2hsv_1(gint audio_level, gint *light_h, gint *light_s, gint *light_v); +void hsv2rgb(gint h, gint s, gint v, gint *r, gint *g, gint *b); + +#endif + diff --git a/tests/test5/gtkvumeter.c b/tests/test5/gtkvumeter.c new file mode 100644 index 0000000..cb0f9d7 --- /dev/null +++ b/tests/test5/gtkvumeter.c @@ -0,0 +1,261 @@ +#include <string.h> +#include "gtkvumeter.h" + +#define MIN_HORIZONTAL_VUMETER_WIDTH 40 +#define HORIZONTAL_VUMETER_HEIGHT 20 +#define VERTICAL_VUMETER_WIDTH 20 +#define MIN_VERTICAL_VUMETER_HEIGHT 40 + +G_DEFINE_TYPE (GtkVuMeter, gtk_vu_meter, GTK_TYPE_DRAWING_AREA); + +static GdkColor default_f_gradient_keys[3] = {{0,65535,0,0},{0,65535,65535,0},{0,0,65535,0}}; +static GdkColor default_b_gradient_keys[3] = {{0,49151,0,0},{0,49151,49151,0},{0,0,49151,0}}; + +static gboolean gtk_vu_meter_expose (GtkWidget *vumeter, GdkEventExpose *event); +static void gtk_vu_meter_setup_colors (GtkVuMeter *vumeter); +static void gtk_vu_meter_free_colors (GtkVuMeter *vumeter); +static void free_drawbuf(guchar *pixels, gpointer data); +static void gtk_vu_meter_size_request (GtkWidget *widget, GtkRequisition *requisition); +static void gtk_vu_meter_size_allocate (GtkWidget *widget, GtkAllocation *allocation); +static gint gtk_vu_meter_sound_level_to_draw_level (GtkVuMeter *vumeter); + +static void gtk_vu_meter_class_init (GtkVuMeterClass *class) { + GtkWidgetClass *widget_class; + widget_class = GTK_WIDGET_CLASS (class); + widget_class->expose_event = gtk_vu_meter_expose; + widget_class->size_request = gtk_vu_meter_size_request; + widget_class->size_allocate = gtk_vu_meter_size_allocate; +} + +static void gtk_vu_meter_init (GtkVuMeter *vumeter) { + vumeter->vertical=TRUE; + gtk_vu_meter_set_gradient(vumeter, 3, default_f_gradient_keys, 3, default_b_gradient_keys); + gtk_vu_meter_setup_colors(vumeter); +} + +void gtk_vu_meter_set_gradient (GtkVuMeter *vumeter, gint f_gradient_key_count, GdkColor *f_gradient_keys, gint b_gradient_key_count, GdkColor *b_gradient_keys) { + //XXX : memdup is a bad idea ? + GdkColor *fgk = g_memdup(f_gradient_keys, f_gradient_key_count*sizeof(GdkColor)); + GdkColor *bgk = g_memdup(b_gradient_keys, b_gradient_key_count*sizeof(GdkColor)); + g_return_if_fail (fgk != NULL); + g_return_if_fail (bgk != NULL); + + vumeter->f_gradient_keys = fgk; + vumeter->f_gradient_key_count=f_gradient_key_count; + vumeter->b_gradient_keys = bgk; + vumeter->b_gradient_key_count=b_gradient_key_count; +} +static void gtk_vu_meter_free_colors (GtkVuMeter *vumeter) { + // TODO : free pixmaps +} + +static void gtk_vu_meter_setup_colors (GtkVuMeter *vumeter) { + + gint i,j; + guchar *f_drawbuf, *b_drawbuf, f_r, f_g, f_b, b_r, b_g, b_b; + gint f_key_len, b_key_len; + gint f_key_i, b_key_i; + gdouble f_key_pos, b_key_pos; + GdkColor *fgk, *bgk; + + gint h=GTK_WIDGET(vumeter)->allocation.height; + gint w=GTK_WIDGET(vumeter)->allocation.width; + + // Clean every previous colors and buffers + gtk_vu_meter_free_colors (vumeter); + + if (vumeter->vertical == TRUE) { + vumeter->colors = MAX(h, 0); + } else { + vumeter->colors = MAX(w, 0); + } + + // Allocate a memory buffers to hold the gradients + f_drawbuf=g_malloc(h*w*3); + b_drawbuf=g_malloc(h*w*3); + g_return_if_fail (f_drawbuf != NULL); + g_return_if_fail (b_drawbuf != NULL); + + // Compute some values before looping for gradient generation + f_key_len = vumeter->colors / (vumeter->f_gradient_key_count-1) + 1; + b_key_len = vumeter->colors / (vumeter->b_gradient_key_count-1) + 1; + fgk=vumeter->f_gradient_keys; + bgk=vumeter->b_gradient_keys; + + for (i=0; i<vumeter->colors; i++) { + // Compute the current position in the gradient keys + f_key_i=i/f_key_len; + f_key_pos=((gdouble) (i%f_key_len)/f_key_len); + b_key_i=i/f_key_len; + b_key_pos=((gdouble) (i%b_key_len)/b_key_len); + + /* Generate the Colours */ + /* foreground */ + f_r = ( fgk[f_key_i].red*(1.0-f_key_pos) + fgk[f_key_i+1].red*f_key_pos ) / 256; + f_g = ( fgk[f_key_i].green*(1.0-f_key_pos) + fgk[f_key_i+1].green*f_key_pos ) / 256; + f_b = ( fgk[f_key_i].blue*(1.0-f_key_pos) + fgk[f_key_i+1].blue*f_key_pos ) / 256; + /* background */ + b_r = ( bgk[b_key_i].red*(1.0-b_key_pos) + bgk[b_key_i+1].red*b_key_pos ) / 256; + b_g = ( bgk[b_key_i].green*(1.0-b_key_pos) + bgk[b_key_i+1].green*b_key_pos ) / 256; + b_b = ( bgk[b_key_i].blue*(1.0-b_key_pos) + bgk[b_key_i+1].blue*b_key_pos ) / 256; + + /* Apply the color in the drawbufs */ + if (vumeter->vertical == TRUE) { + // Vertical mode : draw directly the whole line of identical color + for (j=3*w*i; j<3*w*(i+1); ) { + f_drawbuf[j++]=f_r; + f_drawbuf[j++]=f_g; + f_drawbuf[j++]=f_b; + } + for (j=3*w*i; j<3*w*(i+1); ) { + b_drawbuf[j++]=b_r; + b_drawbuf[j++]=b_g; + b_drawbuf[j++]=b_b; + } + } else { + // Horiziontal mode : draw only the first line (color change at each pixel) + // Others line will be duplicated at the end + f_drawbuf[i]=f_r; + f_drawbuf[i+1]=f_g; + f_drawbuf[i+2]=f_b; + b_drawbuf[i]=b_r; + b_drawbuf[i+1]=b_g; + b_drawbuf[i+2]=b_b; + } + } + if (vumeter->vertical != TRUE) { + // Duplicate the first line over the others + for (j=1; j<h; j++) { + memcpy(f_drawbuf, f_drawbuf+3*w*j, w); + } + } + + vumeter->f_pixbuf = gdk_pixbuf_new_from_data(f_drawbuf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w*3, free_drawbuf, NULL); + vumeter->b_pixbuf = gdk_pixbuf_new_from_data(b_drawbuf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w*3, free_drawbuf, NULL); +} + +static void gtk_vu_meter_size_request (GtkWidget *widget, GtkRequisition *requisition) +{ + GtkVuMeter *vumeter; + + g_return_if_fail (GTK_IS_VU_METER (widget)); + g_return_if_fail (requisition != NULL); + + vumeter = GTK_VU_METER (widget); + + if (vumeter->vertical == TRUE) { + requisition->width = VERTICAL_VUMETER_WIDTH; + requisition->height = MIN_VERTICAL_VUMETER_HEIGHT; + } else { + requisition->width = MIN_HORIZONTAL_VUMETER_WIDTH; + requisition->height = HORIZONTAL_VUMETER_HEIGHT; + } +} + +static void gtk_vu_meter_size_allocate (GtkWidget *widget, GtkAllocation *allocation) +{ + GtkVuMeter *vumeter; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_VU_METER (widget)); + g_return_if_fail (allocation != NULL); + + widget->allocation = *allocation; + vumeter = GTK_VU_METER (widget); + + if (GTK_WIDGET_REALIZED (widget)) { + if (vumeter->vertical == TRUE) { /* veritcal */ + gdk_window_move_resize (widget->window, allocation->x, allocation->y, + VERTICAL_VUMETER_WIDTH, MAX(allocation->height, MIN_VERTICAL_VUMETER_HEIGHT)); + } else { /* horizontal */ + gdk_window_move_resize (widget->window, allocation->x, allocation->y, + MAX(allocation->width, MIN_HORIZONTAL_VUMETER_WIDTH), HORIZONTAL_VUMETER_HEIGHT); + } + /* Fix the colours */ + gtk_vu_meter_setup_colors (vumeter); + } +} + +static void free_drawbuf(guchar *pixels, gpointer data) { + g_free(pixels); +} + +static gboolean gtk_vu_meter_expose (GtkWidget *vumeter, GdkEventExpose *event) { + //gdk_pixbuf_render_to_drawable(pixbuf, dbuf_pixmap, app->style->fg_gc[GTK_STATE_NORMAL], 0, 0, 0, 0, WIDTH, HEIGHT, GDK_RGB_DITHER_NORMAL, 0, 0); + cairo_t *cr; + gint draw_level = gtk_vu_meter_sound_level_to_draw_level(GTK_VU_METER(vumeter)); + + cr = gdk_cairo_create (vumeter->window); + + // set a clip region for the expose event + cairo_rectangle (cr,event->area.x, event->area.y, event->area.width, event->area.height); + cairo_clip(cr); + + // Paint from the stored gradient + gdk_cairo_set_source_pixbuf(cr, GTK_VU_METER(vumeter)->b_pixbuf,0,0); + cairo_paint(cr); + + // set a clip region for the expose event + if (GTK_VU_METER(vumeter)->vertical==TRUE) { + cairo_rectangle (cr,event->area.x, event->area.y+draw_level, event->area.width, event->area.height-draw_level); + } else { + //TODO + cairo_rectangle (cr,event->area.x, event->area.y, event->area.width, 12/*event->area.height*/); + } + cairo_clip(cr); + + // Paint from the stored gradient + gdk_cairo_set_source_pixbuf(cr, GTK_VU_METER(vumeter)->f_pixbuf,0,0); + cairo_paint(cr); + + cairo_destroy(cr); + + return FALSE; +} + +static gint gtk_vu_meter_sound_level_to_draw_level (GtkVuMeter *vumeter) { + gint draw_level; + gdouble level, min, max, height; + + level = (gdouble)vumeter->level; + min = (gdouble)vumeter->min; + max = (gdouble)vumeter->max; + height = (gdouble)vumeter->colors; + + draw_level = (1.0 - (level - min)/(max - min)) * height; + + //printf("1.0 - (%lf - %lf)/(%lf - %lf)) * %lf => %i\n", level, min, max, min, height, draw_level); + + return draw_level; +} + +GtkWidget * gtk_vu_meter_new (gboolean vertical) { + GtkWidget *vumeter = g_object_new (GTK_TYPE_VU_METER, NULL); + GTK_VU_METER(vumeter)->vertical=vertical; + GTK_VU_METER(vumeter)->level=0; + GTK_VU_METER(vumeter)->min=-32767; + GTK_VU_METER(vumeter)->max=32767; +} + + +void gtk_vu_meter_set_min_max (GtkVuMeter *vumeter, gint min, gint max) +{ + g_return_if_fail (vumeter != NULL); + + vumeter->max = MAX(max, min); + vumeter->min = MIN(min, max); + if (vumeter->max == vumeter->min) { + vumeter->max++; + } + vumeter->level = CLAMP (vumeter->level, vumeter->min, vumeter->max); + gtk_widget_queue_draw (GTK_WIDGET(vumeter)); +} + +void gtk_vu_meter_set_level(GtkVuMeter *vumeter, gint level) +{ + g_return_if_fail (vumeter != NULL); + + vumeter->level = CLAMP (level, vumeter->min, vumeter->max); + gtk_widget_queue_draw (GTK_WIDGET(vumeter)); +} + diff --git a/tests/test5/gtkvumeter.h b/tests/test5/gtkvumeter.h new file mode 100644 index 0000000..ec7ee67 --- /dev/null +++ b/tests/test5/gtkvumeter.h @@ -0,0 +1,39 @@ +#ifndef GTKVUMETER_H +#define GTKVUMETER_H +#include <gtk/gtk.h> + +#define GTK_TYPE_VU_METER (gtk_vu_meter_get_type ()) +#define GTK_VU_METER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_VU_METER, GtkVuMeter)) +#define GTK_VU_METER_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GTK_VU_METER, GtkVuMeterClass)) +#define GTK_IS_VU_METER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_VU_METER)) +#define GTK_IS_VU_METER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GTK_TYPE_VU_METER)) +#define GTK_VU_METER_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_VU_METER, GtkVuMeterClass)) + +typedef struct _GtkVuMeter GtkVuMeter; +typedef struct _GtkVuMeterClass GtkVuMeterClass; + +struct _GtkVuMeter { + GtkDrawingArea parent; + + /* private */ + gboolean vertical; + gint level, min, max; + + gint f_gradient_key_count, b_gradient_key_count; + GdkColor *f_gradient_keys, *b_gradient_keys; + + gint colors; + GdkPixbuf *f_pixbuf, *b_pixbuf; +}; + +struct _GtkVuMeterClass { + GtkDrawingAreaClass parent_class; +}; + + +GtkWidget * gtk_vu_meter_new (gboolean vertical); +void gtk_vu_meter_set_gradient (GtkVuMeter *vumeter, gint f_gradient_key_count, GdkColor *f_gradient_keys, gint b_gradient_key_count, GdkColor *b_gradient_keys); +void gtk_vu_meter_set_min_max (GtkVuMeter *vumeter, gint min, gint max); +void gtk_vu_meter_set_level(GtkVuMeter *vumeter, gint level); + +#endif /*GTKVUMETER_H*/ diff --git a/tests/test5/old/test5.c b/tests/test5/old/test5.c new file mode 100644 index 0000000..ae9b15f --- /dev/null +++ b/tests/test5/old/test5.c @@ -0,0 +1,187 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <gtk/gtk.h> + +#include <pulse/pulseaudio.h> +#include <pulse/glib-mainloop.h> + +#define APP_TITLE "Test 5 lpo" +#define BUFSIZE 1024 + +pa_context *context; + +void create_stream(); + +static void stream_state_callback(pa_stream *s, void *unused) { + switch (pa_stream_get_state(s)) { + case PA_STREAM_UNCONNECTED: + case PA_STREAM_CREATING: + break; + + case PA_STREAM_READY: + printf("PA_STREAM_READY\n"); +/* + g_assert(!mainWindow); + mainWindow = new MainWindow(*pa_stream_get_channel_map(s), device_name, device_description); + + g_timeout_add(100, latency_func, NULL); + pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_info_callback, NULL)); +*/ + break; + + case PA_STREAM_FAILED: + printf("PA_STREAM_FAILED\n"); + break; + + case PA_STREAM_TERMINATED: + printf("PA_STREAM_TERMINATED\n"); + //Gtk::Main::quit(); + } +} + +static void context_get_source_info_callback(pa_context *c, const pa_source_info *si, int is_last, void *unused) { + printf("context_get_source_info_callback\n"); + + if (is_last < 0) { + printf("Failed to get source information"); + return; + } + + if (!si) + return; + + create_stream(si->name, si->description, si->sample_spec, si->channel_map); +} + +static void context_get_sink_info_callback(pa_context *c, const pa_sink_info *si, int is_last, void *unused) { + printf("context_get_sink_info_callback\n"); + if (is_last < 0) { + printf("Failed to get sink information"); + return; + } + + if (!si) + return; + + create_stream(si->monitor_source_name, si->description, si->sample_spec, si->channel_map); +} + + +static void stream_read_callback(pa_stream *s, size_t l, void *unused) { + const void *p; + + if (pa_stream_peek(s, &p, &l) < 0) { + printf("pa_stream_peek() failed: %s", pa_strerror(pa_context_errno(context))); + return; + } + + printf("%f, %i\n", *((const float*)p), l/sizeof(float)); + + pa_stream_drop(s); +} + +static void context_state_callback(pa_context *c, void *unused) { + switch (pa_context_get_state(c)) { + case PA_CONTEXT_UNCONNECTED: + printf("PA_CONTEXT_UNCONNECTED\n"); + break; + case PA_CONTEXT_CONNECTING: + printf("PA_CONTEXT_CONNECTING\n"); + break; + case PA_CONTEXT_AUTHORIZING: + printf("PA_CONTEXT_AUTHORIZING\n"); + break; + case PA_CONTEXT_SETTING_NAME: + printf("PA_CONTEXT_SETTING_NAME\n"); + break; + + case PA_CONTEXT_READY: + printf("PA_CONTEXT_READY\n"); + g_assert(!stream); + + //if (device_name && mode == RECORD) + //pa_operation_unref(pa_context_get_source_info_by_name(c, device_name, context_get_source_info_callback, NULL)); + /*else if (device_name && mode == PLAYBACK) + pa_operation_unref(pa_context_get_sink_info_by_name(c, device_name, context_get_sink_info_callback, NULL)); + else + pa_operation_unref(pa_context_get_server_info(c, context_get_server_info_callback, NULL)); + */ + break; + + case PA_CONTEXT_FAILED: + printf("PA_CONTEXT_FAILED\n"); + break; + + case PA_CONTEXT_TERMINATED: + printf("PA_CONTEXT_TERMINATED\n"); + break; + } +} + +void create_stream(const char *name, const char *description, const pa_sample_spec *ss, const pa_channel_map *cmap) { + /* The sample type to use */ + static const pa_sample_spec nss = { + .format = PA_SAMPLE_S16LE, + .rate = 44100, + .channels = 1 + }; + + pa_stream *stream=NULL; + char t[256]; +/* + g_free(device_name); + device_name = g_strdup(name); + g_free(device_description); + device_description = g_strdup(description); +*/ + + printf("Using sample format: %s", pa_sample_spec_snprint(t, sizeof(t), &nss)); + printf("Using channel map: %s", pa_channel_map_snprint(t, sizeof(t), cmap)); + + stream = pa_stream_new(context, APP_TITLE, &nss, cmap); + pa_stream_set_state_callback(stream, stream_state_callback, NULL); + pa_stream_set_read_callback(stream, stream_read_callback, NULL); + pa_stream_connect_record(stream, name, NULL, (enum pa_stream_flags) 0); +} + + +int main(int argc, char*argv[]) { + int res, retval; +/* + int error; + int i,j; + float sum; + g_thread_init(NULL); + gdk_threads_init(); + gdk_threads_enter(); + gtk_init (&argc, &argv); +*/ + +/* pa_glib_mainloop *m; + m = pa_glib_mainloop_new(g_main_context_default()); g_assert(m); + context = pa_context_new(pa_glib_mainloop_get_api(m), APP_TITLE); g_assert(context); +*/ + pa_mainloop *m; + m=pa_mainloop_new(); g_assert(m); + context = pa_context_new(pa_mainloop_get_api(m), APP_TITLE); g_assert(context); + + pa_context_set_state_callback(context, context_state_callback, NULL); + pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); + + res=pa_mainloop_run(m,&retval); + g_assert(res==0); + pa_mainloop_free(m); + +// gtk_main (); +// gdk_threads_leave(); + + return 0; + +} diff --git a/tests/test5/test5.c b/tests/test5/test5.c index 373efb0..33ec53d 100644 --- a/tests/test5/test5.c +++ b/tests/test5/test5.c @@ -1,176 +1,57 @@ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - #include <gtk/gtk.h> +#include <stdlib.h> +#include <pthread.h> +#include "gtkvumeter.h" +#include "win_main.h" +#include "compute.h" +#include "capture.h" + +gint *audio_vumeter_val, *light_h, *light_s, *light_v, *light_r, *light_g, *light_b; + +int main (int argc, char **argv) { + GtkWidget *mainwin; + gint vals_for_vumeters[7]={0,0,0,0,0,0,0}; //sound,h,s,v,r,g,b + //Some handy references to the previous array items to make things clear whenever possible + audio_vumeter_val=vals_for_vumeters+0; + light_h=vals_for_vumeters+1; + light_s=vals_for_vumeters+2; + light_v=vals_for_vumeters+3; + light_r=vals_for_vumeters+4; + light_v=vals_for_vumeters+5; + light_b=vals_for_vumeters+6; + + pthread_t audio_analyzer; + + g_thread_init(NULL); + gdk_threads_init(); + gdk_threads_enter(); + gtk_init (&argc, &argv); + + mainwin=win_main_build(); + gtk_widget_show_all (mainwin); + + pthread_create (&audio_analyzer, (void *)NULL, (void *)audio_thread, (void *)vals_for_vumeters); + g_timeout_add (10, win_main_update_vumeters, (gpointer)vals_for_vumeters); + + gtk_main (); + gdk_threads_leave(); -#include <pulse/pulseaudio.h> -#include <pulse/glib-mainloop.h> - -#define APP_TITLE "Test 5 lpo" -#define BUFSIZE 1024 - -pa_context *context; - -void create_stream(); - -static void stream_state_callback(pa_stream *s, void *unused) { - switch (pa_stream_get_state(s)) { - case PA_STREAM_UNCONNECTED: - case PA_STREAM_CREATING: - break; - - case PA_STREAM_READY: - printf("PA_STREAM_READY\n"); -/* - g_assert(!mainWindow); - mainWindow = new MainWindow(*pa_stream_get_channel_map(s), device_name, device_description); - - g_timeout_add(100, latency_func, NULL); - pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_info_callback, NULL)); -*/ - break; - - case PA_STREAM_FAILED: - printf("PA_STREAM_FAILED\n"); - break; - - case PA_STREAM_TERMINATED: - printf("PA_STREAM_TERMINATED\n"); - //Gtk::Main::quit(); - } -} - -static void context_get_source_info_callback(pa_context *c, const pa_source_info *si, int is_last, void *unused) { - printf("context_get_source_info_callback\n"); - - if (is_last < 0) { - printf("Failed to get source information"); - return; - } - - if (!si) - return; - - create_stream(si->name, si->description, si->sample_spec, si->channel_map); -} - -static void context_get_sink_info_callback(pa_context *c, const pa_sink_info *si, int is_last, void *unused) { - printf("context_get_sink_info_callback\n"); - if (is_last < 0) { - printf("Failed to get sink information"); - return; - } - - if (!si) - return; - - create_stream(si->monitor_source_name, si->description, si->sample_spec, si->channel_map); -} - - -static void stream_read_callback(pa_stream *s, size_t l, void *unused) { - const void *p; - - if (pa_stream_peek(s, &p, &l) < 0) { - printf("pa_stream_peek() failed: %s", pa_strerror(pa_context_errno(context))); - return; - } - - printf("%f, %i\n", *((const float*)p), l/sizeof(float)); - - pa_stream_drop(s); + return 0; } -static void context_state_callback(pa_context *c, void *unused) { - switch (pa_context_get_state(c)) { - case PA_CONTEXT_UNCONNECTED: - printf("PA_CONTEXT_UNCONNECTED\n"); - break; - case PA_CONTEXT_CONNECTING: - printf("PA_CONTEXT_CONNECTING\n"); - break; - case PA_CONTEXT_AUTHORIZING: - printf("PA_CONTEXT_AUTHORIZING\n"); - break; - case PA_CONTEXT_SETTING_NAME: - printf("PA_CONTEXT_SETTING_NAME\n"); - break; +void process(gint sound_level, void *userdata) { - case PA_CONTEXT_READY: - printf("PA_CONTEXT_READY\n"); - //g_assert(!stream); + // Dummy code for audio capture + *audio_vumeter_val=sound_level; - //if (device_name && mode == RECORD) - //pa_operation_unref(pa_context_get_source_info_by_name(c, device_name, context_get_source_info_callback, NULL)); - /*else if (device_name && mode == PLAYBACK) - pa_operation_unref(pa_context_get_sink_info_by_name(c, device_name, context_get_sink_info_callback, NULL)); - else - pa_operation_unref(pa_context_get_server_info(c, context_get_server_info_callback, NULL)); - */ - break; + // Transfert Function + audio2hsv_1(*audio_vumeter_val,light_h,light_s,light_v); - case PA_CONTEXT_FAILED: - printf("PA_CONTEXT_FAILED\n"); - break; + // Conversion + hsv2rgb(*light_h,*light_s,*light_v,light_r,light_g,light_b); + + // Send to DMX + //TODO - case PA_CONTEXT_TERMINATED: - printf("PA_CONTEXT_TERMINATED\n"); - break; - } } -void create_stream(const char *name, const char *description, const pa_sample_spec *ss, const pa_channel_map *cmap) { - /* The sample type to use */ - static const pa_sample_spec nss = { - .format = PA_SAMPLE_S16LE, - .rate = 44100, - .channels = 1 - }; - - pa_stream *stream=NULL; - char t[256]; -/* - g_free(device_name); - device_name = g_strdup(name); - g_free(device_description); - device_description = g_strdup(description); -*/ - - printf("Using sample format: %s", pa_sample_spec_snprint(t, sizeof(t), &nss)); - printf("Using channel map: %s", pa_channel_map_snprint(t, sizeof(t), cmap)); - - stream = pa_stream_new(context, APP_TITLE, &nss, cmap); - pa_stream_set_state_callback(stream, stream_state_callback, NULL); - pa_stream_set_read_callback(stream, stream_read_callback, NULL); - pa_stream_connect_record(stream, name, NULL, (enum pa_stream_flags) 0); -} - - -int main(int argc, char*argv[]) { -/* - int ret = 1; - int error; - int i,j; - float sum; -*/ - pa_glib_mainloop *m; - - m = pa_glib_mainloop_new(g_main_context_default()); -// g_assert(m); - - context = pa_context_new(pa_glib_mainloop_get_api(m), APP_TITLE); -// g_assert(context); - - pa_context_set_state_callback(context, context_state_callback, NULL); - pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); - - sleep(60); - - return 0; -} diff --git a/tests/test5/win_main.c b/tests/test5/win_main.c new file mode 100644 index 0000000..4229c40 --- /dev/null +++ b/tests/test5/win_main.c @@ -0,0 +1,65 @@ +#include "win_main.h" +#include "gtkvumeter.h" + +GtkWidget *vumeter_sound, *vumeter_r, *vumeter_g, *vumeter_b, *vumeter_h, *vumeter_s, *vumeter_v; + +GtkWidget *win_main_build() { + GtkWidget *win, *hbox1; + + GdkColor f_gradient_red[2] = {{0,65535,0,0},{0,0,0,0}}; + GdkColor b_gradient_red[2] = {{0,49151,0,0},{0,0,0,0}}; + GdkColor f_gradient_green[2] = {{0,0,65535,0},{0,0,0,0}}; + GdkColor b_gradient_green[2] = {{0,0,49151,0},{0,0,0,0}}; + GdkColor f_gradient_blue[2] = {{0,0,0,65535},{0,0,0,0}}; + GdkColor b_gradient_blue[2] = {{0,0,0,49151},{0,0,0,0}}; + GdkColor f_gradient_hue[7] = {{0,65535,0,0},{0,65535,0,65535},{0,0,0,65535},{0,0,65535,65535},{0,0,65535,0},{0,65535,65535,0},{0,65535,0,0}}; + GdkColor b_gradient_hue[7] = {{0,49151,0,0},{0,49151,0,49151},{0,0,0,49151},{0,0,49151,49151},{0,0,49151,0},{0,49151,49151,0},{0,49151,0,0}}; + + win = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + hbox1 = gtk_hbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(win), hbox1); + gtk_container_set_border_width(GTK_CONTAINER(hbox1), 5); + +//TODO : gtk_vumeter_set_min_max (GTK_VU_METER(vumeter), min, max); + vumeter_sound = gtk_vu_meter_new (TRUE); + gtk_box_pack_start(GTK_BOX(hbox1), vumeter_sound, FALSE, FALSE, 0); + + vumeter_h = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_h), 7, f_gradient_hue, 7, b_gradient_hue); + gtk_box_pack_start(GTK_BOX(hbox1), vumeter_h, FALSE, FALSE, 0); + + vumeter_s = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_s), 2, f_gradient_red, 2, b_gradient_red); + gtk_box_pack_start(GTK_BOX(hbox1), vumeter_s, FALSE, FALSE, 0); + + vumeter_v = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_v), 2, f_gradient_red, 2, b_gradient_red); + gtk_box_pack_start(GTK_BOX(hbox1), vumeter_v, FALSE, FALSE, 0); + + + vumeter_r = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_r), 2, f_gradient_red, 2, b_gradient_red); + gtk_box_pack_start(GTK_BOX(hbox1), vumeter_r, FALSE, FALSE, 0); + + vumeter_g = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_g), 2, f_gradient_green, 2, b_gradient_green); + gtk_box_pack_start(GTK_BOX(hbox1), vumeter_g, FALSE, FALSE, 0); + + vumeter_b = gtk_vu_meter_new (TRUE); + gtk_vu_meter_set_gradient(GTK_VU_METER(vumeter_b), 2, f_gradient_blue, 2, b_gradient_blue); + gtk_box_pack_start(GTK_BOX(hbox1), vumeter_b, FALSE, FALSE, 0); + + return win; +} + +void win_main_update_vumeters(void *vals) { + gtk_vu_meter_set_level(GTK_VU_METER(vumeter_sound), ((gint*)vals)[0]); + gtk_vu_meter_set_level(GTK_VU_METER(vumeter_h), ((gint*)vals)[1]); + gtk_vu_meter_set_level(GTK_VU_METER(vumeter_s), ((gint*)vals)[2]); + gtk_vu_meter_set_level(GTK_VU_METER(vumeter_v), ((gint*)vals)[3]); + gtk_vu_meter_set_level(GTK_VU_METER(vumeter_r), ((gint*)vals)[4]); + gtk_vu_meter_set_level(GTK_VU_METER(vumeter_g), ((gint*)vals)[5]); + gtk_vu_meter_set_level(GTK_VU_METER(vumeter_b), ((gint*)vals)[6]); +} + diff --git a/tests/test5/win_main.h b/tests/test5/win_main.h new file mode 100644 index 0000000..4f0ee1d --- /dev/null +++ b/tests/test5/win_main.h @@ -0,0 +1,9 @@ +#ifndef WIN_MAIN_H +#define WIN_MAIN_H +#include <gtk/gtk.h> + +GtkWidget *win_main_build(); +void win_main_update_vumeters(void *vals); + +#endif + |