~ubuntu-branches/ubuntu/maverick/zapping/maverick

« back to all changes in this revision

Viewing changes to src/audio.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-03-08 23:19:08 UTC
  • mfrom: (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050308231908-oip7rfv6lcmo8c0e
Tags: 0.9.2-2ubuntu1
Rebuilt for Python transition (2.3 -> 2.4)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
17
 */
18
18
 
 
19
/* $Id: audio.c,v 1.30 2005/02/12 13:31:52 mschimek Exp $ */
 
20
 
 
21
/* XXX gtk+ 2.3 GtkOptionMenu */
 
22
#undef GTK_DISABLE_DEPRECATED
 
23
 
 
24
#include "site_def.h"
 
25
 
19
26
#ifdef HAVE_CONFIG_H
20
 
#  include <config.h>
 
27
#  include "config.h"
21
28
#endif
22
29
 
23
30
#include <gnome.h>
24
 
#include "../common/fifo.h" // current_time()
25
 
#include <math.h>
26
 
#include <unistd.h>
27
31
 
28
32
#include "audio.h"
29
33
#define ZCONF_DOMAIN "/zapping/options/audio/"
34
38
#include "mixer.h"
35
39
#include "osd.h"
36
40
#include "remote.h"
37
 
#include "callbacks.h"
 
41
#include "globals.h"
 
42
#include "v4linterface.h"
38
43
 
 
44
#ifdef HAVE_ESD
39
45
extern audio_backend_info esd_backend;
40
 
#if USE_OSS
 
46
#endif
 
47
#ifdef HAVE_ARTS
 
48
extern audio_backend_info arts_backend;
 
49
#endif
 
50
#ifdef HAVE_OSS
41
51
extern audio_backend_info oss_backend;
42
52
#endif
43
 
#if HAVE_ARTS
44
 
extern audio_backend_info arts_backend;
45
 
#endif
46
 
 
47
 
static audio_backend_info *backends [] =
48
 
{
49
 
  &esd_backend,
50
 
#if USE_OSS
51
 
  &oss_backend,
52
 
#endif
53
 
#if HAVE_ARTS
54
 
  &arts_backend
55
 
#endif
56
 
};
57
 
 
58
 
#define num_backends (sizeof(backends)/sizeof(backends[0]))
59
 
 
60
 
typedef struct mhandle {
61
 
  gint          owner; /* backend owning this handle */
62
 
  gpointer      handle; /* for the backend */
 
53
 
 
54
typedef struct {
 
55
  gpointer              handle; /* for the backend */
 
56
  audio_backend_info *  backend;
63
57
} mhandle;
64
58
 
65
59
void mixer_setup ( void )
66
60
{
67
 
  int cur_line = zcg_int(NULL, "record_source");
68
 
 
69
 
  if (!cur_line)
70
 
    return; /* Use system settings */
71
 
 
72
 
  cur_line--;
73
 
 
74
 
  mixer_set_recording_line(cur_line);
75
 
  mixer_set_volume(cur_line, zcg_int(NULL, "record_volume"));
 
61
  /* FIXME */
 
62
  if (mixer && mixer_line)
 
63
    {
 
64
      if (mixer->rec_gain)
 
65
        tv_mixer_line_set_volume (mixer->rec_gain,
 
66
                                  mixer->rec_gain->reset,
 
67
                                  mixer->rec_gain->reset);
 
68
 
 
69
      tv_mixer_line_record (mixer_line, /* exclusive */ TRUE);
 
70
    }
76
71
}
77
72
 
78
 
/* Generic stuff */
79
73
gpointer
80
 
open_audio_device (gboolean stereo, gint rate, enum audio_format
 
74
open_audio_device (gboolean stereo, guint rate, enum audio_format
81
75
                   format)
82
76
{
83
 
  gint cur_backend = zcg_int(NULL, "backend");
84
 
  gpointer handle = backends[cur_backend]->open(stereo, rate, format);
85
 
  mhandle *mhandle;
 
77
  const gchar *audio_source;
 
78
  audio_backend_info *backend;
 
79
  gpointer handle;
 
80
  mhandle *mh;
 
81
 
 
82
  audio_source = zcg_char (NULL, "audio_source");
 
83
  if (!audio_source)
 
84
    audio_source = "";
 
85
 
 
86
  backend = NULL;
 
87
 
 
88
  if (0)
 
89
    backend = NULL;
 
90
#ifdef HAVE_ESD
 
91
  else if (0 == strcmp (audio_source, "esd"))
 
92
    backend = &esd_backend;
 
93
#endif
 
94
#ifdef HAVE_ARTS
 
95
  else if (0 == strcmp (audio_source, "arts"))
 
96
    backend = &arts_backend;
 
97
#endif
 
98
#ifdef HAVE_OSS
 
99
  else if (0 == strcmp (audio_source, "kernel"))
 
100
    backend = &oss_backend;
 
101
#endif
 
102
 
 
103
  handle = NULL;
 
104
 
 
105
  if (backend)
 
106
    handle = backend->open (stereo, rate, format);
86
107
 
87
108
  if (!handle)
88
109
    {
89
 
      ShowBox(_("Cannot open the configured audio device.\n"
 
110
      ShowBox(("Cannot open the configured audio device.\n"
90
111
                "You might want to setup another kind of audio\n"
91
112
                "device in the Properties dialog."),
92
 
              GNOME_MESSAGE_BOX_WARNING);
 
113
              GTK_MESSAGE_WARNING);
93
114
      return NULL;
94
115
    }
95
116
 
96
 
  mhandle = (struct mhandle *) g_malloc0(sizeof(*mhandle));
97
 
  mhandle->handle = handle;
98
 
  mhandle->owner = cur_backend;
 
117
  mh = g_malloc0 (sizeof (*mh));
 
118
  mh->handle = handle;
 
119
  mh->backend = backend;
99
120
 
100
 
  /* make sure we record from the appropiate source */
 
121
  /* Make sure we record from the appropiate source. */
101
122
  mixer_setup();
102
123
 
103
 
  return mhandle;
 
124
  return mh;
104
125
}
105
126
 
106
127
void
107
128
close_audio_device (gpointer handle)
108
129
{
109
 
  mhandle *mhandle = (struct mhandle *) handle;
110
 
 
111
 
  backends[mhandle->owner]->close(mhandle->handle);
112
 
 
113
 
  g_free(mhandle);
 
130
  mhandle *mh = handle;
 
131
 
 
132
  mh->backend->close (mh->handle);
 
133
 
 
134
  g_free (mh);
114
135
}
115
136
 
116
137
void
117
 
read_audio_data (gpointer handle, gpointer dest, gint num_bytes,
 
138
read_audio_data (gpointer handle, gpointer dest, guint num_bytes,
118
139
                 double *timestamp)
119
140
{
120
 
  mhandle *mhandle = (struct mhandle *) handle;
121
 
 
122
 
  backends[mhandle->owner]->read(mhandle->handle, dest, num_bytes,
123
 
                                timestamp);
124
 
}
125
 
 
126
 
static void
127
 
on_backend_activate     (GtkObject              *menuitem,
128
 
                         gpointer               pindex)
129
 
{
130
 
  gint index = GPOINTER_TO_INT(pindex);
131
 
  GtkObject * audio_backends =
132
 
    GTK_OBJECT(gtk_object_get_user_data(menuitem));
133
 
  gint cur_sel =
134
 
    GPOINTER_TO_INT(gtk_object_get_data(audio_backends, "cur_sel"));
135
 
  GtkWidget **boxes =
136
 
    (GtkWidget**)gtk_object_get_data(audio_backends, "boxes");
137
 
 
138
 
  if (cur_sel == index)
139
 
    return;
140
 
 
141
 
  gtk_object_set_data(audio_backends, "cur_sel", pindex);
142
 
  gtk_widget_hide(boxes[cur_sel]);
143
 
  gtk_widget_set_sensitive(boxes[cur_sel], FALSE);
144
 
 
145
 
  gtk_widget_show(boxes[index]);
146
 
  gtk_widget_set_sensitive(boxes[index], TRUE);
147
 
}
148
 
 
149
 
static void
150
 
build_mixer_lines               (GtkWidget      *optionmenu)
151
 
{
152
 
  GtkMenu *menu = GTK_MENU
153
 
    (gtk_option_menu_get_menu(GTK_OPTION_MENU(optionmenu)));
154
 
  GtkWidget *menuitem;
155
 
  gchar *label;
156
 
  gint i;
157
 
 
158
 
  for (i=0;(label = mixer_get_description(i));i++)
159
 
    {
160
 
      menuitem = gtk_menu_item_new_with_label(label);
161
 
      free(label);
162
 
      gtk_widget_show(menuitem);
163
 
      gtk_menu_append(menu, menuitem);
164
 
    }
165
 
}
166
 
 
167
 
static void
168
 
on_record_source_changed        (GtkWidget      *optionmenu,
169
 
                                 gint           cur_sel,
170
 
                                 GtkRange       *hscale)
171
 
{
172
 
  int min, max;
173
 
  GtkAdjustment *adj;
174
 
 
175
 
  gtk_widget_set_sensitive(GTK_WIDGET(hscale), cur_sel);
176
 
 
177
 
  if (!cur_sel)
178
 
    return;
179
 
 
180
 
  /* note that it's cur_sel-1, the 0 entry is "Use system settings" */
181
 
  g_assert(!mixer_get_bounds(cur_sel-1, &min, &max));
182
 
  
183
 
  adj = gtk_range_get_adjustment(hscale);
184
 
 
185
 
  adj -> lower = min;
186
 
  adj -> upper = max;
187
 
 
188
 
  gtk_adjustment_changed(adj);
189
 
}
190
 
 
191
 
/* Audio */
192
 
static void
193
 
audio_setup             (GtkWidget      *page)
194
 
{
195
 
  GtkWidget *widget;
196
 
  GtkWidget *audio_backends =
197
 
    lookup_widget(page, "audio_backends");
198
 
  GtkWidget **boxes = (GtkWidget**)g_malloc0(num_backends*sizeof(boxes[0]));
199
 
  GtkWidget *vbox39 = lookup_widget(page, "vbox39");
200
 
  GtkWidget *menuitem;
201
 
  GtkWidget *menu = gtk_menu_new();
202
 
  guint cur_backend = zcg_int(NULL, "backend");
203
 
  GtkWidget *record_source = lookup_widget(page, "record_source");
204
 
  gint cur_input = zcg_int(NULL, "record_source");
205
 
  GtkWidget *record_volume = lookup_widget(page, "record_volume");
206
 
  guint i;
207
 
 
208
 
  /* Hook on dialog destruction so there's no mem leak */
209
 
  gtk_object_set_data_full(GTK_OBJECT (audio_backends), "boxes", boxes,
210
 
                           (GtkDestroyNotify)g_free);
211
 
 
212
 
  for (i=0; i<num_backends; i++)
213
 
    {
214
 
      menuitem = gtk_menu_item_new_with_label(_(backends[i]->name));
215
 
      gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
216
 
                         GTK_SIGNAL_FUNC(on_backend_activate),
217
 
                         GINT_TO_POINTER(i));
218
 
      gtk_menu_append(GTK_MENU(menu), menuitem);
219
 
      gtk_object_set_user_data(GTK_OBJECT(menuitem), audio_backends);
220
 
      gtk_widget_show(menuitem);
221
 
 
222
 
      boxes[i] = gtk_vbox_new(FALSE, 3);
223
 
      if (backends[i]->add_props)
224
 
        backends[i]->add_props(GTK_BOX(boxes[i]));
225
 
      gtk_box_pack_start(GTK_BOX(vbox39), boxes[i], FALSE, FALSE, 0);
226
 
      if (i == cur_backend)
227
 
        gtk_widget_show(boxes[i]);
228
 
      else
229
 
        gtk_widget_set_sensitive(boxes[i], FALSE);
230
 
    }
231
 
 
232
 
  gtk_option_menu_set_menu(GTK_OPTION_MENU (audio_backends), menu);
233
 
  gtk_option_menu_set_history(GTK_OPTION_MENU (audio_backends),
234
 
                              cur_backend);
235
 
  gtk_object_set_data(GTK_OBJECT (audio_backends), "cur_sel",
236
 
                      GINT_TO_POINTER(cur_backend));
237
 
 
238
 
  /* Avoid noise while changing channels */
239
 
  widget = lookup_widget(page, "checkbutton1");
240
 
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
241
 
    zconf_get_boolean(NULL, "/zapping/options/main/avoid_noise"));
242
 
 
243
 
  /* Force mixer for volume control */
244
 
  widget = lookup_widget(page, "force_mixer");
245
 
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
246
 
    zconf_get_boolean(NULL, "/zapping/options/audio/force_mixer"));
247
 
 
248
 
  /* Start zapping muted */
249
 
  widget = lookup_widget(page, "checkbutton3");
250
 
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
251
 
    zconf_get_boolean(NULL, "/zapping/options/main/start_muted"));
252
 
 
253
 
  /* Recording source and volume */
254
 
  build_mixer_lines(record_source);
255
 
  z_option_menu_set_active(record_source, cur_input);
256
 
  gtk_signal_connect(GTK_OBJECT(record_source), "changed",
257
 
                     GTK_SIGNAL_FUNC(on_record_source_changed),
258
 
                     record_volume);
259
 
  on_record_source_changed(record_source,
260
 
                           z_option_menu_get_active(record_source),
261
 
                           GTK_RANGE(record_volume));
262
 
  
263
 
  gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(record_volume)),
264
 
                           zcg_int(NULL, "record_volume"));
