~ubuntu-branches/ubuntu/trusty/mediascanner/trusty-proposed

« back to all changes in this revision

Viewing changes to src/mediascanner/glibutils.h

  • Committer: Package Import Robot
  • Author(s): Łukasz 'sil2100' Zemczak
  • Date: 2013-08-13 18:47:34 UTC
  • Revision ID: package-import@ubuntu.com-20130813184734-u3lyvu2u1hgybryc
Tags: upstream-0.3.93
Import upstream version 0.3.93

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of the Ubuntu TV Media Scanner
 
3
 * Copyright (C) 2012-2013 Canonical Ltd.
 
4
 *
 
5
 * This program is free software: you can redistribute it and/or modify
 
6
 * it under the terms of the GNU Lesser General Public License version 3 as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * This program 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
 
12
 * GNU Lesser General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public License
 
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
 *
 
17
 * Contact: Jim Hodapp <jim.hodapp@canonical.com>
 
18
 * Authored by: Mathias Hasselmann <mathias@openismus.com>
 
19
 */
 
20
#ifndef MEDIASCANNER_GLIBUTILS_H
 
21
#define MEDIASCANNER_GLIBUTILS_H
 
22
 
 
23
// GLib Based Libraries
 
24
#include <gio/gio.h>
 
25
#include <gio/gunixmounts.h>
 
26
#include <grilo.h>
 
27
#include <gst/pbutils/gstdiscoverer.h>
 
28
#include <gudev/gudev.h>
 
29
 
 
30
// Boost C++
 
31
#include <boost/function.hpp>
 
32
#include <boost/date_time/posix_time/posix_time_duration.hpp>
 
33
 
 
34
// C++ Standard Library
 
35
#include <string>
 
36
 
 
37
// Media Scanner Library
 
38
#include "mediascanner/declarations.h"
 
