~ubuntu-branches/ubuntu/quantal/gst-plugins-bad-multiverse0.10/quantal

« back to all changes in this revision

Viewing changes to sys/oss4/oss4-mixer-enum.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2010-09-03 16:57:09 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20100903165709-5158pp06sfg0i6dv
Tags: 0.10.20-1
* New upstream release:
  + debian/build-deps.in:
    - Update build dependencies.
* debian/source/format,
  debian/compat,
  debian/rules,
  debian/patches:
  + Update to debhelper compat level 7.
  + Update to source format 3.0 (quilt).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* GStreamer OSS4 mixer enumeration control
2
 
 * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Library General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2 of the License, or (at your option) any later version.
8
 
 *
9
 
 * This library 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 GNU
12
 
 * Library General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Library General Public
15
 
 * License along with this library; if not, write to the
16
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
 
 * Boston, MA 02111-1307, USA.
18
 
 */
19
 
 
20
 
/* An 'enum' in gnome-volume-control / GstMixer is represented by a
21
 
 * GstMixerOptions object
22
 
 */
23
 
 
24
 
#ifdef HAVE_CONFIG_H
25
 
#include "config.h"
26
 
#endif
27
 
 
28
 
#include <gst/gst-i18n-plugin.h>
29
 
 
30
 
#define NO_LEGACY_MIXER
31
 
#include "oss4-mixer.h"
32
 
#include "oss4-mixer-enum.h"
33
 
#include "oss4-soundcard.h"
34
 
 
35
 
GST_DEBUG_CATEGORY_EXTERN (oss4mixer_debug);
36
 
#define GST_CAT_DEFAULT oss4mixer_debug
37
 
 
38
 
static GList *gst_oss4_mixer_enum_get_values (GstMixerOptions * options);
39
 
 
40
 
/* GstMixerTrack is a plain GObject, so let's just use the GLib macro here */
41
 
G_DEFINE_TYPE (GstOss4MixerEnum, gst_oss4_mixer_enum, GST_TYPE_MIXER_OPTIONS);
42
 
 
43
 
static void
44
 
gst_oss4_mixer_enum_init (GstOss4MixerEnum * e)
45
 
{
46
 
  e->need_update = TRUE;
47
 
}
48
 
 
49
 
static void
50
 
gst_oss4_mixer_enum_dispose (GObject * obj)
51
 
{
52
 
  GstMixerOptions *options = GST_MIXER_OPTIONS (obj);
53
 
 
54
 
  /* our list is a flat list with constant strings, but the GstMixerOptions
55
 
   * dispose will try to g_free the contained strings, so clean up the list
56
 
   * before chaining up to GstMixerOptions */
57
 
  g_list_free (options->values);
58
 
  options->values = NULL;
59
 
 
60
 
  G_OBJECT_CLASS (gst_oss4_mixer_enum_parent_class)->dispose (obj);
61
 
}
62
 
 
63
 
static void
64
 
gst_oss4_mixer_enum_class_init (GstOss4MixerEnumClass * klass)
65
 
{
66
 
  GObjectClass *gobject_class = (GObjectClass *) klass;
67
 
  GstMixerOptionsClass *mixeroptions_class = (GstMixerOptionsClass *) klass;
68
 
 
69
 
  gobject_class->dispose = gst_oss4_mixer_enum_dispose;
70
 
  mixeroptions_class->get_values = gst_oss4_mixer_enum_get_values;
71
 
}
72
 
 
73
 
static GList *
74
 
gst_oss4_mixer_enum_get_values_locked (GstMixerOptions * options)
75
 