265
 
}
266
 
 
267
 
static void
268
 
audio_apply             (GtkWidget      *page)
269
 
{
270
 
  GtkWidget *widget;
271
 
  GtkWidget *audio_backends;
272
 
  gint selected;
273
 
  GtkWidget **boxes;
274
 
  GtkWidget *record_source;
275
 
  GtkWidget *record_volume;
276
 
 
277
 
  widget = lookup_widget(page, "checkbutton1"); /* avoid noise */
278
 
  zconf_set_boolean(gtk_toggle_button_get_active(
279
 
        GTK_TOGGLE_BUTTON(widget)), "/zapping/options/main/avoid_noise");
280
 
 
281
 
  widget = lookup_widget(page, "force_mixer");
282
 
  zconf_set_boolean(gtk_toggle_button_get_active(
283
 
        GTK_TOGGLE_BUTTON(widget)), "/zapping/options/audio/force_mixer");
284
 
 
285
 
  widget = lookup_widget(page, "checkbutton3"); /* start muted */
286
 
  zconf_set_boolean(gtk_toggle_button_get_active(
287
 
        GTK_TOGGLE_BUTTON(widget)), "/zapping/options/main/start_muted");  
288
 
 
289
 
  /* Apply the properties */
290
 
  audio_backends = lookup_widget(page, "audio_backends");
291
 
  selected = z_option_menu_get_active(audio_backends);
292
 
  boxes = (GtkWidget**)gtk_object_get_data(GTK_OBJECT(audio_backends),
293
 
                                           "boxes");
294
 
 
295
 
  if (backends[selected]->apply_props)
296
 
    backends[selected]->apply_props(GTK_BOX(boxes[selected]));
297
 
 
298
 
  zcs_int(selected, "backend");
299
 
 
300
 
  record_source = lookup_widget(page, "record_source");
301
 
  zcs_int(z_option_menu_get_active(record_source), "record_source");
302
 
 
303
 
  record_volume = lookup_widget(page, "record_volume");
304
 
  zcs_int((int) gtk_range_get_adjustment(GTK_RANGE(record_volume))->value,
305
 
          "record_volume");
306
 
}
307
 
 
308
 
