2
* Copyright (C) 2008 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>.
3
* Copyright (C) 2009 Jens Georg <mail@jensge.org>.
5
* Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
6
* Author: Jens Georg <mail@jensge.org>
8
* This file is part of Rygel.
10
* Rygel is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU Lesser General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* Rygel is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU Lesser General Public License for more details.
20
* You should have received a copy of the GNU Lesser General Public License
21
* along with this program; if not, write to the Free Software Foundation,
22
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26
#include <glib-object.h>
33
#define GST_TYPE_STREAM_TYPE (gst_stream_type_get_type ())
35
#define RYGEL_TYPE_METADATA_EXTRACTOR (rygel_metadata_extractor_get_type ())
36
#define RYGEL_METADATA_EXTRACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RYGEL_TYPE_METADATA_EXTRACTOR, RygelMetadataExtractor))
37
#define RYGEL_METADATA_EXTRACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RYGEL_TYPE_METADATA_EXTRACTOR, RygelMetadataExtractorClass))
38
#define RYGEL_IS_METADATA_EXTRACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RYGEL_TYPE_METADATA_EXTRACTOR))
39
#define RYGEL_IS_METADATA_EXTRACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RYGEL_TYPE_METADATA_EXTRACTOR))
40
#define RYGEL_METADATA_EXTRACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RYGEL_TYPE_METADATA_EXTRACTOR, RygelMetadataExtractorClass))
42
typedef struct _RygelMetadataExtractor RygelMetadataExtractor;
43
typedef struct _RygelMetadataExtractorClass RygelMetadataExtractorClass;
44
typedef struct _RygelMetadataExtractorPrivate RygelMetadataExtractorPrivate;
45
#define _gst_object_unref0(var) ((var == NULL) ? NULL : (var = (gst_object_unref (var), NULL)))
46
#define _gst_tag_list_free0(var) ((var == NULL) ? NULL : (var = (gst_tag_list_free (var), NULL)))
47
#define _g_queue_free0(var) ((var == NULL) ? NULL : (var = (g_queue_free (var), NULL)))
48
#define _g_free0(var) (var = (g_free (var), NULL))
49
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
50
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
51
#define _gst_caps_unref0(var) ((var == NULL) ? NULL : (var = (gst_caps_unref (var), NULL)))
54
GST_STREAM_TYPE_UNKNOWN = 0,
55
GST_STREAM_TYPE_AUDIO = 1,
56
GST_STREAM_TYPE_VIDEO = 2,
57
GST_STREAM_TYPE_TEXT = 3,
58
GST_STREAM_TYPE_SUBPICTURE = 4,
59
GST_STREAM_TYPE_ELEMENT = 5
62
struct _RygelMetadataExtractor {
63
GObject parent_instance;
64
RygelMetadataExtractorPrivate * priv;
67
struct _RygelMetadataExtractorClass {
68
GObjectClass parent_class;
71
struct _RygelMetadataExtractorPrivate {
79
static gpointer rygel_metadata_extractor_parent_class = NULL;
81
GType gst_stream_type_get_type (void);
82
GType rygel_metadata_extractor_get_type (void);
83
#define RYGEL_METADATA_EXTRACTOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RYGEL_TYPE_METADATA_EXTRACTOR, RygelMetadataExtractorPrivate))
85
RYGEL_METADATA_EXTRACTOR_DUMMY_PROPERTY
87
#define RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_SIZE "rygel-size"
88
#define RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_DURATION "rygel-duration"
89
#define RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_MIME "rygel-mime"
90
#define RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_CHANNELS "rygel-channels"
91
#define RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_RATE "rygel-rate"
92
#define RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_WIDTH "rygel-width"
93
#define RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_HEIGHT "rygel-height"
94
#define RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_DEPTH "rygel-depth"
95
#define RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_MTIME "rygel-mtime"
96
static void _gst_tag_merge_use_first_gst_tag_merge_func (const GValue* dest, const GValue* src);
97
static void rygel_metadata_extractor_register_custom_tag (const char* tag, GType type);
98
static inline void _dynamic_set_video_sink6 (GstElement* obj, GstElement* value);
99
static inline void _dynamic_set_audio_sink7 (GstElement* obj, GstElement* value);
100
static void rygel_metadata_extractor_tag_cb (RygelMetadataExtractor* self, GstBus* bus, GstMessage* message);
101
static void _rygel_metadata_extractor_tag_cb_gst_bus_message (GstBus* _sender, GstMessage* message, gpointer self);
102
static void rygel_metadata_extractor_state_changed_cb (RygelMetadataExtractor* self, GstBus* bus, GstMessage* message);
103
static void _rygel_metadata_extractor_state_changed_cb_gst_bus_message (GstBus* _sender, GstMessage* message, gpointer self);
104
static void rygel_metadata_extractor_error_cb (RygelMetadataExtractor* self, GstBus* bus, GstMessage* message);
105
static void _rygel_metadata_extractor_error_cb_gst_bus_message (GstBus* _sender, GstMessage* message, gpointer self);
106
static void rygel_metadata_extractor_renew_playbin (RygelMetadataExtractor* self);
107
RygelMetadataExtractor* rygel_metadata_extractor_new (void);
108
RygelMetadataExtractor* rygel_metadata_extractor_construct (GType object_type);
109
static void rygel_metadata_extractor_extract_next (RygelMetadataExtractor* self);
110
void rygel_metadata_extractor_extract (RygelMetadataExtractor* self, GFile* file);
111
static gboolean rygel_metadata_extractor_on_harvesting_timeout (RygelMetadataExtractor* self);
112
static void rygel_metadata_extractor_extract_mime_and_size (RygelMetadataExtractor* self, GError** error);
113
static inline void _dynamic_set_uri8 (GstElement* obj, char* value);
114
static gboolean _rygel_metadata_extractor_on_harvesting_timeout_gsource_func (gpointer self);
115
static void rygel_metadata_extractor_extract_duration (RygelMetadataExtractor* self);
116
static void rygel_metadata_extractor_extract_stream_info (RygelMetadataExtractor* self);
117
static void rygel_metadata_extractor_extract_av_info (RygelMetadataExtractor* self, GstPad* pad, GstStreamType type);
118
static inline GstElement* _dynamic_get_video_sink9 (GstElement* obj);
119
static inline GstElement* _dynamic_get_audio_sink10 (GstElement* obj);
120
static void rygel_metadata_extractor_extract_audio_info (RygelMetadataExtractor* self, const GstStructure* structure);
121
static void rygel_metadata_extractor_extract_video_info (RygelMetadataExtractor* self, const GstStructure* structure);
122
static void rygel_metadata_extractor_extract_int_value (RygelMetadataExtractor* self, const GstStructure* structure, const char* key, const char* tag);
123
static void rygel_metadata_extractor_finalize (GObject* obj);
126
static void g_cclosure_user_marshal_VOID__OBJECT_POINTER (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data);
129
GType gst_stream_type_get_type (void) {
130
static GType gst_stream_type_type_id = 0;
131
if (G_UNLIKELY (gst_stream_type_type_id == 0)) {
132
static const GEnumValue values[] = {{GST_STREAM_TYPE_UNKNOWN, "GST_STREAM_TYPE_UNKNOWN", "unknown"}, {GST_STREAM_TYPE_AUDIO, "GST_STREAM_TYPE_AUDIO", "audio"}, {GST_STREAM_TYPE_VIDEO, "GST_STREAM_TYPE_VIDEO", "video"}, {GST_STREAM_TYPE_TEXT, "GST_STREAM_TYPE_TEXT", "text"}, {GST_STREAM_TYPE_SUBPICTURE, "GST_STREAM_TYPE_SUBPICTURE", "subpicture"}, {GST_STREAM_TYPE_ELEMENT, "GST_STREAM_TYPE_ELEMENT", "element"}, {0, NULL, NULL}};
133
gst_stream_type_type_id = g_enum_register_static ("GstStreamType", values);
135
return gst_stream_type_type_id;
139
static void _gst_tag_merge_use_first_gst_tag_merge_func (const GValue* dest, const GValue* src) {
140
gst_tag_merge_use_first (dest, src);
144
static void rygel_metadata_extractor_register_custom_tag (const char* tag, GType type) {
145
g_return_if_fail (tag != NULL);
146
gst_tag_register (tag, GST_TAG_FLAG_META, type, tag, "", _gst_tag_merge_use_first_gst_tag_merge_func);
150
static inline void _dynamic_set_video_sink6 (GstElement* obj, GstElement* value) {
151
g_object_set (obj, "video-sink", value, NULL);
155
static inline void _dynamic_set_audio_sink7 (GstElement* obj, GstElement* value) {
156
g_object_set (obj, "audio-sink", value, NULL);
160
static void _rygel_metadata_extractor_tag_cb_gst_bus_message (GstBus* _sender, GstMessage* message, gpointer self) {
161
rygel_metadata_extractor_tag_cb (self, _sender, message);
165
static void _rygel_metadata_extractor_state_changed_cb_gst_bus_message (GstBus* _sender, GstMessage* message, gpointer self) {
166
rygel_metadata_extractor_state_changed_cb (self, _sender, message);
170
static void _rygel_metadata_extractor_error_cb_gst_bus_message (GstBus* _sender, GstMessage* message, gpointer self) {
171
rygel_metadata_extractor_error_cb (self, _sender, message);
175
static void rygel_metadata_extractor_renew_playbin (RygelMetadataExtractor* self) {
180
g_return_if_fail (self != NULL);
181
self->priv->playbin = (_tmp0_ = gst_element_factory_make ("playbin2", NULL), _gst_object_unref0 (self->priv->playbin), _tmp0_);
182
if (self->priv->playbin == NULL) {
184
self->priv->playbin = (_tmp1_ = gst_element_factory_make ("playbin", NULL), _gst_object_unref0 (self->priv->playbin), _tmp1_);
186
sink = gst_element_factory_make ("fakesink", NULL);
187
gst_object_ref ((GstObject*) sink);
188
_dynamic_set_video_sink6 (self->priv->playbin, sink);
189
sink = (_tmp2_ = gst_element_factory_make ("fakesink", NULL), _gst_object_unref0 (sink), _tmp2_);
190
gst_object_ref ((GstObject*) sink);
191
_dynamic_set_audio_sink7 (self->priv->playbin, sink);
192
bus = gst_element_get_bus (self->priv->playbin);
193
gst_bus_add_signal_watch (bus);
194
g_signal_connect_object (bus, "message::tag", (GCallback) _rygel_metadata_extractor_tag_cb_gst_bus_message, self, 0);
195
g_signal_connect_object (bus, "message::state-changed", (GCallback) _rygel_metadata_extractor_state_changed_cb_gst_bus_message, self, 0);
196
g_signal_connect_object (bus, "message::error", (GCallback) _rygel_metadata_extractor_error_cb_gst_bus_message, self, 0);
197
_gst_object_unref0 (sink);
198
_gst_object_unref0 (bus);
202
RygelMetadataExtractor* rygel_metadata_extractor_construct (GType object_type) {
203
RygelMetadataExtractor * self;
206
self = (RygelMetadataExtractor*) g_object_new (object_type, NULL);
207
rygel_metadata_extractor_register_custom_tag (RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_SIZE, G_TYPE_INT64);
208
rygel_metadata_extractor_register_custom_tag (RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_DURATION, G_TYPE_INT64);
209
rygel_metadata_extractor_register_custom_tag (RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_MIME, G_TYPE_STRING);
210
rygel_metadata_extractor_register_custom_tag (RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_CHANNELS, G_TYPE_INT);
211
rygel_metadata_extractor_register_custom_tag (RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_RATE, G_TYPE_INT);
212
rygel_metadata_extractor_register_custom_tag (RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_WIDTH, G_TYPE_INT);
213
rygel_metadata_extractor_register_custom_tag (RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_HEIGHT, G_TYPE_INT);
214
rygel_metadata_extractor_register_custom_tag (RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_DEPTH, G_TYPE_INT);
215
rygel_metadata_extractor_register_custom_tag (RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_MTIME, G_TYPE_UINT64);
216
self->priv->file_queue = (_tmp0_ = g_queue_new (), _g_queue_free0 (self->priv->file_queue), _tmp0_);
217
self->priv->tag_list = (_tmp1_ = gst_tag_list_new (), _gst_tag_list_free0 (self->priv->tag_list), _tmp1_);
222
RygelMetadataExtractor* rygel_metadata_extractor_new (void) {
223
return rygel_metadata_extractor_construct (RYGEL_TYPE_METADATA_EXTRACTOR);
227
static gpointer _g_object_ref0 (gpointer self) {
228
return self ? g_object_ref (self) : NULL;
232
void rygel_metadata_extractor_extract (RygelMetadataExtractor* self, GFile* file) {
233
gboolean trigger_run;
234
g_return_if_fail (self != NULL);
235
g_return_if_fail (file != NULL);
236
trigger_run = g_queue_get_length (self->priv->file_queue) == 0;
237
g_queue_push_tail (self->priv->file_queue, _g_object_ref0 (file));
239
rygel_metadata_extractor_extract_next (self);
244
static gboolean rygel_metadata_extractor_on_harvesting_timeout (RygelMetadataExtractor* self) {
249
g_return_val_if_fail (self != NULL, FALSE);
250
g_warning ("rygel-metadata-extractor.vala:128: Metadata extractor timed out on %s, restarting", _tmp0_ = g_file_get_uri ((GFile*) g_queue_peek_head (self->priv->file_queue)));
252
gst_element_set_state (self->priv->playbin, GST_STATE_NULL);
253
g_signal_emit_by_name (self, "error", (GFile*) g_queue_peek_head (self->priv->file_queue), _tmp1_ = g_error_new_literal (G_IO_CHANNEL_ERROR, G_IO_CHANNEL_ERROR_FAILED, "Pipeline stuck while reading file info"));
254
_g_error_free0 (_tmp1_);
255
_tmp2_ = (GFile*) g_queue_pop_head (self->priv->file_queue);
256
_g_object_unref0 (_tmp2_);
257
rygel_metadata_extractor_extract_next (self);
263
static inline void _dynamic_set_uri8 (GstElement* obj, char* value) {
264
g_object_set (obj, "uri", value, NULL);
268
static gboolean _rygel_metadata_extractor_on_harvesting_timeout_gsource_func (gpointer self) {
269
return rygel_metadata_extractor_on_harvesting_timeout (self);
273
static void rygel_metadata_extractor_extract_next (RygelMetadataExtractor* self) {
274
GError * _inner_error_;
275
g_return_if_fail (self != NULL);
276
_inner_error_ = NULL;
277
if (self->priv->timeout_id != 0) {
278
g_source_remove (self->priv->timeout_id);
280
if (g_queue_get_length (self->priv->file_queue) > 0) {
285
item = _g_object_ref0 ((GFile*) g_queue_peek_head (self->priv->file_queue));
286
g_debug ("rygel-metadata-extractor.vala:146: Scheduling file %s for metadata extraction", _tmp0_ = g_file_get_uri (item));
288
rygel_metadata_extractor_extract_mime_and_size (self, &_inner_error_);
289
if (_inner_error_ != NULL) {
290
_g_object_unref0 (item);
291
goto __catch41_g_error;
294
rygel_metadata_extractor_renew_playbin (self);
295
_dynamic_set_uri8 (self->priv->playbin, _tmp1_ = g_file_get_uri (item));
297
self->priv->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, (guint) 5, _rygel_metadata_extractor_on_harvesting_timeout_gsource_func, g_object_ref (self), g_object_unref);
298
gst_element_set_state (self->priv->playbin, GST_STATE_PAUSED);
299
_g_object_unref0 (item);
305
_error_ = _inner_error_;
306
_inner_error_ = NULL;
308
rygel_metadata_extractor_extract_next (self);
309
_g_error_free0 (_error_);
313
if (_inner_error_ != NULL) {
314
g_critical ("file %s: line %d: uncaught error: %s", __FILE__, __LINE__, _inner_error_->message);
315
g_clear_error (&_inner_error_);
322
static void rygel_metadata_extractor_tag_cb (RygelMetadataExtractor* self, GstBus* bus, GstMessage* message) {
323
GstTagList* new_tag_list;
327
g_return_if_fail (self != NULL);
328
g_return_if_fail (bus != NULL);
329
g_return_if_fail (message != NULL);
332
gst_message_parse_tag (message, &_tmp0_);
333
new_tag_list = (_tmp1_ = _tmp0_, _gst_tag_list_free0 (new_tag_list), _tmp1_);
334
self->priv->tag_list = (_tmp2_ = gst_tag_list_merge (new_tag_list, self->priv->tag_list, GST_TAG_MERGE_REPLACE), _gst_tag_list_free0 (self->priv->tag_list), _tmp2_);
335
_gst_tag_list_free0 (new_tag_list);
339
static void rygel_metadata_extractor_state_changed_cb (RygelMetadataExtractor* self, GstBus* bus, GstMessage* message) {
343
g_return_if_fail (self != NULL);
344
g_return_if_fail (bus != NULL);
345
g_return_if_fail (message != NULL);
346
if (message->src != GST_OBJECT (self->priv->playbin)) {
351
gst_message_parse_state_changed (message, &old_state, &new_state, NULL);
353
if (new_state == GST_STATE_PAUSED) {
354
_tmp0_ = old_state == GST_STATE_READY;
361
rygel_metadata_extractor_extract_duration (self);
362
rygel_metadata_extractor_extract_stream_info (self);
363
g_signal_emit_by_name (self, "extraction-done", (GFile*) g_queue_peek_head (self->priv->file_queue), self->priv->tag_list);
364
gst_element_set_state (self->priv->playbin, GST_STATE_NULL);
365
self->priv->tag_list = (_tmp1_ = gst_tag_list_new (), _gst_tag_list_free0 (self->priv->tag_list), _tmp1_);
366
_tmp2_ = (GFile*) g_queue_pop_head (self->priv->file_queue);
367
_g_object_unref0 (_tmp2_);
368
rygel_metadata_extractor_extract_next (self);
373
static void rygel_metadata_extractor_error_cb (RygelMetadataExtractor* self, GstBus* bus, GstMessage* message) {
382
g_return_if_fail (self != NULL);
383
g_return_if_fail (bus != NULL);
384
g_return_if_fail (message != NULL);
385
g_return_if_fail (g_queue_get_length (self->priv->file_queue) != 0);
390
(gst_message_parse_error (message, &_tmp0_, &_tmp2_), _error_ = (_tmp1_ = _tmp0_, _g_error_free0 (_error_), _tmp1_));
391
debug = (_tmp3_ = _tmp2_, _g_free0 (debug), _tmp3_);
392
if (_error_ != NULL) {
394
debug = (_tmp4_ = g_strdup (_error_->message), _g_free0 (debug), _tmp4_);
396
g_signal_emit_by_name (self, "error", (GFile*) g_queue_peek_head (self->priv->file_queue), _error_);
397
gst_element_set_state (self->priv->playbin, GST_STATE_NULL);
398
self->priv->tag_list = (_tmp5_ = gst_tag_list_new (), _gst_tag_list_free0 (self->priv->tag_list), _tmp5_);
399
_tmp6_ = (GFile*) g_queue_pop_head (self->priv->file_queue);
400
_g_object_unref0 (_tmp6_);
401
rygel_metadata_extractor_extract_next (self);
402
_g_error_free0 (_error_);
407
static gpointer _g_error_copy0 (gpointer self) {
408
return self ? g_error_copy (self) : NULL;
412
static void rygel_metadata_extractor_extract_mime_and_size (RygelMetadataExtractor* self, GError** error) {
413
GError * _inner_error_;
415
GFileInfo* file_info;
416
const char* content_type;
420
g_return_if_fail (self != NULL);
421
_inner_error_ = NULL;
422
file = _g_object_ref0 ((GFile*) g_queue_peek_head (self->priv->file_queue));
427
_tmp0_ = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE, NULL, &_inner_error_);
428
if (_inner_error_ != NULL) {
429
goto __catch42_g_error;
432
file_info = (_tmp1_ = _tmp0_, _g_object_unref0 (file_info), _tmp1_);
438
_error_ = _inner_error_;
439
_inner_error_ = NULL;
442
g_warning ("rygel-metadata-extractor.vala:232: Failed to query content type for '%s'\n", _tmp2_ = g_file_get_uri (file));
444
g_signal_emit_by_name (self, "error", file, _error_);
445
_inner_error_ = _g_error_copy0 (_error_);
446
if (_inner_error_ != NULL) {
447
_g_error_free0 (_error_);
448
_g_object_unref0 (file);
449
_g_object_unref0 (file_info);
452
_g_error_free0 (_error_);
456
if (_inner_error_ != NULL) {
457
g_propagate_error (error, _inner_error_);
458
_g_object_unref0 (file);
459
_g_object_unref0 (file_info);
462
content_type = g_file_info_get_content_type (file_info);
463
mime = g_content_type_get_mime_type (content_type);
465
gst_tag_list_add (self->priv->tag_list, GST_TAG_MERGE_REPLACE, RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_MIME, mime, NULL);
467
size = g_file_info_get_size (file_info);
468
gst_tag_list_add (self->priv->tag_list, GST_TAG_MERGE_REPLACE, RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_SIZE, size, NULL);
469
mtime = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
470
gst_tag_list_add (self->priv->tag_list, GST_TAG_MERGE_REPLACE, RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_MTIME, mtime, NULL);
471
_g_object_unref0 (file);
472
_g_object_unref0 (file_info);
476
static void rygel_metadata_extractor_extract_duration (RygelMetadataExtractor* self) {
479
g_return_if_fail (self != NULL);
481
format = GST_FORMAT_TIME;
482
if (gst_element_query_duration (self->priv->playbin, &format, &duration)) {
483
gst_tag_list_add (self->priv->tag_list, GST_TAG_MERGE_REPLACE, RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_DURATION, duration, NULL);
488
static inline GstElement* _dynamic_get_video_sink9 (GstElement* obj) {
490
g_object_get (obj, "video-sink", &result, NULL);
495
static inline GstElement* _dynamic_get_audio_sink10 (GstElement* obj) {
497
g_object_get (obj, "audio-sink", &result, NULL);
502
static void rygel_metadata_extractor_extract_stream_info (RygelMetadataExtractor* self) {
503
g_return_if_fail (self != NULL);
504
rygel_metadata_extractor_extract_av_info (self, gst_element_get_pad (_dynamic_get_video_sink9 (self->priv->playbin), "sink"), GST_STREAM_TYPE_VIDEO);
505
rygel_metadata_extractor_extract_av_info (self, gst_element_get_pad (_dynamic_get_audio_sink10 (self->priv->playbin), "sink"), GST_STREAM_TYPE_AUDIO);
509
static void rygel_metadata_extractor_extract_av_info (RygelMetadataExtractor* self, GstPad* pad, GstStreamType type) {
511
const GstStructure* structure;
512
g_return_if_fail (self != NULL);
513
g_return_if_fail (pad != NULL);
517
caps = gst_pad_get_negotiated_caps (pad);
519
_gst_caps_unref0 (caps);
522
structure = gst_caps_get_structure (caps, (guint) 0);
523
if (structure == NULL) {
524
_gst_caps_unref0 (caps);
527
if (type == GST_STREAM_TYPE_AUDIO) {
528
rygel_metadata_extractor_extract_audio_info (self, structure);
530
if (type == GST_STREAM_TYPE_VIDEO) {
531
rygel_metadata_extractor_extract_video_info (self, structure);
534
_gst_caps_unref0 (caps);
538
static void rygel_metadata_extractor_extract_audio_info (RygelMetadataExtractor* self, const GstStructure* structure) {
539
g_return_if_fail (self != NULL);
540
g_return_if_fail (structure != NULL);
541
rygel_metadata_extractor_extract_int_value (self, structure, "channels", RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_CHANNELS);
542
rygel_metadata_extractor_extract_int_value (self, structure, "rate", RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_RATE);
546
static void rygel_metadata_extractor_extract_video_info (RygelMetadataExtractor* self, const GstStructure* structure) {
547
g_return_if_fail (self != NULL);
548
g_return_if_fail (structure != NULL);
549
rygel_metadata_extractor_extract_int_value (self, structure, "width", RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_WIDTH);
550
rygel_metadata_extractor_extract_int_value (self, structure, "height", RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_HEIGHT);
551
rygel_metadata_extractor_extract_int_value (self, structure, "depth", RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_DEPTH);
555
static void rygel_metadata_extractor_extract_int_value (RygelMetadataExtractor* self, const GstStructure* structure, const char* key, const char* tag) {
557
g_return_if_fail (self != NULL);
558
g_return_if_fail (structure != NULL);
559
g_return_if_fail (key != NULL);
560
g_return_if_fail (tag != NULL);
562
if (gst_structure_get_int (structure, key, &val)) {
563
gst_tag_list_add (self->priv->tag_list, GST_TAG_MERGE_REPLACE, tag, val, NULL);
568
static void rygel_metadata_extractor_class_init (RygelMetadataExtractorClass * klass) {
569
rygel_metadata_extractor_parent_class = g_type_class_peek_parent (klass);
570
g_type_class_add_private (klass, sizeof (RygelMetadataExtractorPrivate));
571
G_OBJECT_CLASS (klass)->finalize = rygel_metadata_extractor_finalize;
572
g_signal_new ("extraction_done", RYGEL_TYPE_METADATA_EXTRACTOR, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2, G_TYPE_FILE, G_TYPE_POINTER);
573
g_signal_new ("error", RYGEL_TYPE_METADATA_EXTRACTOR, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2, G_TYPE_FILE, G_TYPE_POINTER);
577
static void rygel_metadata_extractor_instance_init (RygelMetadataExtractor * self) {
578
self->priv = RYGEL_METADATA_EXTRACTOR_GET_PRIVATE (self);
582
static void rygel_metadata_extractor_finalize (GObject* obj) {
583
RygelMetadataExtractor * self;
584
self = RYGEL_METADATA_EXTRACTOR (obj);
585
_gst_object_unref0 (self->priv->playbin);
586
_gst_tag_list_free0 (self->priv->tag_list);
587
_g_queue_free0 (self->priv->file_queue);
588
G_OBJECT_CLASS (rygel_metadata_extractor_parent_class)->finalize (obj);
592
GType rygel_metadata_extractor_get_type (void) {
593
static GType rygel_metadata_extractor_type_id = 0;
594
if (rygel_metadata_extractor_type_id == 0) {
595
static const GTypeInfo g_define_type_info = { sizeof (RygelMetadataExtractorClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) rygel_metadata_extractor_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RygelMetadataExtractor), 0, (GInstanceInitFunc) rygel_metadata_extractor_instance_init, NULL };
596
rygel_metadata_extractor_type_id = g_type_register_static (G_TYPE_OBJECT, "RygelMetadataExtractor", &g_define_type_info, 0);
598
return rygel_metadata_extractor_type_id;
603
static void g_cclosure_user_marshal_VOID__OBJECT_POINTER (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) {
604
typedef void (*GMarshalFunc_VOID__OBJECT_POINTER) (gpointer data1, gpointer arg_1, gpointer arg_2, gpointer data2);
605
register GMarshalFunc_VOID__OBJECT_POINTER callback;
606
register GCClosure * cc;
607
register gpointer data1, data2;
608
cc = (GCClosure *) closure;
609
g_return_if_fail (n_param_values == 3);
610
if (G_CCLOSURE_SWAP_DATA (closure)) {
611
data1 = closure->data;
612
data2 = param_values->data[0].v_pointer;
614
data1 = param_values->data[0].v_pointer;
615
data2 = closure->data;
617
callback = (GMarshalFunc_VOID__OBJECT_POINTER) (marshal_data ? marshal_data : cc->callback);
618
callback (data1, g_value_get_object (param_values + 1), g_value_get_pointer (param_values + 2), data2);