2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
23 #include "gstmikmod.h"
25 #include <gst/audio/audio.h>
28 /* elementfactory information */
29 GstElementDetails mikmod_details = {
31 "Codec/Decoder/Audio",
32 "Module decoder based on libmikmod",
33 "Jeremy SIMON <jsimon13@yahoo.fr>",
37 /* Filter signals and args */
61 static GstStaticPadTemplate mikmod_src_factory =
62 GST_STATIC_PAD_TEMPLATE (
66 GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS)
69 static GstStaticPadTemplate mikmod_sink_factory =
70 GST_STATIC_PAD_TEMPLATE (
74 GST_STATIC_CAPS ("audio/x-mod")
77 static void gst_mikmod_base_init (gpointer g_class);
78 static void gst_mikmod_class_init (GstMikModClass *klass);
79 static void gst_mikmod_init (GstMikMod *filter);
80 static void gst_mikmod_set_property (GObject *object, guint id, const GValue *value, GParamSpec *pspec );
81 static void gst_mikmod_get_property (GObject *object, guint id, GValue *value, GParamSpec *pspec );
82 static GstPadLinkReturn gst_mikmod_srclink (GstPad *pad, const GstCaps *caps);
83 static void gst_mikmod_loop (GstElement *element);
84 static gboolean gst_mikmod_setup (GstMikMod *mikmod);
85 static GstElementStateReturn gst_mikmod_change_state (GstElement *element);
89 static GstElementClass *parent_class = NULL;
92 gst_mikmod_get_type(void) {
93 static GType mikmod_type = 0;
96 static const GTypeInfo mikmod_info = {
97 sizeof(GstMikModClass),
100 (GClassInitFunc)gst_mikmod_class_init,
105 (GInstanceInitFunc)gst_mikmod_init,
107 mikmod_type = g_type_register_static(GST_TYPE_ELEMENT, "GstMikmod", &mikmod_info, 0);
113 gst_mikmod_base_init (gpointer g_class)
115 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
117 gst_element_class_add_pad_template (element_class,
118 gst_static_pad_template_get (&mikmod_src_factory));
119 gst_element_class_add_pad_template (element_class,
120 gst_static_pad_template_get (&mikmod_sink_factory));
121 gst_element_class_set_details (element_class, &mikmod_details);
125 gst_mikmod_class_init (GstMikModClass *klass)
127 GObjectClass *gobject_class;
128 GstElementClass *gstelement_class;
130 gobject_class = (GObjectClass*)klass;
131 gstelement_class = (GstElementClass*)klass;
133 parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
135 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SONGNAME,
136 g_param_spec_string("songname","songname","songname",
137 NULL, G_PARAM_READABLE));
138 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MODTYPE,
139 g_param_spec_string("modtype", "modtype", "modtype",
140 NULL, G_PARAM_READABLE ));
141 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MUSICVOLUME,
142 g_param_spec_int("musicvolume", "musivolume", "musicvolume",
143 0, 128, 128, G_PARAM_READWRITE ));
144 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PANSEP,
145 g_param_spec_int("pansep", "pansep", "pansep",
146 0, 128, 128, G_PARAM_READWRITE ));
147 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_REVERB,
148 g_param_spec_int("reverb", "reverb", "reverb",
149 0, 15, 0, G_PARAM_READWRITE ));
150 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SNDFXVOLUME,
151 g_param_spec_int("sndfxvolume", "sndfxvolume", "sndfxvolume",
152 0, 128, 128, G_PARAM_READWRITE ));
153 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VOLUME,
154 g_param_spec_int("volume", "volume", "volume",
155 0, 128, 96, G_PARAM_READWRITE ));
157 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_INTERP,
158 g_param_spec_boolean("interp", "interp", "interp",
159 FALSE, G_PARAM_READWRITE ));
160 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_REVERSE,
161 g_param_spec_boolean("reverse", "reverse", "reverse",
162 FALSE, G_PARAM_READWRITE ));
163 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SURROUND,
164 g_param_spec_boolean("surround", "surround", "surround",
165 TRUE, G_PARAM_READWRITE ));
166 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HQMIXER,
167 g_param_spec_boolean("hqmixer", "hqmixer", "hqmixer",
168 FALSE, G_PARAM_READWRITE ));
169 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SOFT_MUSIC,
170 g_param_spec_boolean("soft_music", "soft_music", "soft_music",
171 TRUE, G_PARAM_READWRITE ));
172 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SOFT_SNDFX,
173 g_param_spec_boolean("soft_sndfx", "soft_sndfx", "soft_sndfx",
174 TRUE, G_PARAM_READWRITE ));
177 gobject_class->set_property = gst_mikmod_set_property;
178 gobject_class->get_property = gst_mikmod_get_property;
180 gstelement_class->change_state = gst_mikmod_change_state;
185 gst_mikmod_init (GstMikMod *filter)
187 filter->sinkpad = gst_pad_new_from_template(
188 gst_static_pad_template_get (&mikmod_sink_factory),"sink");
189 filter->srcpad = gst_pad_new_from_template(
190 gst_static_pad_template_get (&mikmod_src_factory),"src");
191 gst_pad_use_explicit_caps (filter->srcpad);
193 gst_element_add_pad(GST_ELEMENT(filter),filter->sinkpad);
194 gst_element_add_pad(GST_ELEMENT(filter),filter->srcpad);
195 gst_pad_set_link_function (filter->srcpad, gst_mikmod_srclink);
197 gst_element_set_loop_function (GST_ELEMENT (filter), gst_mikmod_loop);
199 filter->Buffer = NULL;
201 filter->stereo = TRUE;
202 filter->surround = TRUE;
203 filter->_16bit = TRUE;
204 filter->soft_music = TRUE;
205 filter->soft_sndfx = TRUE;
206 filter->mixfreq = 44100;
208 filter->pansep = 128;
209 filter->musicvolume = 128;
211 filter->sndfxvolume = 128;
212 filter->songname = NULL;
213 filter->modtype = NULL;
217 static GstPadLinkReturn
218 gst_mikmod_negotiate (GstMikMod *mikmod)
222 if ( mikmod->_16bit ) {
230 return gst_pad_set_explicit_caps (mikmod->srcpad,
231 gst_caps_new_simple ( "audio/x-raw-int",
232 "endianness", G_TYPE_INT, G_BYTE_ORDER,
233 "signed", G_TYPE_BOOLEAN, sign,
234 "width", G_TYPE_INT, width,
235 "depth", G_TYPE_INT, width,
236 "rate", G_TYPE_INT, mikmod->mixfreq,
237 "channels", G_TYPE_INT, mikmod->stereo ? 2 : 1,
242 static GstPadLinkReturn
243 gst_mikmod_srclink (GstPad *pad, const GstCaps *caps)
246 GstStructure *structure;
250 filter = GST_MIKMOD (gst_pad_get_parent (pad));
252 structure = gst_caps_get_structure (caps, 0);
254 gst_structure_get_int (structure, "depth", &depth);
255 filter->_16bit = (depth == 16);
256 gst_structure_get_int (structure, "channels", &channels);
257 filter->stereo = (channels == 2);
258 gst_structure_get_int (structure, "rate", &filter->mixfreq);
260 return gst_mikmod_negotiate(filter);
265 gst_mikmod_loop (GstElement *element)
268 GstBuffer *buffer_in;
270 g_return_if_fail (element != NULL);
271 g_return_if_fail (GST_IS_MIKMOD (element));
273 mikmod = GST_MIKMOD (element);
274 srcpad = mikmod->srcpad;
275 mikmod->Buffer = NULL;
277 while ((buffer_in = GST_BUFFER (gst_pad_pull( mikmod->sinkpad )))) {
278 if ( GST_IS_EVENT (buffer_in) ) {
279 GstEvent *event = GST_EVENT (buffer_in);
281 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS)
286 if ( mikmod->Buffer ) {
287 mikmod->Buffer = gst_buffer_merge( mikmod->Buffer, buffer_in );
288 gst_buffer_unref( buffer_in );
291 mikmod->Buffer = buffer_in;
295 if (!GST_PAD_CAPS (mikmod->srcpad)) {
296 if (gst_mikmod_negotiate (mikmod) <= 0) {
297 GST_ELEMENT_ERROR (mikmod, CORE, NEGOTIATION, (NULL), (NULL));
301 gst_mikmod_setup( mikmod );
303 MikMod_RegisterDriver(&drv_gst);
304 MikMod_RegisterAllLoaders();
307 reader = GST_READER_new( mikmod );
308 module = Player_LoadGeneric ( reader, 64, 0 );
310 gst_buffer_unref (mikmod->Buffer);
312 if ( ! Player_Active() )
313 Player_Start(module);
316 if ( Player_Active() ) {
318 timestamp = ( module->sngtime / 1024.0 ) * GST_SECOND;
320 gst_element_yield (element);
323 gst_element_set_eos (GST_ELEMENT (mikmod));
324 gst_pad_push (mikmod->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS)));
333 gst_mikmod_setup (GstMikMod *mikmod)
335 md_musicvolume = mikmod->musicvolume;
336 md_pansep = mikmod->pansep;
337 md_reverb = mikmod->reverb;
338 md_sndfxvolume = mikmod->sndfxvolume;
339 md_volume = mikmod->volume;
340 md_mixfreq = mikmod->mixfreq;
344 if ( mikmod->interp )
345 md_mode = md_mode | DMODE_INTERP;
347 if ( mikmod->reverse )
348 md_mode = md_mode | DMODE_REVERSE;
350 if ( mikmod->surround )
351 md_mode = md_mode | DMODE_SURROUND;
353 if ( mikmod->_16bit )
354 md_mode = md_mode | DMODE_16BITS;
356 if ( mikmod->hqmixer )
357 md_mode = md_mode | DMODE_HQMIXER;
359 if ( mikmod->soft_music )
360 md_mode = md_mode | DMODE_SOFT_MUSIC;
362 if ( mikmod->soft_sndfx )
363 md_mode = md_mode | DMODE_SOFT_SNDFX;
365 if ( mikmod->stereo )
366 md_mode = md_mode | DMODE_STEREO;
372 static GstElementStateReturn
373 gst_mikmod_change_state (GstElement *element)
377 g_return_val_if_fail (GST_IS_MIKMOD (element), GST_STATE_FAILURE);
379 mikmod = GST_MIKMOD (element);
381 GST_DEBUG ("state pending %d", GST_STATE_PENDING (element));
383 if (GST_STATE_PENDING (element) == GST_STATE_READY)
385 gst_mikmod_setup(mikmod);
387 if ( Player_Active() )
389 Player_TogglePause();
390 Player_SetPosition( 0 );
395 if (GST_STATE_PENDING (element) == GST_STATE_PLAYING)
397 if ( Player_Active() && Player_Paused() )
398 Player_TogglePause();
400 if ( ! Player_Active() )
401 Player_Start(module);
405 if (GST_STATE_PENDING (element) == GST_STATE_PAUSED)
406 if ( Player_Active() && ! Player_Paused() )
407 Player_TogglePause();
409 if (GST_STATE_PENDING (element) == GST_STATE_NULL)
413 if (GST_ELEMENT_CLASS (parent_class)->change_state)
414 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
416 return GST_STATE_SUCCESS;
422 gst_mikmod_set_property (GObject *object, guint id, const GValue *value, GParamSpec *pspec )
426 /* it's not null if we got it, but it might not be ours */
427 g_return_if_fail(GST_IS_MIKMOD(object));
428 filter = GST_MIKMOD(object);
432 g_free (filter->songname);
433 filter->songname = g_strdup (g_value_get_string (value));
436 g_free (filter->modtype);
437 filter->modtype = g_strdup (g_value_get_string (value));
439 case ARG_MUSICVOLUME:
440 filter->musicvolume = g_value_get_int (value);
443 filter->pansep = g_value_get_int (value);
446 filter->reverb = g_value_get_int (value);
448 case ARG_SNDFXVOLUME:
449 filter->sndfxvolume = g_value_get_int (value);
452 filter->volume = g_value_get_int (value);
455 filter->interp = g_value_get_boolean (value);
458 filter->reverse = g_value_get_boolean (value);
461 filter->surround = g_value_get_boolean (value);
464 filter->hqmixer = g_value_get_boolean (value);
467 filter->soft_music = g_value_get_boolean (value);
470 filter->soft_sndfx = g_value_get_boolean (value);
478 gst_mikmod_get_property (GObject *object, guint id, GValue *value, GParamSpec *pspec )
482 /* it's not null if we got it, but it might not be ours */
483 g_return_if_fail(GST_IS_MIKMOD(object));
484 filter = GST_MIKMOD(object);
487 case ARG_MUSICVOLUME:
488 g_value_set_int (value, filter->musicvolume);
491 g_value_set_int (value, filter->pansep);
494 g_value_set_int (value, filter->reverb);
496 case ARG_SNDFXVOLUME:
497 g_value_set_int (value, filter->sndfxvolume);
500 g_value_set_int (value, filter->volume);
503 g_value_set_boolean (value, filter->interp);
506 g_value_set_boolean (value, filter->reverse);
509 g_value_set_boolean (value, filter->surround);
512 g_value_set_boolean (value, filter->hqmixer);
515 g_value_set_boolean (value, filter->soft_music);
518 g_value_set_boolean (value, filter->soft_sndfx);
526 plugin_init (GstPlugin *plugin)
528 if (!gst_element_register (plugin, "mikmod", GST_RANK_SECONDARY, GST_TYPE_MIKMOD))
538 "Mikmod plugin library",