static void
309
 
add                             (GnomeDialog    *dialog)
310
 
{
311
 
  SidebarEntry general_options[] = {
312
 
    { N_("Audio"), ICON_ZAPPING, "gnome-grecord.png", "vbox39",
313
 
      audio_setup, audio_apply }
314
 
  };
315
 
  SidebarGroup groups[] = {
316
 
    { N_("General Options"), general_options, acount(general_options) }
317
 
  };
318
 
 
319
 
  standard_properties_add(dialog, groups, acount(groups), "zapping.glade");
320
 
}
321
 
 
322
 
extern tveng_device_info * main_info;
323
 
 
324
 
gboolean
325
 
audio_set_mute                  (gint                   mute)
326
 
{
327
 
  int cur_line = zcg_int (NULL, "record_source");
328
 
  gboolean force = zcg_bool (NULL, "force_mixer");
329
 
 
330
 
  if (main_info->audio_mutable && !force)
331
 
    {
332
 
      if (tveng_set_mute (!!mute, main_info) < 0)
333
 
        {
334
 
          printv ("tveng_set_mute failed\n");
335
 
          return FALSE;
336
 
        }
337
 
    }
338
 
  else if (cur_line > 0) /* !use system settings */
339
 
    {
340
 
      if (mixer_set_mute (cur_line - 1, !!mute) < 0)
341
 
        {
342
 
          printv ("mixer_set_mute failed\n");
343
 
          return FALSE;
344
 
        }
345
 
 
346
 
      tveng_set_mute (0, main_info);
347
 
    }
348
 
 
349
 
  return TRUE;
350
 
}
351
 
 
352
 
