~ubuntu-app-review-contributors/ubuntu-app-reviews/eina-player

« back to all changes in this revision

Viewing changes to lomo/lomo-stream.c

  • Committer: Andrew Mitchell
  • Author(s): Luis Lopez
  • Date: 2011-12-16 13:47:22 UTC
  • Revision ID: ajmitch@ubuntu.com-20111216134722-xivouyl2pw3rk425
Tags: upstream-0.14.0
ImportĀ upstreamĀ versionĀ 0.14.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * lomo/lomo-stream.c
 
3
 *
 
4
 * Copyright (C) 2004-2011 Eina
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include "lomo-stream.h"
 
21
 
 
22
#include <string.h>
 
23
#include <glib/gi18n.h>
 
24
#include <gst/gst.h>
 
25
#include "lomo.h"
 
26
 
 
27
G_DEFINE_TYPE (LomoStream, lomo_stream, G_TYPE_OBJECT)
 
28
 
 
29
struct TagFmt {
 
30
        gchar   key;
 
31
        const gchar *tag;
 
32
        gchar  *fmt;
 
33
};
 
34
 
 
35
static struct TagFmt tag_fmt_table [] = {
 
36
        { 'a', LOMO_TAG_ARTIST       , "%s"  },
 
37
        { 'b', LOMO_TAG_ALBUM        , "%s"  },
 
38
        { 't', LOMO_TAG_TITLE        , "%s"  },
 
39
        { 'g', LOMO_TAG_GENRE        , "%s"  },
 
40
        { 'n', LOMO_TAG_TRACK_NUMBER , "%02d"},
 
41
        { 'd', LOMO_TAG_DATE         , "%s"  },
 
42
        {   0, LOMO_TAG_INVALID      , "%p"  }
 
43
};
 
44
 
 
45
struct _LomoStreamPrivate {
 
46
        gboolean all_tags, failed;
 
47
        GList *tags;
 
48
};
 
49
 
 
50
enum {
 
51
        PROP_0,
 
52
        PROP_URI
 
53
};
 
54
 
 
55
enum {
 
56
        SIGNAL_EXTENDED_METADATA_UPDATED,
 
57
        LAST_SIGNAL
 
58
};
 
59
guint lomo_stream_signals[LAST_SIGNAL] = { 0 };
 
60
 
 
61
static void
 
62
stream_set_uri(LomoStream *self, const gchar *uri);
 
63
 
 
64
static void
 
65
destroy_gvalue(GValue *value);
 
66
 
 
67
static void
 
68
lomo_stream_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
 
69
{
 
70
        LomoStream *self = LOMO_STREAM(object);
 
71
        switch (property_id)
 
72
        {
 
73
        case PROP_URI:
 
74
                g_value_set_static_string(value, lomo_stream_get_tag(self, LOMO_TAG_URI));
 
75
                break;
 
76
        default:
 
77
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
78
        }
 
79
}
 
80
 
 
81
static void
 
82
lomo_stream_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
 
83
{
 
84
        LomoStream *self = LOMO_STREAM(object);
 
85
        switch (property_id)
 
86
        {
 
87
        case PROP_URI:
 
88
                stream_set_uri(self, g_value_get_string(value));
 
89
                break;
 
90
        default:
 
91
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
92
        }
 
93
}
 
94
 
 
95
static void
 
96
lomo_stream_dispose (GObject *object)
 
97
{
 
98
        struct _LomoStreamPrivate *priv = LOMO_STREAM(object)->priv;
 
99
 
 
100
        if (priv->tags)
 
101
        {
 
102
                g_list_foreach(priv->tags, (GFunc) g_free, NULL);
 
103
                g_list_free(priv->tags);
 
104
                priv->tags = NULL;
 
105
        }
 
106
 
 
107
        if (G_OBJECT_CLASS (lomo_stream_parent_class)->dispose)
 
108
                G_OBJECT_CLASS (lomo_stream_parent_class)->dispose (object);
 
109
}
 
110
 
 
111
static void
 
112
lomo_stream_class_init (LomoStreamClass *klass)
 
