filter newlines out of GST_DEBUG statements to reflect new core behavior fixes to...
[platform/upstream/gstreamer.git] / ext / mikmod / gstmikmod.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include "gstmikmod.h"
21
22 #include <gst/audio/audio.h>
23 #include <stdlib.h>
24
25 GstElementDetails mikmod_details = {
26   "MikMod",
27   "Audio/Module",
28   "Module decoder based on libmikmod",
29   VERSION,
30   "Jeremy SIMON <jsimon13@yahoo.fr>",
31   "(C) 2001",
32 };
33
34
35 /* Filter signals and args */
36 enum {
37   /* FILL ME */
38   LAST_SIGNAL
39 };
40
41 enum {
42   ARG_0,
43   ARG_SONGNAME,
44   ARG_MODTYPE,
45   ARG_MUSICVOLUME,
46   ARG_PANSEP,
47   ARG_REVERB,
48   ARG_SNDFXVOLUME,
49   ARG_VOLUME,
50   ARG_FIXFREQ,
51   ARG_INTERP,
52   ARG_REVERSE,
53   ARG_SURROUND,
54   ARG_16BIT,
55   ARG_HQMIXER,
56   ARG_SOFT_MUSIC,
57   ARG_SOFT_SNDFX,
58   ARG_STEREO
59 };
60
61
62 static GstPadTemplate*
63 mikmod_src_factory (void)
64 {
65   static GstPadTemplate *template = NULL;
66
67   if (!template) {
68     template = gst_padtemplate_new (
69       "src",
70       GST_PAD_SRC,
71       GST_PAD_ALWAYS,
72       gst_caps_new (
73         "mikmod_src",
74         "audio/raw",
75         gst_props_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),
84             NULL)),NULL);
85   }
86   return template;
87 }
88
89
90 static GstPadTemplate*
91 mikmod_sink_factory (void)
92 {
93   static GstPadTemplate *template = NULL;
94
95   if (!template) {
96     template = gst_padtemplate_new (
97       "sink",
98       GST_PAD_SINK,
99       GST_PAD_ALWAYS,
100       gst_caps_new (
101         "mikmod_sink",
102         "audio/mod",
103         NULL),NULL        
104       );
105   }
106   return template;
107 }
108
109 static GstCaps* 
110 mikmod_typefind (GstBuffer *buf, gpointer private) 
111 {  
112   if ( MOD_CheckType( buf ) )
113     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
114   
115   if ( Mod_669_CheckType( buf ) )
116     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
117   
118   if ( Amf_CheckType( buf ) )
119     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
120   
121   if ( Dsm_CheckType( buf ) )
122     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
123   
124   if ( Fam_CheckType( buf ) )
125     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
126   
127   if ( Gdm_CheckType( buf ) )
128     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
129   
130   if ( Imf_CheckType( buf ) )
131     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
132   
133   if ( It_CheckType( buf ) )
134     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
135   
136   if ( M15_CheckType( buf ) )
137     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
138   
139   /* FIXME
140   if ( Med_CheckType( buf ) )
141     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
142     */
143   
144   if ( Mtm_CheckType( buf ) )
145     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
146   
147   if ( Okt_CheckType( buf ) )
148     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
149   
150   if ( S3m_CheckType( buf ) )
151     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
152   
153   if ( Xm_CheckType( buf ) )
154     return gst_caps_new ("mikmod_typefind", "audio/mod", NULL);
155   
156   return NULL;
157 }
158
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 
161 };
162
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);
170
171
172
173 static GstElementClass *parent_class = NULL;
174
175 #define GST_TYPE_MIKMOD_MIXFREQ (gst_mikmod_mixfreq_get_type())
176
177 static GType 
178 gst_mikmod_mixfreq_get_type (void)
179 {
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" },
186     { 0, NULL, NULL },
187   };
188   if (! mikmod_mixfreq_type ) {
189     mikmod_mixfreq_type = g_enum_register_static ("GstMikmodmixfreq", mikmod_mixfreq);
190   }
191   return mikmod_mixfreq_type;
192 }
193
194 GType
195 gst_mikmod_get_type(void) {
196   static GType mikmod_type = 0;
197
198   if (!mikmod_type) {
199     static const GTypeInfo mikmod_info = {
200       sizeof(GstMikModClass),
201       NULL,
202       NULL,
203       (GClassInitFunc)gst_mikmod_class_init,
204       NULL,
205       NULL,
206       sizeof(GstMikMod),
207       0,
208       (GInstanceInitFunc)gst_mikmod_init,
209     };
210     mikmod_type = g_type_register_static(GST_TYPE_ELEMENT, "GstMikmod", &mikmod_info, 0);
211   }
212   return mikmod_type;
213 }
214
215
216 static void
217 gst_mikmod_class_init (GstMikModClass *klass)
218 {
219   GObjectClass *gobject_class;
220   GstElementClass *gstelement_class;
221
222   gobject_class = (GObjectClass*)klass;
223   gstelement_class = (GstElementClass*)klass;
224
225   parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
226
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 ));
275
276   
277   gobject_class->set_property = gst_mikmod_set_property;
278   gobject_class->get_property = gst_mikmod_get_property;
279
280   gstelement_class->change_state = gst_mikmod_change_state;
281 }
282
283
284 static void
285 gst_mikmod_init (GstMikMod *filter)
286 {  
287   filter->sinkpad = gst_pad_new_from_template(mikmod_sink_factory (),"sink");
288   filter->srcpad = gst_pad_new_from_template(mikmod_src_factory (),"src");
289
290   gst_element_add_pad(GST_ELEMENT(filter),filter->sinkpad);
291   gst_element_add_pad(GST_ELEMENT(filter),filter->srcpad);
292   
293   gst_element_set_loop_function (GST_ELEMENT (filter), gst_mikmod_loop);
294   
295   filter->Buffer = NULL;
296
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;
303   filter->reverb      = 0;
304   filter->pansep      = 128;
305   filter->musicvolume = 128;
306   filter->volume      = 96;
307   filter->sndfxvolume = 128;
308 }
309
310
311 static void
312 gst_mikmod_loop (GstElement *element)
313 {
314   GstMikMod *mikmod;
315   GstBuffer *buffer_in;
316   gint mode16bits;
317   gint first = 0;
318
319   g_return_if_fail (element != NULL);
320   g_return_if_fail (GST_IS_MIKMOD (element));
321         
322   mikmod = GST_MIKMOD (element);
323   srcpad = mikmod->srcpad;
324   mikmod->Buffer = NULL;
325         
326   while ((buffer_in = gst_pad_pull( mikmod->sinkpad ))) {
327     if ( GST_IS_EVENT (buffer_in) ) {
328       GstEvent *event = GST_EVENT (buffer_in);
329                 
330       if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) 
331          break;
332     }
333                 
334     if ( mikmod->Buffer ) {      
335       mikmod->Buffer = gst_buffer_append( mikmod->Buffer, buffer_in );
336       gst_buffer_unref( buffer_in );              
337     }
338     else
339       mikmod->Buffer = buffer_in;
340   }  
341   
342   if ( mikmod->_16bit )
343     mode16bits = 16;
344   else
345     mode16bits = 8;
346
347   MikMod_RegisterDriver(&drv_gst);
348   MikMod_RegisterAllLoaders();
349
350   MikMod_Init("");
351   reader = GST_READER_new( mikmod );
352   module = Player_LoadGeneric ( reader, 64, 0 );
353   
354   gst_buffer_unref (mikmod->Buffer);
355   
356   if ( ! Player_Active() )
357     Player_Start(module);
358
359   gst_pad_try_set_caps (mikmod->srcpad, 
360                           GST_CAPS_NEW (
361                             "mikmod_src",
362                             "audio/raw",
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)));
371                                     
372   do {
373     if ( Player_Active() ) {
374       drv_gst.Update();
375
376       gst_element_yield (element);
377     }
378     else {
379       gst_element_set_eos (GST_ELEMENT (mikmod));
380       gst_pad_push (mikmod->srcpad, GST_BUFFER (gst_event_new (GST_EVENT_EOS)));
381     }
382
383   } 
384   while ( 1 );
385 }
386
387
388 static gboolean
389 gst_mikmod_setup (GstMikMod *mikmod)
390 {
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;
397
398   md_mode = 0;
399
400   if ( mikmod->interp )
401     md_mode = md_mode | DMODE_INTERP;
402
403   if ( mikmod->reverse )
404     md_mode = md_mode | DMODE_REVERSE;
405
406   if ( mikmod->surround )
407     md_mode = md_mode | DMODE_SURROUND;
408
409   if ( mikmod->_16bit )
410     md_mode = md_mode | DMODE_16BITS;
411
412   if ( mikmod->hqmixer )
413     md_mode = md_mode | DMODE_HQMIXER;
414
415   if ( mikmod->soft_music )
416     md_mode = md_mode | DMODE_SOFT_MUSIC;
417
418   if ( mikmod->soft_sndfx )
419     md_mode = md_mode | DMODE_SOFT_SNDFX;
420
421   if ( mikmod->stereo )
422     md_mode = md_mode | DMODE_STEREO;
423
424   return TRUE;
425 }
426
427
428 static GstElementStateReturn
429 gst_mikmod_change_state (GstElement *element)
430 {
431 GstMikMod *mikmod;
432
433   g_return_val_if_fail (GST_IS_MIKMOD (element), GST_STATE_FAILURE);
434
435   mikmod = GST_MIKMOD (element);
436
437   GST_DEBUG (0,"state pending %d", GST_STATE_PENDING (element));
438
439   /* if going down into NULL state, close the file if it's open */
440   if (GST_STATE_PENDING (element) == GST_STATE_READY) 
441   {
442      gst_mikmod_setup(mikmod);
443           
444          if ( Player_Active() )
445          {
446                 Player_TogglePause();
447                 Player_SetPosition( 0 );
448          }
449         
450   }
451   
452   if (GST_STATE_PENDING (element) == GST_STATE_PLAYING) 
453   {      
454          if ( Player_Active() && Player_Paused() )       
455                 Player_TogglePause();
456          else
457            if ( ! Player_Active() )
458              Player_Start(module);
459          
460   }
461         
462   if (GST_STATE_PENDING (element) == GST_STATE_PAUSED) 
463     if ( Player_Active() && ! Player_Paused() )
464        Player_TogglePause();
465
466   if (GST_STATE_PENDING (element) == GST_STATE_NULL) 
467           MikMod_Exit();    
468   
469
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);
473
474   return GST_STATE_SUCCESS;
475 }
476
477
478
479 static void
480 gst_mikmod_set_property (GObject *object, guint id, const GValue *value, GParamSpec *pspec )
481 {
482   GstMikMod *filter;
483
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);
487
488   switch (id) {
489     case ARG_SONGNAME:
490       filter->songname = g_value_get_string (value);
491       break;
492     case ARG_MODTYPE:
493       filter->modtype = g_value_get_string (value);
494       break;
495     case ARG_MUSICVOLUME:
496       filter->musicvolume = g_value_get_int (value);
497       break;
498     case ARG_PANSEP:
499       filter->pansep = g_value_get_int (value);
500       break;
501     case ARG_REVERB:
502       filter->reverb = g_value_get_int (value);
503       break;
504     case ARG_SNDFXVOLUME:
505       filter->sndfxvolume = g_value_get_int (value);
506       break;
507     case ARG_VOLUME:
508       filter->volume = g_value_get_int (value);
509       break;
510     case ARG_FIXFREQ:
511       filter->mixfreq = g_value_get_enum (value);
512       break;
513     case ARG_INTERP:
514       filter->interp = g_value_get_boolean (value);
515       break;
516     case ARG_REVERSE:
517       filter->reverse = g_value_get_boolean (value);
518       break;
519     case ARG_SURROUND:
520       filter->surround = g_value_get_boolean (value);
521       break;
522     case ARG_16BIT:
523       filter->_16bit = g_value_get_boolean (value);
524       break;
525     case ARG_HQMIXER:
526       filter->hqmixer = g_value_get_boolean (value);
527       break;
528     case ARG_SOFT_MUSIC:
529       filter->soft_music = g_value_get_boolean (value);
530       break;
531     case ARG_SOFT_SNDFX:
532       filter->soft_sndfx = g_value_get_boolean (value);
533       break;
534     case ARG_STEREO:
535       filter->stereo = g_value_get_boolean (value);
536       break;
537     default:
538 /*      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); */
539       break;
540   }
541 }
542
543 static void
544 gst_mikmod_get_property (GObject *object, guint id, GValue *value, GParamSpec *pspec )
545 {
546   GstMikMod *filter;
547
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);
551
552   switch (id) {
553     case ARG_MUSICVOLUME:
554       g_value_set_int (value, filter->musicvolume);
555       break;
556     case ARG_PANSEP:
557       g_value_set_int (value, filter->pansep);
558       break;
559     case ARG_REVERB:
560       g_value_set_int (value, filter->reverb);
561       break;
562     case ARG_SNDFXVOLUME:
563       g_value_set_int (value, filter->sndfxvolume);
564       break;
565     case ARG_VOLUME:
566       g_value_set_int (value, filter->volume);
567       break;
568     case ARG_FIXFREQ:
569       g_value_set_int (value, filter->mixfreq);
570       break;
571     case ARG_INTERP:
572       g_value_set_boolean (value, filter->interp);
573       break;
574     case ARG_REVERSE:
575       g_value_set_boolean (value, filter->reverse);
576       break;
577     case ARG_SURROUND:
578       g_value_set_boolean (value, filter->surround);
579       break;
580     case ARG_16BIT:
581       g_value_set_boolean (value, filter->_16bit);
582       break;
583     case ARG_HQMIXER:
584       g_value_set_boolean (value, filter->hqmixer);
585       break;
586     case ARG_SOFT_MUSIC:
587       g_value_set_boolean (value, filter->soft_music);
588       break;
589     case ARG_SOFT_SNDFX:
590       g_value_set_boolean (value, filter->soft_sndfx);
591       break;
592     case ARG_STEREO:
593       g_value_set_boolean (value, filter->stereo);
594       break;
595     default:
596 /*      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); */
597       break;
598   }
599 }
600
601 static gboolean
602 plugin_init (GModule *module, GstPlugin *plugin)
603 {
604   GstElementFactory *factory;
605   GstTypeFactory    *type;  
606         
607   factory = gst_elementfactory_new("mikmod",GST_TYPE_MIKMOD,
608                                    &mikmod_details);
609   g_return_val_if_fail(factory != NULL, FALSE);
610  
611   gst_elementfactory_add_padtemplate (factory, mikmod_src_factory ());
612   gst_elementfactory_add_padtemplate (factory, mikmod_sink_factory ());
613
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));        
617
618   return TRUE;
619 }
620
621 GstPluginDesc plugin_desc = {
622   GST_VERSION_MAJOR,
623   GST_VERSION_MINOR,
624   "mikmod",
625   plugin_init
626 };