gboolean
353
 
audio_get_mute                  (gint *                 mute)
354
 
{
355
 
  int cur_line = zcg_int (NULL, "record_source");
356
 
  gboolean force = zcg_bool (NULL, "force_mixer");
357
 
 
358
 
  if (main_info->audio_mutable && !force)
359
 
    {
360
 
      if ((*mute = tveng_get_mute (main_info)) < 0)
361
 
        {
362
 
          printv ("tveng_get_mute failed\n");
363
 
          return FALSE;
364
 
        }
365
 
    }
366
 
  else if (cur_line > 0) /* !use system settings */
367
 
    {
368
 
      if ((*mute = mixer_get_mute (cur_line - 1)) < 0)
369
 
        {
370
 
          printv ("mixer_get_mute failed\n");
371
 
          return FALSE;
372
 
        }
373
 
    }
374
 
 
375
 
  return TRUE;
376
 
}       
 
141
  mhandle *mh = handle;
 
142
 
 
143
  mh->backend->read (mh->handle,
 
144
                     dest, num_bytes, timestamp);
 
145
}
 
146
 
 
147
/*
 
148
 *  Audio preferences
 
149
 */
 
150
 
 
151
#ifndef AUDIO_MIXER_LOG_FP
 
152
#define AUDIO_MIXER_LOG_FP 0 /* stderr */
 
153
#endif
 
154
 
 
155
static void
 
156
general_audio_apply             (GtkWidget *            page)
 
157
{
 
158
  GtkWidget *widget;
 
159
  gboolean active;
 
160
 
 
161
  widget = lookup_widget (page, "general-audio-start-muted");
 
162
  active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
 
163
  zconf_set_boolean (active, "/zapping/options/main/start_muted");
 
164
 
 
165
  widget = lookup_widget (page, "general-audio-quit-muted");
 
166
  active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
 
167
  zconf_set_boolean (active, "/zapping/options/main/quit_muted");
 
168
 
 
169
  widget = lookup_widget (page, "general-audio-mute-chsw");
 
170
  active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
 
171
  zconf_set_boolean (active, "/zapping/options/main/avoid_noise");
 
172
}
 
173
 
 
174
static void
 
175
general_audio_setup             (GtkWidget *            page)
 
176
{
 
177
  GtkWidget *widget;
 
178
  gboolean active;
 
179
 
 
180
  zconf_get_boolean (&active, "/zapping/options/main/start_muted");
 
181
  widget = lookup_widget (page, "general-audio-start-muted");
 
182
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), active);
 
183
 
 
184
  zconf_get_boolean (&active, "/zapping/options/main/quit_muted");
 
185
  widget = lookup_widget (page, "general-audio-quit-muted");
 
186
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), active);
 
187
 
 
188
  zconf_get_boolean (&active, "/zapping/options/main/avoid_noise");
 
189
  widget = lookup_widget (page, "general-audio-mute-chsw");
 
190
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), active);
 
191
}
 
192
 
 
193
static void
 
194
devices_audio_source_apply      (GtkWidget *            page)
 
195
{
 
196
  GtkWidget *widget;
 
197
  const gchar *audio_source;
 
198
  tv_device_node *n;
 
199
 
 
200
  audio_source = "none";
 
201
 
 
202
  widget = lookup_widget (page, "devices-audio-gnome");
 
203
  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
 
204
    {
 
205
      audio_source = "esd";
 
206
    }
 
207
  else
 
208
    {
 
209
#ifdef HAVE_ARTS
 
210
      widget = lookup_widget (page, "devices-audio-kde");
 
211
      if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
 
212
        {
 
213
          audio_source = "arts";
 
214
        }
 
215
      else
 
216
#endif
 
217
        {
 
218
#ifdef HAVE_OSS
 
219
          widget = lookup_widget (page, "devices-audio-kernel");
 
220
          if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
 
221
            audio_source = "kernel";
 
222
#endif
 
223
        }
 
224
    }
 
225
 
 
226
  zcs_char (audio_source, "audio_source");
 
227
 
 
228
  widget = lookup_widget (page, "devices-audio-kernel-table");
 
229
  if ((n = z_device_entry_selected (widget)))
 
230
    zcs_char (n->device, "pcm_device");
 
231
}
 
