• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer Tuner
2  * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  *
4  * tuner.c: tuner design virtual class function wrappers
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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include "tuner.h"
27 
28 #include <string.h>
29 
30 /**
31  * SECTION:gsttuner
32  * @title: TunEr.h
33  * @short_description: Interface for elements providing tuner operations
34  *
35  * The GstTuner interface is provided by elements that have the ability to
36  * tune into multiple input signals, for example TV or radio capture cards.
37  *
38  * The interpretation of 'tuning into' an input stream depends on the element
39  * implementing the interface. For v4lsrc, it might imply selection of an
40  * input source and/or frequency to be configured on a TV card. Another
41  * GstTuner implementation might be to allow selection of an active input pad
42  * from multiple input pads.
43  *
44  * That said, the GstTuner interface functions are biased toward the
45  * TV capture scenario.
46  *
47  * The general parameters provided are for configuration are:
48  *
49  * * Selection of a current #GstTunerChannel. The current channel
50  *   represents the input source (e.g. Composite, S-Video etc for TV capture).
51  * * The #GstTunerNorm for the channel. The norm chooses the
52  *   interpretation of the incoming signal for the current channel. For example,
53  *   PAL or NTSC, or more specific variants there-of.
54  * * Channel frequency. If the current channel has the ability to tune
55  *   between multiple frequencies (if it has the GST_TUNER_CHANNEL_FREQUENCY flag)
56  *   then the frequency can be changed/retrieved via the
57  *   gst_tuner_set_frequency() and gst_tuner_get_frequency() methods.
58  *
59  * Where applicable, the signal strength can be retrieved and/or monitored
60  * via a signal.
61  *
62  */
63 
64 /* FIXME 0.11: check if we need to add API for sometimes-supportedness
65  * (aka making up for GstImplementsInterface removal) */
66 
67 /* FIXME 0.11: replace signals with messages (+ make API thread-safe) */
68 
69 enum
70 {
71   NORM_CHANGED,
72   CHANNEL_CHANGED,
73   FREQUENCY_CHANGED,
74   SIGNAL_CHANGED,
75   LAST_SIGNAL
76 };
77 
78 static guint gst_tuner_signals[LAST_SIGNAL] = { 0 };
79 
80 G_DEFINE_INTERFACE (GstTuner, gst_tuner, G_TYPE_INVALID);
81 
82 static void
gst_tuner_default_init(GstTunerInterface * iface)83 gst_tuner_default_init (GstTunerInterface * iface)
84 {
85   static gboolean initialized = FALSE;
86 
87   if (!initialized) {
88     /**
89      * GstTuner::norm-changed:
90      * @tuner: The element providing the GstTuner interface
91      * @norm: The new configured norm.
92      *
93      * Reports that the current #GstTunerNorm has changed.
94      */
95     gst_tuner_signals[NORM_CHANGED] =
96         g_signal_new ("norm-changed",
97         GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
98         G_STRUCT_OFFSET (GstTunerInterface, norm_changed),
99         NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_TUNER_NORM);
100     /**
101      * GstTuner::channel-changed:
102      * @tuner: The element providing the GstTuner interface
103      * @channel: The new configured channel.
104      *
105      * Reports that the current #GstTunerChannel has changed.
106      */
107     gst_tuner_signals[CHANNEL_CHANGED] =
108         g_signal_new ("channel-changed",
109         GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
110         G_STRUCT_OFFSET (GstTunerInterface, channel_changed),
111         NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_TUNER_CHANNEL);
112     /**
113      * GstTuner::frequency-changed:
114      * @tuner: The element providing the GstTuner interface
115      * @frequency: The new frequency (an unsigned long)
116      *
117      * Reports that the current frequency has changed.
118      */
119     gst_tuner_signals[FREQUENCY_CHANGED] =
120         g_signal_new ("frequency-changed",
121         GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
122         G_STRUCT_OFFSET (GstTunerInterface, frequency_changed),
123         NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_TUNER_CHANNEL, G_TYPE_ULONG);
124     /**
125      * GstTuner::signal-changed:
126      * @tuner: The element providing the GstTuner interface
127      * @channel: The current #GstTunerChannel
128      * @signal: The new signal strength (an integer)
129      *
130      * Reports that the signal strength has changed.
131      */
132     gst_tuner_signals[SIGNAL_CHANGED] =
133         g_signal_new ("signal-changed",
134         GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
135         G_STRUCT_OFFSET (GstTunerInterface, signal_changed),
136         NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_TUNER_CHANNEL, G_TYPE_INT);
137 
138     gst_type_mark_as_plugin_api (GST_TYPE_TUNER, 0);
139     gst_type_mark_as_plugin_api (GST_TYPE_TUNER_CHANNEL, 0);
140     gst_type_mark_as_plugin_api (GST_TYPE_TUNER_NORM, 0);
141 
142     initialized = TRUE;
143   }
144 
145   /* default virtual functions */
146   iface->list_channels = NULL;
147   iface->set_channel = NULL;
148   iface->get_channel = NULL;
149 
150   iface->list_norms = NULL;
151   iface->set_norm = NULL;
152   iface->get_norm = NULL;
153 
154   iface->set_frequency = NULL;
155   iface->get_frequency = NULL;
156   iface->signal_strength = NULL;
157 }
158 
159 /**
160  * gst_tuner_list_channels:
161  * @tuner: the #GstTuner (a #GstElement) to get the channels from.
162  *
163  * Retrieve a #GList of #GstTunerChannels available
164  * (e.g. 'composite', 's-video', ...) from the given tuner object.
165  *
166  * Returns: A list of channels available on this tuner. The list is
167  *          owned by the GstTuner and must not be freed.
168  */
169 const GList *
gst_tuner_list_channels(GstTuner * tuner)170 gst_tuner_list_channels (GstTuner * tuner)
171 {
172   GstTunerInterface *iface;
173 
174   g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
175 
176   iface = GST_TUNER_GET_INTERFACE (tuner);
177   if (iface->list_channels) {
178     return iface->list_channels (tuner);
179   }
180 
181   return NULL;
182 }
183 
184 /**
185  * gst_tuner_set_channel:
186  * @tuner: the #GstTuner (a #GstElement) that owns the channel.
187  * @channel: the channel to tune to.
188  *
189  * Tunes the object to the given channel, which should be one of the
190  * channels returned by gst_tuner_list_channels().
191  */
192 
193 void
gst_tuner_set_channel(GstTuner * tuner,GstTunerChannel * channel)194 gst_tuner_set_channel (GstTuner * tuner, GstTunerChannel * channel)
195 {
196   GstTunerInterface *iface;
197 
198   g_return_if_fail (GST_IS_TUNER (tuner));
199 
200   iface = GST_TUNER_GET_INTERFACE (tuner);
201   if (iface->set_channel) {
202     iface->set_channel (tuner, channel);
203   }
204 }
205 
206 /**
207  * gst_tuner_get_channel:
208  * @tuner: the #GstTuner (a #GstElement) to get the current channel from.
209  *
210  * Retrieve the current channel from the tuner.
211  *
212  * Returns: the current channel of the tuner object.
213  */
214 
215 GstTunerChannel *
gst_tuner_get_channel(GstTuner * tuner)216 gst_tuner_get_channel (GstTuner * tuner)
217 {
218   GstTunerInterface *iface;
219 
220   g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
221 
222   iface = GST_TUNER_GET_INTERFACE (tuner);
223   if (iface->get_channel) {
224     return iface->get_channel (tuner);
225   }
226 
227   return NULL;
228 }
229 
230 /**
231  * gst_tuner_list_norms:
232  * @tuner: the #GstTuner (*a #GstElement) to get the list of norms from.
233  *
234  * Retrieve a GList of available #GstTunerNorm settings for the currently
235  * tuned channel on the given tuner object.
236  *
237  * Returns: A list of norms available on the current channel for this
238  *          tuner object. The list is owned by the GstTuner and must not
239  *          be freed.
240  */
241 
242 const GList *
gst_tuner_list_norms(GstTuner * tuner)243 gst_tuner_list_norms (GstTuner * tuner)
244 {
245   GstTunerInterface *iface;
246 
247   g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
248 
249   iface = GST_TUNER_GET_INTERFACE (tuner);
250   if (iface->list_norms) {
251     return iface->list_norms (tuner);
252   }
253 
254   return NULL;
255 }
256 
257 /**
258  * gst_tuner_set_norm:
259  * @tuner: the #GstTuner (a #GstElement) to set the norm on.
260  * @norm: the norm to use for the current channel.
261  *
262  * Changes the video norm on this tuner to the given norm, which should be
263  * one of the norms returned by gst_tuner_list_norms().
264  */
265 
266 void
gst_tuner_set_norm(GstTuner * tuner,GstTunerNorm * norm)267 gst_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm)
268 {
269   GstTunerInterface *iface;
270 
271   g_return_if_fail (GST_IS_TUNER (tuner));
272 
273   iface = GST_TUNER_GET_INTERFACE (tuner);
274   if (iface->set_norm) {
275     iface->set_norm (tuner, norm);
276   }
277 }
278 
279 /**
280  * gst_tuner_get_norm:
281  * @tuner: the #GstTuner (a #GstElement) to get the current norm from.
282  *
283  * Get the current video norm from the given tuner object for the
284  * currently selected channel.
285  *
286  * Returns: the current norm.
287  */
288 
289 GstTunerNorm *
gst_tuner_get_norm(GstTuner * tuner)290 gst_tuner_get_norm (GstTuner * tuner)
291 {
292   GstTunerInterface *iface;
293 
294   g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
295 
296   iface = GST_TUNER_GET_INTERFACE (tuner);
297   if (iface->get_norm) {
298     return iface->get_norm (tuner);
299   }
300 
301   return NULL;
302 }
303 
304 /**
305  * gst_tuner_set_frequency:
306  * @tuner: The #GstTuner (a #GstElement) that owns the given channel.
307  * @channel: The #GstTunerChannel to set the frequency on.
308  * @frequency: The frequency to tune in to.
309  *
310  * Sets a tuning frequency on the given tuner/channel. Note that this
311  * requires the given channel to be a "tuning" channel, which can be
312  * checked using GST_TUNER_CHANNEL_HAS_FLAG (), with the proper flag
313  * being GST_TUNER_CHANNEL_FREQUENCY.
314  *
315  * The frequency is in Hz, with minimum steps indicated by the
316  * frequency_multiplicator provided in the #GstTunerChannel. The
317  * valid range is provided in the min_frequency and max_frequency properties
318  * of the #GstTunerChannel.
319  */
320 
321 void
gst_tuner_set_frequency(GstTuner * tuner,GstTunerChannel * channel,gulong frequency)322 gst_tuner_set_frequency (GstTuner * tuner,
323     GstTunerChannel * channel, gulong frequency)
324 {
325   GstTunerInterface *iface;
326 
327   g_return_if_fail (GST_IS_TUNER (tuner));
328   g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
329   g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
330           GST_TUNER_CHANNEL_FREQUENCY));
331 
332   iface = GST_TUNER_GET_INTERFACE (tuner);
333   if (iface->set_frequency) {
334     iface->set_frequency (tuner, channel, frequency);
335   }
336 }
337 
338 /**
339  * gst_tuner_get_frequency:
340  * @tuner: The #GstTuner (a #GstElement) that owns the given channel.
341  * @channel: The #GstTunerChannel to retrieve the frequency from.
342  *
343  * Retrieve the current frequency from the given channel. As for
344  * gst_tuner_set_frequency(), the #GstTunerChannel must support frequency
345  * operations, as indicated by the GST_TUNER_CHANNEL_FREQUENCY flag.
346  *
347  * Returns: The current frequency, or 0 on error.
348  */
349 
350 gulong
gst_tuner_get_frequency(GstTuner * tuner,GstTunerChannel * channel)351 gst_tuner_get_frequency (GstTuner * tuner, GstTunerChannel * channel)
352 {
353   GstTunerInterface *iface;
354 
355   g_return_val_if_fail (GST_IS_TUNER (tuner), 0);
356   g_return_val_if_fail (GST_IS_TUNER_CHANNEL (channel), 0);
357   g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
358           GST_TUNER_CHANNEL_FREQUENCY), 0);
359 
360   iface = GST_TUNER_GET_INTERFACE (tuner);
361 
362   if (iface->get_frequency) {
363     return iface->get_frequency (tuner, channel);
364   }
365 
366   return 0;
367 }
368 
369 /**
370  * gst_tuner_signal_strength:
371  * @tuner: the #GstTuner (a #GstElement) that owns the given channel.
372  * @channel: the #GstTunerChannel to get the signal strength from.
373  *
374  * Get the strength of the signal on this channel. Note that this
375  * requires the current channel to be a "tuning" channel, i.e. a
376  * channel on which frequency can be set. This can be checked using
377  * GST_TUNER_CHANNEL_HAS_FLAG (), and the appropriate flag to check
378  * for is GST_TUNER_CHANNEL_FREQUENCY.
379  *
380  * The valid range of the signal strength is indicated in the
381  * min_signal and max_signal properties of the #GstTunerChannel.
382  *
383  * Returns: Signal strength, or 0 on error.
384  */
385 gint
gst_tuner_signal_strength(GstTuner * tuner,GstTunerChannel * channel)386 gst_tuner_signal_strength (GstTuner * tuner, GstTunerChannel * channel)
387 {
388   GstTunerInterface *iface;
389 
390   g_return_val_if_fail (GST_IS_TUNER (tuner), 0);
391   g_return_val_if_fail (GST_IS_TUNER_CHANNEL (channel), 0);
392   g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
393           GST_TUNER_CHANNEL_FREQUENCY), 0);
394 
395   iface = GST_TUNER_GET_INTERFACE (tuner);
396   if (iface->signal_strength) {
397     return iface->signal_strength (tuner, channel);
398   }
399 
400   return 0;
401 }
402 
403 /**
404  * gst_tuner_find_norm_by_name:
405  * @tuner: A #GstTuner instance
406  * @norm: A string containing the name of a #GstTunerNorm
407  *
408  * Look up a #GstTunerNorm by name.
409  *
410  * Returns: A #GstTunerNorm, or NULL if no norm with the provided name
411  * is available.
412  */
413 GstTunerNorm *
gst_tuner_find_norm_by_name(GstTuner * tuner,gchar * norm)414 gst_tuner_find_norm_by_name (GstTuner * tuner, gchar * norm)
415 {
416   GList *walk;
417 
418   g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
419   g_return_val_if_fail (norm != NULL, NULL);
420 
421   walk = (GList *) gst_tuner_list_norms (tuner);
422   while (walk) {
423     if (strcmp (GST_TUNER_NORM (walk->data)->label, norm) == 0)
424       return GST_TUNER_NORM (walk->data);
425     walk = g_list_next (walk);
426   }
427   return NULL;
428 }
429 
430 /**
431  * gst_tuner_find_channel_by_name:
432  * @tuner: A #GstTuner instance
433  * @channel: A string containing the name of a #GstTunerChannel
434  *
435  * Look up a #GstTunerChannel by name.
436  *
437  * Returns: A #GstTunerChannel, or NULL if no channel with the provided name
438  * is available.
439  */
440 GstTunerChannel *
gst_tuner_find_channel_by_name(GstTuner * tuner,gchar * channel)441 gst_tuner_find_channel_by_name (GstTuner * tuner, gchar * channel)
442 {
443   GList *walk;
444 
445   g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
446   g_return_val_if_fail (channel != NULL, NULL);
447 
448   walk = (GList *) gst_tuner_list_channels (tuner);
449   while (walk) {
450     if (strcmp (GST_TUNER_CHANNEL (walk->data)->label, channel) == 0)
451       return GST_TUNER_CHANNEL (walk->data);
452     walk = g_list_next (walk);
453   }
454   return NULL;
455 }
456 
457 /**
458  * gst_tuner_channel_changed:
459  * @tuner: A #GstTuner instance
460  * @channel: A #GstTunerChannel instance
461  *
462  * Called by elements implementing the #GstTuner interface when the
463  * current channel changes. Fires the #GstTuner::channel-changed signal.
464  */
465 void
gst_tuner_channel_changed(GstTuner * tuner,GstTunerChannel * channel)466 gst_tuner_channel_changed (GstTuner * tuner, GstTunerChannel * channel)
467 {
468   g_return_if_fail (GST_IS_TUNER (tuner));
469   g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
470 
471   g_signal_emit (G_OBJECT (tuner),
472       gst_tuner_signals[CHANNEL_CHANGED], 0, channel);
473 }
474 
475 /**
476  * gst_tuner_norm_changed:
477  * @tuner: A #GstTuner instance
478  * @norm: A #GstTunerNorm instance
479  *
480  * Called by elements implementing the #GstTuner interface when the
481  * current norm changes. Fires the #GstTuner::norm-changed signal.
482  *
483  */
484 void
gst_tuner_norm_changed(GstTuner * tuner,GstTunerNorm * norm)485 gst_tuner_norm_changed (GstTuner * tuner, GstTunerNorm * norm)
486 {
487   g_return_if_fail (GST_IS_TUNER (tuner));
488   g_return_if_fail (GST_IS_TUNER_NORM (norm));
489 
490   g_signal_emit (G_OBJECT (tuner), gst_tuner_signals[NORM_CHANGED], 0, norm);
491 }
492 
493 /**
494  * gst_tuner_frequency_changed:
495  * @tuner: A #GstTuner instance
496  * @channel: The current #GstTunerChannel
497  * @frequency: The new frequency setting
498  *
499  * Called by elements implementing the #GstTuner interface when the
500  * configured frequency changes. Fires the #GstTuner::frequency-changed
501  * signal on the tuner, and the #GstTunerChannel::frequency-changed signal
502  * on the channel.
503  */
504 void
gst_tuner_frequency_changed(GstTuner * tuner,GstTunerChannel * channel,gulong frequency)505 gst_tuner_frequency_changed (GstTuner * tuner,
506     GstTunerChannel * channel, gulong frequency)
507 {
508   g_return_if_fail (GST_IS_TUNER (tuner));
509   g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
510 
511   g_signal_emit (G_OBJECT (tuner),
512       gst_tuner_signals[FREQUENCY_CHANGED], 0, channel, frequency);
513 
514   g_signal_emit_by_name (G_OBJECT (channel), "frequency_changed", frequency);
515 }
516 
517 /**
518  * gst_tuner_signal_changed:
519  * @tuner: A #GstTuner instance
520  * @channel: The current #GstTunerChannel
521  * @signal: The new signal strength
522  *
523  * Called by elements implementing the #GstTuner interface when the
524  * incoming signal strength changes. Fires the #GstTuner::signal-changed
525  * signal on the tuner and the #GstTunerChannel::signal-changed signal on
526  * the channel.
527  */
528 void
gst_tuner_signal_changed(GstTuner * tuner,GstTunerChannel * channel,gint signal)529 gst_tuner_signal_changed (GstTuner * tuner,
530     GstTunerChannel * channel, gint signal)
531 {
532   g_return_if_fail (GST_IS_TUNER (tuner));
533   g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
534 
535   g_signal_emit (G_OBJECT (tuner),
536       gst_tuner_signals[SIGNAL_CHANGED], 0, channel, signal);
537 
538   g_signal_emit_by_name (G_OBJECT (channel), "signal_changed", signal);
539 }
540