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.
20 #include "gstmikmod.h"
22 #include <gst/audio/audio.h>
25 GstElementDetails mikmod_details = {
28 "Module decoder based on libmikmod",
30 "Jeremy SIMON <jsimon13@yahoo.fr>",
35 /* Filter signals and args */
62 static GstPadTemplate*
63 mikmod_src_factory (void)
65 static GstPadTemplate *template = NULL;
68 template = gst_padtemplate_new (
76 "format", GST_PROPS_STRING ("int"),
77 "law", GST_PROPS_INT (0),
78 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
79 "signed", GST_PROPS_BOOLEAN (TRUE),
80 "width", GST_PROPS_INT (16),
81 "depth", GST_PROPS_INT (16),
82 "rate", GST_PROPS_INT_RANGE (8000, 48000),
83 "channels", GST_PROPS_INT_RANGE (1, 2),
90 static GstPadTemplate*
91 mikmod_sink_factory (void)
93 static GstPadTemplate *template = NULL;
96 template = gst_padtemplate_new (
110 mikmod_typefind (GstBuffer *buf, gpointer private)
112 if ( MOD_CheckType( buf ) )
113 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
115 if ( Mod_669_CheckType( buf ) )
116 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
118 if ( Amf_CheckType( buf ) )
119 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
121 if ( Dsm_CheckType( buf ) )
122 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
124 if ( Fam_CheckType( buf ) )
125 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
127 if ( Gdm_CheckType( buf ) )
128 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
130 if ( Imf_CheckType( buf ) )
131 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
133 if ( It_CheckType( buf ) )
134 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
136 if ( M15_CheckType( buf ) )
137 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
140 if ( Med_CheckType( buf ) )
141 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
144 if ( Mtm_CheckType( buf ) )
145 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
147 if ( Okt_CheckType( buf ) )
148 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
150 if ( S3m_CheckType( buf ) )
151 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
153 if ( Xm_CheckType( buf ) )
154 return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
159 static GstTypeDefinition mikmoddefinition = {
160 "mikmod_audio/mod", "audio/mod", ".mod .sam .med .s3m .it .xm .stm .mtm .669 .ult .far .amf .dsm .imf .gdm .stx .okt", mikmod_typefind
163 static void gst_mikmod_class_init (GstMikModClass *klass);
164 static void gst_mikmod_init (GstMikMod *filter);
165 static void gst_mikmod_set_property (GObject *object, guint id, const GValue *value, GParamSpec *pspec );
166 static void gst_mikmod_get_property (GObject *object, guint id, GValue *value, GParamSpec *pspec );
167 static void gst_mikmod_loop (GstElement *element);
168 static gboolean gst_mikmod_setup (GstMikMod *mikmod);
169 static GstElementStateReturn gst_mikmod_change_state (GstElement *element);
173 static GstElementClass *parent_class = NULL;
175 #define GST_TYPE_MIKMOD_MIXFREQ (gst_mikmod_mixfreq_get_type())
178 gst_mikmod_mixfreq_get_type (void)
180 static GType mikmod_mixfreq_type = 0;
181 static GEnumValue mikmod_mixfreq[] = {
182 { 0, "8000", "8000 Hz" },
183 { 1, "11025", "11025 Hz" },
184 { 2, "22100", "22100 Hz" },
185 { 3, "44100", "44100 Hz" },
188 if (! mikmod_mixfreq_type ) {
189 mikmod_mixfreq_type = g_enum_register_static ("GstMikmodmixfreq", mikmod_mixfreq);
191 return mikmod_mixfreq_type;
195 gst_mikmod_get_type(void) {
196 static GType mikmod_type = 0;
199 static const GTypeInfo mikmod_info = {
200 sizeof(GstMikModClass),
203 (GClassInitFunc)gst_mikmod_class_init,
208 (GInstanceInitFunc)gst_mikmod_init,
210 mikmod_type = g_type_register_static(GST_TYPE_ELEMENT, "GstMikmod", &mikmod_info, 0);
217 gst_mikmod_class_init (GstMikModClass *klass)
219 GObjectClass *gobject_class;
220 GstElementClass *gstelement_class;
222 gobject_class = (GObjectClass*)klass;
223 gstelement_class = (GstElementClass*)klass;
225 parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
227 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SONGNAME,
228 g_param_spec_string("songname","songname","songname",
229 "", G_PARAM_READABLE));
230 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MODTYPE,
231 g_param_spec_string("modtype", "modtype", "modtype",
232 "", G_PARAM_READABLE ));
233 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MUSICVOLUME,
234 g_param_spec_int("musicvolume", "musivolume", "musicvolume",
235 0, 128, 128, G_PARAM_READWRITE ));
236 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PANSEP,
237 g_param_spec_int("pansep", "pansep", "pansep",
238 0, 128, 128, G_PARAM_READWRITE ));
239 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_REVERB,
240 g_param_spec_int("reverb", "reverb", "reverb",
241 0, 15, 0, G_PARAM_READWRITE ));
242 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SNDFXVOLUME,
243 g_param_spec_int("sndfxvolume", "sndfxvolume", "sndfxvolume",
244 0, 128, 128, G_PARAM_READWRITE ));
245 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VOLUME,
246 g_param_spec_int("volume", "volume", "volume",
247 0, 128, 96, G_PARAM_READWRITE ));
248 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FIXFREQ,
249 g_param_spec_enum("mixfreq", "mixfreq", "mixfreq",
250 GST_TYPE_MIKMOD_MIXFREQ, 3,G_PARAM_READWRITE ));
251 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_INTERP,
252 g_param_spec_boolean("interp", "interp", "interp",
253 FALSE, G_PARAM_READWRITE ));
254 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_REVERSE,
255 g_param_spec_boolean("reverse", "reverse", "reverse",
256 FALSE, G_PARAM_READWRITE ));
257 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SURROUND,
258 g_param_spec_boolean("surround", "surround", "surround",
259 TRUE, G_PARAM_READWRITE ));
260 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_16BIT,
261 g_param_spec_boolean("use16bit", "use16bit", "use16bit",
262 TRUE, G_PARAM_READWRITE ));
263 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HQMIXER,
264 g_param_spec_boolean("hqmixer", "hqmixer", "hqmixer",
265 FALSE, G_PARAM_READWRITE ));
266 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SOFT_MUSIC,
267 g_param_spec_boolean("soft_music", "soft_music", "soft_music",
268 TRUE, G_PARAM_READWRITE ));
269 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SOFT_SNDFX,
270 g_param_spec_boolean("soft_sndfx", "soft_sndfx", "soft_sndfx",
271 TRUE, G_PARAM_READWRITE ));
272 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_STEREO,
273 g_param_spec_boolean("stereo", "stereo", "stereo",
274 TRUE, G_PARAM_READWRITE ));
277 gobject_class->set_property = gst_mikmod_set_property;
278 gobject_class->get_property = gst_mikmod_get_property;
280 gstelement_class->change_state = gst_mikmod_change_state;
285 gst_mikmod_init (GstMikMod *filter)
287 filter->sinkpad = gst_pad_new_from_template(mikmod_sink_factory (),"sink");
288 filter->srcpad = gst_pad_new_from_template(mikmod_src_factory (),"src");
290 gst_element_add_pad(GST_ELEMENT(filter),filter->sinkpad);
291 gst_element_add_pad(GST_ELEMENT(filter),filter->srcpad);
293 gst_element_set_loop_function (GST_ELEMENT (filter), gst_mikmod_loop);
295 filter->Buffer = NULL;
297 filter->stereo = TRUE;
298 filter->surround = TRUE;
299 filter->_16bit = TRUE;
300 filter->soft_music = TRUE;
301 filter->soft_sndfx = TRUE;
302 filter->mixfreq = 44100;
304 filter->pansep = 128;
305 filter->musicvolume = 128;
307 filter->sndfxvolume = 128;
312 gst_mikmod_loop (GstElement *element)
315 GstBuffer *buffer_in;
319 g_return_if_fail (element != NULL);
320 g_return_if_fail (GST_IS_MIKMOD (element));
322 mikmod = GST_MIKMOD (element);
323 srcpad = mikmod->srcpad;
324 mikmod->Buffer = NULL;
326 while ((buffer_in = gst_pad_pull( mikmod->sinkpad ))) {
327 if ( GST_IS_EVENT (buffer_in) ) {
328 GstEvent *event = GST_EVENT (buffer_in);
330 if (GST_EVENT_TYPE (event) == GST_EVENT_EOS)
334 if ( mikmod->Buffer ) {
335 mikmod->Buffer = gst_buffer_append( mikmod->Buffer, buffer_in );
336 gst_buffer_unref( buffer_in );
339 mikmod->Buffer = buffer_in;
342 if ( mikmod->_16bit )
347 MikMod_RegisterDriver(&drv_gst);
348 MikMod_RegisterAllLoaders();
351 reader = GST_READER_new( mikmod );
352 module = Player_LoadGeneric ( reader, 64, 0 );
354 gst_buffer_unref (mikmod->Buffer);
356 if ( ! Player_Active() )
357 Player_Start(module);
359 gst_pad_try_set_caps (mikmod->srcpad,
363 "format", GST_PROPS_STRING ("int"),
364 "law", GST_PROPS_INT (0),
365 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
366 "signed", GST_PROPS_BOOLEAN (TRUE),
367 "width", GST_PROPS_INT (mode16bits),
368 "depth", GST_PROPS_INT (mode16bits),
369 "rate", GST_PROPS_INT (mikmod->mixfreq),
370 "channels", GST_PROPS_INT (2)));
373 if ( Player_Active() ) {
376 gst_element_yield (element);
379 gst_element_set_eos (GST_ELEMENT (mikmod));
380 gst_pad_push (mikmod->srcpad, GST_BUFFER (gst_event_new (GST_EVENT_EOS)));
389 gst_mikmod_setup (GstMikMod *mikmod)
391 md_musicvolume = mikmod->musicvolume;
392 md_pansep = mikmod->pansep;
393 md_reverb = mikmod->reverb;
394 md_sndfxvolume = mikmod->sndfxvolume;
395 md_volume = mikmod->volume;
396 md_mixfreq = mikmod->mixfreq;
400 if ( mikmod->interp )
401 md_mode = md_mode | DMODE_INTERP;
403 if ( mikmod->reverse )
404 md_mode = md_mode | DMODE_REVERSE;
406 if ( mikmod->surround )
407 md_mode = md_mode | DMODE_SURROUND;
409 if ( mikmod->_16bit )
410 md_mode = md_mode | DMODE_16BITS;
412 if ( mikmod->hqmixer )
413 md_mode = md_mode | DMODE_HQMIXER;
415 if ( mikmod->soft_music )
416 md_mode = md_mode | DMODE_SOFT_MUSIC;
418 if ( mikmod->soft_sndfx )
419 md_mode = md_mode | DMODE_SOFT_SNDFX;
421 if ( mikmod->stereo )
422 md_mode = md_mode | DMODE_STEREO;
428 static GstElementStateReturn
429 gst_mikmod_change_state (GstElement *element)
433 g_return_val_if_fail (GST_IS_MIKMOD (element), GST_STATE_FAILURE);
435 mikmod = GST_MIKMOD (element);
437 GST_DEBUG (0,"state pending %d\n", GST_STATE_PENDING (element));
439 /* if going down into NULL state, close the file if it's open */
440 if (GST_STATE_PENDING (element) == GST_STATE_READY)
442 gst_mikmod_setup(mikmod);
444 if ( Player_Active() )
446 Player_TogglePause();
447 Player_SetPosition( 0 );
452 if (GST_STATE_PENDING (element) == GST_STATE_PLAYING)
454 if ( Player_Active() && Player_Paused() )
455 Player_TogglePause();
457 if ( ! Player_Active() )
458 Player_Start(module);
462 if (GST_STATE_PENDING (element) == GST_STATE_PAUSED)
463 if ( Player_Active() && ! Player_Paused() )
464 Player_TogglePause();
466 if (GST_STATE_PENDING (element) == GST_STATE_NULL)
470 /* if we haven't failed already, give the parent class a chance to ;-) */
471 if (GST_ELEMENT_CLASS (parent_class)->change_state)
472 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
474 return GST_STATE_SUCCESS;
480 gst_mikmod_set_property (GObject *object, guint id, const GValue *value, GParamSpec *pspec )
484 /* it's not null if we got it, but it might not be ours */
485 g_return_if_fail(GST_IS_MIKMOD(object));
486 filter = GST_MIKMOD(object);
490 filter->songname = g_value_get_string (value);
493 filter->modtype = g_value_get_string (value);
495 case ARG_MUSICVOLUME:
496 filter->musicvolume = g_value_get_int (value);
499 filter->pansep = g_value_get_int (value);
502 filter->reverb = g_value_get_int (value);
504 case ARG_SNDFXVOLUME:
505 filter->sndfxvolume = g_value_get_int (value);
508 filter->volume = g_value_get_int (value);
511 filter->mixfreq = g_value_get_enum (value);
514 filter->interp = g_value_get_boolean (value);
517 filter->reverse = g_value_get_boolean (value);
520 filter->surround = g_value_get_boolean (value);
523 filter->_16bit = g_value_get_boolean (value);
526 filter->hqmixer = g_value_get_boolean (value);
529 filter->soft_music = g_value_get_boolean (value);
532 filter->soft_sndfx = g_value_get_boolean (value);
535 filter->stereo = g_value_get_boolean (value);
538 /* G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); */
544 gst_mikmod_get_property (GObject *object, guint id, GValue *value, GParamSpec *pspec )
548 /* it's not null if we got it, but it might not be ours */
549 g_return_if_fail(GST_IS_MIKMOD(object));
550 filter = GST_MIKMOD(object);
553 case ARG_MUSICVOLUME:
554 g_value_set_int (value, filter->musicvolume);
557 g_value_set_int (value, filter->pansep);
560 g_value_set_int (value, filter->reverb);
562 case ARG_SNDFXVOLUME:
563 g_value_set_int (value, filter->sndfxvolume);
566 g_value_set_int (value, filter->volume);
569 g_value_set_int (value, filter->mixfreq);
572 g_value_set_boolean (value, filter->interp);
575 g_value_set_boolean (value, filter->reverse);
578 g_value_set_boolean (value, filter->surround);
581 g_value_set_boolean (value, filter->_16bit);
584 g_value_set_boolean (value, filter->hqmixer);
587 g_value_set_boolean (value, filter->soft_music);
590 g_value_set_boolean (value, filter->soft_sndfx);
593 g_value_set_boolean (value, filter->stereo);
596 /* G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); */
602 plugin_init (GModule *module, GstPlugin *plugin)
604 GstElementFactory *factory;
605 GstTypeFactory *type;
607 factory = gst_elementfactory_new("mikmod",GST_TYPE_MIKMOD,
609 g_return_val_if_fail(factory != NULL, FALSE);
611 gst_elementfactory_add_padtemplate (factory, mikmod_src_factory ());
612 gst_elementfactory_add_padtemplate (factory, mikmod_sink_factory ());
614 type = gst_typefactory_new (&mikmoddefinition);
615 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
616 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
621 GstPluginDesc plugin_desc = {