source: trunk/third/gst-plugins/sys/v4l2/gstv4l2tuner.c @ 21011

Revision 21011, 10.7 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21010, which included commits to RCS files with non-trunk default branches.
Line 
1/* GStreamer Tuner interface implementation
2 * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3 *
4 * gstv4l2tuner.c: tuner interface implementation for V4L2
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., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include <gst/gst.h>
27#include <gst/tuner/tuner.h>
28
29#include "gstv4l2tuner.h"
30#include "gstv4l2element.h"
31#include "v4l2_calls.h"
32
33static void gst_v4l2_tuner_channel_class_init (GstV4l2TunerChannelClass *
34    klass);
35static void gst_v4l2_tuner_channel_init (GstV4l2TunerChannel * channel);
36
37static void gst_v4l2_tuner_norm_class_init (GstV4l2TunerNormClass * klass);
38static void gst_v4l2_tuner_norm_init (GstV4l2TunerNorm * norm);
39
40static const GList *gst_v4l2_tuner_list_channels (GstTuner * mixer);
41static void gst_v4l2_tuner_set_channel (GstTuner * mixer,
42    GstTunerChannel * channel);
43static GstTunerChannel *gst_v4l2_tuner_get_channel (GstTuner * mixer);
44
45static const GList *gst_v4l2_tuner_list_norms (GstTuner * mixer);
46static void gst_v4l2_tuner_set_norm (GstTuner * mixer, GstTunerNorm * norm);
47static GstTunerNorm *gst_v4l2_tuner_get_norm (GstTuner * mixer);
48
49static void gst_v4l2_tuner_set_frequency (GstTuner * mixer,
50    GstTunerChannel * channel, gulong frequency);
51static gulong gst_v4l2_tuner_get_frequency (GstTuner * mixer,
52    GstTunerChannel * channel);
53static gint gst_v4l2_tuner_signal_strength (GstTuner * mixer,
54    GstTunerChannel * channel);
55
56static GstTunerNormClass *norm_parent_class = NULL;
57static GstTunerChannelClass *channel_parent_class = NULL;
58
59GType
60gst_v4l2_tuner_channel_get_type (void)
61{
62  static GType gst_v4l2_tuner_channel_type = 0;
63
64  if (!gst_v4l2_tuner_channel_type) {
65    static const GTypeInfo v4l2_tuner_channel_info = {
66      sizeof (GstV4l2TunerChannelClass),
67      NULL,
68      NULL,
69      (GClassInitFunc) gst_v4l2_tuner_channel_class_init,
70      NULL,
71      NULL,
72      sizeof (GstV4l2TunerChannel),
73      0,
74      (GInstanceInitFunc) gst_v4l2_tuner_channel_init,
75      NULL
76    };
77
78    gst_v4l2_tuner_channel_type =
79        g_type_register_static (GST_TYPE_TUNER_CHANNEL,
80        "GstV4l2TunerChannel", &v4l2_tuner_channel_info, 0);
81  }
82
83  return gst_v4l2_tuner_channel_type;
84}
85
86static void
87gst_v4l2_tuner_channel_class_init (GstV4l2TunerChannelClass * klass)
88{
89  channel_parent_class = g_type_class_ref (GST_TYPE_TUNER_CHANNEL);
90}
91
92static void
93gst_v4l2_tuner_channel_init (GstV4l2TunerChannel * channel)
94{
95  channel->index = 0;
96  channel->tuner = 0;
97  channel->audio = 0;
98}
99
100GType
101gst_v4l2_tuner_norm_get_type (void)
102{
103  static GType gst_v4l2_tuner_norm_type = 0;
104
105  if (!gst_v4l2_tuner_norm_type) {
106    static const GTypeInfo v4l2_tuner_norm_info = {
107      sizeof (GstV4l2TunerNormClass),
108      NULL,
109      NULL,
110      (GClassInitFunc) gst_v4l2_tuner_norm_class_init,
111      NULL,
112      NULL,
113      sizeof (GstV4l2TunerNorm),
114      0,
115      (GInstanceInitFunc) gst_v4l2_tuner_norm_init,
116      NULL
117    };
118
119    gst_v4l2_tuner_norm_type =
120        g_type_register_static (GST_TYPE_TUNER_NORM,
121        "GstV4l2TunerNorm", &v4l2_tuner_norm_info, 0);
122  }
123
124  return gst_v4l2_tuner_norm_type;
125}
126
127static void
128gst_v4l2_tuner_norm_class_init (GstV4l2TunerNormClass * klass)
129{
130  norm_parent_class = g_type_class_ref (GST_TYPE_TUNER_NORM);
131}
132
133static void
134gst_v4l2_tuner_norm_init (GstV4l2TunerNorm * norm)
135{
136  norm->index = 0;
137}
138
139void
140gst_v4l2_tuner_interface_init (GstTunerClass * klass)
141{
142  /* default virtual functions */
143  klass->list_channels = gst_v4l2_tuner_list_channels;
144  klass->set_channel = gst_v4l2_tuner_set_channel;
145  klass->get_channel = gst_v4l2_tuner_get_channel;
146
147  klass->list_norms = gst_v4l2_tuner_list_norms;
148  klass->set_norm = gst_v4l2_tuner_set_norm;
149  klass->get_norm = gst_v4l2_tuner_get_norm;
150
151  klass->set_frequency = gst_v4l2_tuner_set_frequency;
152  klass->get_frequency = gst_v4l2_tuner_get_frequency;
153  klass->signal_strength = gst_v4l2_tuner_signal_strength;
154}
155
156static gboolean
157gst_v4l2_tuner_is_sink (GstV4l2Element * v4l2element)
158{
159  const GList *pads = gst_element_get_pad_list (GST_ELEMENT (v4l2element));
160  GstPadDirection dir = GST_PAD_UNKNOWN;
161
162  /* get direction */
163  if (pads && g_list_length ((GList *) pads) == 1)
164    dir = GST_PAD_DIRECTION (GST_PAD (pads->data));
165
166  return (dir == GST_PAD_SINK);
167}
168
169static G_GNUC_UNUSED gboolean
170gst_v4l2_tuner_contains_channel (GstV4l2Element * v4l2element,
171    GstV4l2TunerChannel * v4l2channel)
172{
173  const GList *item;
174
175  for (item = v4l2element->channels; item != NULL; item = item->next)
176    if (item->data == v4l2channel)
177      return TRUE;
178
179  return FALSE;
180}
181
182static const GList *
183gst_v4l2_tuner_list_channels (GstTuner * mixer)
184{
185  /* ... or output, if we're a sink... */
186  return GST_V4L2ELEMENT (mixer)->channels;
187}
188
189static void
190gst_v4l2_tuner_set_channel (GstTuner * mixer, GstTunerChannel * channel)
191{
192  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
193  GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel);
194
195  /* assert that we're opened and that we're using a known item */
196  g_return_if_fail (GST_V4L2_IS_OPEN (v4l2element));
197  g_return_if_fail (gst_v4l2_tuner_contains_channel (v4l2element, v4l2channel));
198
199  /* ... or output, if we're a sink... */
200  if (gst_v4l2_tuner_is_sink (v4l2element) ?
201      gst_v4l2_set_output (v4l2element, v4l2channel->index) :
202      gst_v4l2_set_input (v4l2element, v4l2channel->index)) {
203    gst_tuner_channel_changed (mixer, channel);
204    g_object_notify (G_OBJECT (v4l2element), "channel");
205  }
206}
207
208static GstTunerChannel *
209gst_v4l2_tuner_get_channel (GstTuner * mixer)
210{
211  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
212  GList *item;
213  gint channel;
214
215  /* assert that we're opened and that we're using a known item */
216  g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), NULL);
217
218  /* ... or output, if we're a sink... */
219  if (gst_v4l2_tuner_is_sink (v4l2element))
220    gst_v4l2_get_output (v4l2element, &channel);
221  else
222    gst_v4l2_get_input (v4l2element, &channel);
223
224  for (item = v4l2element->channels; item != NULL; item = item->next) {
225    if (channel == GST_V4L2_TUNER_CHANNEL (item->data)->index)
226      return (GstTunerChannel *) item->data;
227  }
228
229  return NULL;
230}
231
232static G_GNUC_UNUSED gboolean
233gst_v4l2_tuner_contains_norm (GstV4l2Element * v4l2element,
234    GstV4l2TunerNorm * v4l2norm)
235{
236  const GList *item;
237
238  for (item = v4l2element->norms; item != NULL; item = item->next)
239    if (item->data == v4l2norm)
240      return TRUE;
241
242  return FALSE;
243}
244
245static const GList *
246gst_v4l2_tuner_list_norms (GstTuner * mixer)
247{
248  return GST_V4L2ELEMENT (mixer)->norms;
249}
250
251static void
252gst_v4l2_tuner_set_norm (GstTuner * mixer, GstTunerNorm * norm)
253{
254  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
255  GstV4l2TunerNorm *v4l2norm = GST_V4L2_TUNER_NORM (norm);
256
257  /* assert that we're opened and that we're using a known item */
258  g_return_if_fail (GST_V4L2_IS_OPEN (v4l2element));
259  g_return_if_fail (gst_v4l2_tuner_contains_norm (v4l2element, v4l2norm));
260
261  if (gst_v4l2_set_norm (v4l2element, v4l2norm->index)) {
262    gst_tuner_norm_changed (mixer, norm);
263    g_object_notify (G_OBJECT (v4l2element), "norm");
264  }
265}
266
267static GstTunerNorm *
268gst_v4l2_tuner_get_norm (GstTuner * mixer)
269{
270  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
271  GList *item;
272  v4l2_std_id norm;
273
274  /* assert that we're opened and that we're using a known item */
275  g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), NULL);
276
277  gst_v4l2_get_norm (v4l2element, &norm);
278
279  for (item = v4l2element->norms; item != NULL; item = item->next) {
280    if (norm == GST_V4L2_TUNER_NORM (item->data)->index)
281      return (GstTunerNorm *) item->data;
282  }
283
284  return NULL;
285}
286
287static void
288gst_v4l2_tuner_set_frequency (GstTuner * mixer,
289    GstTunerChannel * channel, gulong frequency)
290{
291  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
292  GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel);
293  gint chan;
294
295  /* assert that we're opened and that we're using a known item */
296  g_return_if_fail (GST_V4L2_IS_OPEN (v4l2element));
297  g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
298          GST_TUNER_CHANNEL_FREQUENCY));
299  g_return_if_fail (gst_v4l2_tuner_contains_channel (v4l2element, v4l2channel));
300
301  gst_v4l2_get_input (v4l2element, &chan);
302  if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index &&
303      GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
304    if (gst_v4l2_set_frequency (v4l2element, v4l2channel->tuner, frequency)) {
305      gst_tuner_frequency_changed (mixer, channel, frequency);
306      g_object_notify (G_OBJECT (v4l2element), "frequency");
307    }
308  }
309}
310
311static gulong
312gst_v4l2_tuner_get_frequency (GstTuner * mixer, GstTunerChannel * channel)
313{
314  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
315  GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel);
316  gint chan;
317  gulong frequency = 0;
318
319  /* assert that we're opened and that we're using a known item */
320  g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), 0);
321  g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
322          GST_TUNER_CHANNEL_FREQUENCY), 0);
323  g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2element,
324          v4l2channel), 0);
325
326  gst_v4l2_get_input (v4l2element, &chan);
327  if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index &&
328      GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
329    gst_v4l2_get_frequency (v4l2element, v4l2channel->tuner, &frequency);
330  }
331
332  return frequency;
333}
334
335static gint
336gst_v4l2_tuner_signal_strength (GstTuner * mixer, GstTunerChannel * channel)
337{
338  GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer);
339  GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel);
340  gint chan;
341  gulong signal = 0;
342
343  /* assert that we're opened and that we're using a known item */
344  g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), 0);
345  g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
346          GST_TUNER_CHANNEL_FREQUENCY), 0);
347  g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2element,
348          v4l2channel), 0);
349
350  gst_v4l2_get_input (v4l2element, &chan);
351  if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index &&
352      GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
353    gst_v4l2_signal_strength (v4l2element, v4l2channel->tuner, &signal);
354  }
355
356  return signal;
357}
Note: See TracBrowser for help on using the repository browser.