113
{
 
114
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
115
 
 
116
        g_type_class_add_private (klass, sizeof (LomoStreamPrivate));
 
117
 
 
118
        object_class->get_property = lomo_stream_get_property;
 
119
        object_class->set_property = lomo_stream_set_property;
 
120
        object_class->dispose = lomo_stream_dispose;
 
121
 
 
122
        /**
 
123
         * LomoStream:uri:
 
124
         *
 
125
         * URI corresponding to the stream
 
126
         */
 
127
        g_object_class_install_property(object_class, PROP_URI,
 
128
                g_param_spec_string("uri", "uri", "uri",
 
129
                        NULL,  G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY|G_PARAM_STATIC_STRINGS));
 
130
 
 
131
        /**
 
132
         * LomoStream::extended-metadata-updated:
 
133
         * @stream: the object that recieved the signal
 
134
         * @key: Name of the updated metadata key
 
135
         *
 
136
         * Emitted when extended metadata (cover, lyrics, etc...) is updated
 
137
         * for the stream
 
138
         */
 
139
        lomo_stream_signals[SIGNAL_EXTENDED_METADATA_UPDATED] =
 
140
                g_signal_new ("extended-metadata-updated",
 
141
                        G_OBJECT_CLASS_TYPE (object_class),
 
142
                        G_SIGNAL_RUN_LAST,
 
143
                        G_STRUCT_OFFSET (LomoStreamClass, extended_metadata_updated),
 
144
                        NULL, NULL,
 
145
                        g_cclosure_marshal_VOID__STRING,
 
146
                        G_TYPE_NONE,
 
147
                        1,
 
148
                        G_TYPE_STRING);
 
149
}
 
150
 
 
151
static void
 
152
lomo_stream_init (LomoStream *self)
 
153
{
 
154
        LomoStreamPrivate *priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), LOMO_TYPE_STREAM, LomoStreamPrivate);
 
155
 
 
156
        priv->all_tags = FALSE;
 
157
        priv->tags     = NULL;
 
158
}
 
159
 
 
160
/**
 
161
 * lomo_stream_new:
 
162
 * @uri: An uri to create a #LomoStream from.
 
163
 *
 
164
 * Create a new #LomoStream from an uri
 
165
 * 
 
166
 * Returns: A new #LomoStream
 
167
 */
 
168
LomoStream*
 
169
lomo_stream_new (const gchar *uri)
 
170
{
 
171
        return g_object_new (LOMO_TYPE_STREAM, "uri", uri, NULL);
 
172
}
 
173
 
 
174
static void
 
175
stream_set_uri(LomoStream *self, const gchar *uri)
 
176
{
 
177
        g_return_if_fail(LOMO_IS_STREAM(self));
 
178
        g_return_if_fail(uri != NULL);
 
179
 
 
180
        // Check valid URI, more strict methods than this: g_uri_parse_scheme
 
181
        for (guint i = 0; uri[i] != '\0'; i++)
 
182
                if ((uri[i] < 20) || (uri[i] > 126))
 
183
                        g_warning(_("'%s' is not a valid URI"), uri);
 
184
 
 
185
        if (!uri && (strstr(uri, "://") == NULL))
 
186
                g_warning(_("'%s' is not a valid URI"), uri);
 
187
 
 
188
        g_object_set_data_full(G_OBJECT(self), LOMO_TAG_URI, g_strdup(uri), g_free);
 
189
}
 
190
 
 
191
gchar *
 
192
lomo_stream_string_parser_cb(gchar tag_key, LomoStream *self)
 
193
{
 
194
        gchar *ret = NULL;
 
195
        gchar *tag_str = lomo_stream_get_tag_by_id(self, tag_key);
 
196
 
 
197
        if (tag_str != NULL)
 
198
                return tag_str;
 
199
 
 
200
        if ((tag_key == 't') && (ret == NULL))
 
201
        {
 
202
                const gchar *tmp = lomo_stream_get_tag(self, LOMO_TAG_URI);
 
203
                gchar *tmp2 = g_uri_unescape_string(tmp, NULL);
 
204
                ret = g_path_get_basename(tmp2);
 
205
                g_free(tmp2);
 
206
        }
 
207
        return ret;
 
208
}
 
209
 
 
210
/**
 
211
 * lomo_stream_get_tag:
 
212
 * @self: a #LomoStream
 
213
 * @tag: a #LomoTag
 
214
 *
 
215
 * Gets a tag from #LomoStream. The returned value is owned by @stream, and
 
216
 * should not be modified (Internally it uses g_object_get_data).
 
217
 *
 
218
 * Returns: A pointer to the tag value
 
219
 */
 
220
const gchar*
 
221
lomo_stream_get_tag(LomoStream *self, const gchar *tag)
 
222
{
 
223
        g_return_val_if_fail(LOMO_IS_STREAM(self), NULL);
 
224
        g_return_val_if_fail(tag, NULL);
 
225
 
 
226
        const gchar *ret = g_object_get_data((GObject *) self, tag);
 
227
        return ret;
 
228
}
 