{
76
 
  GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM_CAST (options);
77
 
  GList *oldlist, *list = NULL;
78
 
  int i;
79
 
 
80
 
  /* if current list of values is empty, update/re-check in any case */
81
 
  if (!e->need_update && options->values != NULL)
82
 
    return options->values;
83
 
 
84
 
  GST_LOG_OBJECT (e, "updating available values for %s", e->mc->mixext.extname);
85
 
 
86
 
  for (i = 0; i < e->mc->mixext.maxvalue; ++i) {
87
 
    const gchar *s;
88
 
 
89
 
    s = g_quark_to_string (e->mc->enum_vals[i]);
90
 
    if (MIXEXT_ENUM_IS_AVAILABLE (e->mc->mixext, i)) {
91
 
      GST_LOG_OBJECT (e, "option '%s' is available", s);
92
 
      list = g_list_prepend (list, (gpointer) s);
93
 
    } else {
94
 
      GST_LOG_OBJECT (e, "option '%s' is currently not available", s);
95
 
    }
96
 
  }
97
 
 
98
 
  list = g_list_reverse (list);
99
 
 
100
 
  /* this is not thread-safe, but then the entire GstMixer API isn't really,
101
 
   * since we return foo->list and not a copy and don't take any locks, so
102
 
   * not much we can do here but pray; we're usually either called from _new()
103
 
   * or from within _get_values() though, so it should be okay. We could use
104
 
   * atomic ops here, but I'm not sure how much more that really buys us.*/
105
 
  oldlist = options->values;    /* keep window small */
106
 
  options->values = list;
107
 
  g_list_free (oldlist);
108
 
 
109
 
  e->need_update = FALSE;
110
 
 
111
 
  return options->values;
112
 
}
113
 
 
114
 
static GList *
115
 
gst_oss4_mixer_enum_get_values (GstMixerOptions * options)
116
 
{
117
 
  GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM (options);
118
 
  GList *list;
119
 
 
120
 
  /* we take the lock here mostly to serialise ioctls with the watch thread */
121
 
  GST_OBJECT_LOCK (e->mixer);
122
 
 
123
 
  list = gst_oss4_mixer_enum_get_values_locked (options);
124
 
 
125
 
  GST_OBJECT_UNLOCK (e->mixer);
126
 
 
127
 
  return list;
128
 
}
129
 
 
130
 
static const gchar *
131
 
gst_oss4_mixer_enum_get_current_value (GstOss4MixerEnum * e)
132
 
{
133
 
  const gchar *cur_val = NULL;
134
 
 
135
 
  if (e->mc->enum_vals != NULL && e->mc->last_val < e->mc->mixext.maxvalue) {
136
 
    cur_val = g_quark_to_string (e->mc->enum_vals[e->mc->last_val]);
137
 
  }
138
 
 
139
 
  return cur_val;
140
 
}
141
 
 
142
 
static gboolean
143
 
gst_oss4_mixer_enum_update_current (GstOss4MixerEnum * e)
144
 
{
145
 
  int cur = -1;
146
 
 
147
 
  if (!gst_oss4_mixer_get_control_val (e->mixer, e->mc, &cur))
148
 
    return FALSE;
149
 
 
150
 
  if (cur < 0 || cur >= e->mc->mixext.maxvalue) {
151
 
    GST_WARNING_OBJECT (e, "read value %d out of bounds [0-%d]", cur,
152
 
        e->mc->mixext.maxvalue - 1);
153
 
    e->mc->last_val = 0;
154
 
    return FALSE;
155
 
  }
156
 
 
157
 
  return TRUE;
158
 
}
159
 
 
160
 
gboolean
161
 
gst_oss4_mixer_enum_set_option (GstOss4MixerEnum * e, const gchar * value)
162
 
