#include <glib.h>
#include <glib/gi18n-lib.h>
#include <libchimara/glk.h>
-#ifdef GSTREAMER_SOUND
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
#include <gst/gst.h>
-#endif
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
#include "magic.h"
#include "schannel.h"
#include "chimara-glk-private.h"
#define VOLUME_TIMER_RESOLUTION 1.0 /* In milliseconds */
-extern GPrivate *glk_data_key;
+#ifdef GSTREAMER_0_10_SOUND
+#define OGG_MIMETYPE "application/ogg"
+#endif
+#ifdef GSTREAMER_1_0_SOUND
+#define OGG_MIMETYPE "audio/ogg"
+#endif
+
+extern GPrivate glk_data_key;
-#ifdef GSTREAMER_SOUND
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
/* Stop any currently playing sound on this channel, and remove any
format-specific GStreamer elements from the channel. */
static void
on_type_found(GstElement *typefind, guint probability, GstCaps *caps, schanid_t s)
{
gchar *type = gst_caps_to_string(caps);
- if(strcmp(type, "application/ogg") == 0) {
+ if(strcmp(type, OGG_MIMETYPE) == 0) {
s->demux = gst_element_factory_make("oggdemux", NULL);
s->decode = gst_element_factory_make("vorbisdec", NULL);
if(!s->demux || !s->decode) {
WARNING(_("Could not link GStreamer elements"));
goto finally;
}
- } else if(strcmp(type, "audio/x-mod") == 0) {
+ } else if(g_str_has_prefix(type, "audio/x-mod")) {
+ /* "audio/x-mod, type=(string)s3m" has been observed */
s->decode = gst_element_factory_make("modplug", NULL);
if(!s->decode) {
WARNING(_("Could not create 'modplug' GStreamer element"));
WARNING_S(_("Unexpected audio type in blorb"), type);
}
+ /* This is necessary in case this handler occurs in the middle of a state
+ change */
+ gst_element_sync_state_with_parent(s->decode);
+ if(s->demux != NULL)
+ gst_element_sync_state_with_parent(s->demux);
+
finally:
g_free(type);
}
-#endif /* GSTREAMER_SOUND */
+
+/* Load a sound resource into a GInputStream, by whatever method */
+static GInputStream *
+load_resource_into_giostream(glui32 snd)
+{
+ ChimaraGlkPrivate *glk_data = g_private_get(&glk_data_key);
+ GInputStream *retval;
+
+ if(glk_data->resource_map == NULL) {
+ if(glk_data->resource_load_callback == NULL) {
+ WARNING(_("No resource map has been loaded yet."));
+ return NULL;
+ }
+ char *filename = glk_data->resource_load_callback(CHIMARA_RESOURCE_SOUND, snd, glk_data->resource_load_callback_data);
+ if(filename == NULL) {
+ WARNING(_("Error loading resource from alternative location."));
+ return NULL;
+ }
+
+ GError *err = NULL;
+ GFile *file = g_file_new_for_path(filename);
+ retval = G_INPUT_STREAM(g_file_read(file, NULL, &err));
+ if(retval == NULL)
+ IO_WARNING(_("Error loading resource from file"), filename, err->message);
+ g_free(filename);
+ g_object_unref(file);
+ } else {
+ giblorb_result_t resource;
+ giblorb_err_t result = giblorb_load_resource(glk_data->resource_map, giblorb_method_Memory, &resource, giblorb_ID_Snd, snd);
+ if(result != giblorb_err_None) {
+ WARNING_S( _("Error loading resource"), giblorb_get_error_message(result) );
+ return NULL;
+ }
+ retval = g_memory_input_stream_new_from_data(resource.data.ptr, resource.length, NULL);
+ }
+ return retval;
+}
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
/**
* glk_schannel_create:
schanid_t
glk_schannel_create_ext(glui32 rock, glui32 volume)
{
-#ifdef GSTREAMER_SOUND
- ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
+ ChimaraGlkPrivate *glk_data = g_private_get(&glk_data_key);
schanid_t s = g_new0(struct glk_schannel_struct, 1);
s->magic = MAGIC_SCHANNEL;
return NULL;
#else
return NULL;
-#endif /* GSTREAMER_SOUND */
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
}
/**
{
VALID_SCHANNEL(chan, return);
-#ifdef GSTREAMER_SOUND
- ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
+ ChimaraGlkPrivate *glk_data = g_private_get(&glk_data_key);
if(!gst_element_set_state(chan->pipeline, GST_STATE_NULL))
WARNING_S(_("Could not set GstElement state to"), "NULL");
chan->magic = MAGIC_FREE;
g_free(chan);
-#endif
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
}
/**
{
VALID_SCHANNEL_OR_NULL(chan, return NULL);
-#ifdef GSTREAMER_SOUND
- ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
+ ChimaraGlkPrivate *glk_data = g_private_get(&glk_data_key);
GList *retnode;
if(chan == NULL)
return retval;
#else
return NULL;
-#endif /* GSTREAMER_SOUND */
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
}
/**
glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats, glui32 notify)
{
VALID_SCHANNEL(chan, return 0);
-#ifdef GSTREAMER_SOUND
- ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
- GInputStream *stream;
-
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
/* Stop the previous sound */
clean_up_after_playing_sound(chan);
return 1;
}
- /* Load the sound into a GInputStream, by whatever method */
- if(!glk_data->resource_map) {
- if(!glk_data->resource_load_callback) {
- WARNING(_("No resource map has been loaded yet."));
- return 0;
- }
- gchar *filename = glk_data->resource_load_callback(CHIMARA_RESOURCE_SOUND, snd, glk_data->resource_load_callback_data);
- if(!filename) {
- WARNING(_("Error loading resource from alternative location."));
- return 0;
- }
-
- GError *err = NULL;
- GFile *file = g_file_new_for_path(filename);
- stream = G_INPUT_STREAM(g_file_read(file, NULL, &err));
- if(!stream) {
- IO_WARNING(_("Error loading resource from file"), filename, err->message);
- g_free(filename);
- g_object_unref(file);
- return 0;
- }
- g_free(filename);
- g_object_unref(file);
- } else {
- giblorb_result_t resource;
- giblorb_err_t result = giblorb_load_resource(glk_data->resource_map, giblorb_method_Memory, &resource, giblorb_ID_Snd, snd);
- if(result != giblorb_err_None) {
- WARNING_S( _("Error loading resource"), giblorb_get_error_message(result) );
- return 0;
- }
- stream = g_memory_input_stream_new_from_data(resource.data.ptr, resource.length, NULL);
- }
+ GInputStream *stream = load_resource_into_giostream(snd);
+ if(stream == NULL)
+ return 0;
chan->source = gst_element_factory_make("giostreamsrc", NULL);
g_object_set(chan->source, "stream", stream, NULL);
return 1;
#else
return 0;
-#endif
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
}
/**
for(count = 0; count < chancount; count++)
VALID_SCHANNEL(chanarray[count], return 0);
-#ifdef GSTREAMER_SOUND
- ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
- GInputStream *stream;
-
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
+ ChimaraGlkPrivate *glk_data = g_private_get(&glk_data_key);
if(!glk_data->resource_map && !glk_data->resource_load_callback) {
WARNING(_("No resource map has been loaded yet."));
return 0;
/* Stop the previous sound */
clean_up_after_playing_sound(chanarray[count]);
- /* Load the sound into a GInputStream, by whatever method */
- if(!glk_data->resource_map) {
- gchar *filename = glk_data->resource_load_callback(CHIMARA_RESOURCE_SOUND, sndarray[count], glk_data->resource_load_callback_data);
- if(!filename) {
- WARNING(_("Error loading resource from alternative location."));
- skiparray[count] = TRUE;
- continue;
- }
-
- GError *err = NULL;
- GFile *file = g_file_new_for_path(filename);
- stream = G_INPUT_STREAM(g_file_read(file, NULL, &err));
- if(!stream) {
- IO_WARNING(_("Error loading resource from file"), filename, err->message);
- g_free(filename);
- g_object_unref(file);
- skiparray[count] = TRUE;
- continue;
- }
- g_free(filename);
- g_object_unref(file);
- } else {
- giblorb_result_t resource;
- giblorb_err_t result = giblorb_load_resource(glk_data->resource_map, giblorb_method_Memory, &resource, giblorb_ID_Snd, sndarray[count]);
- if(result != giblorb_err_None) {
- WARNING_S( _("Error loading resource"), giblorb_get_error_message(result) );
- skiparray[count] = TRUE;
- continue;
- }
- stream = g_memory_input_stream_new_from_data(resource.data.ptr, resource.length, NULL);
+ GInputStream *stream = load_resource_into_giostream(sndarray[count]);
+ if(stream == NULL) {
+ skiparray[count] = TRUE;
+ continue;
}
chanarray[count]->source = gst_element_factory_make("giostreamsrc", NULL);
return successes;
#else
return 0;
-#endif
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
}
/**
glk_schannel_stop(schanid_t chan)
{
VALID_SCHANNEL(chan, return);
-#ifdef GSTREAMER_SOUND
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
clean_up_after_playing_sound(chan);
#endif
}
/* Mark the channel as paused even if there is no sound playing yet */
chan->paused = TRUE;
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
GstState state;
if(gst_element_get_state(chan->pipeline, &state, NULL, GST_CLOCK_TIME_NONE) != GST_STATE_CHANGE_SUCCESS) {
WARNING(_("Could not get GstElement state"));
WARNING_S(_("Could not set GstElement state to"), "PAUSED");
return;
}
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
}
/**
/* Mark the channel as not paused in any case */
chan->paused = FALSE;
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
GstState state;
if(gst_element_get_state(chan->pipeline, &state, NULL, GST_CLOCK_TIME_NONE) != GST_STATE_CHANGE_SUCCESS) {
WARNING(_("Could not get GstElement state"));
WARNING_S(_("Could not set GstElement state to"), "PLAYING");
return;
}
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
}
/**
glk_schannel_set_volume_ext(chan, vol, 0, 0);
}
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
static double
volume_glk_to_gstreamer(glui32 volume_glk)
{
return CLAMP(((double)volume_glk / 0x10000), 0.0, 10.0);
}
-#ifdef GSTREAMER_SOUND
static gboolean
volume_change_timeout(schanid_t chan)
{
return TRUE;
}
-#endif /* GSTREAMER_SOUND */
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
/**
* glk_schannel_set_volume_ext:
VALID_SCHANNEL(chan, return);
/* Silently ignore out-of-range volume values */
-#ifdef GSTREAMER_SOUND
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
/* Interrupt a previous volume change */
if(chan->volume_timer_id > 0)
g_source_remove(chan->volume_timer_id);
/* Set up a timer for the volume */
chan->volume_timer_id = g_timeout_add(VOLUME_TIMER_RESOLUTION, (GSourceFunc)volume_change_timeout, chan);
-#endif
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
}
/**
void
glk_sound_load_hint(glui32 snd, glui32 flag)
{
-#ifdef GSTREAMER_SOUND
- ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
+#if defined(GSTREAMER_0_10_SOUND) || defined(GSTREAMER_1_0_SOUND)
+ ChimaraGlkPrivate *glk_data = g_private_get(&glk_data_key);
giblorb_result_t resource;
giblorb_err_t result;
return;
}
}
-#endif /* GSTREAMER_SOUND */
+#endif /* GSTREAMER_0_10_SOUND || GSTREAMER_1_0_SOUND */
}