39
 
 
40
namespace mediascanner {
 
41
namespace internal {
 
42
 
 
43
// GObject structure to GType mappings /////////////////////////////////////////
 
44
 
 
45
template<typename> GType GetGType();
 
46
 
 
47
template<> inline GType GetGType<GArray>() {
 
48
    return G_TYPE_ARRAY;
 
49
}
 
50
 
 
51
template<> inline GType GetGType<GByteArray>() {
 
52
    return G_TYPE_BYTE_ARRAY;
 
53
}
 
54
 
 
55
template<> inline GType GetGType<GClosure>() {
 
56
    return G_TYPE_CLOSURE;
 
57
}
 
58
 
 
59
template<> inline GType GetGType<GDate>() {
 
60
    return G_TYPE_DATE;
 
61
}
 
62
 
 
63
template<> inline GType GetGType<GDateTime>() {
 
64
    return G_TYPE_DATE_TIME;
 
65
}
 
66
 
 
67
template<> inline GType GetGType<GDrive>() {
 
68
    return G_TYPE_DRIVE;
 
69
}
 
70
 
 
71
template<> inline GType GetGType<GError>() {
 
72
    return G_TYPE_ERROR;
 
73
}
 
74
 
 
75
template<> inline GType GetGType<GFile>() {
 
76
    return G_TYPE_FILE;
 
77
}
 
78
 
 
79
template<> inline GType GetGType<GFileMonitor>() {
 
80
    return G_TYPE_FILE_MONITOR;
 
81
}
 
82
 
 
83
template<> inline GType GetGType<GFileType>() {
 
84
    return G_TYPE_FILE_TYPE;
 
85
}
 
86
 
 
87
template<> inline GType GetGType<GHashTable>() {
 
88
    return G_TYPE_HASH_TABLE;
 
89
}
 
90
 
 
91
template<> inline GType GetGType<GKeyFile>() {
 
92
    return G_TYPE_KEY_FILE;
 
93
}
 
94
 
 
95
template<> inline GType GetGType<GIcon>() {
 
96
    return G_TYPE_ICON;
 
97
}
 
98
 
 
99
template<> inline GType GetGType<GMainContext>() {
 
100
    return G_TYPE_MAIN_CONTEXT;
 
101
}
 
102
 
 
103
template<> inline GType GetGType<GMainLoop>() {
 
104
    return G_TYPE_MAIN_LOOP;
 
105
}
 
106
 
 
107
template<> inline GType GetGType<GMatchInfo>() {
 
108
    return G_TYPE_MATCH_INFO;
 
109
}
 
110
 
 
111
template<> inline GType GetGType<GMount>() {
 
112
    return G_TYPE_MOUNT;
 
113
}
 
114
 
 
115
template<> inline GType GetGType<GObject>() {
 
116
    return G_TYPE_OBJECT;
 
117
}
 
118
 
 
119
template<> inline GType GetGType<GPtrArray>() {
 
120
    return G_TYPE_PTR_ARRAY;
 
121
}
 
122
 
 
123
template<> inline GType GetGType<GRegex>() {
 
124
    return G_TYPE_REGEX;
 
125
}
 
126
 
 
127
template<> inline GType GetGType<GSettings>() {
 
128
    return G_TYPE_SETTINGS;
 
129
}
 
130
 
 
131
template<> inline GType GetGType<GSource>() {
 
132
    return G_TYPE_SOURCE;
 
133
}
 
134
 
 
135
template<> inline GType GetGType<GString>() {
 
136
    return G_TYPE_GSTRING;
 
137
}
 
138
 
 
139
template<> inline GType GetGType<GValue>() {
 
140
    return G_TYPE_VALUE;
 
141
}
 
142
 
 
143
template<> inline GType GetGType<GVolume>() {
 
144
    return G_TYPE_VOLUME;
 
145
}
 
146
 
 
147
template<> inline GType GetGType<GVolumeMonitor>() {
 
148
    return G_TYPE_VOLUME_MONITOR;
 
149
}
 
150
 
 
151
template<> inline GType GetGType<GVariantBuilder>() {
 
152
    return G_TYPE_VARIANT_BUILDER;
 
153
}
 
154
 
 
155
template<> inline GType GetGType<GVariantType>() {
 
156
    return G_TYPE_VARIANT;
 
157
}
 
158
 
 
159
template<> inline GType GetGType<GrlCaps>() {
 
160
    return GRL_CAPS_TYPE;
 
161
}
 
162
 
 
163
template<> inline GType GetGType<GrlConfig>() {
 
164
    return GRL_TYPE_CONFIG;
 
165
}
 
166
 
 
167
template<> inline GType GetGType<GrlData>() {
 
168
    return GRL_TYPE_DATA;
 
169
}
 
170
 
 
171
template<> inline GType GetGType<GrlMedia>() {
 
172
    return GRL_TYPE_MEDIA;
 
173
}
 
174
 
 
175
template<> inline GType GetGType<GrlPlugin>() {
 
176
    return GRL_TYPE_PLUGIN;
 
177
}
 
178
 
 
179
template<> inline GType GetGType<GrlRegistry>() {
 
180
    return GRL_TYPE_REGISTRY;
 
181
}
 
182
 
 
183
template<> inline GType GetGType<GrlRelatedKeys>() {
 
184
    return GRL_TYPE_RELATED_KEYS;
 
185
}
 
186
 
 
187
template<> inline GType GetGType<GrlSource>() {
 
188
    return GRL_TYPE_SOURCE;
 
189
}
 
190
 
 
191
template<> inline GType GetGType<GstDiscovererInfo>() {
 
192
    return GST_TYPE_DISCOVERER_INFO;
 
193
}
 
194
 
 
195
template<> inline GType GetGType<GstDiscovererStreamInfo>() {
 
196
    return GST_TYPE_DISCOVERER_STREAM_INFO;
 
197
}
 
198
 
 
199
template<> inline GType GetGType<GstDiscovererAudioInfo>() {
 
200
    return GST_TYPE_DISCOVERER_AUDIO_INFO;
 
201
}
 
202
 
 
203
template<> inline GType GetGType<GstDiscovererContainerInfo>() {
 
204
    return GST_TYPE_DISCOVERER_CONTAINER_INFO;
 
205
}
 
206
 
 
207
template<> inline GType GetGType<GstDiscovererVideoInfo>() {
 
208
    return GST_TYPE_DISCOVERER_VIDEO_INFO;
 
209
}
 
210
 
 
211
template<> inline GType GetGType<GUdevClient>() {
 
212
    return G_UDEV_TYPE_CLIENT;
 
213
}
 
214
 
 
215
template<> inline GType GetGType<GUdevDevice>() {
 
216
    return G_UDEV_TYPE_DEVICE;
 
217
}
 
218
 
 
219
// GLib boxing and GObject reference counting //////////////////////////////////
 
220
 
 
221
template<typename Type>
 
222
struct CopyHelper {
 
223
    static Type *Copy(Type *p);
 
224
    static void Free(Type *p);
 
225
};
 
226
 
 
227
template<typename Type>
 
228
struct BoxedCopyHelper {
 
229
    static Type *Copy(Type *p) {
 
230
        return static_cast<Type *>(g_boxed_copy(GetGType<Type>(), p));
 
231
    }
 
232
 
 
233
    static void Free(Type *p) {
 
234
        g_boxed_free(GetGType<Type>(), p);
 
235
    }
 
236
};
 
237
 
 
238
template<typename Type>
 
239
struct MiniObjectCopyHelper {
 
240
    static Type *Copy(Type *p) {
 
241
        return reinterpret_cast<Type *>
 
242
                (gst_mini_object_ref(GST_MINI_OBJECT_CAST(p)));
 
243
    }
 
244
 
 
245
    static void Free(Type *p) {
 
246
        gst_mini_object_unref(GST_MINI_OBJECT_CAST(p));
 
247
    }
 
248
};
 
249
 
 
250
template<typename Type>
 
251
struct ObjectCopyHelper {
 
252
    static Type *Copy(Type *p) {
 
253
        return static_cast<Type *>(g_object_ref(p));
 
254
    }
 
255
 
 
256
    static void Free(Type *p) {
 
257
        g_object_unref(p);
 
258
    }
 
259
};
 
260
 
 
261
template<typename Type, typename List = GList>
 
262
struct ListCopyHelper {
 
263
    static List *Copy(List *const other) {
 
264
        List *const copy = CopyHelper<List>::Copy(other);
 
265
 
 
266
        for (List *l = copy; l; l = l->next) {
 
267
            Type *const data = static_cast<Type *>(l->data);
 
268
            l->data = CopyHelper<Type>::Copy(data);
 
269
        }
 
270
 
 
271
        return copy;
 
272
    }
 
273
 
 
274
    static void Free(GList *list) {
 
275
        for (List *l = list; l; l = l->next) {
 
276
            Type *const data = static_cast<Type *>(l->data);
 
277
            CopyHelper<Type>::Free(data);
 
278
        }
 
279
 
 
280
        CopyHelper<List>::Free(list);
 
281
    }
 
282
};
 
283
 
 
284
template<> struct CopyHelper<GMainLoop> :
 
285
        public BoxedCopyHelper<GMainLoop> { };
 
286
template<> struct CopyHelper<GMainContext> :
 
287
        public BoxedCopyHelper<GMainContext> { };
 
288
template<> struct CopyHelper<GValue> :
 
289
        public BoxedCopyHelper<GValue> { };
 
290
 
 
291
template<> struct CopyHelper<GCancellable> :
 
292
        public ObjectCopyHelper<GCancellable> { };
 
293
template<> struct CopyHelper<GDBusConnection> :
 
294
        public ObjectCopyHelper<GDBusConnection> { };
 
295
template<> struct CopyHelper<GDrive> :
 
296
        public ObjectCopyHelper<GDrive> { };
 
297
template<> struct CopyHelper<GFile> :
 
298
        public ObjectCopyHelper<GFile> { };
 
299
template<> struct CopyHelper<GFileEnumerator> :
 
300
        public ObjectCopyHelper<GFileEnumerator> { };
 
301
template<> struct CopyHelper<GFileInfo> :
 
302
        public ObjectCopyHelper<GFileInfo> { };
 
303
template<> struct CopyHelper<GFileMonitor> :
 
304
        public ObjectCopyHelper<GFileMonitor> { };
 
305
template<> struct CopyHelper<GIcon> :
 
306
        public ObjectCopyHelper<GIcon> { };
 
307
template<> struct CopyHelper<GMount> :
 
308
        public ObjectCopyHelper<GMount> { };
 
309
template<> struct CopyHelper<GSettings> :
 
310
        public ObjectCopyHelper<GSettings> { };
 
311
template<> struct CopyHelper<GVolume> :
 
312
        public ObjectCopyHelper<GVolume> { };
 
313
template<> struct CopyHelper<GVolumeMonitor> :
 
314
        public ObjectCopyHelper<GVolumeMonitor> { };
 
315
 
 
316
template<> struct CopyHelper<GDBusMethodInvocation> :
 
317
        public ObjectCopyHelper<GDBusMethodInvocation> { };
 
318
template<> struct CopyHelper<GDBusProxy> :
 
319
        public ObjectCopyHelper<GDBusProxy> { };
 
320
 
 
321
template<> struct CopyHelper<GrlCaps> :
 
322
        public ObjectCopyHelper<GrlCaps> { };
 
323
template<> struct CopyHelper<GrlConfig> :
 
324
        public ObjectCopyHelper<GrlConfig> { };
 
325
template<> struct CopyHelper<GrlData> :
 
326
        public ObjectCopyHelper<GrlData> { };
 
327
template<> struct CopyHelper<GrlMedia> :
 
328
        public ObjectCopyHelper<GrlMedia> { };
 
329
template<> struct CopyHelper<GrlOperationOptions> :
 
330
        public ObjectCopyHelper<GrlOperationOptions> { };
 
331
template<> struct CopyHelper<GrlPlugin> :
 
332
        public ObjectCopyHelper<GrlPlugin> { };
 
333
template<> struct CopyHelper<GrlRegistry> :
 
334
        public ObjectCopyHelper<GrlRegistry> { };
 
335
template<> struct CopyHelper<GrlRelatedKeys> :
 
336
        public ObjectCopyHelper<GrlRelatedKeys> { };
 
337
template<> struct CopyHelper<GrlSource> :
 
338
        public ObjectCopyHelper<GrlSource> { };
 
339
 
 
340
template<> struct CopyHelper<GstCaps> :
 
341
        public MiniObjectCopyHelper<GstCaps> { };
 
342
template<> struct CopyHelper<GstDiscoverer> :
 
343
        public ObjectCopyHelper<GstDiscoverer> { };
 
344
template<> struct CopyHelper<GstDiscovererInfo> :
 
345
        public ObjectCopyHelper<GstDiscovererInfo> { };
 
346
template<> struct CopyHelper<GstDiscovererStreamInfo> :
 
347
        public ObjectCopyHelper<GstDiscovererStreamInfo> { };
 
348
 
 
349
template<> struct CopyHelper<GUdevClient> :
 
350
        public ObjectCopyHelper<GUdevClient> { };
 
351
template<> struct CopyHelper<GUdevDevice> :
 
352
        public ObjectCopyHelper<GUdevDevice> { };
 
353
 
 
354
template<> struct CopyHelper<char> {
 
355
    static char *Copy(char *p) { return g_strdup(p); }
 
356
    static void Free(char *p) { g_free(p); }
 
357
};
 
358
 
 
359
template<> struct CopyHelper<char *> {
 
360
    static char **Copy(char **p) { return g_strdupv(p); }
 
361
    static void Free(char **p) { g_strfreev(p); }
 
362
};
 
363
 
 
364
template<> struct CopyHelper<GDBusArgInfo> {
 
365
    static GDBusArgInfo *Copy(GDBusArgInfo *p) {
 
366
        return g_dbus_arg_info_ref(p);
 
367
    }
 
368
 
 
369
    static void Free(GDBusArgInfo *p) {
 
370
        g_dbus_arg_info_unref(p);
 
371
    }
 
372
};
 
373
 
 
374
template<> struct CopyHelper<GDBusInterfaceInfo> {
 
375
    static GDBusInterfaceInfo *Copy(GDBusInterfaceInfo *p) {
 
376
        return g_dbus_interface_info_ref(p);
 
377
    }
 
378
 
 
379
    static void Free(GDBusInterfaceInfo *p) {
 
380
        g_dbus_interface_info_unref(p);
 
381
    }
 
382
};
 
383
 
 
384
template<> struct CopyHelper<GDBusMethodInfo> {
 
385
    static GDBusMethodInfo *Copy(GDBusMethodInfo *p) {
 
386
        return g_dbus_method_info_ref(p);
 
387
    }
 
388
 
 
389
    static void Free(GDBusMethodInfo *p) {
 
390
        g_dbus_method_info_unref(p);
 
391
    }
 
392
};
 
393
 
 
394
template<> struct CopyHelper<GDBusPropertyInfo> {
 
395
    static GDBusPropertyInfo *Copy(GDBusPropertyInfo *p) {
 
396
        return g_dbus_property_info_ref(p);
 
397
    }
 
398
 
 
399
    static void Free(GDBusPropertyInfo *p) {
 
400
        g_dbus_property_info_unref(p);
 
401
    }
 
402
};
 
403
 
 
404
template<> struct CopyHelper<GDBusSignalInfo> {
 
405
    static GDBusSignalInfo *Copy(GDBusSignalInfo *p) {
 
406
        return g_dbus_signal_info_ref(p);
 
407
    }
 
408
 
 
409
    static void Free(GDBusSignalInfo *p) {
 
410
        g_dbus_signal_info_unref(p);
 
411
    }
 
412
};
 
413
 
 
414
template<> struct CopyHelper<GError> {
 
415
    static GError *Copy(GError *p) { return g_error_copy(p); }
 
416
    static void Free(GError *p) { g_error_free(p); }
 
417
};
 
418
 
 
419
template<> struct CopyHelper<GKeyFile> {
 
420
    static GKeyFile *Copy(GKeyFile *p) {
 
421
        return g_key_file_ref(p);
 
422
    }
 
423
 
 
424
    static void Free(GKeyFile *p) {
 
425
        g_key_file_unref(p);
 
426
    }
 
427
};
 
428
 
 
429
template<> struct CopyHelper<GList> {
 
430
    static GList *Copy(GList *p) { return g_list_copy(p); }
 
431
    static void Free(GList *p) { g_list_free(p); }
 
432
};
 
433
 
 
434
template<> struct CopyHelper<GParamSpec> {
 
435
    static GParamSpec *Copy(GParamSpec *p) { return g_param_spec_ref(p); }
 
436
    static void Free(GParamSpec *p) { g_param_spec_unref(p); }
 
437
};
 
438
 
 
439
template<> struct CopyHelper<GPtrArray> {
 
440
    static GPtrArray *Copy(GPtrArray *p) { return g_ptr_array_ref(p); }
 
441
    static void Free(GPtrArray *p) { g_ptr_array_unref(p); }
 
442
};
 
443
 
 
444
template<> struct CopyHelper<GThread> {
 
445
    static GThread *Copy(GThread *p) { return g_thread_ref(p); }
 
446
    static void Free(GThread *p) { g_thread_unref(p); }
 
447
};
 
448
 
 
449
template<> struct CopyHelper<GUnixMountEntry> {
 
450
    static void Free(GUnixMountEntry *p) { g_unix_mount_free(p); }
 
451
};
 
452
 
 
453
template<> struct CopyHelper<GVariant> {
 
454
    static GVariant *Copy(GVariant *p) { return g_variant_ref(p); }
 
455
    static void Free(GVariant *p) { g_variant_unref(p); }
 
456
};
 
457
 
 
458
template<> struct CopyHelper<GstStructure> {
 
459
    static GstStructure *Copy(GstStructure *p) { return gst_structure_copy(p); }
 
460
    static void Free(GstStructure *p) { gst_structure_free(p); }
 
461
};
 
462
 
 
463
// Cast helpers ////////////////////////////////////////////////////////////////
 
464
 
 
465
template<typename SourceType, typename TargetType>
 
466
struct CastHelper {
 
467
    static TargetType *cast(SourceType *p);
 
468
};
 
469
 
 
470
template<typename SourceType, typename TargetType>
 
471
struct TypeInstanceCastHelper {
 
472
    static TargetType *Apply(SourceType *p) {
 
473
        if (G_TYPE_CHECK_INSTANCE_TYPE(p, GetGType<TargetType>()))
 
474
            return reinterpret_cast<TargetType *>(p);
 
475
 
 
476
        return 0;
 
477
    }
 
478
};
 
479
 
 
480
template<typename SourceType>
 
481
struct TypeInstanceCastHelper<SourceType, GTypeInstance> {
 
482
    static GTypeInstance *Apply(SourceType *p) {
 
483
        return reinterpret_cast<GTypeInstance *>(p);
 
484
    }
 
485
};
 
486
 
 
487
template<typename TargetType>
 
488
struct CastHelper<GrlMedia, TargetType> :
 
489
        public TypeInstanceCastHelper<GrlMedia, TargetType> { };
 
490
 
 
491
template<typename TargetType>
 
492
struct CastHelper<GrlSource, TargetType> :
 
493
        public TypeInstanceCastHelper<GrlSource, TargetType> { };
 
494
 
 
495
template<typename TargetType>
 
496
struct CastHelper<GstDiscovererStreamInfo, TargetType> :
 
497
        public TypeInstanceCastHelper<GstDiscovererStreamInfo, TargetType> { };
 
498
 
 
499
} // namespace internal
 
500
 
 
501
// Smart pointers for GLib boxed types and GObjects ////////////////////////////
 
502
 
 
503
/**
 
504
 * @brief A shared smart-pointer for GLib related types. Via its helper classes
 
505
 * this smart-pointer supports a wide variety of GLib related types, such as
 
506
 * GObjects, GstMiniObjects, boxed types, and even simple GLists.
 
507
 * @see internal::CopyHelper, internal::CastHelper
 
508
 */
 
509
template<typename T, typename CopyHelper>
 
510
class Wrapper {
 
511
public:
 
512
    /**
 
513
     * @brief Creates an emtpy pointer not holding any object.
 
514
     */
 
515
    Wrapper()
 
516
        : m_ptr(0) {
 
517
    }
 
518
 
 
519
    /**
 
520
     * @brief Copies another pointer instance. For reference counted objects
 
521
     * this new pointer will hold a new reference to the object. For boxed
 
522
     * types and similiar a new copy of the original object is created.
 
523
     * @param other The instance to initialize from.
 
524
     * @see take(), wrap(), wrap_static()
 
525
     */
 
526
    Wrapper(const Wrapper<T> &other)
 
527
        : m_ptr(0) {
 
528
        reset(other.get());
 
529
    }
 
530
 
 
531
    /**
 
532
     * @brief Destroys the smart-pointer. For reference counted objects
 
533
     * this drops the reference hold, for other types this frees the object
 
534
     * instance.
 
535
     */
 
536
    ~Wrapper() {
 
537
        if (m_ptr)
 
538
            CopyHelper::Free(m_ptr);
 
539
    }
 
540
 
 
541
    /**
 
542
     * @brief Releases the wrapped object. This detaches the wrapped object
 
543
     * from this smart-pointer without dropping the reference or freeing it.
 
544
     * Use this function to transfer ownership of the wrapped object.
 
545
     * @return A pointer to the wrapped object, or @c null if no object
 
546
     * was wrapped.
 
547
     */
 
548
    T *release() {
 
549
        T *const p = m_ptr;
 
550
        m_ptr = 0;
 
551
        return p;
 
552
    }
 
553
 
 
554
    /**
 
555
     * @brief This function gives access to the wrapped object.
 
556
     * @return A pointer to the wrapped object.
 
557
     */
 
558
    T *get() const {
 
559
        return m_ptr;
 
560
    }
 
561
 
 
562
    /**
 
563
     * @brief Creates a new reference to, or a new copy of the wrapped object.
 
564
     * This function is useful to initialize C structures or arrays.
 
565
     * @return A pointer to the new reference, or the new object.
 
566
     */
 
567
    T *dup() const {
 
568
        return CopyHelper::Copy(get());
 
569
    }
 
570
 
 
571
    /**
 
572
     * @brief This function casts the wrapped object to a different type.
 
573
     * @return A pointer to the wrapped object.
 
574
     */
 
575
    template<typename B> B *get() const {
 
576
        return internal::CastHelper<T, B>::Apply(get());
 
577
    }
 
578
 
 
579
    /**
 
580
     * @brief This operator gives access to the wrapped object's members.
 
581
     * @return A pointer to the wrapped object.
 
582
     */
 
583
    T *operator->() const {
 
584
        return get();
 
585
    }
 
586
 
 
587
    /**
 
588
     * @brief This function requests to wrap a different object.
 
589
     * If the wrapped objects are reference-counted, the reference to the
 
590
     * old object is dropped, and a reference to the new object is stored.
 
591
     * For other types the old object is freed and a copy of the new object
 
592
     * is stored.
 
593
     * @param p The new object to store, or @c null.
 
594
     * @see take(), out_param()
 
595
     */
 
596
    void reset(T *p = 0) {
 
597
        if (p != m_ptr) {
 
598
            if (m_ptr)
 
599
                CopyHelper::Free(m_ptr);
 
600
 
 
601
            m_ptr = 0;
 
602
 
 
603
            if (p)
 
604
                m_ptr = CopyHelper::Copy(p);
 
605
        }
 
606
    }
 
607
 
 
608
    /**
 
609
     * @brief This function requests to take ownership of a different object.
 
610
     * If the wrapped objects are reference-counted, the reference to the
 
611
     * old object is dropped, for other types the old object is freed.
 
612
     * As this function takes ownership of the passed object, no new reference
 
613
     * is created, and no copy is created.
 
614
     * @param p The new object to store, or @c null.
 
615
     * @see reset(), out_param()
 
616
     */
 
617
    void take(T *p) {
 
618
        if (p != m_ptr) {
 
619
            if (m_ptr)
 
620
                CopyHelper::Free(m_ptr);
 
621
 
 
622
            m_ptr = p;
 
623
        }
 
624
    }
 
625
 
 
626
    /**
 
627
     * @brief Resets the smart-pointer and returns a pointer to the internal
 
628
     * object pointer. This is useful to wrap objects retreived by output
 
629
     * parameters.
 
630
     * @return A pointer to the internal object pointer.
 
631
     * @see reset(), take()
 
632
     */
 
633
    T **out_param() {
 
634
        reset();
 
635
        return &m_ptr;
 
636
    }
 
637
 
 
638
    /**
 
639
     * @brief The assignment operator is an alias of the reset() method.
 
640
     * @param p The new object to store, or @c null
 
641
     * @return A reference to this smart-pointer.
 
642
     */
 
643
    Wrapper<T> &operator=(T *p) {
 
644
        reset(p);
 
645
        return *this;
 
646
    }
 
647
 
 
648
    /**
 
649
     * @brief The assignment operator is an alias of the reset() method.
 
650
     * @param p The new object to store, or @c null
 
651
     * @return A reference to this smart-pointer.
 
652
     */
 
653
    Wrapper<T> &operator=(const Wrapper<T> &other) {
 
654
        return operator=(other.get());
 
655
    }
 
656
 
 
657
    /**
 
658
     * @brief This operator casts the wrapped object to another type.
 
659
     * This cast operator also serves as safe bool cast. The more natural
 
660
     * operator bool() is problematic because it leads to unwanted implicit
 
661
     * casts. Also note that there is no non-const "operatpr T *()" to avoid
 
662
     * ambiguity problems for the compiler.
 
663
     */
 
664
    operator const T *() const {
 
665
        return get();
 
666
    }
 
667
 
 
668
    /**
 
669
     * @brief This operator checks if this pointer actually wraps an object.
 
670
     * @return @c true if this pointer wraps an object.
 
671
     */
 
672
    bool operator!() const {
 
673
        return get() == 0;
 
674
    }
 
675
 
 
676
    /**
 
677
     * @brief This operator compares two pointers for equality.
 
678
     * @param p The other pointer to compare with.
 
679
     * @return @c true if both pointers are equal.
 
680
     */
 
681
    bool operator==(const T *p) const {
 
682
        return m_ptr == p;
 
683
    }
 
684
 
 
685
    /**
 
686
     * @brief This operator compares two pointers for inequality.
 
687
     * @param p The other pointer to compare with.
 
688
     * @return @c true if both pointers are not equal.
 
689
     */
 
690
    bool operator!=(const T *p) const {
 
691
        return !operator==(p);
 
692
    }
 
693
 
 
694
private:
 
695
    T *m_ptr;
 
696
};
 
697
 
 
698
template<typename T, typename List = GList>
 
699
struct ListWrapper : public Wrapper<List, internal::ListCopyHelper<T> > {
 
700
    typedef Wrapper<List, internal::ListCopyHelper<T> > inherited;
 
701
 
 
702
    ListWrapper(const Wrapper<List> &other) // NOLINT: runtime/explicit
 
703
        : inherited(other) {
 
704
    }
 
705
 
 
706
    /**
 
707
     * @brief Constructs a ListWrapper that directly takes ownership of @list.
 
708
     * This constructor is useful since creating a deep copy of a list can be
 
709
     * pretty expensive.
 
710
     */
 
711
    explicit ListWrapper(List *list) {
 
712
        inherited::take(list);
 
713
    }
 
714
};
 
715
 
 
716
/**
 
717
 * @brief A type-safe function for creating shallow copies of structures.
 
718
 * @param T The structure's type.
 
719
 * @param p A pointer to the structure to copy.
 
720
 * @return A new copy of the structure, as returned by @c g_memdup().
 
721
 */
 
722
template<typename T>
 
723
inline T* shallow_copy(const T *p) {
 
724
    return static_cast<T *>(g_memdup(p, sizeof(T)));
 
725
}
 
726
 
 
727
/**
 
728
 * @brief A type-safe function for creating shallow copies of pointer arrays.
 
729
 * @param T The array's element type.
 
730
 * @param N The number of elements in the array.
 
731
 * @param p A pointer to the array to copy.
 
732
 * @return A new copy of the array, as returned by @c g_memdup().
 
733
 */
 
734
template<typename T, size_t N>
 
735
static T* array_copy(const T (&p)[N]) {
 
736
    return static_cast<T*>(g_memdup(p, sizeof p));
 
737
}
 
738
 
 
739
/**
 
740
 * @brief Wraps a pointer to an object by a shared smart-pointer.
 
741
 * This function doesn't take ownership of the object. It therefore @b does
 
742
 * increase the object's reference count.
 
743
 * @param T The type of the object to wrap.
 
744
 * @param p The pointer to the object to wrap.
 
745
 * @return A new Wrapper instance that holds a new reference to the object.
 
746
 */
 
747
template<typename T>
 
748
inline Wrapper<T> wrap(T *p) {
 
749
    Wrapper<T> wrapped;
 
750
    wrapped.reset(p);
 
751
    return wrapped;
 
752
}
 
753
 
 
754
/**
 
755
 * @brief Wraps a pointer to an object by a shared smart-pointer.
 
756
 * This function takes ownership of the object. It therefore @b doesn't
 
757
 * increase the object's reference count.
 
758
 * @param T The type of the object to wrap.
 
759
 * @param p The pointer to the object to wrap.
 
760
 * @return A new Wrapper instance that holds now owns the object.
 
761
 */
 
762
template<typename T>
 
763
inline Wrapper<T> take(T *p) {
 
764
    Wrapper<T> owned;
 
765
    owned.take(p);
 
766
    return owned;
 
767
}
 
768
 
 
769
/**
 
770
 * @brief Wraps a statically allocated structure by a shared smart-pointer.
 
771
 * This function creates a shallow copy of the structure and then takes
 
772
 * ownership of that copy.
 
773
 * @param T The type of the structure to wrap.
 
774
 * @param p The pointer to the structure to wrap.
 
775
 * @return A new Wrapper instance that holds owns a copy of the structure.
 
776
 */
 
777
template<typename T>
 
778
inline Wrapper<T> wrap_static(const T *p) {
 
779
    return take(shallow_copy(p));
 
780
}
 
781
 
 
782
// GLib event loop integration /////////////////////////////////////////////////
 
783
 
 
784
/**
 
785
 * @brief Type-safe destroy notifier.
 
786
 * This function can be used as destroy notifier for GLib functions.
 
787
 * It automatically invokes the proper @c delete operator of @p T.
 
788
 * @param T The type of the object to destroy.
 
789
 * @param user_data A pointer to the object to destroy.
 
790
 */
 
791
template<typename T>
 
792
inline void DestroyNotify(gpointer user_data) {
 
793
    delete static_cast<T *>(user_data);
 
794
}
 
795
 
 
796
template<typename T>
 
797
inline void ClosureNotify(gpointer user_data, GClosure *) {
 
798
    delete static_cast<T *>(user_data);
 
799
}
 
800
 
 
801
/**
 
802
 * @brief The Source class provides access to the GLib event source mechanism.
 
803
 */
 
804
class Source {
 
805
public:
 
806
    /**
 
807
     * @brief The signature of a regular idle source.
 
808
     * @return If this function returns @c false it is automatically removed
 
809
     * from the list of event sources and will not be called again.
 
810
     */
 
811
    typedef boost::function<bool()> SourceFunction;
 
812
 
 
813
    /**
 
814
     * @brief The signature of a single-call idle source.
 
815
     * This function is called excactly once. After returning it is
 
816
     * automatically removed from the list of event sources and will not be
 
817
     * called again.
 
818
     */
 
819
    typedef boost::function<void()> OneCallFunction;
 
820
 
 
821
    /**
 
822
     * @brief Removes an event source handler.
 
823
     * @param id The source handler's identifier.
 
824
     * @return @c True if the identifier was valid and the handler got removed.
 
825
     */
 
826
    static bool Remove(unsigned id) {
 
827
        return g_source_remove(id);
 
828
    }
 
829
 
 
830
protected:
 
831
    static gboolean on_source_function(gpointer data) {
 
832
        SourceFunction *const function = static_cast<SourceFunction *>(data);
 
833
 
 
834
        if (function)
 
835
            return (*function)();
 
836
 
 
837
        return false;
 
838
    }
 
839
 
 
840
    static gboolean on_one_call_function(gpointer data) {
 
841
        OneCallFunction *const function = static_cast<OneCallFunction *>(data);
 
842
 
 
843
        if (function)
 
844
            (*function)();
 
845
 
 
846
        return false;
 
847
    }
 
848
};
 
849
 
 
850
/**
 
851
 * @brief The Idle class provides access to GLib's idle source mechanism.
 
852
 * It manages functions which get called whenever there are no higher priority
 
853
 * events pending to the default main loop.
 
854
 *
 
855
 * @see Timeout
 
856
 */
 
857
class Idle : public Source {
 
858
public:
 
859
    /**
 
860
     * @brief Installs a regular idle source. This source will be invoked
 
861
     * until the @p function returns @c false. After that it be removed
 
862
     * automatically from the list of event sources.
 
863
     * @param function The function to be called on idle.
 
864
     * @param priority The priority of the idle source.
 
865
     * @return The identifier (greater than 0) of the event source.
 
866
     * @see AddOnce(), Source::Remove()
 
867
     */
 
868
    static unsigned Add(const SourceFunction &function,
 
869
                        int priority = G_PRIORITY_DEFAULT) {
 
870
        return g_idle_add_full(priority,
 
871
                               &Source::on_source_function,
 
872
                               new SourceFunction(function),
 
873
                               &DestroyNotify<SourceFunction>);
 
874
    }
 
875
 
 
876
    /**
 
877
     * @brief Installs a single-call idle source. This source will be called
 
878
     * exactly once. After that it be removed automatically from the list of
 
879
     * event sources.
 
880
     * @param function The function to be called on idle.
 
881
     * @param priority The priority of the idle source.
 
882
     * @return The identifier (greater than 0) of the event source.
 
883
     * @see Add(), Source::Remove()
 
884
     */
 
885
    static unsigned AddOnce(const OneCallFunction &function,
 
886
                            int priority = G_PRIORITY_DEFAULT) {
 
887
        return g_idle_add_full(priority,
 
888
                               &Source::on_one_call_function,
 
889
                               new OneCallFunction(function),
 
890
                               &DestroyNotify<OneCallFunction>);
 
891
    }
 
892
};
 
893
 
 
894
/**
 
895
 * @brief The Timeout class provides access to GLib's timeout mechanism.
 
896
 * It manages functions which get called whenever a given time interval
 
897
 * has passed.
 
898
 *
 
899
 * Note that timeout functions might get delayed if the event loop gets
 
900
 * blocked by other sources.
 
901
 *
 
902
 * @see Idle
 
903
 */
 
904
class Timeout : public Source {
 
905
public:
 
906
    /**
 
907
     * @brief This type describes time durations. Note that the duration's
 
908
     * resolution impacts which resolution the timeout source will have.
 
909
     */
 
910
    typedef boost::posix_time::time_duration Duration;
 
911
 
 
912
    /**
 
913
     * @brief Adds a new timeout function to the event loop. The timeout
 
914
     * gets automatically removed from the list of event sources if @p function
 
915
     * returns @c false.
 
916
     *
 
917
     * Note that the exact timeout mechanism is selected upon the @p interval
 
918
     * parameter's resolution. If the resolution is in seconds (or even less
 
919
     * granular) timeout sources of seconds precision are created. Otherwise
 
920
     * the sources have milliseconds resolution.
 
921
     *
 
922
     * @param interval The time between calls to the function.
 
923
     * @param function The function to be called on idle.
 
924
     * @param priority The priority of the idle source.
 
925
     * @return The identifier (greater than 0) of the event source.
 
926
     * @see AddOnce(), Source::Remove()
 
927
     */
 
928
    static unsigned Add(Duration interval,
 
929
                        const SourceFunction &function,
 
930
                        int priority = G_PRIORITY_DEFAULT_IDLE) {
 
931
        if (interval.resolution() == boost::date_time::sec) {
 
932
            return g_timeout_add_seconds_full(priority,
 
933
                                              interval.total_seconds(),
 
934
                                              &Source::on_source_function,
 
935
                                              new SourceFunction(function),
 
936
                                              &DestroyNotify<SourceFunction>);
 
937
        }
 
938
 
 
939
        return g_timeout_add_full(priority,
 
940
                                  interval.total_milliseconds(),
 
941
                                  &Source::on_source_function,
 
942
                                  new SourceFunction(function),
 
943
                                  &DestroyNotify<SourceFunction>);
 
944
    }
 
945
 
 
946
    /**
 
947
     * @brief Adds a new timeout function to the event loop that is called
 
948
     * exactly once. After its invocation the timeout gets automatically
 
949
     * removed from the list of event sources if @p function returns @c false.
 
950
     *
 
951
     * Note that the exact timeout mechanism is selected upon the @p interval
 
952
     * parameter's resolution. If the resolution is in seconds (or even less
 
953
     * granular) timeout sources of seconds precision are created. Otherwise
 
954
     * the sources have milliseconds resolution.
 
955
     *
 
956
     * @param interval The time between calls to the function.
 
957
     * @param function The function to be called on idle.
 
958
     * @param priority The priority of the idle source.
 
959
     * @return The identifier (greater than 0) of the event source.
 
960
     * @see AddOnce(), Source::Remove()
 
961
     */
 
962
    static unsigned AddOnce(Duration interval,
 
963
                            const OneCallFunction &function,
 
964
                            int priority = G_PRIORITY_DEFAULT_IDLE) {
 
965
        if (interval.fractional_seconds() == 0) {
 
966
            return g_timeout_add_seconds_full(priority,
 
967
                                              interval.total_seconds(),
 
968
                                              &Source::on_one_call_function,
 
969
                                              new OneCallFunction(function),
 
970
                                              &DestroyNotify<OneCallFunction>);
 
971
        }
 
972
 
 
973
        return g_timeout_add_full(priority,
 
974
                                  interval.total_milliseconds(),
 
975
                                  &Source::on_one_call_function,
 
976
                                  new OneCallFunction(function),
 
977
                                  &DestroyNotify<OneCallFunction>);
 
978
    }
 
979
};
 
980
 
 
981
// String conversions //////////////////////////////////////////////////////////
 
982
 
 
983
/**
 
984
 * @brief Describes a @c GError. The returned string contains
 
985
 * the error domain, the error code, and of course the error message.
 
986
 * @param error The error to describe, or @c null
 
987
 * @return A description of the error if appliable.
 
988
 */
 
989
std::string to_string(const GError *error);
 
990
 
 
991
/**
 
992
 * @brief Describes GStreamer capabilities
 
993
 * @param caps The capabilities to describe, or @c null
 
994
 * @return A describption of the capabilities if appliable
 
995
 */
 
996
std::string to_string(const GstCaps *caps);
 
997
 
 
998
// GParamSpec helpers //////////////////////////////////////////////////////////
 
999
 
 
1000
/**
 
1001
 * @brief Creates a @c GParamSpec for boxed types. This function is useful in
 
1002
 * static variable initialization to defer @c G_TYPE_* calls that could lead
 
1003
 * to warnings about the missing @c g_type_init() invocation.
 
1004
 * @param BoxedType G_TYPE_BOXED derived type of this property.
 
1005
 * @param name Canonical name of the property specified.
 
1006
 * @param nick Nick name for the property specified.
 
1007
 * @param blurb Description of the property specified.
 
1008
 * @param flags Flags for the property specified.
 
1009
 * @return A newly created parameter specification.
 
1010
 */
 
1011
template<typename BoxedType>
 
1012
inline GParamSpec *MakeParamSpecBoxed(const char *name,
 
1013
                                      const char *nick,
 
1014
                                      const char *blurb,
 
1015
                                      GParamFlags flags) {
 
1016
    return ::g_param_spec_boxed(name, nick, blurb,
 
1017
                                internal::GetGType<BoxedType>(), flags);
 
1018
}
 
1019
 
 
1020
} // namespace mediascanner
 
1021
 
 
1022
#endif // MEDIASCANNER_GLIBUTILS_H