~ubuntu-branches/ubuntu/precise/rygel/precise

« back to all changes in this revision

Viewing changes to src/rygel/rygel-metadata-extractor.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Henriksson
  • Date: 2009-09-26 14:04:05 UTC
  • Revision ID: james.westby@ubuntu.com-20090926140405-d5x3j13k10psa1gu
Tags: upstream-0.4.1
ImportĀ upstreamĀ versionĀ 0.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>.
 
3
 * Copyright (C) 2009 Jens Georg <mail@jensge.org>.
 
4
 *
 
5
 * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
 
6
 * Author: Jens Georg <mail@jensge.org>
 
7
 *
 
8
 * This file is part of Rygel.
 
9
 *
 
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.
 
14
 *
 
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.
 
19
 *
 
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.
 
23
 */
 
24
 
 
25
#include <glib.h>
 
26
#include <glib-object.h>
 
27
#include <gst/gst.h>
 
28
#include <gio/gio.h>
 
29
#include <stdlib.h>
 
30
#include <string.h>
 
31
 
 
32
 
 
33
#define GST_TYPE_STREAM_TYPE (gst_stream_type_get_type ())
 
34
 
 
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))
 
41
 
 
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)))
 
52
 
 
53
typedef enum  {
 
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
 
60
} GstStreamType;
 
61
 
 
62
struct _RygelMetadataExtractor {
 
63
        GObject parent_instance;
 
64
        RygelMetadataExtractorPrivate * priv;
 
65
};
 
66
 
 
67
struct _RygelMetadataExtractorClass {
 
68
        GObjectClass parent_class;
 
69
};
 
70
 
 
71
struct _RygelMetadataExtractorPrivate {
 
72
        GstElement* playbin;
 
73
        GstTagList* tag_list;
 
74
        GQueue* file_queue;
 
75
        guint timeout_id;
 
76
};
 
77
 
 
78
 
 
79
static gpointer rygel_metadata_extractor_parent_class = NULL;
 
80
 
 
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))
 
84
enum  {
 
85
        RYGEL_METADATA_EXTRACTOR_DUMMY_PROPERTY
 
86
};
 
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);
 
124
 
 
125
 
 
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);
 
127
 
 
128
 
 
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);
 
134
        }
 
135
        return gst_stream_type_type_id;
 
136
}
 
137
 
 
138
 
 
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);
 
141
}
 
142
 
 
143
 
 
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);
 
147
}
 
148
 
 
149
 
 
150
static inline void _dynamic_set_video_sink6 (GstElement* obj, GstElement* value) {
 
151
        g_object_set (obj, "video-sink", value, NULL);
 
152
}
 
153
 
 
154
 
 
155
static inline void _dynamic_set_audio_sink7 (GstElement* obj, GstElement* value) {
 
156
        g_object_set (obj, "audio-sink", value, NULL);
 
157
}
 
158
 
 
159
 
 
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);
 
162
}
 
163
 
 
164
 
 
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);
 
167
}
 
168
 
 
169
 
 
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);
 
172
}
 
173
 
 
174
 
 
175
static void rygel_metadata_extractor_renew_playbin (RygelMetadataExtractor* self) {
 
176
        GstElement* _tmp0_;
 
177
        GstElement* sink;
 
178
        GstElement* _tmp2_;
 
179
        GstBus* bus;
 
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) {
 
183
                GstElement* _tmp1_;
 
184
                self->priv->playbin = (_tmp1_ = gst_element_factory_make ("playbin", NULL), _gst_object_unref0 (self->priv->playbin), _tmp1_);
 
185
        }
 
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);
 
199
}
 
200
 
 
201
 
 
202
RygelMetadataExtractor* rygel_metadata_extractor_construct (GType object_type) {
 
203
        RygelMetadataExtractor * self;
 
204
        GQueue* _tmp0_;
 
205
        GstTagList* _tmp1_;
 
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_);
 
218
        return self;
 
219
}
 
220
 
 
221
 
 
222
RygelMetadataExtractor* rygel_metadata_extractor_new (void) {
 
223
        return rygel_metadata_extractor_construct (RYGEL_TYPE_METADATA_EXTRACTOR);
 
224
}
 
225
 
 
226
 
 
227
static gpointer _g_object_ref0 (gpointer self) {
 
228
        return self ? g_object_ref (self) : NULL;
 
229
}
 
230
 
 
231
 
 
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));
 
238
        if (trigger_run) {
 
239
                rygel_metadata_extractor_extract_next (self);
 
240
        }
 
241
}
 
242
 
 
243
 
 
244
static gboolean rygel_metadata_extractor_on_harvesting_timeout (RygelMetadataExtractor* self) {
 
245
        gboolean result;
 
246
        char* _tmp0_;
 
247
        GError* _tmp1_;
 
248
        GFile* _tmp2_;
 
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)));
 
251
        _g_free0 (_tmp0_);
 
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);
 
