1 /*
2  * Copyright (C) 2012,2013 Intel Corporation.
3  *
4  * Authors: Krzesimir Nowak <krnowak@openismus.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif /* HAVE_CONFIG_H_ */
25 #include "gupnp-dlna-gst-audio-information.h"
26 #include "gupnp-dlna-gst-info-utils.h"
27 
28 G_DEFINE_TYPE (GUPnPDLNAGstAudioInformation,
29                gupnp_dlna_gst_audio_information,
30                GUPNP_TYPE_DLNA_AUDIO_INFORMATION)
31 
32 struct _GUPnPDLNAGstAudioInformationPrivate {
33         GstDiscovererInfo *info;
34         GList *stream_list;
35         GstDiscovererAudioInfo *audio_info;
36         GstCaps *caps;
37 };
38 
39 enum
40 {
41         PROP_0,
42 
43         PROP_INFO
44 };
45 
46 static GstDiscovererAudioInfo *
get_audio_info(GUPnPDLNAGstAudioInformation * gst_info)47 get_audio_info (GUPnPDLNAGstAudioInformation *gst_info)
48 {
49         GUPnPDLNAGstAudioInformationPrivate *priv = gst_info->priv;
50 
51         if (!priv->audio_info) {
52                 GList *iter;
53 
54                 if (!priv->stream_list) {
55                         priv->stream_list =
56                                gst_discoverer_info_get_stream_list (priv->info);
57                         if (!priv->stream_list)
58                                 return NULL;
59                 }
60 
61                 for (iter = priv->stream_list; iter; iter = iter->next) {
62                         GstDiscovererStreamInfo *stream =
63                                         GST_DISCOVERER_STREAM_INFO (iter->data);
64                         GType stream_type = G_TYPE_FROM_INSTANCE (stream);
65 
66                         if (stream_type == GST_TYPE_DISCOVERER_AUDIO_INFO) {
67                                 priv->audio_info =
68                                              GST_DISCOVERER_AUDIO_INFO (stream);
69 
70                                 break;
71                         }
72                 }
73         }
74 
75         return priv->audio_info;
76 }
77 
78 static GstCaps *
get_caps(GUPnPDLNAGstAudioInformation * gst_info)79 get_caps (GUPnPDLNAGstAudioInformation *gst_info)
80 {
81         GUPnPDLNAGstAudioInformationPrivate *priv = gst_info->priv;
82 
83         if (!priv->caps)
84                 priv->caps = gst_discoverer_stream_info_get_caps
85                        (GST_DISCOVERER_STREAM_INFO (get_audio_info (gst_info)));
86 
87         return priv->caps;
88 }
89 
90 static GUPnPDLNAIntValue
get_int_value(GUPnPDLNAGstAudioInformation * gst_info,const gchar * name)91 get_int_value (GUPnPDLNAGstAudioInformation *gst_info,
92                const gchar *name)
93 {
94         GstCaps *caps = get_caps (gst_info);
95         GstDiscovererStreamInfo *stream =
96                          GST_DISCOVERER_STREAM_INFO (get_audio_info (gst_info));
97         GstDiscovererInfo *info = gst_info->priv->info;
98 
99         return gupnp_dlna_gst_get_int_value (caps, stream, info, name);
100 }
101 
102 static GUPnPDLNAStringValue
get_string_value(GUPnPDLNAGstAudioInformation * gst_info,const gchar * name)103 get_string_value (GUPnPDLNAGstAudioInformation *gst_info,
104                   const gchar *name)
105 {
106         GstCaps *caps = get_caps (gst_info);
107         GstDiscovererStreamInfo *stream =
108                          GST_DISCOVERER_STREAM_INFO (get_audio_info (gst_info));
109         GstDiscovererInfo *info = gst_info->priv->info;
110 
111         return gupnp_dlna_gst_get_string_value (caps, stream, info, name);
112 }
113 
114 static GUPnPDLNAIntValue
backend_get_bitrate(GUPnPDLNAAudioInformation * self)115 backend_get_bitrate (GUPnPDLNAAudioInformation *self)
116 {
117         GUPnPDLNAGstAudioInformation* gst_info =
118                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
119         GstDiscovererAudioInfo *audio_info = get_audio_info (gst_info);
120         guint data = gst_discoverer_audio_info_get_bitrate (audio_info);
121         GUPnPDLNAIntValue value = GUPNP_DLNA_INT_VALUE_UNSET;
122 
123         if (data > 0 && data <= G_MAXINT) {
124                 value.state = GUPNP_DLNA_VALUE_STATE_SET;
125                 value.value = (gint) data;
126         }
127 
128         return value;
129 }
130 
131 static GUPnPDLNAIntValue
backend_get_channels(GUPnPDLNAAudioInformation * self)132 backend_get_channels (GUPnPDLNAAudioInformation *self)
133 {
134         GUPnPDLNAGstAudioInformation* gst_info =
135                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
136         GstDiscovererAudioInfo *audio_info = get_audio_info (gst_info);
137         guint data = gst_discoverer_audio_info_get_channels (audio_info);
138         GUPnPDLNAIntValue value = GUPNP_DLNA_INT_VALUE_UNSET;
139 
140         if (data > 0 && data <= G_MAXINT) {
141                 value.state = GUPNP_DLNA_VALUE_STATE_SET;
142                 value.value = (gint) data;
143         }
144 
145         return value;
146 }
147 
148 static GUPnPDLNAIntValue
backend_get_depth(GUPnPDLNAAudioInformation * self)149 backend_get_depth (GUPnPDLNAAudioInformation *self)
150 {
151         GUPnPDLNAGstAudioInformation* gst_info =
152                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
153         GstDiscovererAudioInfo *audio_info = get_audio_info (gst_info);
154         guint data = gst_discoverer_audio_info_get_depth (audio_info);
155         GUPnPDLNAIntValue value = GUPNP_DLNA_INT_VALUE_UNSET;
156 
157         if (data > 0 && data <= G_MAXINT) {
158                 value.state = GUPNP_DLNA_VALUE_STATE_SET;
159                 value.value = (gint) data;
160         }
161 
162         return value;
163 }
164 
165 static GUPnPDLNAIntValue
backend_get_layer(GUPnPDLNAAudioInformation * self)166 backend_get_layer (GUPnPDLNAAudioInformation *self)
167 {
168         GUPnPDLNAGstAudioInformation* gst_info =
169                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
170 
171         return get_int_value (gst_info, "layer");
172 }
173 
174 static GUPnPDLNAStringValue
backend_get_level(GUPnPDLNAAudioInformation * self)175 backend_get_level (GUPnPDLNAAudioInformation *self)
176 {
177         GUPnPDLNAGstAudioInformation* gst_info =
178                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
179         return get_string_value (gst_info, "level");
180 }
181 
182 static GUPnPDLNAIntValue
backend_get_mpeg_audio_version(GUPnPDLNAAudioInformation * self)183 backend_get_mpeg_audio_version (GUPnPDLNAAudioInformation *self)
184 {
185         GUPnPDLNAGstAudioInformation* gst_info =
186                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
187 
188         return get_int_value (gst_info, "mpegaudioversion");
189 }
190 
191 static GUPnPDLNAIntValue
backend_get_mpeg_version(GUPnPDLNAAudioInformation * self)192 backend_get_mpeg_version (GUPnPDLNAAudioInformation *self)
193 {
194         GUPnPDLNAGstAudioInformation* gst_info =
195                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
196 
197         return get_int_value (gst_info, "mpegversion");
198 }
199 
200 static GUPnPDLNAStringValue
backend_get_profile(GUPnPDLNAAudioInformation * self)201 backend_get_profile (GUPnPDLNAAudioInformation *self)
202 {
203         GUPnPDLNAGstAudioInformation* gst_info =
204                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
205 
206         return get_string_value (gst_info, "profile");
207 }
208 
209 static GUPnPDLNAIntValue
backend_get_rate(GUPnPDLNAAudioInformation * self)210 backend_get_rate (GUPnPDLNAAudioInformation *self)
211 {
212         GUPnPDLNAGstAudioInformation* gst_info =
213                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
214         GstDiscovererAudioInfo *audio_info = get_audio_info (gst_info);
215         guint data = gst_discoverer_audio_info_get_sample_rate (audio_info);
216         GUPnPDLNAIntValue value = GUPNP_DLNA_INT_VALUE_UNSET;
217 
218         if (data > 0 && data <= G_MAXINT) {
219                 value.state = GUPNP_DLNA_VALUE_STATE_SET;
220                 value.value = (gint) data;
221         }
222 
223         return value;
224 }
225 
226 static GUPnPDLNAStringValue
backend_get_stream_format(GUPnPDLNAAudioInformation * self)227 backend_get_stream_format (GUPnPDLNAAudioInformation *self)
228 {
229         GUPnPDLNAGstAudioInformation* gst_info =
230                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
231 
232         return get_string_value (gst_info, "stream-format");
233 }
234 
235 static GUPnPDLNAIntValue
backend_get_wma_version(GUPnPDLNAAudioInformation * self)236 backend_get_wma_version (GUPnPDLNAAudioInformation *self)
237 {
238         GUPnPDLNAGstAudioInformation* gst_info =
239                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
240 
241         return get_int_value (gst_info, "wmaversion");
242 }
243 
244 static GUPnPDLNAStringValue
backend_get_mime(GUPnPDLNAAudioInformation * self)245 backend_get_mime (GUPnPDLNAAudioInformation *self)
246 {
247         GUPnPDLNAGstAudioInformation* gst_info =
248                                         GUPNP_DLNA_GST_AUDIO_INFORMATION (self);
249 
250         return gupnp_dlna_gst_get_mime (get_caps (gst_info));
251 }
252 
253 static void
gupnp_dlna_gst_audio_information_dispose(GObject * object)254 gupnp_dlna_gst_audio_information_dispose (GObject *object)
255 {
256         GUPnPDLNAGstAudioInformation *info =
257                                       GUPNP_DLNA_GST_AUDIO_INFORMATION (object);
258         GUPnPDLNAGstAudioInformationPrivate *priv = info->priv;
259         GObjectClass *parent_class =
260                  G_OBJECT_CLASS (gupnp_dlna_gst_audio_information_parent_class);
261 
262         g_clear_pointer (&priv->info, gupnp_dlna_gst_discoverer_info_unref);
263         g_clear_pointer (&priv->stream_list,
264                          gst_discoverer_stream_info_list_free);
265         /* priv->audio_info is freed with stream list above */
266         priv->audio_info = NULL;
267         g_clear_pointer (&priv->caps, gst_caps_unref);
268         parent_class->dispose (object);
269 }
270 
271 static void
gupnp_dlna_gst_audio_information_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)272 gupnp_dlna_gst_audio_information_set_property (GObject      *object,
273                                                guint         property_id,
274                                                const GValue *value,
275                                                GParamSpec   *pspec)
276 {
277         GUPnPDLNAGstAudioInformation *info =
278                                       GUPNP_DLNA_GST_AUDIO_INFORMATION (object);
279         GUPnPDLNAGstAudioInformationPrivate *priv = info->priv;
280 
281         switch (property_id) {
282         case PROP_INFO:
283                 g_clear_pointer (&priv->info,
284                                  gupnp_dlna_gst_discoverer_info_unref);
285                 priv->info =
286                         GST_DISCOVERER_INFO (gst_value_dup_mini_object (value));
287                 break;
288 
289         default:
290                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
291                 break;
292         }
293 }
294 
295 static void
gupnp_dlna_gst_audio_information_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)296 gupnp_dlna_gst_audio_information_get_property (GObject    *object,
297                                                guint       property_id,
298                                                GValue     *value,
299                                                GParamSpec *pspec)
300 {
301         GUPnPDLNAGstAudioInformation *info =
302                                       GUPNP_DLNA_GST_AUDIO_INFORMATION (object);
303         GUPnPDLNAGstAudioInformationPrivate *priv = info->priv;
304 
305         switch (property_id) {
306         case PROP_INFO:
307                 gst_value_set_mini_object (value, GST_MINI_OBJECT (priv->info));
308                 break;
309 
310         default:
311                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
312                 break;
313         }
314 }
315 
316 static void
gupnp_dlna_gst_audio_information_class_init(GUPnPDLNAGstAudioInformationClass * gst_info_class)317 gupnp_dlna_gst_audio_information_class_init
318                              (GUPnPDLNAGstAudioInformationClass *gst_info_class)
319 {
320         GUPnPDLNAAudioInformationClass *info_class =
321                             GUPNP_DLNA_AUDIO_INFORMATION_CLASS (gst_info_class);
322         GObjectClass *object_class = G_OBJECT_CLASS (gst_info_class);
323         GParamSpec *pspec;
324 
325         object_class->get_property =
326                                   gupnp_dlna_gst_audio_information_get_property;
327         object_class->set_property =
328                                   gupnp_dlna_gst_audio_information_set_property;
329         object_class->dispose = gupnp_dlna_gst_audio_information_dispose;
330 
331         info_class->get_bitrate = backend_get_bitrate;
332         info_class->get_channels = backend_get_channels;
333         info_class->get_depth = backend_get_depth;
334         info_class->get_layer = backend_get_layer;
335         info_class->get_level = backend_get_level;
336         info_class->get_mpeg_audio_version = backend_get_mpeg_audio_version;
337         info_class->get_mpeg_version = backend_get_mpeg_version;
338         info_class->get_profile = backend_get_profile;
339         info_class->get_rate = backend_get_rate;
340         info_class->get_stream_format = backend_get_stream_format;
341         info_class->get_wma_version = backend_get_wma_version;
342         info_class->get_mime = backend_get_mime;
343 
344         pspec = gst_param_spec_mini_object ("info",
345                                             "info",
346                                             "discoverer info",
347                                             GST_TYPE_DISCOVERER_INFO,
348                                             G_PARAM_READWRITE |
349                                             G_PARAM_CONSTRUCT);
350         g_object_class_install_property (object_class,
351                                          PROP_INFO,
352                                          pspec);
353 
354         g_type_class_add_private (gst_info_class,
355                                   sizeof (GUPnPDLNAGstAudioInformationPrivate));
356 }
357 
358 static void
gupnp_dlna_gst_audio_information_init(GUPnPDLNAGstAudioInformation * self)359 gupnp_dlna_gst_audio_information_init (GUPnPDLNAGstAudioInformation *self)
360 {
361         GUPnPDLNAGstAudioInformationPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE
362                                         (self,
363                                          GUPNP_TYPE_DLNA_GST_AUDIO_INFORMATION,
364                                          GUPnPDLNAGstAudioInformationPrivate);
365 
366         priv->info = NULL;
367         priv->stream_list = NULL;
368         priv->audio_info = NULL;
369         priv->caps = NULL;
370         self->priv = priv;
371 }
372 
373 GUPnPDLNAGstAudioInformation *
gupnp_dlna_gst_audio_information_new_from_discoverer_info(GstDiscovererInfo * info)374 gupnp_dlna_gst_audio_information_new_from_discoverer_info (GstDiscovererInfo *info)
375 {
376         GList* audio_list;
377         GUPnPDLNAGstAudioInformation *audio_info = NULL;
378 
379         g_return_val_if_fail (GST_IS_DISCOVERER_INFO (info), NULL);
380 
381         audio_list = gst_discoverer_info_get_audio_streams (info);
382 
383         if (audio_list) {
384                 audio_info = GUPNP_DLNA_GST_AUDIO_INFORMATION (g_object_new
385                                          (GUPNP_TYPE_DLNA_GST_AUDIO_INFORMATION,
386                                           "info", info,
387                                           NULL));
388                 gst_discoverer_stream_info_list_free (audio_list);
389         }
390 
391         return audio_info;
392 }
393