229
 
 
230
/**
 
231
 * lomo_stream_set_tag:
 
232
 * @self: a #LomoStream
 
233
 * @tag: (in) (type gchar*) (transfer none): a #const gchar *to set
 
234
 * @value: (in) (type gchar*) (transfer none): value for tag, must not be modified. It becomes owned by #LomoStream
 
235
 *
 
236
 * Sets a tag in a #LomoStream
 
237
 */
 
238
void
 
239
lomo_stream_set_tag(LomoStream *self, const gchar *tag, gpointer value)
 
240
{
 
241
        LomoStreamPrivate *priv = self->priv;
 
242
        GList *link = g_list_find_custom(priv->tags, tag, (GCompareFunc) strcmp);
 
243
 
 
244
        if (tag != NULL)
 
245
        {
 
246
                if (link != NULL)
 
247
                {
 
248
                        g_free(link->data);
 
249
                        link->data = g_strdup(tag);
 
250
                }
 
251
                else
 
252
                        priv->tags = g_list_prepend(priv->tags, g_strdup(tag));
 
253
        }
 
254
        else
 
255
        {
 
256
                priv->tags = g_list_remove_link(priv->tags, link);
 
257
                g_free(link->data);
 
258
                g_list_free(link);
 
259
        }
 
260
        g_object_set_data_full(G_OBJECT(self), tag, value, g_free);
 
261
}
 
262
 
 
263
/**
 
264
 * lomo_stream_get_tags:
 
265
 * @self: a #LomoStream
 
266
 *
 
267
 * Gets the list of #const gchar *for a #LomoStream
 
268
 *
 
269
 * Return value: (element-type utf8) (transfer full): a #GList, it must be freed when no longer needed, data too
 
270
 */
 
271
GList*
 
272
lomo_stream_get_tags(LomoStream *self)
 
273
{
 
274
        GList *ret = NULL;
 
275
        GList *iter = self->priv->tags;
 
276
        while (iter)
 
277
        {
 
278
                ret = g_list_prepend(ret, g_strdup((gchar *) iter->data));
 
279
                iter = iter->next;
 
280
        }
 
281
        return ret;
 
282
}
 
283
 
 
284
/**
 
285
 * lomo_stream_set_all_tags_flag:
 
286
 * @self: a #LomoStream
 
287
 * @value: (in): value for flag
 
288
 *
 
289
 * Sets the all_tags flag to value
 
290
 **/
 
291
void
 
292
lomo_stream_set_all_tags_flag(LomoStream *self, gboolean value)
 
293
{
 
294
        self->priv->all_tags = value;
 
295
}
 
296
 
 
297
/**
 
298
 * lomo_stream_get_all_tags_flag:
 
299
 * @self: a #LomoStream
 
300
 *
 
301
 * Gets value of all_tags flag
 
302
 *
 
303
 * Returns: the value of all_tags flag
 
304
 */
 
305
gboolean
 
306
lomo_stream_get_all_tags_flag(LomoStream *self)
 
307
{
 
308
        return self->priv->all_tags;
 
309
}
 
310
 
 
311
/**
 
312
 * lomo_stream_set_failed_flag:
 
313
 * @self: a #LomoStream
 
314
 * @value: (in): value for flag
 
315
 *
 
316
 * Sets the failed flag to value
 
317
 */
 
318
void
 
319
lomo_stream_set_failed_flag(LomoStream *self, gboolean value)
 
320
{
 
321
        self->priv->failed = value;
 
322
}
 
323
 
 
324
/**
 
325
 * lomo_stream_get_failed_flag:
 
326
 * @self: a #LomoStream
 
327
 *
 
328
 * Gets value of failed flag
 
329
 *
 
330
 * Returns: the value of failed flag
 
331
 */
 
332
gboolean
 
333
lomo_stream_get_failed_flag(LomoStream *self)
 
334
{
 
335
        return self->priv->failed;
 
336
}
 
337
 
 
338
/**
 
339
 * lomo_stream_set_extended_metadata:
 
340
 * @self: A #LomoStream
 
341
 * @key: (transfer none): Key
 
342
 * @value: (transfer full): Value to store
 
343
 *
 
344
 * Adds (or replaces) the value for the extended metadata for key
 
345
 */
 
346
void
 
347
lomo_stream_set_extended_metadata(LomoStream *self, const gchar *key, GValue *value)
 
348
{
 
349
        g_return_if_fail(LOMO_IS_STREAM(self));
 
350
        g_return_if_fail(key != NULL);
 
351
        g_return_if_fail(G_IS_VALUE(value));
 
352
 
 
353
        gchar *k = g_strconcat("x-lomo-extended-metadata-", key, NULL);
 
354
        g_object_set_data_full(G_OBJECT(self), k, value, (GDestroyNotify) destroy_gvalue);
 
355
        g_free(k);
 
356
 
 
357
        g_signal_emit(self, lomo_stream_signals[SIGNAL_EXTENDED_METADATA_UPDATED], 0, key);
 
358
}
 
