2 * Dictix / DixTagReader - dix-tag-reader.c
4 * Copyright (C) Martin Blanchard 2011 <tinram@gmx.fr>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29 #include <glib/gi18n.h>
32 #include <gst/pbutils/pbutils.h>
34 #include "dix-tag-reader.h"
41 struct _DixTagReaderPrivate
45 GstDiscoverer
*discoverer
;
58 #define DIX_TAG_READER_GET_PRIVATE(obj) \
59 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), DIX_TYPE_TAG_READER, DixTagReaderPrivate))
61 G_DEFINE_TYPE (DixTagReader
, dix_tag_reader
, GST_TYPE_PIPELINE
)
63 static void dix_tag_reader_load_tag (const GstTagList
*list
, const gchar
*tag
, gpointer
*data
);
66 dix_tag_reader_set_property (GObject
*object
, guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
68 DixTagReader
*reader
= (DixTagReader
*) object
;
69 DixTagReaderPrivate
*priv
= reader
->priv
;
73 priv
->uri
= g_strdup (g_value_get_string (value
));
77 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
82 dix_tag_reader_get_property (GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
84 DixTagReader
*reader
= (DixTagReader
*) object
;
85 DixTagReaderPrivate
*priv
= reader
->priv
;
89 g_value_set_string (value
, priv
->uri
);
93 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
98 dix_tag_reader_finalize (GObject
*object
)
100 DixTagReader
*reader
= (DixTagReader
*) object
;
101 DixTagReaderPrivate
*priv
= reader
->priv
;
103 if (priv
->discoverer
!= NULL
) {
104 g_object_unref (G_OBJECT (priv
->discoverer
));
106 priv
->discoverer
= NULL
;
111 if (priv
->title
!= NULL
) {
112 g_free (priv
->title
);
115 if (priv
->codec
!= NULL
) {
116 g_free (priv
->codec
);
120 G_OBJECT_CLASS (dix_tag_reader_parent_class
)->finalize (object
);
124 dix_tag_reader_class_init (DixTagReaderClass
* klass
)
126 GObjectClass
*gobject_class
= (GObjectClass
*) klass
;
128 gobject_class
->set_property
= dix_tag_reader_set_property
;
129 gobject_class
->get_property
= dix_tag_reader_get_property
;
130 gobject_class
->finalize
= dix_tag_reader_finalize
;
132 g_object_class_install_property (gobject_class
,
134 g_param_spec_string ("file-uri",
135 "FLAC audio file uri",
136 "Uri of the flac audio file we're about to parse",
138 G_PARAM_CONSTRUCT_ONLY
| G_PARAM_READWRITE
));
140 g_type_class_add_private (gobject_class
, sizeof (DixTagReaderPrivate
));
144 dix_tag_reader_init (DixTagReader
* reader
)
146 DixTagReaderPrivate
*priv
= DIX_TAG_READER_GET_PRIVATE (reader
);
148 GError
*error
= NULL
;
150 gst_object_set_name (GST_OBJECT(reader
), "DictixTagReader");
154 priv
->discoverer
= gst_discoverer_new (20 * GST_SECOND
, NULL
);
155 if (priv
->discoverer
== NULL
) {
156 g_warning (error
->message
);
157 g_error_free (error
);
167 priv
->sample_rate
= -1;
172 dix_tag_reader_new (const gchar
* uri
)
174 g_return_val_if_fail ((uri
!= NULL
), NULL
);
175 if (g_str_has_suffix (uri
, ".flac") == FALSE
) {
176 g_warning ("TagReader only support FLAC audio file.\n");
181 return g_object_new (DIX_TYPE_TAG_READER
, "file-uri", uri
, NULL
);
185 dix_tag_reader_load (DixTagReader
*reader
)
187 g_return_if_fail (DIX_IS_TAG_READER (reader
));
188 DixTagReaderPrivate
*priv
= reader
->priv
;
189 GError
*error
= NULL
;
190 /* GFile *file = NULL;*/
191 /* GstDiscovererInfo *info = NULL;*/
192 /* GstDiscovererStreamInfo *stream_info = NULL;*/
193 /* const GstTagList *tags;*/
194 /* GList *streams = NULL;*/
195 /* GstClockTime length = 0;*/
196 GstElement
*source
= NULL
;
197 GstElement
*decoder
= NULL
;
198 GstElement
*sink
= NULL
;
202 GFileInfo
*info
= NULL
;
204 GstCaps
*caps
= NULL
;
205 GstStructure
*structure
= NULL
;
209 if (G_UNLIKELY (priv
->uri
== NULL
)) {
210 g_warning ("No file specified...\n");
215 /* file = g_file_new_for_uri (priv->uri);*/
216 /* if (file != NULL) {*/
217 /* GFileInfo *info = NULL;*/
219 /* info = g_file_query_info (file,*/
220 /* G_FILE_ATTRIBUTE_STANDARD_SIZE,*/
221 /* G_FILE_QUERY_INFO_NONE,*/
225 /* priv->bytes = (guint64) g_file_info_get_size (info);*/
228 /* if (G_LIKELY (priv->discoverer != NULL)) {*/
229 /* info = gst_discoverer_discover_uri (priv->discoverer,*/
232 /* if (error != NULL) {*/
233 /* g_warning (error->message);*/
234 /* g_error_free (error);*/
239 /* tags = gst_discoverer_info_get_tags (info);*/
240 /* if (tags != NULL) {*/
241 /* gst_tag_list_foreach (tags,(GstTagForeachFunc) dix_tag_reader_load_tag, reader);*/
245 /* priv->duration = gst_discoverer_info_get_duration (info);*/
247 /* stream_info = gst_discoverer_info_get_stream_info (info);*/
248 /* if (stream_info != NULL) {*/
251 /* gst_discoverer_stream_info_unref (stream_info);*/
254 /* streams = gst_discoverer_info_get_audio_streams (info);*/
255 /* if (streams != NULL) {*/
256 /* priv->channels = gst_discoverer_audio_info_get_channels (streams->data);*/
257 /* priv->sample_rate = gst_discoverer_audio_info_get_sample_rate (streams->data);*/
258 /* priv->bit_rate = gst_discoverer_audio_info_get_bitrate (streams->data);*/
260 /* gst_discoverer_stream_info_list_free (streams);*/
263 if (G_LIKELY (priv
->bus
== NULL
)) {
264 source
= gst_element_factory_make ("giosrc", "DictixTagReaderSource");
265 if (source
== NULL
) {
268 g_object_set (G_OBJECT (source
), "location", priv
->uri
, NULL
);
269 gst_bin_add (GST_BIN (reader
), source
);
271 decoder
= gst_element_factory_make ("flacdec", "DictixTagReaderDecoder");
272 if (decoder
== NULL
) {
273 gst_object_unref (source
);
277 gst_bin_add (GST_BIN (reader
), decoder
);
278 gst_element_link (source
, decoder
);
280 sink
= gst_element_factory_make ("fakesink", "DictixTagReaderSink");
282 gst_object_unref (source
);
283 gst_object_unref (decoder
);
287 gst_bin_add (GST_BIN (reader
), sink
);
288 gst_element_link (decoder
, sink
);
290 priv
->bus
= gst_element_get_bus (GST_ELEMENT (reader
));
293 /* Go to GST_STATE_PAUSE: decoder will read metadata */
294 gst_element_set_state (GST_ELEMENT(reader
), GST_STATE_PAUSED
);
297 GstTagList
*tags
= NULL
;
299 message
= gst_bus_timed_pop_filtered (priv
->bus
,
301 GST_MESSAGE_TAG
| GST_MESSAGE_ERROR
| GST_MESSAGE_ASYNC_DONE
);
303 if (GST_MESSAGE_TYPE (message
) != GST_MESSAGE_TAG
) {
304 /* We've found an error or async is done */
308 gst_message_parse_tag (message
, &tags
);
309 gst_tag_list_foreach (tags
,(GstTagForeachFunc
) dix_tag_reader_load_tag
, reader
);
311 gst_tag_list_free (tags
);
312 gst_message_unref (message
);
315 if (GST_MESSAGE_TYPE (message
) == GST_MESSAGE_ERROR
) {
316 gst_message_parse_error (message
, &error
, NULL
);
318 g_warning (error
->message
);
324 state
= gst_element_get_state (GST_ELEMENT (reader
), NULL
, NULL
, GST_CLOCK_TIME_NONE
);
325 if (state
!= GST_STATE_CHANGE_SUCCESS
) {
326 g_warning ("Failed going to PAUSE state while metadata reading...");
331 gst_message_unref (message
);
333 /* At this point we are shure to be in GST_STATE_PAUSE state */
334 format
= GST_FORMAT_TIME
;
335 if (gst_element_query_duration (sink
, &format
, &length
) == TRUE
) {
336 if (format
== GST_FORMAT_TIME
) {
337 priv
->duration
= length
;
341 g_object_get (G_OBJECT (source
), "file", &file
, NULL
);
343 info
= g_file_query_info (file
,
344 G_FILE_ATTRIBUTE_STANDARD_SIZE
,
345 G_FILE_QUERY_INFO_NONE
,
349 priv
->bytes
= (guint64
) g_file_info_get_size (info
);
352 pad
= gst_element_get_static_pad (sink
, "sink");
354 caps
= gst_pad_get_negotiated_caps (pad
);
356 structure
= gst_caps_get_structure (caps
, 0);
358 gst_structure_get_int (structure
, "channels", &priv
->channels
);
359 gst_structure_get_int (structure
, "rate", &priv
->sample_rate
);
363 gst_element_set_state (GST_ELEMENT(reader
), GST_STATE_NULL
);
367 dix_tag_reader_get_title (DixTagReader
*reader
)
369 g_return_val_if_fail (DIX_IS_TAG_READER (reader
), NULL
);
370 DixTagReaderPrivate
*priv
= reader
->priv
;
372 return g_strdup (priv
->title
);
376 dix_tag_reader_get_codec (DixTagReader
*reader
)
378 g_return_val_if_fail (DIX_IS_TAG_READER (reader
), NULL
);
379 DixTagReaderPrivate
*priv
= reader
->priv
;
381 return g_strdup (priv
->codec
);
385 dix_tag_reader_get_size (DixTagReader
*reader
)
387 g_return_val_if_fail (DIX_IS_TAG_READER (reader
), 0);
388 DixTagReaderPrivate
*priv
= reader
->priv
;
390 return (gint64
) priv
->bytes
;
394 dix_tag_reader_get_duration (DixTagReader
*reader
)
396 g_return_val_if_fail (DIX_IS_TAG_READER (reader
), -1);
397 DixTagReaderPrivate
*priv
= reader
->priv
;
399 /* GST_FORMAT_TIME is nanoseconds... */
400 return priv
->duration
/ GST_SECOND
;
404 dix_tag_reader_get_channels (DixTagReader
*reader
)
406 g_return_val_if_fail (DIX_IS_TAG_READER (reader
), -1);
407 DixTagReaderPrivate
*priv
= reader
->priv
;
409 return priv
->channels
;
413 dix_tag_reader_get_sample_rate (DixTagReader
*reader
)
415 g_return_val_if_fail (DIX_IS_TAG_READER (reader
), -1);
416 DixTagReaderPrivate
*priv
= reader
->priv
;
418 return priv
->sample_rate
;
422 dix_tag_reader_get_bit_rate (DixTagReader
*reader
)
424 g_return_val_if_fail (DIX_IS_TAG_READER (reader
), -1);
425 DixTagReaderPrivate
*priv
= reader
->priv
;
427 return priv
->bit_rate
;
431 dix_tag_reader_load_tag (const GstTagList
*list
, const gchar
*tag
, gpointer
*data
)
433 DixTagReader
*reader
= (DixTagReader
*) data
;
434 DixTagReaderPrivate
*priv
= reader
->priv
;
435 const GValue
*value
= NULL
;
438 size
= gst_tag_list_get_tag_size (list
, tag
);
443 value
= gst_tag_list_get_value_index (list
, tag
, 0);
445 if (! g_strcmp0 (tag
, GST_TAG_TITLE
)) {
446 priv
->title
= g_strdup (g_value_get_string (value
));
448 if (! g_strcmp0 (tag
, GST_TAG_AUDIO_CODEC
)) {
449 priv
->codec
= g_strdup (g_value_get_string (value
));
451 if (! g_strcmp0 (tag
, GST_TAG_BITRATE
)) {
452 priv
->bit_rate
= (gint
) g_value_get_uint (value
);
454 if (! g_strcmp0 (tag
, GST_TAG_NOMINAL_BITRATE
)) {
455 priv
->bit_rate
= (gint
) g_value_get_uint (value
);
457 if (! g_strcmp0 (tag
, GST_TAG_MAXIMUM_BITRATE
)) {
458 priv
->bit_rate
= (gint
) g_value_get_uint (value
);