232
 
 
233
static void
 
234
devices_audio_mixer_apply       (GtkWidget *            page)
 
235
{
 
236
  GtkWidget *widget;
 
237
  gboolean active;
 
238
  tv_device_node *n;
 
239
 
 
240
  widget = lookup_widget (page, "devices-audio-mixer");
 
241
  active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
 
242
  zconf_set_boolean (active, "/zapping/options/audio/force_mixer");
 
243
 
 
244
  widget = lookup_widget (page, "devices-audio-mixer-table");
 
245
 
 
246
  if ((n = z_device_entry_selected (widget)))
 
247
    {
 
248
      tv_audio_line *l;
 
249
      gint index;
 
250
 
 
251
      zcs_char (n->device, "mixer_device");
 
252
 
 
253
      widget = g_object_get_data (G_OBJECT (widget), "mixer_lines");
 
254
 
 
255
      if (widget)
 
256
        {
 
257
          index = z_option_menu_get_active (widget);
 
258
 
 
259
          for (l = PARENT (n, tv_mixer, node)->inputs; l; l = l->_next)
 
260
            if (0 == index--)
 
261
              {
 
262
                zcs_int ((int) l->hash, "mixer_input");
 
263
                break;
 
264
              }
 
265
        }
 
266
    }
 
267
}
 
268
 
 
269
static void
 
270
devices_audio_apply             (GtkWidget *            page)
 
271
{
 
272
  tveng_tc_control *tcc;
 
273
  guint num_controls;
 
274
 
 
275
  devices_audio_source_apply (page);
 
276
  devices_audio_mixer_apply (page);
 
277
 
 
278
  store_control_values (zapping->info, &tcc, &num_controls);
 
279
  startup_mixer (zapping->info);
 
280
  update_control_box (zapping->info);
 
281
  load_control_values (zapping->info, tcc, num_controls);
 
282
}
 
283
 
 
284
static void
 
285
on_enable_device_entry_toggled  (GtkToggleButton *      toggle_button,
 
286
                                 GtkWidget *            widget)
 
287
{
 
288
  gboolean active;
 
289
 
 
290
  active = gtk_toggle_button_get_active (toggle_button);
 
291
 
 
292
  gtk_widget_set_sensitive (widget, active);
 
293
 
 
294
  if (active)
 
295
    z_device_entry_grab_focus (widget);
 
296
}
 
297
 
 
298
static tv_device_node *
 
299
devices_audio_kernel_open       (GtkWidget *            table _unused_,
 
300
                                 tv_device_node *       list,
 
301
                                 const char *           name,
 
302
                                 gpointer               user_data _unused_)
 
303
{
 
304
  tv_device_node *n;
 
305
 
 
306
  if ((n = tv_device_node_find (list, name)))
 
307
    return n;
 
308
 
 
309
  /* FIXME report errors */
 
310
  if ((n = oss_pcm_open (NULL, NULL, name)))
 
311
    return n;
 
312
 
 
313
  return NULL;
 
314
}
 
315
 
 
316
static void
 
317
devices_audio_source_setup      (GtkWidget *            page)
 
318
{
 
319
  GtkWidget *alignment;
 
320
  GtkWidget *table;
 
321
  GtkWidget *widget;
 
322
  tv_device_node *list;
 
323
  const gchar *audio_source;
 
324
 
 
325
  audio_source = zcg_char (NULL, "audio_source");
 
326
  if (!audio_source)
 
327
    audio_source = "";
 
328
 
 
329
  widget = lookup_widget (page, "devices-audio-none");
 
330
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
 
331
 
 
332
  widget = lookup_widget (page, "devices-audio-gnome");
 
333
  if (0 == strcmp (audio_source, "esd"))
 
334
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
 
335
 
 
336
  widget = lookup_widget (page, "devices-audio-kde");
 
337
#ifdef HAVE_ARTS
 
338
  if (0 == strcmp (audio_source, "arts"))
 
339
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
 
340
#else
 
341
  gtk_widget_set_sensitive (widget, FALSE);
 
342
#endif
 
343
 
 
344
  widget = lookup_widget (page, "devices-audio-kernel");
 
345
#ifdef HAVE_OSS
 
346
  if (0 == strcmp (audio_source, "kernel"))
 
347
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
 
348
 
 
349
  /* XXX "oss"? */
 
350
  list = oss_pcm_scan (NULL, NULL);
 
351
 
 
352
  alignment = lookup_widget (page, "devices-audio-kernel-alignment");
 
353
  
 
354
  table = z_device_entry_new (/* prompt */ NULL,
 
355
                              list,
 
356
                              zcg_char (NULL, "pcm_device"),
 
357
                              devices_audio_kernel_open, NULL,
 
358
                              /* user_data */ NULL);
 
359
  gtk_widget_show (table);
 
360
  gtk_container_add (GTK_CONTAINER (alignment), table);
 
361
  register_widget (NULL, table, "devices-audio-kernel-table");
 
362
 
 
363
  g_signal_connect (G_OBJECT (widget), "toggled",
 
364
                    G_CALLBACK (on_enable_device_entry_toggled), table);
 
365
  on_enable_device_entry_toggled (GTK_TOGGLE_BUTTON (widget), table);
 
366
#else /* !HAVE_OSS */
 
367
  gtk_widget_set_sensitive (widget, FALSE);
 
368
#endif
 
369
}
 
370
 
 
371
static void
 