359
/**
 
360
 * lomo_stream_set_extended_metadata:
 
361
 * @self: A #LomoStream
 
362
 * @key: (transfer none): Key
 
363
 * @value: (transfer none): Value to store
 
364
 *
 
365
 * Adds (or replaces) the value for the extended metadata for key
 
366
 */
 
367
void
 
368
lomo_stream_set_extended_metadata_as_string(LomoStream *self, const gchar *key, const gchar *value)
 
369
{
 
370
        g_return_if_fail(LOMO_IS_STREAM(self));
 
371
        g_return_if_fail(key);
 
372
        g_return_if_fail(value);
 
373
 
 
374
        GValue *v = g_new0(GValue, 1);
 
375
        g_value_set_string(g_value_init(v, G_TYPE_STRING), value);
 
376
        lomo_stream_set_extended_metadata(self, key, v);
 
377
}
 
378
 
 
379
/**
 
380
 * lomo_stream_get_extended_metadata:
 
381
 * @self: A #LomoStream
 
382
 * @key: A Key
 
383
 *
 
384
 * See g_object_get_data()
 
385
 *
 
386
 * Returns: (transfer none): The value associated with the key
 
387
 */
 
388
GValue *
 
389
lomo_stream_get_extended_metadata(LomoStream *self, const gchar *key)
 
390
{
 
391
        g_return_val_if_fail(LOMO_IS_STREAM(self), NULL);
 
392
 
 
393
        gchar *k = g_strconcat("x-lomo-extended-metadata-", key, NULL);
 
394
        GValue *ret = g_object_get_data(G_OBJECT(self), k);
 
395
        g_free(k);
 
396
 
 
397
        return ret;
 
398
}
 
399
 
 
400
/**
 
401
 * lomo_stream_get_extended_metadata_as_string
 
402
 * @self: A #LomoStream
 
403
 * @key: A Key
 
404
 *
 
405
 * See lomo_stream_get_extended_metadata()
 
406
 *
 
407
 * Returns: (transfer none): The value associated with the key as a string or
 
408
 *          %NULL if not found or key is not a string
 
409
 */
 
410
const gchar *
 
411
lomo_stream_get_extended_metadata_as_string(LomoStream *self, const gchar *key)
 
412
{
 
413
        GValue *v = lomo_stream_get_extended_metadata(self, key);
 
414
        return (v && G_VALUE_HOLDS_STRING(v) ? g_value_get_string(v) : NULL);
 
415
}
 
416
 
 
417
/**
 
418
 * lomo_stream_get_tag_by_id:
 
419
 * @self: a #LomoStream
 
420
 * @id: (in): identifier for tag (t = title, b = album, etc...)
 
421
 *
 
422
 * Gets the tag value as string for the matching id
 
423
 *
 
424
 * Retuns: the tag value as string
 
425
 */
 
426
gchar *
 
427
lomo_stream_get_tag_by_id(LomoStream *self, gchar id)
 
428
{
 
429
        gint i;
 
430
        gchar *ret = NULL;
 
431
 
 
432
        for (i = 0; tag_fmt_table[i].key != 0; i++)
 
433
        {
 
434
                if (tag_fmt_table[i].key == id)
 
435
                {
 
436
                        const gchar *tag_str = lomo_stream_get_tag(self, tag_fmt_table[i].tag);
 
437
                        if (tag_str == NULL)
 
438
                                return NULL;
 
439
                        ret = g_strdup_printf(tag_fmt_table[i].fmt, tag_str);
 
440
                        break;
 
441
                }
 
442
        }
 
443
        return ret;
 
444
}
 
445
 
 
446
/*
 
447
 * lomo_tag_get_gtype:
 
448
 * @tag: (in) (transfer none): a #LomoTag
 
449
 *
 
450
 * Queries for the #GType corresponding for the tag
 
451
 *
 
452
 * Returns: the #GType for tag
 
453
 */
 
454
GType
 
455
lomo_tag_get_gtype(const gchar *tag)
 
456
{
 
457
        if (g_str_equal(tag, "uri")) 
 
458
                return G_TYPE_STRING;
 
459
        return gst_tag_get_type(tag);
 
460
}
 
461
 
 
462
static void
 
463
destroy_gvalue(GValue *value)
 
464
{
 
465
        if (value != NULL)
 
466
        {
 
467
                g_return_if_fail(G_IS_VALUE(value));
 
468
                g_value_unset(value);
 
469
                g_free(value);
 
470
        }
 
471
}