258
        result = FALSE;
 
259
        return result;
 
260
}
 
261
 
 
262
 
 
263
static inline void _dynamic_set_uri8 (GstElement* obj, char* value) {
 
264
        g_object_set (obj, "uri", value, NULL);
 
265
}
 
266
 
 
267
 
 
268
static gboolean _rygel_metadata_extractor_on_harvesting_timeout_gsource_func (gpointer self) {
 
269
        return rygel_metadata_extractor_on_harvesting_timeout (self);
 
270
}
 
271
 
 
272
 
 
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);
 
279
        }
 
280
        if (g_queue_get_length (self->priv->file_queue) > 0) {
 
281
                {
 
282
                        GFile* item;
 
283
                        char* _tmp0_;
 
284
                        char* _tmp1_;
 
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));
 
287
                        _g_free0 (_tmp0_);
 
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;
 
292
                                goto __finally41;
 
293
                        }
 
294
                        rygel_metadata_extractor_renew_playbin (self);
 
295
                        _dynamic_set_uri8 (self->priv->playbin, _tmp1_ = g_file_get_uri (item));
 
296
                        _g_free0 (_tmp1_);
 
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);
 
300
                }
 
301
                goto __finally41;
 
302
                __catch41_g_error:
 
303
                {
 
304
                        GError * _error_;
 
305
                        _error_ = _inner_error_;
 
306
                        _inner_error_ = NULL;
 
307
                        {
 
308
                                rygel_metadata_extractor_extract_next (self);
 
309
                                _g_error_free0 (_error_);
 
310
                        }
 
311
                }
 
312
                __finally41:
 
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_);
 
316
                        return;
 
317
                }
 
318
        }
 
319
}
 
320
 
 
321
 
 
322
static void rygel_metadata_extractor_tag_cb (RygelMetadataExtractor* self, GstBus* bus, GstMessage* message) {
 
323
        GstTagList* new_tag_list;
 
324
        GstTagList* _tmp1_;
 
325
        GstTagList* _tmp0_;
 
326
        GstTagList* _tmp2_;
 
327
        g_return_if_fail (self != NULL);
 
328
        g_return_if_fail (bus != NULL);
 
329
        g_return_if_fail (message != NULL);
 
330
        new_tag_list = NULL;
 
331
        _tmp0_ = 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);
 
336
}
 
337
 
 
338
 
 
339
static void rygel_metadata_extractor_state_changed_cb (RygelMetadataExtractor* self, GstBus* bus, GstMessage* message) {
 
340
        GstState new_state;
 
341
        GstState old_state;
 
342
        gboolean _tmp0_;
 
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)) {
 
347
                return;
 
348
        }
 
349
        new_state = 0;
 
350
        old_state = 0;
 
351
        gst_message_parse_state_changed (message, &old_state, &new_state, NULL);
 
352
        _tmp0_ = FALSE;
 
353
        if (new_state == GST_STATE_PAUSED) {
 
354
                _tmp0_ = old_state == GST_STATE_READY;
 
355
        } else {
 
356
                _tmp0_ = FALSE;
 
357
        }
 
358
        if (_tmp0_) {
 
359
                GstTagList* _tmp1_;
 
360
                GFile* _tmp2_;
 
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);
 
369
        }
 
370
}
 
371
 
 
372
 
 
373
static void rygel_metadata_extractor_error_cb (RygelMetadataExtractor* self, GstBus* bus, GstMessage* message) {
 
374
        GError* _error_;
 
375
        char* debug;
 
376
        char* _tmp3_;
 
377
        char* _tmp2_;
 
378
        GError* _tmp1_;
 
379
        GError* _tmp0_;
 
380
        GstTagList* _tmp5_;
 
381
        GFile* _tmp6_;
 
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);
 
386
        _error_ = NULL;
 
387
        debug = NULL;
 
388
        _tmp2_ = NULL;
 
389
        _tmp0_ = NULL;
 
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) {
 
393
                char* _tmp4_;
 
394
                debug = (_tmp4_ = g_strdup (_error_->message), _g_free0 (debug), _tmp4_);
 
395
        }
 
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_);
 
403
        _g_free0 (debug);
 
404
}
 
405
 
 
406
 
 
407
static gpointer _g_error_copy0 (gpointer self) {
 
408
        return self ? g_error_copy (self) : NULL;
 
409
}
 
410
 
 
411
 
 
412
static void rygel_metadata_extractor_extract_mime_and_size (RygelMetadataExtractor* self, GError** error) {
 
413
        GError * _inner_error_;
 
414
        GFile* file;
 
415
        GFileInfo* file_info;
 
416
        const char* content_type;
 
417
        const char* mime;
 
418
        gint64 size;
 
419
        guint64 mtime;
 
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));
 
423
        file_info = NULL;
 
424
        {
 
425
                GFileInfo* _tmp0_;
 
426
                GFileInfo* _tmp1_;
 
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;
 
430
                        goto __finally42;
 
431
                }
 