372
devices_audio_mixer_select      (GtkWidget *            table,
 
373
                                 tv_device_node *       n,
 
374
                                 gpointer               user_data _unused_)
 
375
{
 
376
  GtkWidget *menu;
 
377
  GtkWidget *optionmenu;
 
378
 
 
379
  if ((optionmenu = g_object_get_data (G_OBJECT (table), "mixer_lines")))
 
380
    {
 
381
      gtk_widget_destroy (optionmenu);
 
382
      optionmenu = NULL;
 
383
    }
 
384
 
 
385
  if (n)
 
386
    {
 
387
      tv_mixer *mixer;
 
388
      tv_audio_line *line;
 
389
      guint hash = (guint) -1;
 
390
      guint index;
 
391
 
 
392
      mixer = PARENT (n, tv_mixer, node);
 
393
      g_assert (mixer->inputs != NULL);
 
394
 
 
395
      if (0 == strcmp (zcg_char (NULL, "mixer_device"), n->device))
 
396
        hash = zcg_int (NULL, "mixer_input");
 
397
 
 
398
      optionmenu = gtk_option_menu_new ();
 
399
      gtk_widget_show (optionmenu);
 
400
 
 
401
      menu = gtk_menu_new ();
 
402
      gtk_widget_show (menu);
 
403
      gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
 
404
  
 
405
      index = 0;
 
406
 
 
407
      for (line = mixer->inputs; line; line = line->_next)
 
408
        {
 
409
          GtkWidget *menu_item;
 
410
          
 
411
          menu_item = gtk_menu_item_new_with_label (line->label);
 
412
          gtk_widget_show (menu_item);
 
413
          gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
 
414
 
 
415
          if (index == 0 || line->hash == hash)
 
416
            gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), index);
 
417
 
 
418
          index++;
 
419
        }
 
420
 
 
421
      if (mixer->inputs->_next == NULL)
 
422
        gtk_widget_set_sensitive (GTK_WIDGET (optionmenu), FALSE);
 
423
 
 
424
      gtk_table_attach (GTK_TABLE (table), optionmenu, 1, 1 + 1, 3, 3 + 1,
 
425
                        GTK_FILL | GTK_EXPAND, 0, 0, 0);
 
426
    }
 
427
 
 
428
  g_object_set_data (G_OBJECT (table), "mixer_lines", optionmenu);
 
429
}
 
430
 
 
431
static tv_device_node *
 
432
devices_audio_mixer_open        (GtkWidget *            table _unused_,
 
433
                                 tv_device_node *       list,
 
434
                                 const char *           name,
 
435
                                 gpointer               user_data _unused_)
 
436
{
 
437
  tv_mixer *m;
 
438
  tv_device_node *n;
 
439
 
 
440
  if ((n = tv_device_node_find (list, name)))
 
441
    return n;
 
442
 
 
443
  /* FIXME report errors */
 
444
  if ((m = tv_mixer_open (AUDIO_MIXER_LOG_FP, name)))
 
445
    {
 
446
      if (m->inputs != NULL)
 
447
        return &m->node;
 
448
 
 
449
      tv_mixer_close (m);
 
450
    }
 
451
 
 
452
  return NULL;
 
453
}
 
454
 
 
455
static void
 
456
devices_audio_mixer_setup       (GtkWidget *            page)
 
457
{
 
458
  tv_mixer *m;
 
459
  tv_device_node *list, *n;
 
460
  GtkWidget *checkbutton;
 
461
  GtkWidget *alignment;
 
462
  GtkWidget *table;
 
463
  GtkWidget *label;
 
464
 
 
465
  m = tv_mixer_scan (AUDIO_MIXER_LOG_FP);
 
466
  list = m ? &m->node : NULL;
 
467
 
 
468
  /* Remove tv card mixer interfaces, these are special
 
469
     and we fall back to them automatically. */
 
470
  for (n = list; n;)
 
471
    {
 
472
      if (PARENT (n, tv_mixer, node)->inputs == NULL)
 
473
        {
 
474
          tv_device_node *next;
 
475
          
 
476
          next = n->next;
 
477
          tv_device_node_delete (&list, n, FALSE);
 
478
          n = next;
 
479
        }
 
480
      else
 
481
        {
 
482
          n = n->next;
 
483
        }
 
484
    }
 
485
 
 
486
  checkbutton = lookup_widget (page, "devices-audio-mixer");
 
487
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton),
 
488
                                zcg_bool (NULL, "force_mixer"));
 
489
 
 
490
  alignment = lookup_widget (page, "devices-audio-mixer-alignment");
 
491
 
 
492
  table = z_device_entry_new (/* prompt */ NULL,
 
493
                              list,
 
494
                              zcg_char (NULL, "mixer_device"),
 
495
                              devices_audio_mixer_open,
 
496
                              devices_audio_mixer_select,
 
497
                              /* user_data */ NULL);
 
498
  gtk_widget_show (table);
 
499
  gtk_container_add (GTK_CONTAINER (alignment), table);
 
500
  register_widget (NULL, table, "devices-audio-mixer-table");
 
501
 
 
502
  g_signal_connect (G_OBJECT (checkbutton), "toggled",
 
503
                    G_CALLBACK (on_enable_device_entry_toggled), table);
 
504
  on_enable_device_entry_toggled (GTK_TOGGLE_BUTTON (checkbutton), table);
 
505
 
 
506
  /* TRANSLATORS: Soundcard mixer line. */
 
507
  label = gtk_label_new (_("Input:"));
 
