adding lame
[platform/upstream/gst-plugins-good.git] / ext / lame / gstlame.c
1 /* Gnome-Streamer
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 <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <sys/ioctl.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <dirent.h>
31 #include <errno.h>
32
33 #include <sys/soundcard.h>
34
35 #include "gstlame.h"
36
37
38 static GstElementDetails gst_lame_details = {
39   "L.A.M.E. mp3 encoder",
40   "Filter/Encoder/Audio",
41   "High-quality free MP3 encoder",
42   VERSION,
43   "Erik Walthinsen <omega@cse.ogi.edu>",
44   "(C) 2000",
45 };
46
47 GST_PADTEMPLATE_FACTORY (gst_lame_sink_factory,
48   "sink",
49   GST_PAD_SINK,
50   GST_PAD_ALWAYS,
51   GST_CAPS_NEW (
52     "gstlame_sink",
53     "audio/raw",
54       "format",     GST_PROPS_STRING ("int"),
55       "law",        GST_PROPS_INT (0),
56       "endianness", GST_PROPS_INT (G_BYTE_ORDER),
57       "signed",     GST_PROPS_BOOLEAN (TRUE),
58       "width",      GST_PROPS_INT (16),
59       "depth",      GST_PROPS_INT (16),
60       "rate",       GST_PROPS_INT_RANGE (8000, 48000),
61       "channels",   GST_PROPS_INT_RANGE (1, 2)
62   )
63 )
64
65 GST_PADTEMPLATE_FACTORY (gst_lame_src_factory,
66   "src",
67   GST_PAD_SRC,
68   GST_PAD_ALWAYS,
69   GST_CAPS_NEW (
70     "gstlame_src",
71     "audio/mp3",
72     NULL
73   )
74 )
75
76 /********** Define useful types for non-programmatic interfaces **********/
77 #define GST_TYPE_LAME_MODE (gst_lame_mode_get_type())
78 static GType
79 gst_lame_mode_get_type (void)
80 {
81   static GType lame_mode_type = 0;
82   static GEnumValue lame_modes[] = {
83     { 0, "0", "Stereo" },
84     { 1, "1", "Joint-Stereo" },
85     { 2, "2", "Dual channel" },
86     { 3, "3", "Mono" },
87     { 0, NULL, NULL },
88   };
89   if (!lame_mode_type) {
90     lame_mode_type = g_enum_register_static ("GstLameMode", lame_modes);
91   }
92   return lame_mode_type;
93 }
94
95 #define GST_TYPE_LAME_QUALITY (gst_lame_quality_get_type())
96 static GType
97 gst_lame_quality_get_type (void)
98 {
99   static GType lame_quality_type = 0;
100   static GEnumValue lame_quality[] = {
101     { 0, "0", "0 - Best" },
102     { 1, "1", "1" },
103     { 2, "2", "2" },
104     { 3, "3", "3" },
105     { 4, "4", "4" },
106     { 5, "5", "5 - Default" },
107     { 6, "6", "6" },
108     { 7, "7", "7" },
109     { 8, "8", "8" },
110     { 9, "9", "9 - Worst" },
111     { 0, NULL, NULL },
112   };
113   if (!lame_quality_type) {
114     lame_quality_type = g_enum_register_static ("GstLameQuality", lame_quality);
115   }
116   return lame_quality_type;
117 }
118
119 #define GST_TYPE_LAME_PADDING (gst_lame_padding_get_type())
120 static GType
121 gst_lame_padding_get_type (void)
122 {
123   static GType lame_padding_type = 0;
124   static GEnumValue lame_padding[] = {
125     { 0, "0", "No Padding" },
126     { 1, "1", "Always Pad" },
127     { 2, "2", "Adjust Padding" },
128     { 0, NULL, NULL },
129   };
130   if (!lame_padding_type) {
131     lame_padding_type = g_enum_register_static ("GstLamePadding", lame_padding);
132   }
133   return lame_padding_type;
134 }
135
136 /********** Standard stuff for signals and arguments **********/
137 /* GstLame signals and args */
138 enum {
139   /* FILL_ME */
140   LAST_SIGNAL
141 };
142
143 enum {
144   ARG_0,
145   ARG_BITRATE,
146   ARG_COMPRESSION_RATIO,
147   ARG_QUALITY,
148   ARG_MODE,
149   ARG_FORCE_MS,
150   ARG_FREE_FORMAT,
151   ARG_COPYRIGHT,
152   ARG_ORIGINAL,
153   ARG_ERROR_PROTECTION,
154   ARG_PADDING_TYPE,
155   ARG_EXTENSION,
156   ARG_STRICT_ISO,
157   ARG_DISABLE_RESERVOIR,
158   ARG_VBR,
159   ARG_VBR_MEAN_BITRATE,
160   ARG_VBR_MIN_BITRATE,
161   ARG_VBR_MAX_BITRATE,
162   ARG_VBR_HARD_MIN,
163   ARG_LOWPASS_FREQ,
164   ARG_LOWPASS_WIDTH,
165   ARG_HIGHPASS_FREQ,
166   ARG_HIGHPASS_WIDTH,
167   ARG_ATH_ONLY,
168   ARG_ATH_SHORT,
169   ARG_NO_ATH,
170 //  ARG_ATH_TYPE,               // note: CVS has this, 3.87 doesn't
171   ARG_ATH_LOWER,
172   ARG_CWLIMIT,
173   ARG_ALLOW_DIFF_SHORT,
174   ARG_NO_SHORT_BLOCKS,
175   ARG_EMPHASIS,
176 };
177
178
179 static void                     gst_lame_class_init     (GstLameClass *klass);
180 static void                     gst_lame_init           (GstLame *gst_lame);
181
182 static void                     gst_lame_set_property   (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
183 static void                     gst_lame_get_property   (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
184
185 static void                     gst_lame_chain          (GstPad *pad, GstBuffer *buf);
186 static gboolean                 gst_lame_setup          (GstLame *lame);
187
188 static GstElementClass *parent_class = NULL;
189 //static guint gst_lame_signals[LAST_SIGNAL] = { 0 };
190
191 GType
192 gst_lame_get_type (void)
193 {
194   static GType gst_lame_type = 0;
195
196   if (!gst_lame_type) {
197     static const GTypeInfo gst_lame_info = {
198       sizeof(GstLameClass),      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","bitrate",
225                      G_MININT,G_MAXINT,128,G_PARAM_READWRITE)); // CHECKME
226   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_COMPRESSION_RATIO,
227     g_param_spec_float("compression_ratio","compression_ratio","compression_ratio",
228                        0.0,200.0,11.0,G_PARAM_READWRITE)); // CHECKME
229   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_QUALITY,
230     g_param_spec_enum("quality","quality","quality",
231                       GST_TYPE_LAME_QUALITY,5,G_PARAM_READWRITE)); // CHECKME!
232   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MODE,
233     g_param_spec_enum("mode","mode","mode",
234                       GST_TYPE_LAME_MODE,0,G_PARAM_READWRITE)); // CHECKME!
235   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FORCE_MS,
236     g_param_spec_boolean("force_ms","force_ms","force_ms",
237                          TRUE,G_PARAM_READWRITE)); // CHECKME
238   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FREE_FORMAT,
239     g_param_spec_boolean("free_format","free_format","free_format",
240                          TRUE,G_PARAM_READWRITE)); // CHECKME
241   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_COPYRIGHT,
242     g_param_spec_boolean("copyright","copyright","copyright",
243                          TRUE,G_PARAM_READWRITE)); // CHECKME
244   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ORIGINAL,
245     g_param_spec_boolean("original","original","original",
246                          TRUE,G_PARAM_READWRITE)); // CHECKME
247   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ERROR_PROTECTION,
248     g_param_spec_boolean("error_protection","error_protection","error_protection",
249                          TRUE,G_PARAM_READWRITE)); // CHECKME
250   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PADDING_TYPE,
251     g_param_spec_enum("padding_type","padding_type","padding_type",
252                       GST_TYPE_LAME_PADDING,0,G_PARAM_READWRITE)); // CHECKME!
253   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_EXTENSION,
254     g_param_spec_boolean("extension","extension","extension",
255                          TRUE,G_PARAM_READWRITE)); // CHECKME
256   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_STRICT_ISO,
257     g_param_spec_boolean("strict_iso","strict_iso","strict_iso",
258                          TRUE,G_PARAM_READWRITE)); // CHECKME
259   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DISABLE_RESERVOIR,
260     g_param_spec_boolean("disable_reservoir","disable_reservoir","disable_reservoir",
261                          TRUE,G_PARAM_READWRITE)); // CHECKME
262   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VBR,
263     g_param_spec_boolean("vbr","vbr","vbr",
264                          TRUE,G_PARAM_READWRITE)); // CHECKME
265   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VBR_MEAN_BITRATE,
266     g_param_spec_int("vbr_mean_bitrate","vbr_mean_bitrate","vbr_mean_bitrate",
267                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
268   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VBR_MIN_BITRATE,
269     g_param_spec_int("vbr_min_bitrate","vbr_min_bitrate","vbr_min_bitrate",
270                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
271   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VBR_MAX_BITRATE,
272     g_param_spec_int("vbr_max_bitrate","vbr_max_bitrate","vbr_max_bitrate",
273                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
274   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VBR_HARD_MIN,
275     g_param_spec_int("vbr_hard_min","vbr_hard_min","vbr_hard_min",
276                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
277   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_LOWPASS_FREQ,
278     g_param_spec_int("lowpass_freq","lowpass_freq","lowpass_freq",
279                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
280   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_LOWPASS_WIDTH,
281     g_param_spec_int("lowpass_width","lowpass_width","lowpass_width",
282                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
283   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HIGHPASS_FREQ,
284     g_param_spec_int("highpass_freq","highpass_freq","highpass_freq",
285                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
286   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HIGHPASS_WIDTH,
287     g_param_spec_int("highpass_width","highpass_width","highpass_width",
288                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
289   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ATH_ONLY,
290     g_param_spec_boolean("ath_only","ath_only","ath_only",
291                          TRUE,G_PARAM_READWRITE)); // CHECKME
292   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ATH_SHORT,
293     g_param_spec_boolean("ath_short","ath_short","ath_short",
294                          TRUE,G_PARAM_READWRITE)); // CHECKME
295   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NO_ATH,
296     g_param_spec_boolean("no_ath","no_ath","no_ath",
297                          TRUE,G_PARAM_READWRITE)); // CHECKME
298 //  gtk_object_add_arg_type ("GstLame::ath_type", G_TYPE_INT,
299 //                             GTK_ARG_READWRITE, ARG_ATH_TYPE);
300   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ATH_LOWER,
301     g_param_spec_int("ath_lower","ath_lower","ath_lower",
302                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
303   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CWLIMIT,
304     g_param_spec_int("cwlimit","cwlimit","cwlimit",
305                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
306   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ALLOW_DIFF_SHORT,
307     g_param_spec_boolean("allow_diff_short","allow_diff_short","allow_diff_short",
308                          TRUE,G_PARAM_READWRITE)); // CHECKME
309   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NO_SHORT_BLOCKS,
310     g_param_spec_boolean("no_short_blocks","no_short_blocks","no_short_blocks",
311                          TRUE,G_PARAM_READWRITE)); // CHECKME
312   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_EMPHASIS,
313     g_param_spec_boolean("emphasis","emphasis","emphasis",
314                          TRUE,G_PARAM_READWRITE)); // CHECKME
315
316   gobject_class->set_property = gst_lame_set_property;
317   gobject_class->get_property = gst_lame_get_property;
318 }
319
320 static void
321 gst_lame_newcaps (GstPad *pad, GstCaps *caps)
322 {
323   GstLame *lame;
324
325   lame = GST_LAME (gst_pad_get_parent (pad));
326
327   lame->samplerate = gst_caps_get_int (caps, "rate");
328   lame->num_channels = gst_caps_get_int (caps, "channels");
329
330   GST_DEBUG (0, "rate=%d, channels=%d\n", lame->samplerate, lame->num_channels);
331
332   gst_lame_setup (lame);
333 }
334
335 static void
336 gst_lame_init (GstLame *lame)
337 {
338   GST_DEBUG_ENTER("(\"%s\")", gst_element_get_name (GST_ELEMENT (lame)));
339
340   lame->sinkpad = gst_pad_new_from_template (GST_PADTEMPLATE_GET (gst_lame_sink_factory), "sink");
341   gst_element_add_pad (GST_ELEMENT (lame), lame->sinkpad);
342   gst_pad_set_chain_function (lame->sinkpad, gst_lame_chain);
343   gst_pad_set_newcaps_function (lame->sinkpad, gst_lame_newcaps);
344
345   lame->srcpad = gst_pad_new_from_template (GST_PADTEMPLATE_GET (gst_lame_src_factory), "src");
346   gst_element_add_pad (GST_ELEMENT (lame), lame->srcpad);
347   gst_pad_set_caps (lame->srcpad, gst_pad_get_padtemplate_caps (lame->srcpad));
348
349   GST_DEBUG (0,"setting up lame encoder\n");
350   lame->lgf = lame_init();
351
352   lame->samplerate = 44100;
353   lame->num_channels = 2;
354
355   lame->bitrate = lame_get_brate(lame->lgf);
356   lame->compression_ratio = lame_get_compression_ratio(lame->lgf);
357   lame->quality = lame_get_quality(lame->lgf);
358   lame->mode = lame_get_mode(lame->lgf);
359   lame->force_ms = lame_get_force_ms(lame->lgf);
360   lame->free_format = lame_get_free_format(lame->lgf);
361   lame->copyright = lame_get_copyright(lame->lgf);
362   lame->original = lame_get_original(lame->lgf);
363   lame->error_protection = lame_get_error_protection(lame->lgf);
364   lame->padding_type = lame_get_padding_type(lame->lgf);
365   lame->extension = lame_get_extension(lame->lgf);
366   lame->strict_iso = lame_get_strict_ISO(lame->lgf);
367   lame->disable_reservoir = lame_get_disable_reservoir(lame->lgf);
368   lame->vbr = lame_get_VBR_q(lame->lgf);
369   lame->vbr_mean_bitrate = lame_get_VBR_mean_bitrate_kbps(lame->lgf);
370   lame->vbr_min_bitrate = lame_get_VBR_min_bitrate_kbps(lame->lgf);
371   lame->vbr_max_bitrate = lame_get_VBR_max_bitrate_kbps(lame->lgf);
372   lame->vbr_hard_min = lame_get_VBR_hard_min(lame->lgf);
373   lame->lowpass_freq = lame_get_lowpassfreq(lame->lgf);
374   lame->lowpass_width = lame_get_lowpasswidth(lame->lgf);
375   lame->highpass_freq = lame_get_highpassfreq(lame->lgf);
376   lame->highpass_width = lame_get_highpasswidth(lame->lgf);
377   lame->ath_only = lame_get_ATHonly(lame->lgf);
378   lame->ath_short = lame_get_ATHshort(lame->lgf);
379   lame->no_ath = lame_get_noATH(lame->lgf);
380 //  lame->ath_type = lame_get_ATHtype(lame->lgf);
381   lame->ath_lower = lame_get_ATHlower(lame->lgf);
382   lame->cwlimit = lame_get_cwlimit(lame->lgf);
383   lame->allow_diff_short = lame_get_allow_diff_short(lame->lgf);
384   lame->no_short_blocks = lame_get_no_short_blocks(lame->lgf);
385   lame->emphasis = lame_get_emphasis(lame->lgf);
386
387   GST_DEBUG (0,"done initializing lame element\n");;
388 }
389
390
391 static void
392 gst_lame_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
393 {
394   GstLame *lame;
395
396   /* it's not null if we got it, but it might not be ours */
397   g_return_if_fail (GST_IS_LAME (object));
398
399   lame = GST_LAME (object);
400
401   switch (prop_id) {
402     case ARG_BITRATE:
403       lame->bitrate = g_value_get_int (value);
404       break;
405     case ARG_COMPRESSION_RATIO:
406       lame->compression_ratio = g_value_get_float (value);
407       break;
408     case ARG_QUALITY:
409       lame->quality = g_value_get_int (value);
410       break;
411     case ARG_MODE:
412       lame->mode = g_value_get_int (value);
413       break;
414     case ARG_FORCE_MS:
415       lame->force_ms = g_value_get_boolean (value);
416       break;
417     case ARG_FREE_FORMAT:
418       lame->free_format = g_value_get_boolean (value);
419       break;
420     case ARG_COPYRIGHT:
421       lame->copyright = g_value_get_boolean (value);
422       break;
423     case ARG_ORIGINAL:
424       lame->original = g_value_get_boolean (value);
425       break;
426     case ARG_ERROR_PROTECTION:
427       lame->error_protection = g_value_get_boolean (value);
428       break;
429     case ARG_PADDING_TYPE:
430       lame->padding_type = g_value_get_int (value);
431       break;
432     case ARG_EXTENSION:
433       lame->extension = g_value_get_boolean (value);
434       break;
435     case ARG_STRICT_ISO:
436       lame->strict_iso = g_value_get_boolean (value);
437       break;
438     case ARG_DISABLE_RESERVOIR:
439       lame->disable_reservoir = g_value_get_boolean (value);
440       break;
441     case ARG_VBR:
442       lame->vbr = g_value_get_boolean (value);
443       break;
444     case ARG_VBR_MEAN_BITRATE:
445       lame->vbr_mean_bitrate = g_value_get_int (value);
446       break;
447     case ARG_VBR_MIN_BITRATE:
448       lame->vbr_min_bitrate = g_value_get_int (value);
449       break;
450     case ARG_VBR_MAX_BITRATE:
451       lame->vbr_max_bitrate = g_value_get_int (value);
452       break;
453     case ARG_VBR_HARD_MIN:
454       lame->vbr_hard_min = g_value_get_int (value);
455       break;
456     case ARG_LOWPASS_FREQ:
457       lame->lowpass_freq = g_value_get_int (value);
458       break;
459     case ARG_LOWPASS_WIDTH:
460       lame->lowpass_width = g_value_get_int (value);
461       break;
462     case ARG_HIGHPASS_FREQ:
463       lame->highpass_freq = g_value_get_int (value);
464       break;
465     case ARG_HIGHPASS_WIDTH:
466       lame->highpass_width = g_value_get_int (value);
467       break;
468     case ARG_ATH_ONLY:
469       lame->ath_only = g_value_get_boolean (value);
470       break;
471     case ARG_ATH_SHORT:
472       lame->ath_short = g_value_get_boolean (value);
473       break;
474     case ARG_NO_ATH:
475       lame->no_ath = g_value_get_boolean (value);
476       break;
477 //    case ARG_ATH_TYPE:
478 //      lame->ath_type = G_VALUE_INT (*arg);
479 //      break;
480     case ARG_ATH_LOWER:
481       lame->ath_lower = g_value_get_int (value);
482       break;
483     case ARG_CWLIMIT:
484       lame->cwlimit = g_value_get_int (value);
485       break;
486     case ARG_ALLOW_DIFF_SHORT:
487       lame->allow_diff_short = g_value_get_boolean (value);
488       break;
489     case ARG_NO_SHORT_BLOCKS:
490       lame->no_short_blocks = g_value_get_boolean (value);
491       break;
492     case ARG_EMPHASIS:
493       lame->emphasis = g_value_get_boolean (value);
494       break;
495     default:
496       break;
497   }
498
499 }
500
501 static void
502 gst_lame_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
503 {
504   GstLame *lame;
505
506   /* it's not null if we got it, but it might not be ours */
507   g_return_if_fail (GST_IS_LAME (object));
508
509   lame = GST_LAME (object);
510
511   switch (prop_id) {
512     case ARG_BITRATE:
513       g_value_set_int (value, lame->bitrate);
514       break;
515     case ARG_COMPRESSION_RATIO:
516       g_value_set_float (value, lame->compression_ratio);
517       break;
518     case ARG_QUALITY:
519       g_value_set_enum (value, lame->quality);
520       break;
521     case ARG_MODE:
522       g_value_set_enum (value, lame->mode);
523       break;
524     case ARG_FORCE_MS:
525       g_value_set_boolean (value, lame->force_ms);
526       break;
527     case ARG_FREE_FORMAT:
528       g_value_set_boolean (value, lame->free_format);
529       break;
530     case ARG_COPYRIGHT:
531       g_value_set_boolean (value, lame->copyright);
532       break;
533     case ARG_ORIGINAL:
534       g_value_set_boolean (value, lame->original);
535       break;
536     case ARG_ERROR_PROTECTION:
537       g_value_set_boolean (value, lame->error_protection);
538       break;
539     case ARG_PADDING_TYPE:
540       g_value_set_enum (value, lame->padding_type);
541       break;
542     case ARG_EXTENSION:
543       g_value_set_boolean (value, lame->extension);
544       break;
545     case ARG_STRICT_ISO:
546       g_value_set_boolean (value, lame->strict_iso);
547       break;
548     case ARG_DISABLE_RESERVOIR:
549       g_value_set_boolean (value, lame->disable_reservoir);
550       break;
551     case ARG_VBR:
552       g_value_set_boolean (value, lame->vbr);
553       break;
554     case ARG_VBR_MEAN_BITRATE:
555       g_value_set_int (value, lame->vbr_mean_bitrate);
556       break;
557     case ARG_VBR_MIN_BITRATE:
558       g_value_set_int (value, lame->vbr_min_bitrate);
559       break;
560     case ARG_VBR_MAX_BITRATE:
561       g_value_set_int (value, lame->vbr_max_bitrate);
562       break;
563     case ARG_VBR_HARD_MIN:
564       g_value_set_int (value, lame->vbr_hard_min);
565       break;
566     case ARG_LOWPASS_FREQ:
567       g_value_set_int (value, lame->lowpass_freq);
568       break;
569     case ARG_LOWPASS_WIDTH:
570       g_value_set_int (value, lame->lowpass_width);
571       break;
572     case ARG_HIGHPASS_FREQ:
573       g_value_set_int (value, lame->highpass_freq);
574       break;
575     case ARG_HIGHPASS_WIDTH:
576       g_value_set_int (value, lame->highpass_width);
577       break;
578     case ARG_ATH_ONLY:
579       g_value_set_boolean (value, lame->ath_only);
580       break;
581     case ARG_ATH_SHORT:
582       g_value_set_boolean (value, lame->ath_short);
583       break;
584     case ARG_NO_ATH:
585       g_value_set_boolean (value, lame->no_ath);
586       break;
587 //    case ARG_ATH_TYPE:
588 //      G_VALUE_INT (*arg) = lame->ath_type;
589 //      break;
590     case ARG_ATH_LOWER:
591       g_value_set_int (value, lame->ath_lower);
592       break;
593     case ARG_CWLIMIT:
594       g_value_set_int (value, lame->cwlimit);
595       break;
596     case ARG_ALLOW_DIFF_SHORT:
597       g_value_set_boolean (value, lame->allow_diff_short);
598       break;
599     case ARG_NO_SHORT_BLOCKS:
600       g_value_set_boolean (value, lame->no_short_blocks);
601       break;
602     case ARG_EMPHASIS:
603       g_value_set_boolean (value, lame->emphasis);
604       break;
605     default:
606       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
607       break;
608   }
609 }
610
611 static void
612 gst_lame_chain (GstPad *pad, GstBuffer *buf)
613 {
614   GstLame *lame;
615   GstBuffer *outbuf;
616   gchar *mp3_data;
617   gint mp3_buffer_size, mp3_size = 0;
618
619   g_return_if_fail (pad != NULL);
620   lame = GST_LAME (gst_pad_get_parent (pad));
621
622   GST_DEBUG (0,"entered\n");
623
624   mp3_buffer_size = ((GST_BUFFER_SIZE(buf) / (2+lame->num_channels)) * 1.25) + 7200;
625   mp3_data = g_malloc (mp3_buffer_size);
626
627   if (lame->num_channels == 2) {
628     mp3_size = lame_encode_buffer_interleaved (lame->lgf, (short int *)(GST_BUFFER_DATA (buf)),
629               GST_BUFFER_SIZE (buf) / 4, mp3_data, mp3_buffer_size);
630   }
631   else {
632     mp3_size = lame_encode_buffer (lame->lgf, 
633                     (short int *)(GST_BUFFER_DATA (buf)),
634                     (short int *)(GST_BUFFER_DATA (buf)),
635                     GST_BUFFER_SIZE (buf) / 2, 
636                     mp3_data, mp3_buffer_size);
637   }
638
639   GST_DEBUG (0,"encoded %d bytes of audio to %d bytes of mp3\n",GST_BUFFER_SIZE (buf), mp3_size);
640   gst_buffer_unref(buf);
641   
642   if (mp3_size > 0) {
643     outbuf = gst_buffer_new ();
644     GST_BUFFER_DATA (outbuf) = mp3_data;
645     GST_BUFFER_SIZE (outbuf) = mp3_size;
646
647     gst_pad_push(lame->srcpad,outbuf);
648   }
649   else g_free (mp3_data);
650
651 }
652
653 /* transition to the READY state by configuring the gst_lame encoder */
654 static gboolean
655 gst_lame_setup (GstLame *lame)
656 {
657   GST_DEBUG_ENTER("(\"%s\")", gst_element_get_name (GST_ELEMENT (lame)));
658
659   // copy the parameters over
660   lame_set_in_samplerate(lame->lgf, lame->samplerate);
661   // force mono encoding if we only have one channel
662   if (lame->num_channels == 1) 
663     lame->mode = 3;
664
665   lame_set_brate(lame->lgf, lame->bitrate);
666   lame_set_compression_ratio(lame->lgf, lame->compression_ratio);
667   lame_set_quality(lame->lgf, lame->quality);
668   lame_set_mode(lame->lgf, lame->mode);
669   lame_set_force_ms(lame->lgf, lame->force_ms);
670   lame_set_free_format(lame->lgf, lame->free_format);
671   lame_set_copyright(lame->lgf, lame->copyright);
672   lame_set_original(lame->lgf, lame->original);
673   lame_set_error_protection(lame->lgf, lame->error_protection);
674   lame_set_padding_type(lame->lgf, lame->padding_type);
675   lame_set_extension(lame->lgf, lame->extension);
676   lame_set_strict_ISO(lame->lgf, lame->strict_iso);
677   lame_set_disable_reservoir(lame->lgf, lame->disable_reservoir);
678   lame_set_VBR_q(lame->lgf, lame->vbr);
679   lame_set_VBR_mean_bitrate_kbps(lame->lgf, lame->vbr_mean_bitrate);
680   lame_set_VBR_min_bitrate_kbps(lame->lgf, lame->vbr_min_bitrate);
681   lame_set_VBR_max_bitrate_kbps(lame->lgf, lame->vbr_max_bitrate);
682   lame_set_VBR_hard_min(lame->lgf, lame->vbr_hard_min);
683   lame_set_lowpassfreq(lame->lgf, lame->lowpass_freq);
684   lame_set_lowpasswidth(lame->lgf, lame->lowpass_width);
685   lame_set_highpassfreq(lame->lgf, lame->highpass_freq);
686   lame_set_highpasswidth(lame->lgf, lame->highpass_width);
687   lame_set_ATHonly(lame->lgf, lame->ath_only);
688   lame_set_ATHshort(lame->lgf, lame->ath_short);
689   lame_set_noATH(lame->lgf, lame->no_ath);
690 //  lame_set_ATHtype(lame->lgf, lame->ath_type);
691   lame_set_ATHlower(lame->lgf, lame->ath_lower);
692   lame_set_cwlimit(lame->lgf, lame->cwlimit);
693   lame_set_allow_diff_short(lame->lgf, lame->allow_diff_short);
694   lame_set_no_short_blocks(lame->lgf, lame->no_short_blocks);
695   lame_set_emphasis(lame->lgf, lame->emphasis);
696
697   // initialize the lame encoder
698   if (lame_init_params(lame->lgf) < 0) {
699     GST_DEBUG (0,"error initializinglame library\n");
700     return FALSE;
701   }
702
703   GST_DEBUG_LEAVE("");
704
705   return TRUE;
706 }
707
708 static GstElementStateReturn
709 gst_lame_change_state (GstElement *element)
710 {
711   g_return_val_if_fail (GST_IS_LAME (element), GST_STATE_FAILURE);
712
713   GST_DEBUG (0,"state pending %d\n", GST_STATE_PENDING (element));
714
715   /* if going down into NULL state, close the file if it's open */
716   if (GST_STATE_PENDING (element) == GST_STATE_READY) {
717     gst_lame_setup(GST_LAME(element));
718   }
719
720   /* if we haven't failed already, give the parent class a chance to ;-) */
721   if (GST_ELEMENT_CLASS (parent_class)->change_state)
722     return GST_ELEMENT_CLASS (parent_class)->change_state (element);
723
724   return GST_STATE_SUCCESS;
725 }
726
727 static gboolean
728 plugin_init (GModule *module, GstPlugin *plugin)
729 {
730   GstElementFactory *factory;
731
732   /* create an elementfactory for the gst_lame element */
733   factory = gst_elementfactory_new ("lame", GST_TYPE_LAME,
734                                     &gst_lame_details);
735   g_return_val_if_fail (factory != NULL, FALSE);
736
737   /* register the source's padtemplate */
738   gst_elementfactory_add_padtemplate (factory, 
739                 GST_PADTEMPLATE_GET (gst_lame_src_factory));
740
741   /* register the sink's padtemplate */
742   gst_elementfactory_add_padtemplate (factory, 
743                 GST_PADTEMPLATE_GET (gst_lame_sink_factory));
744
745   /* and add the gst_lame element factory to the plugin */
746   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
747
748   return TRUE;
749 }
750
751 GstPluginDesc plugin_desc = {
752   GST_VERSION_MAJOR,
753   GST_VERSION_MINOR,
754   "lame",
755   plugin_init
756 };