{
163
 
  GQuark q;
164
 
  int i;
165
 
 
166
 
  q = g_quark_try_string (value);
167
 
  if (q == 0) {
168
 
    GST_WARNING_OBJECT (e, "unknown option '%s'", value);
169
 
    return FALSE;
170
 
  }
171
 
 
172
 
  for (i = 0; i < e->mc->mixext.maxvalue; ++i) {
173
 
    if (q == e->mc->enum_vals[i])
174
 
      break;
175
 
  }
176
 
 
177
 
  if (i >= e->mc->mixext.maxvalue) {
178
 
    GST_WARNING_OBJECT (e, "option '%s' is not valid for this control", value);
179
 
    return FALSE;
180
 
  }
181
 
 
182
 
  GST_LOG_OBJECT (e, "option '%s' = %d", value, i);
183
 
 
184
 
  if (!MIXEXT_ENUM_IS_AVAILABLE (e->mc->mixext, i)) {
185
 
    GST_WARNING_OBJECT (e, "option '%s' is not selectable currently", value);
186
 
    return FALSE;
187
 
  }
188
 
 
189
 
  if (!gst_oss4_mixer_set_control_val (e->mixer, e->mc, i)) {
190
 
    GST_WARNING_OBJECT (e, "could not set option '%s' (%d)", value, i);
191
 
    return FALSE;
192
 
  }
193
 
 
194
 
  /* and re-read current value with sanity checks (or could just assign here) */
195
 
  gst_oss4_mixer_enum_update_current (e);
196
 
 
197
 
  return TRUE;
198
 
}
199
 
 
200
 
const gchar *
201
 
gst_oss4_mixer_enum_get_option (GstOss4MixerEnum * e)
202
 
{
203
 
  const gchar *cur_str = NULL;
204
 
 
205
 
  if (!gst_oss4_mixer_enum_update_current (e)) {
206
 
    GST_WARNING_OBJECT (e, "failed to read current value");
207
 
    return NULL;
208
 
  }
209
 
 
210
 
  cur_str = gst_oss4_mixer_enum_get_current_value (e);
211
 
  GST_LOG_OBJECT (e, "%s (%d)", GST_STR_NULL (cur_str), e->mc->last_val);
212
 
  return cur_str;
213
 
}
214
 
 
215
 
GstMixerTrack *
216
 
gst_oss4_mixer_enum_new (GstOss4Mixer * mixer, GstOss4MixerControl * mc)
217
 
{
218
 
  GstOss4MixerEnum *e;
219
 
  GstMixerTrack *track;
220
 
 
221
 
  e = g_object_new (GST_TYPE_OSS4_MIXER_ENUM, "untranslated-label",
222
 
      mc->mixext.extname, NULL);
223
 
  e->mixer = mixer;
224
 
  e->mc = mc;
225
 
 
226
 
  track = GST_MIXER_TRACK (e);
227
 
 
228
 
  /* caller will set track->label and track->flags */
229
 
 
230
 
  track->num_channels = 0;
231
 
  track->min_volume = 0;
232
 
  track->max_volume = 0;
233
 
 
234
 
  (void) gst_oss4_mixer_enum_get_values_locked (GST_MIXER_OPTIONS (track));
235
 
 
236
 
  if (!gst_oss4_mixer_enum_update_current (e)) {
237
 
    GST_WARNING_OBJECT (track, "failed to read current value, returning NULL");
238
 
    g_object_unref (track);
239
 
    track = NULL;
240
 
  }
241
 
 
242
 
  GST_LOG_OBJECT (e, "current value: %d (%s)", e->mc->last_val,
243
 
      gst_oss4_mixer_enum_get_current_value (e));
244
 
 
245
 
  return track;
246
 
}
247
 
 
248
 
/* This is called from the watch thread */
249
 
void
250
 
gst_oss4_mixer_enum_process_change_unlocked (GstMixerTrack * track)
251
 
{
252
 
  GstOss4MixerEnum *e = GST_OSS4_MIXER_ENUM_CAST (track);
253
 
 
254
 
  gchar *cur;
255
 
 
256
 
  if (!e->mc->changed && !e->mc->list_changed)
257
 
    return;
258
 
 
259
 
  if (e->mc->list_changed) {
260
 
    gst_mixer_options_list_changed (GST_MIXER (e->mixer),
261
 
        GST_MIXER_OPTIONS (e));
262
 
  }
263
 
 
264
 
  GST_OBJECT_LOCK (e->mixer);
265
 
  cur = (gchar *) gst_oss4_mixer_enum_get_current_value (e);
266
 
  GST_OBJECT_UNLOCK (e->mixer);
267
 
 
268
 
  gst_mixer_option_changed (GST_MIXER (e->mixer), GST_MIXER_OPTIONS (e), cur);
269
 
}