508
  gtk_widget_show (label);
 
509
  gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
 
510
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 
511
  gtk_misc_set_padding (GTK_MISC (label), 3, 3);
 
512
  gtk_table_attach (GTK_TABLE (table), label,
 
513
                    0, 0 + 1,
 
514
                    3, 3 + 1,
 
515
                    GTK_FILL, 0, 0, 0);
 
516
}
 
517
 
 
518
static void
 
519
devices_audio_setup             (GtkWidget *            page)
 
520
{
 
521
  devices_audio_source_setup (page);
 
522
  devices_audio_mixer_setup (page);
 
523
}
 
524
 
 
525
static void
 
526
properties_add                  (GtkDialog *            dialog)
 
527
{
 
528
  SidebarEntry devices [] = {
 
529
    { N_("Audio"), "gnome-grecord.png", "vbox53",
 
530
      devices_audio_setup, devices_audio_apply,
 
531
      .help_link_id = "zapping-settings-audio-device" }
 
532
  };
 
533
  SidebarEntry general [] = {
 
534
    { N_("Audio"), "gnome-grecord.png", "vbox39",
 
535
      general_audio_setup, general_audio_apply,
 
536
      .help_link_id = "zapping-settings-audio-options" }
 
537
  };
 
538
  SidebarGroup groups [] = {
 
539
    { N_("Devices"),         devices, G_N_ELEMENTS (devices) },
 
540
    { N_("General Options"), general, G_N_ELEMENTS (general) }
 
541
  };
 
542
 
 
543
  standard_properties_add (dialog, groups, G_N_ELEMENTS (groups),
 
544
                           "zapping.glade2");
 
545
}
 
546
 
 
547
/*
 
548
 *  Mute stuff
 
549
 */
 
550
 
 
551
static guint            quiet_timeout_id = NO_SOURCE_ID;
377
552
 
378
553
static gboolean
379
 
volume_incr_cmd                         (GtkWidget *    widget,
380
 
                                         gint           argc,
381
 
                                         gchar **       argv,
382
 
                                         gpointer       user_data)
383
 
{
384
 
  int cur_line = zcg_int (NULL, "record_source");
385
 
  int min, max, range, step, cur;
386
 
  gint value = +1;
387
 
 
388
 
  if (argc > 1)
389
 
    value = strtol (argv[1], NULL, 0);
390
 
 
391
 
  if (value < -100 || value > +100)
392
 
    return FALSE;
393
 
 
394
 
  if (!cur_line)
395
 
    return FALSE;
396
 
 
397
 
  cur_line--; /* 0 is "system setting" */
398
 
 
399
 
  if (mixer_get_bounds (cur_line, &min, &max) == -1)
400
 
    return FALSE;
401
 
 
402
 
  range = max - min + 1;
403
 
  step = (int)(((double) value) * range / 100.0);
404
 
  if (value != 0 && step == 0)
405
 
    step = (value >> 31) | 1;
406
 
 
407
 
  cur = zcg_int(NULL, "record_volume");
408
 
 
409
 
  cur += step;
410
 
 
411
 
  if (cur > max)
412
 
    cur = max;
413
 
  else if (cur < min)
414
 
    cur = min;
415
 
 
416
 
  if (mixer_set_volume(cur_line, cur) == -1)
417
 
    return FALSE;
418
 
 
419
 
  zcs_int(cur, "record_volume");
420
 
 
421
 
#ifdef HAVE_LIBZVBI
422
 
  /* NLS: Record volume */
423
 
  osd_render_sgml(NULL, _("<blue>%3d %%</blue>"),
424
 
                  (cur - min) * 100 / range);
425
 
#endif
426
 
 
 
554
quiet_timeout                   (gpointer               user_data _unused_)
 
555
{
 
556
  tv_quiet_set (zapping->info, FALSE);
 
557
  return FALSE; /* don't call again */
 
558
}
 
559
 
 
560
void
 
561
reset_quiet                     (tveng_device_info *    info _unused_,
 
562
                                 guint                  delay)
 
563
{
 
564
  if (quiet_timeout_id > 0)
 
565
    g_source_remove (quiet_timeout_id);
 
566
 
 
567
  if (delay > 0)
 
568
    {
 
569
      quiet_timeout_id =
 
570
        g_timeout_add (delay /* ms */, (GSourceFunc) quiet_timeout, NULL);
 
571
    }
 
572
  else
 
573
    {
 
574
      tv_quiet_set (zapping->info, FALSE);
 
575
    }
 
576
}
 
577
 
 
578
/*
 
579
 *  Global mute function. XXX switch to callbacks.
 
580
 *  mode: 0=sound, 1=mute, 2=toggle, 3=just update GUI
 
581
 *  controls: update controls box
 
582
 *  osd: show state on screen
 
583
 */
 
584
gboolean
 
585
set_mute                                (gint           mode,
 
586
                                         gboolean       controls _unused_,
 
587
                                         gboolean       osd)
 
588
{
 
589
  static gboolean recursion = FALSE;
 
590
  gint mute;
 
591
 
 
592
  if (recursion)
 
593
    return TRUE;
 
594
 
 
595
  recursion = TRUE;
 
596
 
 
597
  /* Get current state */
 
598
 
 
599
  if (mode >= 2)
 
600
    {
 
601
      mute = tv_mute_get (zapping->info, TRUE);
 
602
      if (mute == -1)
 
603
        goto failure;
 
604
 
 
605
      if (mode == 2)
 
606
        mute = !mute;
 
607
    }
 
608
  else
 
609
    mute = !!mode;
 
610
 
 
611
  /* Set new state */
 
612
 
 
613
  if (mode <= 2)
 
614
    if (-1 == tv_mute_set (zapping->info, mute))
 
615
      goto failure;
 
616
 
 
617
  /* Update GUI */
 
618
 
 
619
  {
 
620
    GtkAction *action;
 
621
 
 
622
    action = gtk_action_group_get_action (zapping->generic_action_group,
 
623
                                          "Mute");
 
624
    if (mute != gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
 
625
      gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), mute);
 
626
 
 
627
    if (osd)
 
628
      {
 
629
        BonoboDockItem *dock_item;
 
630
 
 
631
        dock_item = gnome_app_get_dock_item_by_name
 
632
          (&zapping->app, GNOME_APP_TOOLBAR_NAME);
 
633
 
 
634
        if (DISPLAY_MODE_BACKGROUND == zapping->display_mode
 
635
            || DISPLAY_MODE_FULLSCREEN == zapping->display_mode
 
636
            || dock_item == NULL
 
637
            || !GTK_WIDGET_VISIBLE (GTK_WIDGET (dock_item)))
 
638
          osd_render_markup_printf (NULL, mute ?
 
639
                             _("<span foreground=\"blue\">Audio off</span>") :
 
640
                             _("<span foreground=\"yellow\">Audio on</span>"));
 
641
      }
 
642
  }
 
643
 
 
644
  recursion = FALSE;
427
645
  return TRUE;
 
646
 
 
647
 failure:
 
648
  recursion = FALSE;
 
649
  return FALSE;
 
650
}
 
