#define DEFAULT_TICK_PERIOD_MS 10
#define DEFAULT_POLL_TIMEOUT_MS (DEFAULT_TICK_PERIOD_MS / 2)
-GST_DEBUG_CATEGORY (mysrc_debug);
-#define GST_CAT_DEFAULT mysrc_debug
+GST_DEBUG_CATEGORY (mysource_debug);
+#define GST_CAT_DEFAULT mysource_debug
typedef struct _App App;
guint64 tick;
};
-App s_app;
+static App s_app;
static int
init_seq (App * app)
goto error;
}
+ /*
+ * Prevent Valgrind from reporting cached configuration as memory leaks, see:
+ * http://git.alsa-project.org/?p=alsa-lib.git;a=blob;f=MEMORY-LEAK;hb=HEAD
+ */
+ snd_config_update_free_global();
+
ret = snd_seq_set_client_name (app->seq, DEFAULT_CLIENT_NAME);
if (ret < 0) {
GST_ERROR ("Cannot set client name - %s", snd_strerror (ret));
static void
push_buffer (App * app, gpointer data, guint size)
{
- GstBuffer *buffer;
GstClockTime time;
- int ret;
gpointer local_data;
+ GstBuffer *buffer;
+ int ret;
- /* read the next chunk */
buffer = gst_buffer_new ();
time = app->tick * DEFAULT_TICK_PERIOD_MS * GST_MSECOND;
GST_BUFFER_DTS (buffer) = time;
GST_BUFFER_PTS (buffer) = time;
- GST_BUFFER_OFFSET (buffer) = time;
- GST_BUFFER_DURATION (buffer) = DEFAULT_TICK_PERIOD_MS * GST_MSECOND;
- local_data = g_malloc (size);
- memcpy (local_data, data, size);
+ local_data = g_memdup (data, size);
gst_buffer_append_memory (buffer,
gst_memory_new_wrapped (0, local_data, size, 0, size, local_data,
g_free));
+ GST_MEMDUMP ("MIDI data:", local_data, size);
+
GST_DEBUG ("feed buffer %p, tick %" G_GUINT64_FORMAT " size: %u",
(gpointer) buffer, app->tick, size);
g_signal_emit_by_name (app->appsrc, "push-buffer", buffer, &ret);
ret = poll (app->pfds, app->npfds, DEFAULT_POLL_TIMEOUT_MS);
if (ret < 0) {
GST_ERROR ("ERROR in poll: %s", strerror (errno));
+ gst_app_src_end_of_stream (GST_APP_SRC (appsrc));
} else if (ret == 0) {
push_tick_buffer (app);
} else {
do {
snd_seq_event_t *event;
err = snd_seq_event_input (app->seq, &event);
- if (err < 0)
+ if (err < 0 && err != -EAGAIN) {
+ GST_ERROR ("Error in snd_seq_event_input: %s", snd_strerror (err));
+ gst_app_src_end_of_stream (GST_APP_SRC (appsrc));
break;
+ }
if (event) {
size_ev =
snd_midi_event_decode (app->parser, app->buffer, DEFAULT_BUFSIZE,
} else {
GST_ERROR ("Error decoding event from ALSA to output: %s",
strerror (-size_ev));
+ gst_app_src_end_of_stream (GST_APP_SRC (appsrc));
break;
}
} else {
GOptionContext *ctx;
GError *err = NULL;
gchar *ports = NULL;
+ gboolean verbose = FALSE;
GOptionEntry options[] = {
{"ports", 'p', 0, G_OPTION_ARG_STRING, &ports,
"Comma separated list of sequencer ports", "client:port,..."},
+ {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+ "Output status information and property notifications", NULL},
{NULL}
};
gst_init (&argc, &argv);
- GST_DEBUG_CATEGORY_INIT (mysrc_debug, "mysrc", 0,
+ GST_DEBUG_CATEGORY_INIT (mysource_debug, "mysource", 0,
"ALSA MIDI sequencer appsrc pipeline");
ret = app_init (app, ports);
("appsrc name=mysource ! fluiddec ! audioconvert ! autoaudiosink", NULL);
g_assert (app->pipeline);
+ if (verbose)
+ g_signal_connect (app->pipeline, "deep-notify", G_CALLBACK (gst_object_default_deep_notify), NULL);
+
bus = gst_pipeline_get_bus (GST_PIPELINE (app->pipeline));
g_assert (bus);