cleanups
[platform/upstream/gst-plugins-good.git] / ext / lame / gstlame.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 "gstlame.h"
21
22 /* elementfactory information */
23 static GstElementDetails gst_lame_details = 
24 {
25   "L.A.M.E. mp3 encoder",
26   "Codec/Audio/Encoder",
27   "GPL",
28   "High-quality free MP3 encoder",
29   VERSION,
30   "Erik Walthinsen <omega@cse.ogi.edu>",
31   "(C) 2000",
32 };
33
34 GST_PAD_TEMPLATE_FACTORY (gst_lame_sink_factory,
35   "sink",
36   GST_PAD_SINK,
37   GST_PAD_ALWAYS,
38   GST_CAPS_NEW (
39     "gstlame_sink",
40     "audio/raw",
41       "format",     GST_PROPS_STRING ("int"),
42       "law",        GST_PROPS_INT (0),
43       "endianness", GST_PROPS_INT (G_BYTE_ORDER),
44       "signed",     GST_PROPS_BOOLEAN (TRUE),
45       "width",      GST_PROPS_INT (16),
46       "depth",      GST_PROPS_INT (16),
47       "rate",       GST_PROPS_LIST (
48                       GST_PROPS_INT (8000), 
49                       GST_PROPS_INT (11025), 
50                       GST_PROPS_INT (12000), 
51                       GST_PROPS_INT (16000), 
52                       GST_PROPS_INT (22050),
53                       GST_PROPS_INT (24000),
54                       GST_PROPS_INT (32000),
55                       GST_PROPS_INT (44100),
56                       GST_PROPS_INT (48000)
57                     ),
58       "channels",   GST_PROPS_INT_RANGE (1, 2)
59   )
60 )
61
62 GST_PAD_TEMPLATE_FACTORY (gst_lame_src_factory,
63   "src",
64   GST_PAD_SRC,
65   GST_PAD_ALWAYS,
66   GST_CAPS_NEW (
67     "gstlame_src",
68     "audio/mp3",
69     NULL
70   )
71 )
72
73 /********** Define useful types for non-programmatic interfaces **********/
74 #define GST_TYPE_LAME_MODE (gst_lame_mode_get_type())
75 static GType
76 gst_lame_mode_get_type (void)
77 {
78   static GType lame_mode_type = 0;
79   static GEnumValue lame_modes[] = {
80     { 0, "0", "Stereo" },
81     { 1, "1", "Joint-Stereo" },
82     { 2, "2", "Dual channel" },
83     { 3, "3", "Mono" },
84     { 4, "4", "Auto" },
85     { 0, NULL, NULL },
86   };
87   if (!lame_mode_type) {
88     lame_mode_type = g_enum_register_static ("GstLameMode", lame_modes);
89   }
90   return lame_mode_type;
91 }
92
93 #define GST_TYPE_LAME_QUALITY (gst_lame_quality_get_type())
94 static GType
95 gst_lame_quality_get_type (void)
96 {
97   static GType lame_quality_type = 0;
98   static GEnumValue lame_quality[] = {
99     { 0, "0", "0 - Best" },
100     { 1, "1", "1" },
101     { 2, "2", "2" },
102     { 3, "3", "3" },
103     { 4, "4", "4" },
104     { 5, "5", "5 - Default" },
105     { 6, "6", "6" },
106     { 7, "7", "7" },
107     { 8, "8", "8" },
108     { 9, "9", "9 - Worst" },
109     { 0, NULL, NULL },
110   };
111   if (!lame_quality_type) {
112     lame_quality_type = g_enum_register_static ("GstLameQuality", lame_quality);
113   }
114   return lame_quality_type;
115 }
116
117 #define GST_TYPE_LAME_PADDING (gst_lame_padding_get_type())
118 static GType
119 gst_lame_padding_get_type (void)
120 {
121   static GType lame_padding_type = 0;
122   static GEnumValue lame_padding[] = {
123     { 0, "0", "No Padding" },
124     { 1, "1", "Always Pad" },
125     { 2, "2", "Adjust Padding" },
126     { 0, NULL, NULL },
127   };
128   if (!lame_padding_type) {
129     lame_padding_type = g_enum_register_static ("GstLamePadding", lame_padding);
130   }
131   return lame_padding_type;
132 }
133
134 /********** Standard stuff for signals and arguments **********/
135 /* GstLame signals and args */
136 enum {
137   /* FILL_ME */
138   LAST_SIGNAL
139 };
140
141 enum {
142   ARG_0,
143   ARG_BITRATE,
144   ARG_COMPRESSION_RATIO,
145   ARG_QUALITY,
146   ARG_MODE,
147   ARG_FORCE_MS,
148   ARG_FREE_FORMAT,
149   ARG_COPYRIGHT,
150   ARG_ORIGINAL,
151   ARG_ERROR_PROTECTION,
152   ARG_PADDING_TYPE,
153   ARG_EXTENSION,
154   ARG_STRICT_ISO,
155   ARG_DISABLE_RESERVOIR,
156   ARG_VBR,
157   ARG_VBR_MEAN_BITRATE,
158   ARG_VBR_MIN_BITRATE,
159   ARG_VBR_MAX_BITRATE,
160   ARG_VBR_HARD_MIN,
161   ARG_LOWPASS_FREQ,
162   ARG_LOWPASS_WIDTH,
163   ARG_HIGHPASS_FREQ,
164   ARG_HIGHPASS_WIDTH,
165   ARG_ATH_ONLY,
166   ARG_ATH_SHORT,
167   ARG_NO_ATH,
168   ARG_ATH_LOWER,
169   ARG_CWLIMIT,
170   ARG_ALLOW_DIFF_SHORT,
171   ARG_NO_SHORT_BLOCKS,
172   ARG_EMPHASIS,
173 };
174
175
176 static void                     gst_lame_class_init     (GstLameClass *klass);
177 static void                     gst_lame_init           (GstLame *gst_lame);
178
179 static void                     gst_lame_set_property   (GObject *object, guint prop_id, 
180                                                          const GValue *value, GParamSpec *pspec);
181 static void                     gst_lame_get_property   (GObject *object, guint prop_id, 
182                                                          GValue *value, GParamSpec *pspec);
183 static void                     gst_lame_chain          (GstPad *pad, GstBuffer *buf);
184 static gboolean                 gst_lame_setup          (GstLame *lame);
185 static GstElementStateReturn    gst_lame_change_state   (GstElement *element);
186
187 static GstElementClass *parent_class = NULL;
188 /* static guint gst_lame_signals[LAST_SIGNAL] = { 0 }; */
189
190 GType
191 gst_lame_get_type (void)
192 {
193   static GType gst_lame_type = 0;
194
195   if (!gst_lame_type) {
196     static const GTypeInfo gst_lame_info = {
197       sizeof (GstLameClass),      
198       NULL,
199       NULL,
200       (GClassInitFunc) gst_lame_class_init,
201       NULL,
202       NULL,
203       sizeof(GstLame),
204       0,
205       (GInstanceInitFunc) gst_lame_init,
206     };
207     gst_lame_type = g_type_register_static (GST_TYPE_ELEMENT, "GstLame", &gst_lame_info, 0);
208   }
209   return gst_lame_type;
210 }
211
212 static void
213 gst_lame_class_init (GstLameClass *klass)
214 {
215   GObjectClass *gobject_class;
216   GstElementClass *gstelement_class;
217
218   gobject_class = (GObjectClass*)klass;
219   gstelement_class = (GstElementClass*)klass;
220
221   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
222
223   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
224     g_param_spec_int("bitrate", "Bitrate (kb/s)", "Bitrate in kbit/sec",
225                      8, 320, 128, G_PARAM_READWRITE)); 
226   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COMPRESSION_RATIO,
227     g_param_spec_float ("compression_ratio", "Compression Ratio",
228                         "choose bitrate to achive selected compression ratio",
229                         1.0, 200.0, 11.0, G_PARAM_READWRITE));
230   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
231     g_param_spec_enum ("quality", "Quality", "Encoding Quality",
232                        GST_TYPE_LAME_QUALITY, 5, G_PARAM_READWRITE));
233   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MODE,
234     g_param_spec_enum ("mode", "Mode", "Encoding mode",
235                        GST_TYPE_LAME_MODE, 0, G_PARAM_READWRITE));
236   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FORCE_MS,
237     g_param_spec_boolean ("force_ms","Force ms","Force ms_stereo on all frames",
238                           TRUE, G_PARAM_READWRITE));
239   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FREE_FORMAT,
240     g_param_spec_boolean ("free_format","Free format","Produce a free format bitstream",
241                           TRUE, G_PARAM_READWRITE));
242   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COPYRIGHT,
243     g_param_spec_boolean ("copyright","Copyright","Mark as copyright",
244                           TRUE, G_PARAM_READWRITE));
245   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ORIGINAL,
246     g_param_spec_boolean("original", "Original", "Mark as non-original",
247                          TRUE, G_PARAM_READWRITE));
248   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ERROR_PROTECTION,
249     g_param_spec_boolean ("error_protection","Error protection",
250                           "Adds 16 bit checksum to every frame",
251                           TRUE, G_PARAM_READWRITE));
252   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PADDING_TYPE,
253     g_param_spec_enum ("padding_type", "Padding type", "Padding type",
254                        GST_TYPE_LAME_PADDING, 0, G_PARAM_READWRITE));
255   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EXTENSION,
256     g_param_spec_boolean ("extension", "Extension", "Extension",
257                           TRUE, G_PARAM_READWRITE));
258   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STRICT_ISO,
259     g_param_spec_boolean ("strict_iso", "Strict ISO",
260                           "Comply as much as possible to ISO MPEG spec",
261                           TRUE, G_PARAM_READWRITE));
262   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DISABLE_RESERVOIR,
263     g_param_spec_boolean ("disable_reservoir", "Disable reservoir", "Disable the bit reservoir",
264                           TRUE, G_PARAM_READWRITE));
265   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR,
266     g_param_spec_boolean ("vbr", "VBR", "Use variable bitrate",
267                           TRUE, G_PARAM_READWRITE));
268   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MEAN_BITRATE,
269     g_param_spec_int ("vbr_mean_bitrate", "VBR mean bitrate", "Specify mean bitrate",
270                       0, G_MAXINT, 0, G_PARAM_READWRITE));
271   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MIN_BITRATE,
272     g_param_spec_int ("vbr_min_bitrate", "VBR min bitrate", "Specify min bitrate",
273                       0, G_MAXINT, 0, G_PARAM_READWRITE));
274   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VBR_MAX_BITRATE,
275     g_param_spec_int ("vbr_max_bitrate", "VBR max bitrate", "Specify max bitrate",
276                       0, G_MAXINT, 0, G_PARAM_READWRITE));
277   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VBR_HARD_MIN,
278     g_param_spec_int ("vbr_hard_min", "VBR hard min", "Specify hard min bitrate",
279                       0, G_MAXINT, 0, G_PARAM_READWRITE));
280   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOWPASS_FREQ,
281     g_param_spec_int ("lowpass_freq", "Lowpass freq", 
282                         "frequency(kHz), lowpass filter cutoff above freq",
283                         0, 50000, 0, G_PARAM_READWRITE));
284   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOWPASS_WIDTH,
285     g_param_spec_int ("lowpass_width", "Lowpass width", 
286                       "frequency(kHz) - default 15% of lowpass freq",
287                       0, G_MAXINT, 0, G_PARAM_READWRITE)); 
288   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HIGHPASS_FREQ,
289     g_param_spec_int ("highpass_freq", "Highpass freq", 
290                       "frequency(kHz), highpass filter cutoff below freq",
291                       0, 50000, 0, G_PARAM_READWRITE));
292   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HIGHPASS_WIDTH,
293     g_param_spec_int ("highpass_width", "Highpass width",
294                       "frequency(kHz) - default 15% of highpass freq",
295                       0, G_MAXINT, 0, G_PARAM_READWRITE));
296   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_ONLY,
297     g_param_spec_boolean ("ath_only", "ATH only", 
298                           "Ignore GPSYCHO completely, use ATH only",
299                           TRUE, G_PARAM_READWRITE));
300   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_SHORT,
301     g_param_spec_boolean ("ath_short", "ATH short", 
302                           "Ignore GPSYCHO for short blocks, use ATH only",
303                           TRUE, G_PARAM_READWRITE));
304   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NO_ATH,
305     g_param_spec_boolean ("no_ath", "No ath", "turns ATH down to a flat noise floor",
306                           TRUE, G_PARAM_READWRITE));
307   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_LOWER,
308     g_param_spec_int ("ath_lower", "ATH lower", "lowers ATH by x dB",
309                       G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
310   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CWLIMIT,
311     g_param_spec_int ("cwlimit", "Cwlimit", "Compute tonality up to freq (in kHz) default 8.8717",
312                       0, 50000, 0, G_PARAM_READWRITE));
313   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ALLOW_DIFF_SHORT,
314     g_param_spec_boolean ("allow_diff_short", "Allow diff short", "Allow diff short",
315                           TRUE, G_PARAM_READWRITE)); 
316   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NO_SHORT_BLOCKS,
317     g_param_spec_boolean ("no_short_blocks", "No short blocks", "Do not use short blocks",
318                           TRUE, G_PARAM_READWRITE));
319   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EMPHASIS,
320     g_param_spec_boolean ("emphasis", "Emphasis", "Emphasis",
321                           TRUE, G_PARAM_READWRITE));
322
323   gobject_class->set_property = gst_lame_set_property;
324   gobject_class->get_property = gst_lame_get_property;
325
326   gstelement_class->change_state = gst_lame_change_state;
327 }
328
329 static GstPadConnectReturn
330 gst_lame_sinkconnect (GstPad *pad, GstCaps *caps)
331 {
332   GstLame *lame;
333
334   lame = GST_LAME (gst_pad_get_parent (pad));
335
336   if (!GST_CAPS_IS_FIXED (caps)) {
337     GST_DEBUG (GST_CAT_CAPS, "caps on lame pad %s:%s not fixed, delayed",
338                GST_DEBUG_PAD_NAME (pad));
339     return GST_PAD_CONNECT_DELAYED;
340   }
341
342   gst_caps_get_int (caps, "rate", &lame->samplerate);
343   gst_caps_get_int (caps, "channels", &lame->num_channels);
344
345   if (!gst_lame_setup (lame)) {
346     gst_element_error (GST_ELEMENT (lame), 
347                        "could not initialize encoder (wrong parameters?)");
348     return GST_PAD_CONNECT_REFUSED;
349   }
350
351   return GST_PAD_CONNECT_OK;
352 }
353
354 static void
355 gst_lame_init (GstLame *lame)
356 {
357   GST_DEBUG_ENTER ("(\"%s\")", gst_element_get_name (GST_ELEMENT (lame)));
358
359   lame->sinkpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (gst_lame_sink_factory), "sink");
360   gst_element_add_pad (GST_ELEMENT (lame), lame->sinkpad);
361   gst_pad_set_chain_function (lame->sinkpad, gst_lame_chain);
362   gst_pad_set_connect_function (lame->sinkpad, gst_lame_sinkconnect);
363
364   lame->srcpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (gst_lame_src_factory), "src");
365   gst_element_add_pad (GST_ELEMENT (lame), lame->srcpad);
366
367   GST_FLAG_SET (lame, GST_ELEMENT_EVENT_AWARE);
368
369   GST_DEBUG (GST_CAT_PLUGIN_INFO, "setting up lame encoder");
370   lame->lgf = lame_init ();
371
372   lame->samplerate = 44100;
373   lame->num_channels = 2;
374   lame->initialized = FALSE;
375
376   lame->bitrate = lame_get_brate (lame->lgf);
377   lame->compression_ratio = lame_get_compression_ratio (lame->lgf);
378   lame->quality = lame_get_quality (lame->lgf);
379   lame->mode = lame_get_mode (lame->lgf);
380   lame->force_ms = lame_get_force_ms (lame->lgf);
381   lame->free_format = lame_get_free_format (lame->lgf);
382   lame->copyright = lame_get_copyright (lame->lgf);
383   lame->original = lame_get_original (lame->lgf);
384   lame->error_protection = lame_get_error_protection (lame->lgf);
385   lame->padding_type = lame_get_padding_type (lame->lgf);
386   lame->extension = lame_get_extension (lame->lgf);
387   lame->strict_iso = lame_get_strict_ISO (lame->lgf);
388   lame->disable_reservoir = lame_get_disable_reservoir (lame->lgf);
389   lame->vbr = lame_get_VBR_q (lame->lgf);
390   lame->vbr_mean_bitrate = lame_get_VBR_mean_bitrate_kbps (lame->lgf);
391   lame->vbr_min_bitrate = lame_get_VBR_min_bitrate_kbps (lame->lgf);
392   lame->vbr_max_bitrate = lame_get_VBR_max_bitrate_kbps (lame->lgf);
393   lame->vbr_hard_min = lame_get_VBR_hard_min (lame->lgf);
394   lame->lowpass_freq = lame_get_lowpassfreq (lame->lgf);
395   lame->lowpass_width = lame_get_lowpasswidth (lame->lgf);
396   lame->highpass_freq = lame_get_highpassfreq (lame->lgf);
397   lame->highpass_width = lame_get_highpasswidth (lame->lgf);
398   lame->ath_only = lame_get_ATHonly (lame->lgf);
399   lame->ath_short = lame_get_ATHshort (lame->lgf);
400   lame->no_ath = lame_get_noATH (lame->lgf);
401   /*  lame->ath_type = lame_get_ATHtype (lame->lgf); */
402   lame->ath_lower = lame_get_ATHlower (lame->lgf);
403   lame->cwlimit = lame_get_cwlimit (lame->lgf);
404   lame->allow_diff_short = lame_get_allow_diff_short (lame->lgf);
405   lame->no_short_blocks = lame_get_no_short_blocks (lame->lgf);
406   lame->emphasis = lame_get_emphasis (lame->lgf);
407
408   GST_DEBUG (GST_CAT_PLUGIN_INFO, "done initializing lame element");
409 }
410
411
412 static void
413 gst_lame_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
414 {
415   GstLame *lame;
416
417   /* it's not null if we got it, but it might not be ours */
418   g_return_if_fail (GST_IS_LAME (object));
419
420   lame = GST_LAME (object);
421
422   switch (prop_id) {
423     case ARG_BITRATE:
424       lame->bitrate = g_value_get_int (value);
425       break;
426     case ARG_COMPRESSION_RATIO:
427       lame->compression_ratio = g_value_get_float (value);
428       break;
429     case ARG_QUALITY:
430       lame->quality = g_value_get_enum (value);
431       break;
432     case ARG_MODE:
433       lame->mode = g_value_get_enum (value);
434       break;
435     case ARG_FORCE_MS:
436       lame->force_ms = g_value_get_boolean (value);
437       break;
438     case ARG_FREE_FORMAT:
439       lame->free_format = g_value_get_boolean (value);
440       break;
441     case ARG_COPYRIGHT:
442       lame->copyright = g_value_get_boolean (value);
443       break;
444     case ARG_ORIGINAL:
445       lame->original = g_value_get_boolean (value);
446       break;
447     case ARG_ERROR_PROTECTION:
448       lame->error_protection = g_value_get_boolean (value);
449       break;
450     case ARG_PADDING_TYPE:
451       lame->padding_type = g_value_get_int (value);
452       break;
453     case ARG_EXTENSION:
454       lame->extension = g_value_get_boolean (value);
455       break;
456     case ARG_STRICT_ISO:
457       lame->strict_iso = g_value_get_boolean (value);
458       break;
459     case ARG_DISABLE_RESERVOIR:
460       lame->disable_reservoir = g_value_get_boolean (value);
461       break;
462     case ARG_VBR:
463       lame->vbr = g_value_get_boolean (value);
464       break;
465     case ARG_VBR_MEAN_BITRATE:
466       lame->vbr_mean_bitrate = g_value_get_int (value);
467       break;
468     case ARG_VBR_MIN_BITRATE:
469       lame->vbr_min_bitrate = g_value_get_int (value);
470       break;
471     case ARG_VBR_MAX_BITRATE:
472       lame->vbr_max_bitrate = g_value_get_int (value);
473       break;
474     case ARG_VBR_HARD_MIN:
475       lame->vbr_hard_min = g_value_get_int (value);
476       break;
477     case ARG_LOWPASS_FREQ:
478       lame->lowpass_freq = g_value_get_int (value);
479       break;
480     case ARG_LOWPASS_WIDTH:
481       lame->lowpass_width = g_value_get_int (value);
482       break;
483     case ARG_HIGHPASS_FREQ:
484       lame->highpass_freq = g_value_get_int (value);
485       break;
486     case ARG_HIGHPASS_WIDTH:
487       lame->highpass_width = g_value_get_int (value);
488       break;
489     case ARG_ATH_ONLY:
490       lame->ath_only = g_value_get_boolean (value);
491       break;
492     case ARG_ATH_SHORT:
493       lame->ath_short = g_value_get_boolean (value);
494       break;
495     case ARG_NO_ATH:
496       lame->no_ath = g_value_get_boolean (value);
497       break;
498     case ARG_ATH_LOWER:
499       lame->ath_lower = g_value_get_int (value);
500       break;
501     case ARG_CWLIMIT:
502       lame->cwlimit = g_value_get_int (value);
503       break;
504     case ARG_ALLOW_DIFF_SHORT:
505       lame->allow_diff_short = g_value_get_boolean (value);
506       break;
507     case ARG_NO_SHORT_BLOCKS:
508       lame->no_short_blocks = g_value_get_boolean (value);
509       break;
510     case ARG_EMPHASIS:
511       lame->emphasis = g_value_get_boolean (value);
512       break;
513     default:
514       break;
515   }
516
517 }
518
519 static void
520 gst_lame_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
521 {
522   GstLame *lame;
523
524   /* it's not null if we got it, but it might not be ours */
525   g_return_if_fail (GST_IS_LAME (object));
526
527   lame = GST_LAME (object);
528
529   switch (prop_id) {
530     case ARG_BITRATE:
531       g_value_set_int (value, lame->bitrate);
532       break;
533     case ARG_COMPRESSION_RATIO:
534       g_value_set_float (value, lame->compression_ratio);
535       break;
536     case ARG_QUALITY:
537       g_value_set_enum (value, lame->quality);
538       break;
539     case ARG_MODE:
540       g_value_set_enum (value, lame->mode);
541       break;
542     case ARG_FORCE_MS:
543       g_value_set_boolean (value, lame->force_ms);
544       break;
545     case ARG_FREE_FORMAT:
546       g_value_set_boolean (value, lame->free_format);
547       break;
548     case ARG_COPYRIGHT:
549       g_value_set_boolean (value, lame->copyright);
550       break;
551     case ARG_ORIGINAL:
552       g_value_set_boolean (value, lame->original);
553       break;
554     case ARG_ERROR_PROTECTION:
555       g_value_set_boolean (value, lame->error_protection);
556       break;
557     case ARG_PADDING_TYPE:
558       g_value_set_enum (value, lame->padding_type);
559       break;
560     case ARG_EXTENSION:
561       g_value_set_boolean (value, lame->extension);
562       break;
563     case ARG_STRICT_ISO:
564       g_value_set_boolean (value, lame->strict_iso);
565       break;
566     case ARG_DISABLE_RESERVOIR:
567       g_value_set_boolean (value, lame->disable_reservoir);
568       break;
569     case ARG_VBR:
570       g_value_set_boolean (value, lame->vbr);
571       break;
572     case ARG_VBR_MEAN_BITRATE:
573       g_value_set_int (value, lame->vbr_mean_bitrate);
574       break;
575     case ARG_VBR_MIN_BITRATE:
576       g_value_set_int (value, lame->vbr_min_bitrate);
577       break;
578     case ARG_VBR_MAX_BITRATE:
579       g_value_set_int (value, lame->vbr_max_bitrate);
580       break;
581     case ARG_VBR_HARD_MIN:
582       g_value_set_int (value, lame->vbr_hard_min);
583       break;
584     case ARG_LOWPASS_FREQ:
585       g_value_set_int (value, lame->lowpass_freq);
586       break;
587     case ARG_LOWPASS_WIDTH:
588       g_value_set_int (value, lame->lowpass_width);
589       break;
590     case ARG_HIGHPASS_FREQ:
591       g_value_set_int (value, lame->highpass_freq);
592       break;
593     case ARG_HIGHPASS_WIDTH:
594       g_value_set_int (value, lame->highpass_width);
595       break;
596     case ARG_ATH_ONLY:
597       g_value_set_boolean (value, lame->ath_only);
598       break;
599     case ARG_ATH_SHORT:
600       g_value_set_boolean (value, lame->ath_short);
601       break;
602     case ARG_NO_ATH:
603       g_value_set_boolean (value, lame->no_ath);
604       break;
605     case ARG_ATH_LOWER:
606       g_value_set_int (value, lame->ath_lower);
607       break;
608     case ARG_CWLIMIT:
609       g_value_set_int (value, lame->cwlimit);
610       break;
611     case ARG_ALLOW_DIFF_SHORT:
612       g_value_set_boolean (value, lame->allow_diff_short);
613       break;
614     case ARG_NO_SHORT_BLOCKS:
615       g_value_set_boolean (value, lame->no_short_blocks);
616       break;
617     case ARG_EMPHASIS:
618       g_value_set_boolean (value, lame->emphasis);
619       break;
620     default:
621       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
622       break;
623   }
624 }
625
626 static void
627 gst_lame_chain (GstPad *pad, GstBuffer *buf)
628 {
629   GstLame *lame;
630   GstBuffer *outbuf;
631   gchar *mp3_data = NULL;
632   gint mp3_buffer_size, mp3_size = 0;
633   gboolean eos = FALSE;
634
635   lame = GST_LAME (gst_pad_get_parent (pad));
636
637   GST_DEBUG (GST_CAT_PLUGIN_INFO, "entered chain");
638
639   if (GST_IS_EVENT (buf)) {
640     switch (GST_EVENT_TYPE (buf)) {
641       case GST_EVENT_EOS:
642         eos = TRUE;
643       case GST_EVENT_FLUSH:
644         mp3_buffer_size = 7200;
645         mp3_data = g_malloc (mp3_buffer_size);
646         
647         mp3_size = lame_encode_flush_nogap (lame->lgf, mp3_data, mp3_buffer_size);
648         gst_event_unref (GST_EVENT (buf));
649         break;  
650       default:
651         gst_pad_event_default (pad, GST_EVENT (buf));
652         break;
653     }
654   }
655   else {
656     if (!lame->initialized) {
657       gst_buffer_unref (buf);
658       gst_element_error (GST_ELEMENT (lame), "encoder not initialized (input is not audio?)");
659       return;
660     }
661
662     /* allocate space for output */
663     mp3_buffer_size = ((GST_BUFFER_SIZE(buf) / (2+lame->num_channels)) * 1.25) + 7200;
664     mp3_data = g_malloc (mp3_buffer_size);
665
666     if (lame->num_channels == 2) {
667       mp3_size = lame_encode_buffer_interleaved (lame->lgf, 
668                     (short int *) (GST_BUFFER_DATA (buf)),
669                     GST_BUFFER_SIZE (buf) / 4, 
670                     mp3_data, mp3_buffer_size);
671     }
672     else {
673       mp3_size = lame_encode_buffer (lame->lgf, 
674                     (short int *) (GST_BUFFER_DATA (buf)),
675                     (short int *) (GST_BUFFER_DATA (buf)),
676                     GST_BUFFER_SIZE (buf) / 2, 
677                     mp3_data, mp3_buffer_size);
678     }
679
680     GST_DEBUG (GST_CAT_PLUGIN_INFO, 
681                "encoded %d bytes of audio to %d bytes of mp3", 
682                GST_BUFFER_SIZE (buf), mp3_size);
683
684     gst_buffer_unref (buf);
685   }
686   
687   if (mp3_size > 0) {
688     outbuf = gst_buffer_new ();
689     GST_BUFFER_DATA (outbuf) = mp3_data;
690     GST_BUFFER_SIZE (outbuf) = mp3_size;
691
692     gst_pad_push (lame->srcpad,outbuf);
693   }
694   else { 
695     g_free (mp3_data);
696   }
697
698   if (eos) {
699     gst_pad_push (lame->srcpad, GST_BUFFER (gst_event_new (GST_EVENT_EOS)));
700     gst_element_set_eos (GST_ELEMENT (lame));
701   }
702 }
703
704 /* transition to the READY state by configuring the gst_lame encoder */
705 static gboolean
706 gst_lame_setup (GstLame *lame)
707 {
708   GST_DEBUG_ENTER ("(\"%s\")", gst_element_get_name (GST_ELEMENT (lame)));
709
710   /* check if we're already initialized; if we are, we might want to check
711    * if this initialization is compatible with the previous one */
712   /* FIXME: do this */
713   if (lame->initialized)
714     g_warning ("already initialized");
715
716   /* copy the parameters over */
717   lame_set_in_samplerate (lame->lgf, lame->samplerate);
718
719   /* force mono encoding if we only have one channel */
720   if (lame->num_channels == 1) 
721     lame->mode = 3;
722
723   lame_set_brate (lame->lgf, lame->bitrate);
724   lame_set_compression_ratio (lame->lgf, lame->compression_ratio);
725   lame_set_quality (lame->lgf, lame->quality);
726   lame_set_mode (lame->lgf, lame->mode);
727   lame_set_force_ms (lame->lgf, lame->force_ms);
728   lame_set_free_format (lame->lgf, lame->free_format);
729   lame_set_copyright (lame->lgf, lame->copyright);
730   lame_set_original (lame->lgf, lame->original);
731   lame_set_error_protection (lame->lgf, lame->error_protection);
732   lame_set_padding_type (lame->lgf, lame->padding_type);
733   lame_set_extension (lame->lgf, lame->extension);
734   lame_set_strict_ISO (lame->lgf, lame->strict_iso);
735   lame_set_disable_reservoir (lame->lgf, lame->disable_reservoir);
736   lame_set_VBR_q (lame->lgf, lame->vbr);
737   lame_set_VBR_mean_bitrate_kbps (lame->lgf, lame->vbr_mean_bitrate);
738   lame_set_VBR_min_bitrate_kbps (lame->lgf, lame->vbr_min_bitrate);
739   lame_set_VBR_max_bitrate_kbps (lame->lgf, lame->vbr_max_bitrate);
740   lame_set_VBR_hard_min (lame->lgf, lame->vbr_hard_min);
741   lame_set_lowpassfreq (lame->lgf, lame->lowpass_freq);
742   lame_set_lowpasswidth (lame->lgf, lame->lowpass_width);
743   lame_set_highpassfreq (lame->lgf, lame->highpass_freq);
744   lame_set_highpasswidth (lame->lgf, lame->highpass_width);
745   lame_set_ATHonly (lame->lgf, lame->ath_only);
746   lame_set_ATHshort (lame->lgf, lame->ath_short);
747   lame_set_noATH (lame->lgf, lame->no_ath);
748   lame_set_ATHlower (lame->lgf, lame->ath_lower);
749   lame_set_cwlimit (lame->lgf, lame->cwlimit);
750   lame_set_allow_diff_short (lame->lgf, lame->allow_diff_short);
751   lame_set_no_short_blocks (lame->lgf, lame->no_short_blocks);
752   lame_set_emphasis (lame->lgf, lame->emphasis);
753
754   /* initialize the lame encoder */
755   if (lame_init_params (lame->lgf) < 0) {
756     lame->initialized = FALSE;
757   }
758   else {
759     lame->initialized = TRUE;
760     /* FIXME: it would be nice to print out the mode here */
761     GST_INFO (GST_CAT_PLUGIN_INFO, 
762               "lame encoder initialized (%d kbit/s, %d Hz, %d channels)", 
763               lame->bitrate, lame->samplerate, lame->num_channels);
764   }
765
766   GST_DEBUG_LEAVE ("");
767
768   return lame->initialized;
769 }
770
771 static GstElementStateReturn
772 gst_lame_change_state (GstElement *element)
773 {
774   GstLame *lame;
775   
776   g_return_val_if_fail (GST_IS_LAME (element), GST_STATE_FAILURE);
777
778   lame = GST_LAME (element);
779
780   GST_DEBUG (0,"state pending %d", GST_STATE_PENDING (element));
781
782   switch (GST_STATE_TRANSITION (element)) {
783     case GST_STATE_READY_TO_NULL:
784       if (lame->initialized) {
785         lame_close (lame->lgf);
786         lame->initialized = FALSE;
787       }
788       break;
789     default:
790       break;
791   }
792
793   /* if we haven't failed already, give the parent class a chance to ;-) */
794   if (GST_ELEMENT_CLASS (parent_class)->change_state)
795     return GST_ELEMENT_CLASS (parent_class)->change_state (element);
796
797   return GST_STATE_SUCCESS;
798 }
799
800 static gboolean
801 plugin_init (GModule *module, GstPlugin *plugin)
802 {
803   GstElementFactory *factory;
804
805   /* create an elementfactory for the gst_lame element */
806   factory = gst_element_factory_new ("lame", GST_TYPE_LAME,
807                                     &gst_lame_details);
808   g_return_val_if_fail (factory != NULL, FALSE);
809
810   /* register the source's padtemplate */
811   gst_element_factory_add_pad_template (factory, 
812                 GST_PAD_TEMPLATE_GET (gst_lame_src_factory));
813
814   /* register the sink's padtemplate */
815   gst_element_factory_add_pad_template (factory, 
816                 GST_PAD_TEMPLATE_GET (gst_lame_sink_factory));
817
818   /* and add the gst_lame element factory to the plugin */
819   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
820
821   return TRUE;
822 }
823
824 GstPluginDesc plugin_desc = {
825   GST_VERSION_MAJOR,
826   GST_VERSION_MINOR,
827   "lame",
828   plugin_init
829 };