1 /* GStreamer
2 *
3 * Copyright (C) 2014-2015 Sebastian Dröge <sebastian@centricular.com>
4 * Copyright (C) 2015 Brijesh Singh <brijesh.ksingh@gmail.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library 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 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 /**
23 * SECTION:gstplayer-visualization
24 * @title: GstPlayerVisualization
25 * @short_description: Player Visualization
26 *
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "gstplayer-visualization.h"
34
35 #include <string.h>
36
37 static GMutex vis_lock;
38 static GQueue vis_list = G_QUEUE_INIT;
39 static guint32 vis_cookie;
40
41 G_DEFINE_BOXED_TYPE (GstPlayerVisualization, gst_player_visualization,
42 (GBoxedCopyFunc) gst_player_visualization_copy,
43 (GBoxedFreeFunc) gst_player_visualization_free);
44
45 /**
46 * gst_player_visualization_free:
47 * @vis: #GstPlayerVisualization instance
48 *
49 * Frees a #GstPlayerVisualization.
50 */
51 void
gst_player_visualization_free(GstPlayerVisualization * vis)52 gst_player_visualization_free (GstPlayerVisualization * vis)
53 {
54 g_return_if_fail (vis != NULL);
55
56 g_free (vis->name);
57 g_free (vis->description);
58 g_free (vis);
59 }
60
61 /**
62 * gst_player_visualization_copy:
63 * @vis: #GstPlayerVisualization instance
64 *
65 * Makes a copy of the #GstPlayerVisualization. The result must be
66 * freed using gst_player_visualization_free().
67 *
68 * Returns: (transfer full): an allocated copy of @vis.
69 */
70 GstPlayerVisualization *
gst_player_visualization_copy(const GstPlayerVisualization * vis)71 gst_player_visualization_copy (const GstPlayerVisualization * vis)
72 {
73 GstPlayerVisualization *ret;
74
75 g_return_val_if_fail (vis != NULL, NULL);
76
77 ret = g_new0 (GstPlayerVisualization, 1);
78 ret->name = vis->name ? g_strdup (vis->name) : NULL;
79 ret->description = vis->description ? g_strdup (vis->description) : NULL;
80
81 return ret;
82 }
83
84 /**
85 * gst_player_visualizations_free:
86 * @viss: a %NULL terminated array of #GstPlayerVisualization to free
87 *
88 * Frees a %NULL terminated array of #GstPlayerVisualization.
89 */
90 void
gst_player_visualizations_free(GstPlayerVisualization ** viss)91 gst_player_visualizations_free (GstPlayerVisualization ** viss)
92 {
93 GstPlayerVisualization **p;
94
95 g_return_if_fail (viss != NULL);
96
97 p = viss;
98 while (*p) {
99 g_free ((*p)->name);
100 g_free ((*p)->description);
101 g_free (*p);
102 p++;
103 }
104 g_free (viss);
105 }
106
107 static void
gst_player_update_visualization_list(void)108 gst_player_update_visualization_list (void)
109 {
110 GList *features;
111 GList *l;
112 guint32 cookie;
113 GstPlayerVisualization *vis;
114
115 g_mutex_lock (&vis_lock);
116
117 /* check if we need to update the list */
118 cookie = gst_registry_get_feature_list_cookie (gst_registry_get ());
119 if (vis_cookie == cookie) {
120 g_mutex_unlock (&vis_lock);
121 return;
122 }
123
124 /* if update is needed then first free the existing list */
125 while ((vis = g_queue_pop_head (&vis_list)))
126 gst_player_visualization_free (vis);
127
128 features = gst_registry_get_feature_list (gst_registry_get (),
129 GST_TYPE_ELEMENT_FACTORY);
130
131 for (l = features; l; l = l->next) {
132 GstPluginFeature *feature = l->data;
133 const gchar *klass;
134
135 klass = gst_element_factory_get_metadata (GST_ELEMENT_FACTORY (feature),
136 GST_ELEMENT_METADATA_KLASS);
137
138 if (strstr (klass, "Visualization")) {
139 vis = g_new0 (GstPlayerVisualization, 1);
140
141 vis->name = g_strdup (gst_plugin_feature_get_name (feature));
142 vis->description =
143 g_strdup (gst_element_factory_get_metadata (GST_ELEMENT_FACTORY
144 (feature), GST_ELEMENT_METADATA_DESCRIPTION));
145 g_queue_push_tail (&vis_list, vis);
146 }
147 }
148 gst_plugin_feature_list_free (features);
149
150 vis_cookie = cookie;
151
152 g_mutex_unlock (&vis_lock);
153 }
154
155 /**
156 * gst_player_visualizations_get:
157 *
158 * Returns: (transfer full) (array zero-terminated=1) (element-type GstPlayerVisualization):
159 * a %NULL terminated array containing all available
160 * visualizations. Use gst_player_visualizations_free() after
161 * usage.
162 */
163 GstPlayerVisualization **
gst_player_visualizations_get(void)164 gst_player_visualizations_get (void)
165 {
166 gint i = 0;
167 GList *l;
168 GstPlayerVisualization **ret;
169
170 gst_player_update_visualization_list ();
171
172 g_mutex_lock (&vis_lock);
173 ret = g_new0 (GstPlayerVisualization *, g_queue_get_length (&vis_list) + 1);
174 for (l = vis_list.head; l; l = l->next)
175 ret[i++] = gst_player_visualization_copy (l->data);
176 g_mutex_unlock (&vis_lock);
177
178 return ret;
179 }
180