651
 
 
652
static PyObject *
 
653
py_mute                         (PyObject *             self _unused_,
 
654
                                 PyObject *             args)
 
655
{
 
656
  int value = 2; /* toggle by default */
 
657
 
 
658
  if (!ParseTuple (args, "|i", &value))
 
659
    {
 
660
      g_warning ("zapping.mute(|i)");
 
661
      py_return_false;
 
662
    }
 
663
 
 
664
  set_mute (value, TRUE, TRUE);
 
665
 
 
666
  py_return_true;
428
667
}
429
668
 
430
669
void startup_audio ( void )
431
670
{
432
 
  guint i;
433
 
 
434
 
  property_handler audio_handler =
435
 
  {
436
 
    add: add
 
671
  static const property_handler audio_handler = {
 
672
    .add = properties_add,
437
673
  };
438
674
 
439
 
  prepend_property_handler(&audio_handler);
440
 
 
441
 
  zcc_int(0, "Default audio backend", "backend");
442
 
  zcc_int(0, "Recording source", "record_source");
443
 
  zcc_int(0xffff, "Recording volume", "record_volume");
444
 
 
445
 
  for (i=0; i<num_backends; i++)
446
 
    if (backends[i]->init)
447
 
      backends[i]->init();
448
 
 
449
 
  cmd_register ("mute", mute_cmd, NULL);
450
 
  cmd_register ("volume_incr", volume_incr_cmd, NULL);
 
675
  prepend_property_handler (&audio_handler);
 
676
 
 
677
  zcc_char ("kernel", "PCM recording source", "audio_source");
 
678
  zcc_char ("/dev/dsp", "PCM recording kernel device", "pcm_device");
 
679
 
 
680
  zcc_char ("", "Mixer device", "mixer_device");
 
681
  zcc_int (-1, "Mixer input line (hash)", "mixer_input");
 
682
 
 
683
  zconf_create_boolean (FALSE, "Mute when Zapping is started",
 
684
                        "/zapping/options/main/start_muted");
 
685
  zconf_create_boolean (TRUE, "Mute on exit",
 
686
                        "/zapping/options/main/quit_muted");
 
687
  zconf_create_boolean (TRUE, "Mute when changing channels",
 
688
                        "/zapping/options/main/avoid_noise");
 
689
 
 
690
#ifdef HAVE_ESD
 
691
  if (esd_backend.init)
 
692
    esd_backend.init ();
 
693
#endif
 
694
#ifdef HAVE_ARTS
 
695
  if (arts_backend.init)
 
696
    arts_backend.init ();
 
697
#endif
 
698
#ifdef HAVE_OSS
 
699
  if (oss_backend.init)
 
700
    oss_backend.init ();
 
701
#endif
 
702
 
 
703
  cmd_register ("mute", py_mute, METH_VARARGS,
 
704
                ("Mute/unmute"), "zapping.mute()",
 
705
                ("Mute"), "zapping.mute(1)",
 
706
                ("Unmute"), "zapping.mute(0)");
451
707
}
452
708
 
453
709
void shutdown_audio ( void )
454
710
{
455
 
  guint i;
456
 
 
457
 
  for (i=0; i<num_backends; i++)
458
 
    if (backends[i]->shutdown)
459
 
      backends[i]->shutdown();
 
711
#ifdef HAVE_ESD
 
712
  if (esd_backend.shutdown)
 
713
    esd_backend.shutdown ();
 
714
#endif
 
715
#ifdef HAVE_ARTS
 
716
  if (arts_backend.shutdown)
 
717
    arts_backend.shutdown ();
 
718
#endif
 
719
#ifdef HAVE_OSS
 
720
  if (oss_backend.shutdown)
 
721
    oss_backend.shutdown ();
 
722
#endif
460
723
}