>From 2f087041d6edbd5c445f3bcfd626733be03fe16e Mon Sep 17 00:00:00 2001
From: Alexander Varnin
Date: Mon, 14 Mar 2011 20:42:33 +0300
Subject: [PATCH] Pulseaudio support based on Samo Pogacnik patch.
---
configure.ac | 2 +-
src/dsp.c | 217 +++++++++++++++++++++++++++++++++++++++++++----------
src/dsp.h | 13 ++-
src/globals.h | 5 +-
src/gtkoptions.c | 87 ++++++++++++++++++----
src/metro.c | 218 +++++++++++++++++++++++++++++++++++------------------
src/metro.h | 12 ++--
src/options.h | 5 +-
src/threadtalk.h | 5 +-
9 files changed, 417 insertions(+), 147 deletions(-)
diff --git a/configure.ac b/configure.ac
index db9b643..152b4b9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,7 +37,7 @@ AC_PROG_GCC_TRADITIONAL
AC_FUNC_MALLOC
AC_CHECK_FUNCS([floor strdup setlocale strtol])
-PKG_CHECK_MODULES(DEPS, gtk+-2.0 gthread-2.0)
+PKG_CHECK_MODULES(DEPS, gtk+-2.0 gthread-2.0 libpulse-simple)
# samplerate
#AC_ARG_WITH([alsa],
diff --git a/src/dsp.c b/src/dsp.c
index dde4a87..4bfe36d 100644
--- a/src/dsp.c
+++ b/src/dsp.c
@@ -54,6 +54,10 @@
#include
#endif
+#include
+#include
+#include
+
/* own headers */
#include "g711.h"
#include "globals.h"
@@ -110,7 +114,7 @@ static format_t formats[] = {
*/
dsp_t* dsp_new(comm_t* comm) {
dsp_t* result;
-
+
result = (dsp_t*) g_malloc0(sizeof(dsp_t));
result->dspfd = -1;
comm_server_register(comm);
@@ -136,7 +140,7 @@ void dsp_delete(dsp_t* dsp) {
static void encode_sample(short sample, int format, unsigned char* dest)
{
static int error = 0;
-
+
switch (format) {
case AFMT_MU_LAW:
*dest = linear2ulaw(sample);
@@ -202,7 +206,7 @@ static int limit_int(int x, int limit) {
* from_channels: number of channels in
* dsp: the dsp_t structure holding rate, channels, samplesize
* and format of the initialized dsp
- *
+ *
* output:
* to: the pointer to the allocated data, ready for playback
* return value: number of bytes generated, -1 on error
@@ -238,12 +242,12 @@ static int generate_data(short* from,
double dummy;
double frac = modf(leftbound, &dummy);
double weight;
-
+
if (rightbound - leftbound < 1)
weight = rightbound - leftbound;
else
weight = 1.0;
-
+
for (j = 0; j < from_channels; j++) {
mixdown += weight * (
(1.0 - frac) * from[from_channels * index + j] +
@@ -256,7 +260,7 @@ static int generate_data(short* from,
}
for (j = 0; j < dsp->channels; j++) { /* for each channel */
double sample;
-
+
if (dsp->channels != from_channels) {
sample = mixdown;
} else {
@@ -269,12 +273,12 @@ static int generate_data(short* from,
double dummy;
double frac = modf(leftbound, &dummy);
double weight;
-
+
if (rightbound - leftbound < 1)
weight = rightbound - leftbound;
else
weight = 1.0;
-
+
sample += weight * (
(1.0 - frac) * from[from_channels * index + j] +
frac * from[from_channels * limit_int(index + 1, from_size) + j]);
@@ -326,7 +330,7 @@ int generate_sine(int samplefreq, double sinfreq, double sigdur, double fadedur,
(-cos((double)(size - i) / (samplefreq * sigdur) * 2 * M_PI) + 1) * 0.5;
s[i] = sample * scale;
}
-
+
*samples = s;
return size;
}
@@ -361,15 +365,15 @@ int sndfile_get_samples(const char* filename,
}
if (!sfinfo.seekable)
return -1;
-
+
frames = sfinfo.frames;
*rate = sfinfo.samplerate;
*channels = sfinfo.channels ;
*samples = (short*) g_malloc(frames * sizeof(short) * sfinfo.channels);
-
+
sf_readf_short(sf, *samples, frames);
-
+
sf_close(sf);
return frames;
}
@@ -409,7 +413,7 @@ static int init_sample(dsp_t* dsp) {
return 0;
}
-
+
/*
* allocates and initializes dsp->tickdata{0,1,2}
* and initializes dsp->td{0,1,2}_size
@@ -422,7 +426,7 @@ static int prepare_buffers(dsp_t* dsp) {
int i;
int attack = 0;
-
+
/* generate single ticks */
if ((dsp->td0_size = generate_data(dsp->frames, dsp->number_of_frames,
dsp->rate_in, dsp->channels_in, dsp, &dsp->tickdata0)) == -1)
@@ -432,7 +436,7 @@ static int prepare_buffers(dsp_t* dsp) {
/* generate first tick */
if ((dsp->td1_size = generate_data(dsp->frames, dsp->number_of_frames,
- dsp->rate_in * 2, dsp->channels_in, dsp, &dsp->tickdata1)) == -1)
+ dsp->rate_in / 2, dsp->channels_in, dsp, &dsp->tickdata1)) == -1)
{
return -1;
}
@@ -447,19 +451,19 @@ static int prepare_buffers(dsp_t* dsp) {
if (attack < dsp->number_of_frames / 3) {
unsigned char* newdata;
int offset;
-
+
offset = attack / 2 * dsp->channels * dsp->samplesize / 8;
if ((newdata = realloc(dsp->tickdata1, dsp->td1_size + offset))) {
int modul = dsp->channels * dsp->samplesize / 8;
int i;
-
+
dsp->tickdata1 = newdata;
-
+
for (i = dsp->td1_size - 1; i >= 0; i--)
dsp->tickdata1[i + offset] = dsp->tickdata1[i];
for (i = 0; i < offset; i++)
dsp->tickdata1[i] = dsp->silence[i % modul];
-
+
dsp->td1_size += offset;
if (debug)
@@ -483,6 +487,62 @@ static int prepare_buffers(dsp_t* dsp) {
}
/*
+ * Opens pulseaudio connection
+ *
+ * returns 0 on success, -1 otherwise
+ */
+static int pulse_open(dsp_t *dsp)
+{
+ static int debug_todo = 1;
+ /* The Sample format to use */
+ static const pa_sample_spec pulse_format = {
+ .format = PA_SAMPLE_S16LE, /* DEFAULT_FORMAT */
+ .rate = DEFAULT_RATE,
+ .channels = DEFAULT_CHANNELS
+ };
+ int error;
+ unsigned int format_index;
+
+ dsp->pas = NULL;
+ /* Create a new playback stream */
+ if (!(dsp->pas = pa_simple_new(NULL, "GTick metronome", PA_STREAM_PLAYBACK, NULL, "gtick", &pulse_format, NULL, NULL, &error))) {
+ fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
+ return -1;
+ }
+
+ dsp->format = DEFAULT_FORMAT;
+ for (format_index = 0;
+ formats[format_index].format != 0 &&
+ formats[format_index].format != dsp->format;
+ format_index++);
+
+ if (debug && debug_todo) {
+ g_print("pulse_open: Used sample format: %s (%s)\n",
+ formats[format_index].name, formats[format_index].description);
+ }
+
+ dsp->rate = DEFAULT_RATE; /* requested default */
+ if (debug && debug_todo) {
+ g_print("pulse_open: Sampling rate = %d\n", dsp->rate);
+ }
+
+ dsp->channels = DEFAULT_CHANNELS;
+ if (debug && debug_todo) {
+ g_print("pulse_open: Number of channels = %d\n", dsp->channels);
+ }
+
+ dsp->samplesize = formats[format_index].samplesize;
+ dsp->fragmentsize = dsp->rate / 10 /*0.1s fragment time*/ * dsp->channels * dsp->samplesize / 8;
+
+ if (debug && debug_todo)
+ g_print ("pulse_open: fragment size = %d\n", dsp->fragmentsize);
+
+ dsp->fragment = g_malloc(dsp->fragmentsize);
+
+ return 0;
+}
+
+/*
* Opens sound device specified in dsp
*
* returns 0 on success, -1 otherwise
@@ -492,14 +552,16 @@ int dsp_open(dsp_t* dsp) {
unsigned int format_index;
int requested_format = DEFAULT_FORMAT;
audio_buf_info info;
-
+
dsp->fragmentsize = 0x7fff0008; /* at least request fragment size 2^8=256 */
/* = minimum recommended size */
if (debug && debug_todo)
g_print ("dsp_open: Initialising %s ...\n", dsp->devicename);
/* Initialise sound device */
- if ((dsp->dspfd = open(dsp->devicename, O_WRONLY)) == -1)
+ if(!strcmp(dsp->soundsystem, ""))
+ return pulse_open(dsp);
+ else if ((dsp->dspfd = open(dsp->devicename, O_WRONLY)) == -1)
{
perror(dsp->devicename);
return -1;
@@ -514,7 +576,7 @@ int dsp_open(dsp_t* dsp) {
if (debug && debug_todo) {
unsigned int i;
int mask;
-
+
if (ioctl(dsp->dspfd, SNDCTL_DSP_GETFMTS, &mask) == -1) {
perror("SNDCTL_DSP_GETFMTS");
}
@@ -532,19 +594,19 @@ int dsp_open(dsp_t* dsp) {
perror ("SNDCTL_DSP_SETFMT");
return -1;
}
-
+
for (format_index = 0;
formats[format_index].format != 0 &&
formats[format_index].format != dsp->format;
format_index++);
-
+
if (debug && debug_todo) {
g_print("dsp_open: Used sample format: %s (%s)\n",
formats[format_index].name, formats[format_index].description);
}
dsp->samplesize = formats[format_index].samplesize;
-
+
/* Set dsp to default: mono */
dsp->channels = DEFAULT_CHANNELS;
if (ioctl (dsp->dspfd, SNDCTL_DSP_CHANNELS, &dsp->channels) == -1) {
@@ -554,7 +616,7 @@ int dsp_open(dsp_t* dsp) {
if (debug && debug_todo) {
g_print("dsp_open: Number of channels = %d\n", dsp->channels);
}
-
+
/* Set the DSP rate (in Hz) */
dsp->rate = DEFAULT_RATE; /* requested default */
if (ioctl (dsp->dspfd, SNDCTL_DSP_SPEED, &dsp->rate) == -1) {
@@ -585,7 +647,7 @@ int dsp_open(dsp_t* dsp) {
if (debug && debug_todo)
g_print("dsp_open: Total number of fragments in DSP buffer = %d.\n",
dsp->fragstotal);
-
+
debug_todo = 0;
return 0;
}
@@ -595,7 +657,7 @@ int dsp_open(dsp_t* dsp) {
*/
void dsp_close(dsp_t* dsp) {
static int debug_todo = 1;
-
+
if (debug && debug_todo)
g_print ("dsp_close: Closing sound device ...\n");
if (dsp->dspfd != -1) {
@@ -610,6 +672,9 @@ void dsp_close(dsp_t* dsp) {
}
}
+ if (dsp->pas)
+ pa_simple_free(dsp->pas);
+
debug_todo = 0;
}
@@ -621,16 +686,16 @@ void dsp_close(dsp_t* dsp) {
int dsp_init(dsp_t* dsp)
{
short silencelevel = 0;
-
+
if (dsp_open(dsp) == -1)
return -1;
-
+
dsp->frames = NULL;
dsp->silence = NULL;
dsp->tickdata0 = NULL;
dsp->tickdata1 = NULL;
dsp->tickdata2 = NULL;
-
+
/* silence */
generate_data(&silencelevel, 1, dsp->rate, 1, dsp, &dsp->silence);
@@ -658,7 +723,7 @@ void dsp_deinit(dsp_t* dsp)
{
dsp->running = 0;
dsp_close(dsp);
-
+
if (dsp->tickdata0) {
g_free(dsp->tickdata0);
dsp->tickdata0 = NULL;
@@ -686,7 +751,7 @@ void dsp_deinit(dsp_t* dsp)
*/
static void wrap_position(dsp_t* dsp, int ticklen) {
unsigned int* reply;
-
+
if (dsp->tickpos >= ticklen) {
dsp->tickpos = 0;
dsp->cyclepos++;
@@ -701,6 +766,67 @@ static void wrap_position(dsp_t* dsp, int ticklen) {
}
/*
+ * Feed pulseaudio stream with next samples
+ */
+gboolean pulse_feed(dsp_t* dsp)
+{
+ int ticklen = rint(dsp->rate / dsp->frequency) *
+ dsp->channels * dsp->samplesize / 8;
+ unsigned char *the_data; /* pointer to actual buffer */
+ int data_size; /* size of actual buffer */
+
+ int fragments; /* number of fragments yet to write */
+ int error;
+ fragments = 1;
+
+ wrap_position(dsp, ticklen);
+
+ /* write as many fragments as possible */
+ while (fragments > 0) {
+ int i;
+
+ /* generate fragment */
+ for (i = 0; i < dsp->fragmentsize; i++) {
+ int index;
+
+ if (dsp->meter == 1) { /* single ticks */
+ the_data = dsp->tickdata0;
+ data_size = dsp->td0_size;
+ } else if (dsp->accents[dsp->cyclepos]) { /* accentuate 1st tick */
+ the_data = dsp->tickdata1;
+ data_size = dsp->td1_size;
+ } else { /* sound of 2nd tick */
+ the_data = dsp->tickdata2;
+ data_size = dsp->td2_size;
+ }
+
+ if ((index = dsp->tickpos) < data_size) { /* tick! */
+ dsp->fragment[i] = the_data[index];
+ } else { /* silence (between ticks) */
+ dsp->fragment[i] =
+ dsp->silence[i % (dsp->samplesize / 8 * dsp->channels)];
+ }
+
+ dsp->tickpos++;
+ wrap_position(dsp, ticklen);
+ }
+
+ if (pa_simple_write(dsp->pas, dsp->fragment, (size_t) dsp->fragmentsize, &error) < 0) {
+ g_print("pulse_feed: pa_simple_write ERROR: %s\n", pa_strerror(error));
+ }
+ fragments--;
+ }
+
+#if 0
+ if (pa_simple_drain(dsp->pas, &error) < 0) {
+ g_print("pulse_feed: pa_simple_drain ERROR: %s\n", pa_strerror(error));
+ }
+#endif
+
+ return 1;
+}
+
+/*
* Feed dsp device with next samples
*
* used as output start and callback
@@ -715,7 +841,7 @@ gboolean dsp_feed(dsp_t* dsp)
int fragments; /* number of fragments yet to write */
int limit; /* number of fragments we want to have filled */
-
+
/* get number of fragments to write to dsp */
if (ioctl(dsp->dspfd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
perror("SNDCTL_DSP_GETOSPACE");
@@ -733,11 +859,11 @@ gboolean dsp_feed(dsp_t* dsp)
/* write as many fragments as possible */
while (fragments > 0) {
int i;
-
+
/* generate fragment */
for (i = 0; i < dsp->fragmentsize; i++) {
int index;
-
+
if (dsp->meter == 1) { /* single ticks */
the_data = dsp->tickdata0;
data_size = dsp->td0_size;
@@ -793,7 +919,7 @@ void dsp_set_volume(dsp_t* dsp, double volume)
free(dsp->tickdata0);
free(dsp->tickdata1);
free(dsp->tickdata2);
-
+
prepare_buffers(dsp);
}
}
@@ -812,12 +938,12 @@ void dsp_main_loop(dsp_t* dsp) {
void* message;
int get_volume = 0; /* flag */
void* reply = NULL;
-
+
while ((message_type = comm_server_try_get_query(dsp->inter_thread_comm,
&message))
!= MESSAGE_TYPE_NO_MESSAGE)
{
-
+
switch (message_type) {
case MESSAGE_TYPE_STOP_SERVER:
repeat_flag = 0;
@@ -830,6 +956,10 @@ void dsp_main_loop(dsp_t* dsp) {
if (dsp->soundname) free(dsp->soundname);
dsp->soundname = (char*) message;
break;
+ case MESSAGE_TYPE_SET_SOUNDSYSTEM:
+ if (dsp->soundsystem) free(dsp->soundsystem);
+ dsp->soundsystem = (char*) message;
+ break;
case MESSAGE_TYPE_SET_METER:
dsp->meter = *((int*) message);
free(message);
@@ -872,7 +1002,7 @@ void dsp_main_loop(dsp_t* dsp) {
if (get_volume) {
double volume = dsp_get_volume(dsp);
-
+
reply = (double*) g_malloc0 (sizeof(double));
*((double*)reply) = volume;
if (*((double*)reply) != -1) {
@@ -884,8 +1014,13 @@ void dsp_main_loop(dsp_t* dsp) {
}
if (dsp->running) { /* metronome running */
- dsp_feed(dsp);
+ if (dsp->dspfd != -1) { /* metronome running */
+ dsp_feed(dsp);
+ } else {
+ pulse_feed(dsp);
+ }
}
+
nanosleep(&requested, &remaining);
}
}
diff --git a/src/dsp.h b/src/dsp.h
index 7567896..e619382 100644
--- a/src/dsp.h
+++ b/src/dsp.h
@@ -1,8 +1,8 @@
-/*
+/*
* DSP interface
*
* This file is part of GTick
- *
+ *
*
* Copyright (c) 1999, Alex Roberts
* Copyright (c) 2003, 2004, 2005, 2006 Roland Stigge
@@ -28,12 +28,17 @@
/* GTK headers */
#include
+#include
+
/* own headers */
#include "threadtalk.h"
typedef struct dsp_t {
char* devicename;
char* soundname;
+ char* soundsystem;
+
+ pa_simple *pas; /* pa simple playback stream */
int dspfd; /* file descriptor */
int fragmentsize; /* fragment size */
@@ -47,7 +52,7 @@ typedef struct dsp_t {
int channels_in; /* number of channels of input data in Hz */
unsigned char* fragment;
-
+
unsigned char* tickdata0; /* raw dsp sample bytes for single tick */
int td0_size; /* length in bytes */
unsigned char* tickdata1; /* raw dsp sample bytes for first tick */
@@ -69,7 +74,7 @@ typedef struct dsp_t {
int running; /* on/off flag */
double volume; /* 0.0 ... 1.0 */
-
+
int sync_flag;
comm_t* inter_thread_comm;
diff --git a/src/globals.h b/src/globals.h
index 1c56b80..836ad0e 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1,8 +1,8 @@
-/*
+/*
* Global definitions
*
* This file is part of GTick
- *
+ *
*
* Copyright (c) 1999, Alex Roberts
* Copyright (c) 2003, 2004, 2005, 2006 Roland Stigge
@@ -43,6 +43,7 @@
#define VOLUME_MIN 0
#define VOLUME_MAX 100
#define MAX_METER 100
+#define DEFAULT_SOUND_SYSTEM ""
#define DEFAULT_SOUND_DEVICE_FILENAME "/dev/dsp"
#define DEFAULT_SAMPLE_FILENAME ""
#define DEFAULT_SPEED 75
diff --git a/src/gtkoptions.c b/src/gtkoptions.c
index ad0d4c4..f46104f 100644
--- a/src/gtkoptions.c
+++ b/src/gtkoptions.c
@@ -18,7 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with GTick; if not, see .
- *
+ *
*/
#include
@@ -84,6 +84,34 @@ sound_button_toggled(GtkToggleButton *togglebutton, options_t* options)
}
static void
+soundsystem_button_toggled(GtkToggleButton *togglebutton, options_t* options)
+{
+ GSList* group;
+ GtkWidget* radio_button;
+ const char* soundsystem;
+
+ /*
+ * Sample filename setup
+ */
+ group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(togglebutton));
+ while (group &&
+ !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(group->data)))
+ {
+ group = group->next;
+ }
+ radio_button = GTK_WIDGET(group->data);
+ soundsystem = g_object_get_data(G_OBJECT(radio_button), "choice");
+ if (strcmp(soundsystem, "")!=0 && strcmp(soundsystem, "")!=0)
+ {
+ fprintf(stderr, "Warning: Unhandled samplename case: \"%s\".\n",
+ (char*) g_object_get_data(G_OBJECT(radio_button), "choice"));
+ soundsystem = "";
+ }
+
+ option_set(options->option_list, "SoundSystem", soundsystem);
+}
+
+static void
sound_device_entry_changed(GtkEntry *entry, options_t* options)
{
const char* sounddevice;
@@ -185,7 +213,7 @@ static void choose_cb(GtkWidget *button) {
GtkWidget* file_selection =
gtk_file_selection_new(_("Please choose a sound file."));
gtk_window_set_modal(GTK_WINDOW(file_selection), TRUE);
-
+
g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(file_selection)->ok_button),
"sample_name_entry",
g_object_get_data(G_OBJECT(button), "sample_name_entry"));
@@ -196,19 +224,19 @@ static void choose_cb(GtkWidget *button) {
"clicked",
G_CALLBACK(choose_cb_store),
NULL);
-
+
/* destroy file selection dialog if ok or cancel button has been clicked */
g_signal_connect_swapped(
GTK_OBJECT(GTK_FILE_SELECTION(file_selection)->ok_button),
"clicked",
- G_CALLBACK(gtk_widget_destroy),
- (gpointer) file_selection);
+ G_CALLBACK(gtk_widget_destroy),
+ (gpointer) file_selection);
g_signal_connect_swapped(
GTK_OBJECT(GTK_FILE_SELECTION(file_selection)->cancel_button),
"clicked",
G_CALLBACK(gtk_widget_destroy),
- (gpointer) file_selection);
-
+ (gpointer) file_selection);
+
gtk_widget_show(file_selection);
}
#endif /* WITH_SNDFILE */
@@ -261,6 +289,7 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) {
GtkWidget* alignment;
GtkSizeGroup* sizegroup;
const char* samplename;
+ const char* soundsystem;
if (!(samplename = option_get(options->option_list,
"SampleFilename", 0, NULL)))
@@ -272,14 +301,14 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) {
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(window)->vbox), 12);
-
+
vbox = gtk_vbox_new(FALSE, 18);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->vbox), vbox);
gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
gtk_widget_show(vbox);
sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
+
/*
* Sound effect setting
*/
@@ -366,7 +395,7 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) {
G_CALLBACK(sound_button_toggled), options);
g_signal_connect(G_OBJECT(entry), "changed",
G_CALLBACK(sample_name_entry_changed), options);
-
+
/* save entry at button to retrieve value in file selection dialog */
g_object_set_data(G_OBJECT(button), "sample_name_entry", entry);
@@ -374,11 +403,11 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) {
G_CALLBACK(choose_cb), options);
#endif /* WITH_SNDFILE */
-
+
/*
* Sound device setting
*/
- frame = gtk_frame_new(_("Sound Device"));
+ frame = gtk_frame_new(_("Sound System"));
label = gtk_frame_get_label_widget(GTK_FRAME(frame));
gtk_label_attr_bold(GTK_LABEL(label));
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
@@ -394,6 +423,34 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) {
gtk_container_add(GTK_CONTAINER(alignment), devicevbox);
gtk_widget_show(devicevbox);
+ if(! (soundsystem = option_get(options->option_list,
+ "SoundSystem", 0, NULL)) )
+ soundsystem = "";
+
+ radiobutton = gtk_radio_button_new_with_label(NULL, _("Pulseaudio"));
+ g_object_set_data(G_OBJECT(radiobutton), "choice", "");
+ if (!strcmp(soundsystem, ""))
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobutton), TRUE);
+ gtk_box_pack_start(GTK_BOX(devicevbox), radiobutton, FALSE, TRUE, 0);
+ gtk_widget_show(radiobutton);
+
+ /* Instant apply */
+ g_signal_connect(G_OBJECT(radiobutton), "toggled",
+ G_CALLBACK(soundsystem_button_toggled), options);
+
+ radiobutton =
+ gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radiobutton),
+ _("OSS"));
+ g_object_set_data(G_OBJECT(radiobutton), "choice", "");
+ if (!strcmp(soundsystem, ""))
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobutton), TRUE);
+ gtk_box_pack_start(GTK_BOX(devicevbox), radiobutton, FALSE, TRUE, 0);
+ gtk_widget_show(radiobutton);
+
+ /* Instant apply */
+ g_signal_connect(G_OBJECT(radiobutton), "toggled",
+ G_CALLBACK(soundsystem_button_toggled), options);
+
hbox = gtk_hbox_new(FALSE, 12);
gtk_box_pack_start(GTK_BOX(devicevbox), hbox, FALSE, TRUE, 0);
gtk_widget_show(hbox);
@@ -452,7 +509,7 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) {
/* Instant apply */
g_signal_connect(G_OBJECT(entry), "changed",
G_CALLBACK(cmd_start_entry_changed), options);
-
+
label = gtk_label_new(_("Execute on stop:"));
gtk_size_group_add_widget(sizegroup, label);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
@@ -508,7 +565,7 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) {
gtk_widget_show(spinbutton);
g_signal_connect(G_OBJECT(spinbutton), "value-changed",
G_CALLBACK(min_bpm_value_changed), options);
-
+
label = gtk_label_new(_("Maximum BPM:"));
gtk_size_group_add_widget(sizegroup, label);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
@@ -525,7 +582,7 @@ GtkWidget* gtk_options_dialog_new(GtkWidget* parent, options_t* options) {
gtk_widget_show(spinbutton);
g_signal_connect(G_OBJECT(spinbutton), "value-changed",
G_CALLBACK(max_bpm_value_changed), options);
-
+
g_signal_connect(G_OBJECT(window), "response",
G_CALLBACK(response_cb), options);
return window;
diff --git a/src/metro.c b/src/metro.c
index 8429026..2611792 100644
--- a/src/metro.c
+++ b/src/metro.c
@@ -1,8 +1,8 @@
-/*
+/*
* Metronome session
*
* This file is part of GTick
- *
+ *
*
* Copyright (c) 1999, Alex Roberts
* Copyright (c) 2005 Marco Tulio Gontijo e Silva
@@ -22,7 +22,7 @@
* along with GTick; if not, see .
*
*/
-
+
#include
/* GNU headers */
@@ -168,7 +168,7 @@ static guint get_name_index_from_speed(int speed) {
while (result < sizeof(speed_names) / sizeof(speed_name_t) &&
(speed_names[result].min_bpm > speed ||
speed_names[result].max_bpm <= speed)) {
-
+
result ++;
}
@@ -204,10 +204,10 @@ static void tap_cb(metro_t* metro)
assert(metro != NULL);
gettimeofday(&thistime, NULL);
-
+
timeval_subtract(&diffval, &thistime, &metro->lasttap);
timediff = diffval.tv_sec + (double)diffval.tv_usec / 1000000.0;
-
+
if (timediff < 10.0) {
gtk_adjustment_set_value(GTK_ADJUSTMENT(metro->speed_adjustment),
round(60.0 / timediff));
@@ -263,14 +263,14 @@ static void set_speed_cb(metro_t *metro)
double* frequency = (double*) g_malloc(sizeof(double));
gint old_index;
gint new_index;
-
+
*frequency = GTK_ADJUSTMENT(metro->speed_adjustment)->value / 60.0;
if (debug)
g_print ("set_speed_cb(): rate=%f bpm\n", *frequency * 60.0);
old_index = (gint) gtk_combo_box_get_active(GTK_COMBO_BOX(metro->speed_name));
new_index = get_name_index_from_speed((int)round(*frequency * 60.0));
-
+
if (new_index != old_index)
gtk_combo_box_set_active(GTK_COMBO_BOX(metro->speed_name), new_index);
@@ -310,7 +310,7 @@ static void accents_changed_cb(metro_t* metro) {
message[i] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
metro->accentbuttons[i]));
}
-
+
comm_client_query(metro->inter_thread_comm, MESSAGE_TYPE_SET_ACCENTS,
message);
}
@@ -319,9 +319,9 @@ static void accents_changed_cb(metro_t* metro) {
* Change state
*/
static void set_state(metro_t* metro, int state) {
-
+
if (state != metro->state) {
-
+
if (metro->state == STATE_RUNNING && state == STATE_IDLE) {
comm_client_query(metro->inter_thread_comm,
MESSAGE_TYPE_STOP_METRONOME, NULL);
@@ -334,7 +334,7 @@ static void set_state(metro_t* metro, int state) {
} else {
fprintf(stderr, "Warning: Unhandled state change.\n");
}
-
+
gtk_statusbar_pop(GTK_STATUSBAR(metro->statusbar),
metro->status_context);
gtk_statusbar_push(GTK_STATUSBAR(metro->statusbar),
@@ -345,7 +345,7 @@ static void set_state(metro_t* metro, int state) {
/* Set Start/Stop label */
g_object_set(metro->start_action, "label",
_(state_data[state].toggle_label), NULL);
-
+
metro->state = state;
}
}
@@ -368,7 +368,7 @@ static gint handle_comm(metro_t* metro) {
break;
case MESSAGE_TYPE_RESPONSE_START_ERROR:
gtk_widget_show(metro->start_error);
-
+
set_state(metro, STATE_IDLE);
break;
default:
@@ -407,7 +407,7 @@ static void toggle_accenttable_cb(GtkToggleAction *action _U_, metro_t *metro) {
*/
static void metro_toggle_cb(GtkToggleAction *action _U_, metro_t *metro) {
int new_state;
-
+
if (metro->state == STATE_IDLE) {
new_state = STATE_RUNNING;
} else {
@@ -568,6 +568,67 @@ static int set_sound_device_name(metro_t* metro,
return 0;
}
+
+/*
+ * option system callback for initializing sound system with default value
+ * returns 0 on success, -1 otherwise
+ */
+
+static int new_sound_system(metro_t* metro) {
+ metro->options->sound_device_name = strdup(DEFAULT_SOUND_SYSTEM);
+ comm_client_query(metro->inter_thread_comm,
+ MESSAGE_TYPE_SET_SOUNDSYSTEM,
+ strdup(DEFAULT_SOUND_SYSTEM));
+ if (metro->options->soundsystem)
+ return 0;
+ else
+ return -1;
+}
+
+/*
+ * option system callback for destroying sound system
+ */
+static void delete_sound_system(metro_t* metro) {
+ if (metro->options->soundsystem)
+ free(metro->options->soundsystem);
+}
+
+/*
+ * option system callback for choosing the sound system
+ *
+ * returns 0 on success, -1 otherwise
+ */
+static int set_sound_system(metro_t* metro,
+ const char* option_name _U_,
+ const char* sound_system)
+{
+ if (metro->options->soundsystem)
+ free(metro->options->soundsystem);
+ else
+ fprintf(stderr,
+ "free() error: metro->options->sound_device_name not allocated.\n");
+ metro->options->soundsystem = strdup(sound_system);
+ comm_client_query(metro->inter_thread_comm,
+ MESSAGE_TYPE_SET_SOUNDSYSTEM, strdup(sound_system));
+ if (metro->state == STATE_RUNNING) {
+ comm_client_query(metro->inter_thread_comm,
+ MESSAGE_TYPE_STOP_METRONOME, NULL);
+ comm_client_query(metro->inter_thread_comm,
+ MESSAGE_TYPE_START_METRONOME, NULL);
+ }
+
+ return 0;
+}
+
+/*
+ * option system callback for spotting the sound device name
+ */
+static const char* get_sound_system(metro_t* metro,
+ int n _U_, char** option_name _U_)
+{
+ return metro->options->soundsystem;
+}
+
/*
* option system callback for spotting the sound device name
*/
@@ -590,7 +651,7 @@ static int set_min_bpm(metro_t* metro,
if (!metro || !metro->speed_adjustment || !min_bpm)
return -1;
-
+
new_min_bpm = abs(strtol(min_bpm, NULL, 0));
if (new_min_bpm >= MIN_BPM && new_min_bpm <= MAX_BPM) {
if (new_min_bpm > GTK_ADJUSTMENT(metro->speed_adjustment)->upper)
@@ -650,7 +711,7 @@ static int set_max_bpm(metro_t* metro,
if (!metro || !metro->speed_adjustment || !max_bpm)
return -1;
-
+
new_max_bpm = abs(strtol(max_bpm, NULL, 0));
if (new_max_bpm >= MIN_BPM && new_max_bpm <= MAX_BPM) {
if (new_max_bpm < GTK_ADJUSTMENT(metro->speed_adjustment)->lower)
@@ -658,7 +719,7 @@ static int set_max_bpm(metro_t* metro,
GTK_ADJUSTMENT(metro->speed_adjustment)->upper = (gdouble) new_max_bpm;
gtk_adjustment_changed(GTK_ADJUSTMENT(metro->speed_adjustment));
}
-
+
return 0;
}
@@ -706,7 +767,7 @@ int set_speed(metro_t* metro, const char* option_name _U_, const char* speed)
{
if (!metro || !metro->speed_adjustment || !speed)
return -1;
-
+
gtk_adjustment_set_value(GTK_ADJUSTMENT(metro->speed_adjustment),
(gdouble) strtol(speed, NULL, 0));
@@ -757,7 +818,7 @@ int set_volume(metro_t* metro,
{
if (!metro || !metro->volume_adjustment || !volume)
return -1;
-
+
gtk_adjustment_set_value(GTK_ADJUSTMENT(metro->volume_adjustment),
g_ascii_strtod(volume, NULL));
@@ -807,7 +868,7 @@ static void set_meter_int(metro_t* metro, int meter)
{
int* message;
int i;
-
+
switch (meter) {
case 1:
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(metro->meter_button_1),
@@ -845,7 +906,7 @@ static void set_meter_int(metro_t* metro, int meter)
}
}
gtk_window_resize(GTK_WINDOW(metro->window), 1, 1);
-
+
if (debug)
g_print("new meter: %d\n", meter);
@@ -873,14 +934,14 @@ static void set_meter_cb(GtkWidget* widget, metro_t *metro) {
int set_meter(metro_t* metro, const char* option_name _U_, const char* meter)
{
int n;
-
+
if (!metro || !meter)
return -1;
n = (int) strtol(meter, NULL, 0);
set_meter_int(metro, n);
-
+
return 0;
}
@@ -895,12 +956,12 @@ const char* get_meter(metro_t* metro, int n _U_, char** option_name _U_)
if (result)
free(result);
-
+
if (metro == NULL)
return NULL;
result = g_strdup_printf("%d", gui_get_meter(metro));
-
+
return result;
}
@@ -914,7 +975,7 @@ static int new_meter(metro_t* metro) {
s = g_strdup_printf("%d", DEFAULT_METER);
set_meter(metro, NULL, s);
free(s);
-
+
meter = (int*) g_malloc (sizeof(int));
*meter = DEFAULT_METER;
comm_client_query(metro->inter_thread_comm, MESSAGE_TYPE_SET_METER, meter);
@@ -1130,7 +1191,7 @@ const char* get_accents(metro_t* metro,
int n _U_, char** option_name _U_)
{
static char result[MAX_METER + 1];
-
+
if (metro) {
int i;
@@ -1140,9 +1201,9 @@ const char* get_accents(metro_t* metro,
metro->accentbuttons[i])) ?
'1' : '0';
}
-
+
result[MAX_METER] = '\0';
-
+
i = MAX_METER - 1;
while (i > 0 && result[i] == '0') {
result[i] = '\0';
@@ -1157,7 +1218,7 @@ const char* get_accents(metro_t* metro,
/*
* returns the (main) menu bar for the specified window
- *
+ *
* further initialization done in metro:
* - menu-prepared accel_group added to window
* - visualtick_menu_item
@@ -1413,10 +1474,10 @@ metro_t* metro_new(void) {
if (debug)
printf("Creating metro object at %p.\n", metro);
-
+
metro->options = options_new();
metro->state = STATE_IDLE; /* set default */
-
+
metro->inter_thread_comm = comm_new();
metro->audio_thread =
g_thread_create_full((GThreadFunc) audio_loop,
@@ -1427,7 +1488,7 @@ metro_t* metro_new(void) {
G_THREAD_PRIORITY_NORMAL, /* G_THREAD_PRIORITY_URGENT
would be highest priority */
NULL /* no GError reporting */);
-
+
option_register(&metro->options->option_list,
"SampleFilename",
(option_new_t) new_sample,
@@ -1437,6 +1498,15 @@ metro_t* metro_new(void) {
(option_get_t) get_sample,
(void*) metro);
option_register(&metro->options->option_list,
+ "SoundSystem",
+ (option_new_t) new_sound_system,
+ (option_delete_t) delete_sound_system,
+ (option_set_t) set_sound_system,
+ (option_get_n_t) option_return_one,
+ (option_get_t) get_sound_system,
+ (void*) metro);
+
+ option_register(&metro->options->option_list,
"SoundDevice",
(option_new_t) new_sound_device_name,
(option_delete_t) delete_sound_device_name,
@@ -1461,7 +1531,7 @@ metro_t* metro_new(void) {
(option_get_n_t) option_return_one,
(option_get_t) get_command_on_stop,
(void*) metro->options);
-
+
metro->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(metro->window), "destroy",
@@ -1494,7 +1564,7 @@ metro_t* metro_new(void) {
metro->status_context =
gtk_statusbar_get_context_id(GTK_STATUSBAR(metro->statusbar), "status");
gtk_statusbar_push(GTK_STATUSBAR(metro->statusbar),
- metro->status_context,
+ metro->status_context,
_(state_data[metro->state].state));
gtk_box_pack_end(GTK_BOX(windowvbox), metro->statusbar, FALSE, TRUE, 0);
gtk_widget_show(metro->statusbar);
@@ -1526,7 +1596,7 @@ metro_t* metro_new(void) {
gtk_table_set_row_spacings(GTK_TABLE(table), 6);
gtk_table_set_col_spacings(GTK_TABLE(table), 12);
gtk_widget_show(table);
-
+
metro->speed_name = gtk_combo_box_new_text();
for (i = 0; i < sizeof(speed_names) / sizeof(speed_name_t); i++) {
gchar tmpbuf[1000];
@@ -1544,7 +1614,7 @@ metro_t* metro_new(void) {
"changed",
G_CALLBACK(set_speed_name_cb),
metro);
-
+
/* TRANSLATORS: This button needs to be clicked ("tapped") at least twice for
specifying a tempo */
button = gtk_button_new_with_label(_("Tap"));
@@ -1611,7 +1681,7 @@ metro_t* metro_new(void) {
(option_get_n_t) option_return_one,
(option_get_t) get_speed,
(void*) metro);
-
+
option_register(&metro->options->option_list,
"Volume",
(option_new_t) new_volume,
@@ -1620,14 +1690,14 @@ metro_t* metro_new(void) {
(option_get_n_t) option_return_one,
(option_get_t) get_volume,
(void*) metro);
-
+
label = gtk_label_new (_("Volume:"));
gtk_table_attach(GTK_TABLE(table), label,
0, 1, 2, 3,
GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_widget_show (label);
-
+
metro->volume_adjustment = gtk_adjustment_new(DEFAULT_VOLUME,
VOLUME_MIN, VOLUME_MAX, 5.0, 25.0, 0.0);
g_signal_connect_swapped(G_OBJECT(metro->volume_adjustment),
@@ -1635,7 +1705,7 @@ metro_t* metro_new(void) {
G_CALLBACK(set_volume_cb),
metro);
set_volume_cb(metro);
-
+
scale = gtk_hscale_new (GTK_ADJUSTMENT(metro->volume_adjustment));
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_CONTINUOUS);
gtk_scale_set_digits (GTK_SCALE (scale), 0);
@@ -1644,7 +1714,7 @@ metro_t* metro_new(void) {
1, 2, 2, 3,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_widget_show (scale);
-
+
spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(metro->volume_adjustment),
1.0, /* Step */
1 /* number of decimals */);
@@ -1652,9 +1722,9 @@ metro_t* metro_new(void) {
2, 3, 2, 3,
GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_widget_show(spinbutton);
-
+
/* Timing UI Code */
-
+
beatframe = gtk_frame_new (_("Meter"));
gtk_frame_set_shadow_type(GTK_FRAME(beatframe), GTK_SHADOW_NONE);
label = gtk_frame_get_label_widget(GTK_FRAME(beatframe));
@@ -1687,7 +1757,7 @@ metro_t* metro_new(void) {
"toggled",
G_CALLBACK(set_meter_cb),
metro);
-
+
metro->meter_button_2 =
gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(metro->meter_button_1),
/* TRANSLATORS: duple meter */
@@ -1698,7 +1768,7 @@ metro_t* metro_new(void) {
"toggled",
G_CALLBACK(set_meter_cb),
metro);
-
+
metro->meter_button_3 =
gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(metro->meter_button_2),
/* TRANSLATORS: triple meter */
@@ -1732,7 +1802,7 @@ metro_t* metro_new(void) {
"toggled",
G_CALLBACK(set_meter_cb),
metro);
-
+
adjustment = gtk_adjustment_new(5, 5, MAX_METER, 1, 4, 0);
metro->meter_spin_button =
gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 1, 0);
@@ -1769,7 +1839,7 @@ metro_t* metro_new(void) {
for (i = 0; i < (MAX_METER - 1) / 10 + 1; i++) {
for (j = 0; j < 10; j++) {
char* temp;
-
+
temp = g_strdup_printf("%d", i * 10 + j + 1);
button = gtk_check_button_new_with_label(temp);
free(temp);
@@ -1779,7 +1849,7 @@ metro_t* metro_new(void) {
g_signal_connect_swapped(button, "toggled",
G_CALLBACK(accents_changed_cb), metro);
-
+
metro->accentbuttons[i * 10 + j] = button;
}
}
@@ -1809,7 +1879,7 @@ metro_t* metro_new(void) {
(option_get_n_t) option_return_one,
(option_get_t) get_accents,
(void*) metro);
-
+
/* Profiles */
metro->profileframe = profiles_new(metro);
gtk_box_pack_start(GTK_BOX(vbox), metro->profileframe, FALSE, TRUE, 0);
@@ -1823,7 +1893,7 @@ metro_t* metro_new(void) {
togglebutton = gtk_button_new();
g_signal_connect(G_OBJECT(togglebutton), "clicked",
G_CALLBACK(metro_toggle_cb), metro);
-
+
gtk_box_pack_start(GTK_BOX(hbox), togglebutton, TRUE, FALSE, 0);
GTK_WIDGET_SET_FLAGS (togglebutton, GTK_CAN_DEFAULT);
gtk_widget_grab_default (togglebutton);
@@ -1851,43 +1921,43 @@ metro_t* metro_new(void) {
gtk_accel_group_connect(metro->accel_group, '+', GDK_CONTROL_MASK, 0,
g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_plus), metro, NULL));
gtk_accel_group_connect(metro->accel_group, '-', GDK_CONTROL_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minus),metro, NULL));
-
+ g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minus),metro, NULL));
+
gtk_accel_group_connect(metro->accel_group, 'x', GDK_MOD1_MASK, 0,
g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_plusTwo), metro, NULL));
gtk_accel_group_connect(metro->accel_group, 'z', GDK_MOD1_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minusTwo),metro, NULL));
-
+ g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minusTwo),metro, NULL));
+
gtk_accel_group_connect(metro->accel_group, 'd', GDK_CONTROL_MASK, 0,
g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_double), metro, NULL));
gtk_accel_group_connect(metro->accel_group, 'h', GDK_CONTROL_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_half), metro, NULL));
-
+ g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_half), metro, NULL));
+
gtk_accel_group_connect(metro->accel_group, 'w', GDK_MOD1_MASK, 0,
g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_double), metro, NULL));
gtk_accel_group_connect(metro->accel_group, 'q', GDK_MOD1_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_half), metro, NULL));
-
+ g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_half), metro, NULL));
+
gtk_accel_group_connect(metro->accel_group, 's', GDK_MOD1_MASK, 0,
g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_plusTen), metro, NULL));
gtk_accel_group_connect(metro->accel_group, 'a', GDK_MOD1_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minusTen), metro, NULL));
-
+ g_cclosure_new_swap(G_CALLBACK(set_speed_shortcut_cb_minusTen), metro, NULL));
+
gtk_accel_group_connect(metro->accel_group, 'x', GDK_SHIFT_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_plusTwo), metro, NULL));
+ g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_plusTwo), metro, NULL));
gtk_accel_group_connect(metro->accel_group, 'z', GDK_SHIFT_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_minusTwo),metro, NULL));
-
+ g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_minusTwo),metro, NULL));
+
gtk_accel_group_connect(metro->accel_group, 's', GDK_SHIFT_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_plusTen), metro, NULL));
+ g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_plusTen), metro, NULL));
gtk_accel_group_connect(metro->accel_group, 'a', GDK_SHIFT_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_minusTen),metro, NULL));
+ g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_minusTen),metro, NULL));
gtk_accel_group_connect(metro->accel_group, 'w', GDK_SHIFT_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_double), metro, NULL));
+ g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_double), metro, NULL));
gtk_accel_group_connect(metro->accel_group, 'q', GDK_SHIFT_MASK, 0,
- g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_half),metro, NULL));
-
+ g_cclosure_new_swap(G_CALLBACK(set_volume_shortcut_cb_half),metro, NULL));
+
option_register(&metro->options->option_list,
"VisualTick",
(option_new_t) new_visualtick,
@@ -1896,19 +1966,19 @@ metro_t* metro_new(void) {
(option_get_n_t) option_return_one,
(option_get_t) get_visualtick,
(void*) metro);
-
+
/* read rc file */
option_restore_all(metro->options->option_list);
/* set up additional handlers */
gtk_timeout_add(TIMER_DELAY, (GtkFunction) timeout_callback, metro);
gtk_timeout_add(VISUAL_DELAY * 1000, (GtkFunction) handle_comm, metro);
-
+
signal(SIGINT, &terminate_signal_callback);
signal(SIGTERM, &terminate_signal_callback);
/* additional helper widgets: */
-
+
/* Start error message */
metro->start_error = gtk_message_dialog_new(GTK_WINDOW(metro->window),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -1922,7 +1992,7 @@ metro_t* metro_new(void) {
"response",
G_CALLBACK(gtk_widget_hide),
G_OBJECT(metro->start_error));
-
+
gtk_widget_show (metro->window);
return metro;
diff --git a/src/metro.h b/src/metro.h
index 1358f41..fd21309 100644
--- a/src/metro.h
+++ b/src/metro.h
@@ -1,8 +1,8 @@
-/*
+/*
* Metronome session interface
*
* This file is part of GTick
- *
+ *
*
* Copyright (c) 1999, Alex Roberts
* Copyright (c) 2005 Marco Tulio Gontijo e Silva
@@ -22,7 +22,7 @@
* along with GTick; if not, see .
*
*/
-
+
#ifndef METRO_H
#define METRO_H
@@ -43,7 +43,7 @@
typedef enum state_t {
STATE_IDLE, /* Metronome off */
STATE_RUNNING, /* Metronome on */
-
+
STATE_NUMBER
} state_t;
@@ -80,7 +80,7 @@ typedef struct metro_t {
GtkWidget* meter_button_4;
GtkWidget* meter_button_more;
GtkWidget* meter_spin_button;
-
+
GtkWidget* togglebutton_label;
GtkWidget* speed_name; /* ComboBox */
@@ -93,7 +93,7 @@ typedef struct metro_t {
GtkWidget* accentframe; /* show / hide */
GtkWidget** accentbuttons; /* to switch on / off */
GtkToggleAction* accenttable_action;
-
+
GtkWidget* profileframe; /* show / hide */
GtkToggleAction* profiles_action;
GtkTreeView* profiles_tree;
diff --git a/src/options.h b/src/options.h
index e1285a2..d70e6d1 100644
--- a/src/options.h
+++ b/src/options.h
@@ -1,8 +1,8 @@
-/*
+/*
* Metronome options object interface
*
* This file is part of GTick
- *
+ *
*
* Copyright (c) 1999, Alex Roberts
* Copyright (c) 2003, 2004, 2005, 2006 Roland Stigge
@@ -34,6 +34,7 @@ typedef struct options_t {
option_list_t* option_list; /* list of available rc options */
char* sample_name;
+ char* soundsystem;
char* sound_device_name;
char* command_on_start;
char* command_on_stop;
diff --git a/src/threadtalk.h b/src/threadtalk.h
index 7f30fa0..e99cef7 100644
--- a/src/threadtalk.h
+++ b/src/threadtalk.h
@@ -38,10 +38,11 @@ typedef struct comm_t {
*/
enum message_type_t {
MESSAGE_TYPE_NO_MESSAGE,
-
+
MESSAGE_TYPE_STOP_SERVER,
MESSAGE_TYPE_SET_DEVICE, /* param: char*: device */
MESSAGE_TYPE_SET_SOUND, /* param: char* sound name or filename */
+ MESSAGE_TYPE_SET_SOUNDSYSTEM,
MESSAGE_TYPE_SET_METER, /* param: int*: meter */
MESSAGE_TYPE_SET_ACCENTS, /* param: char*: accent list: {'0','1'}* */
MESSAGE_TYPE_SET_FREQUENCY, /* param: double*: frequency */
@@ -51,7 +52,7 @@ enum message_type_t {
MESSAGE_TYPE_STOP_SYNC,
MESSAGE_TYPE_SET_VOLUME, /* param: double*: volume 0.0 ... 1.0 */
MESSAGE_TYPE_GET_VOLUME, /* response needed: double*: volume 0.0...1.0 */
-
+
MESSAGE_TYPE_RESPONSE_VOLUME, /* param: int*: volume 0 ... 100 */
MESSAGE_TYPE_RESPONSE_SYNC, /* param: unsigned int*: position in meter*/
MESSAGE_TYPE_RESPONSE_START_ERROR
--
1.7.1