432
                file_info = (_tmp1_ = _tmp0_, _g_object_unref0 (file_info), _tmp1_);
 
433
        }
 
434
        goto __finally42;
 
435
        __catch42_g_error:
 
436
        {
 
437
                GError * _error_;
 
438
                _error_ = _inner_error_;
 
439
                _inner_error_ = NULL;
 
440
                {
 
441
                        char* _tmp2_;
 
442
                        g_warning ("rygel-metadata-extractor.vala:232: Failed to query content type for '%s'\n", _tmp2_ = g_file_get_uri (file));
 
443
                        _g_free0 (_tmp2_);
 
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);
 
450
                                goto __finally42;
 
451
                        }
 
452
                        _g_error_free0 (_error_);
 
453
                }
 
454
        }
 
455
        __finally42:
 
456
        if (_inner_error_ != NULL) {
 
457
                g_propagate_error (error, _inner_error_);
 
458
                _g_object_unref0 (file);
 
459
                _g_object_unref0 (file_info);
 
460
                return;
 
461
        }
 
462
        content_type = g_file_info_get_content_type (file_info);
 
463
        mime = g_content_type_get_mime_type (content_type);
 
464
        if (mime != NULL) {
 
465
                gst_tag_list_add (self->priv->tag_list, GST_TAG_MERGE_REPLACE, RYGEL_METADATA_EXTRACTOR_TAG_RYGEL_MIME, mime, NULL);
 
466
        }
 
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);
 
473
}
 
474
 
 
475
 
 
476
static void rygel_metadata_extractor_extract_duration (RygelMetadataExtractor* self) {
 
477
        gint64 duration;
 
478
        GstFormat format;
 
479
        g_return_if_fail (self != NULL);
 
480
        duration = 0LL;
 
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);
 
484
        }
 
485
}
 
486
 
 
487
 
 
488
static inline GstElement* _dynamic_get_video_sink9 (GstElement* obj) {
 
489
        GstElement* result;
 
490
        g_object_get (obj, "video-sink", &result, NULL);
 
491
        return result;
 
492
}
 
493
 
 
494
 
 
495
static inline GstElement* _dynamic_get_audio_sink10 (GstElement* obj) {
 
496
        GstElement* result;
 
497
        g_object_get (obj, "audio-sink", &result, NULL);
 
498
        return result;
 
499
}
 
500
 
 
501
 
 
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);
 
506
}
 
507
 
 
508
 
 
509
static void rygel_metadata_extractor_extract_av_info (RygelMetadataExtractor* self, GstPad* pad, GstStreamType type) {
 
510
        GstCaps* caps;
 
511
        const GstStructure* structure;
 
512
        g_return_if_fail (self != NULL);
 
513
        g_return_if_fail (pad != NULL);
 
514
        if (pad == NULL) {
 
515
                return;
 
516
        }
 
517
        caps = gst_pad_get_negotiated_caps (pad);
 
518
        if (caps == NULL) {
 
519
                _gst_caps_unref0 (caps);
 
520
                return;
 
521
        }
 
522
        structure = gst_caps_get_structure (caps, (guint) 0);
 
523
        if (structure == NULL) {
 
524
                _gst_caps_unref0 (caps);
 
525
                return;
 
526
        }
 
527
        if (type == GST_STREAM_TYPE_AUDIO) {
 
528
                rygel_metadata_extractor_extract_audio_info (self, structure);
 
529
        } else {
 
530
                if (type == GST_STREAM_TYPE_VIDEO) {
 
531
                        rygel_metadata_extractor_extract_video_info (self, structure);
 
532
                }
 
533
        }
 
534
        _gst_caps_unref0 (caps);
 
535
}
 
536
 
 
537
 
 
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);
 
543
}
 
544
 
 
545
 
 
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);
 
552
}
 
553
 
 
554
 
 
555
static void rygel_metadata_extractor_extract_int_value (RygelMetadataExtractor* self, const GstStructure* structure, const char* key, const char* tag) {
 
556
        gint val;
 
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);
 
561
        val = 0;
 
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);
 
564
        }
 
565
}
 
566
 
 
567
 
 
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);
 
574
}
 
575
 
 
576
 
 
577
static void rygel_metadata_extractor_instance_init (RygelMetadataExtractor * self) {
 
578
        self->priv = RYGEL_METADATA_EXTRACTOR_GET_PRIVATE (self);
 
579
}
 
580
 
 
581
 
 
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);
 
589
}
 
590
 
 
591
 
 
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);
 
597
        }
 
598
        return rygel_metadata_extractor_type_id;
 
599
}
 
600
 
 
601
 
 
602
 
 
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;
 
613
        } else {
 
614
                data1 = param_values->data[0].v_pointer;
 
615
                data2 = closure->data;
 
616
        }
 
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);
 
619
}
 
620
 
 
621
 
 
622