~ubuntu-branches/ubuntu/natty/alsa-utils/natty

« back to all changes in this revision

Viewing changes to alsamixer/card_select.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich, Daniel T Chen
  • Date: 2009-11-06 11:29:35 UTC
  • mfrom: (2.3.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091106112935-stzy6l7u9auw6hm0
Tags: 1.0.21-1ubuntu1
* Merge from debian unstable, remaining changes:
  - debian/init:
    + wait until /usr/bin and /var/lib/alsa exist
    + only display an error when dealing with alsactl if there is no card
      specified
    + Set sane level for 'Speaker' and 'Headphone', needed for Dell Mini 9
      and Dell E series
    + ute PC Beep on hda cards that support it during initial volume setup
    + update lsb header to indicate no running of the script unless the
      udev rule is run
    + Mute *Analog/Digital Control for Creative cards by default
    + Default Digital Input Source to be Digital Mic 1 so that users
      with digital mic will be able to use it out of the box
    + Make use of lsb-functions/log calls
    + Mute "IEC958 Optical Raw" by default (LP: #408370)
  - debian/rules:
    + ship udev rules file in /lib/udev/rules.d
    + Do not install start symlinks for the alsa-utils init script, it gets
      run from a udev rule
  - debian/udev.script: do not use hotplug functions
  - debian/README.init.cs4236: Include in /usr/share/doc/alsa-utils so that
    users of snd-cs4236 (e.g., ThinkPad 600) can have audible sound
  - debian/patches/unset_pulse_internal.patch: We don't want alsamixer to
    show the pulse mixer by default, since it can be controlled from
    pulseaudio itself.
  - debian/patches/fix_misspelling_speaker-test_man_page.patch: Fix
    misspelling in speaker-test(1)
  - Set sane level for headphone 1 for Dell Studio XPS with 2.6.30.
  - Remove alsaconf from build system and remove po files

[ Daniel T Chen ]
"The beginning of the great initscript-sectomy"

* debian/alsa-mixer-save.upstart: Create an upstart job specifically
  saving mixer levels to resolve race (LP: #454265)
* debian/control: Version build-dep to upstart-aware debhelper.
* debian/init:
  + Revert all initscript changes in 1.0.20-2ubuntu[456]. They were
    crackful.
  + Restore more sane behavior/compatibility with 8.10 by not mucking
    with sound card state if alsactl restore fails.
  + Don't wait for 1 second after alsactl store, which already is
    expensive. Also, if store is going to fail, this wait is useless.
* debian/preinst: Handle upgrades from upstart-unaware versions.
* debian/rules: Move the former initscript into /sbin. We now have an
  upstart job just for handling alsactl store.
* debian/NOTES:
  debian/README.Debian:
  debian/modprobe-post-install-part:
  debian/udev.script: Use the new script path.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * card_select.c - select a card by list or device name
 
3
 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
 
4
 *
 
5
 * This program is free software: you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation, either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include "aconfig.h"
 
20
#include <stdio.h>
 
21
#include <stdlib.h>
 
22
#include <assert.h>
 
23
#include <alsa/asoundlib.h>
 
24
#include <menu.h>
 
25
#include "gettext_curses.h"
 
26
#include "die.h"
 
27
#include "mem.h"
 
28
#include "utils.h"
 
29
#include "colors.h"
 
30
#include "widget.h"
 
31
#include "mixer_widget.h"
 
32
#include "device_name.h"
 
33
#include "card_select.h"
 
34
 
 
35
struct card {
 
36
        struct card *next;
 
37
        char *indexstr;
 
38
        char *name;
 
39
        char *device_name;
 
40
};
 
41
 
 
42
static struct widget list_widget;
 
43
static struct card first_card;
 
44
static ITEM **items;
 
45
static MENU *menu;
 
46
static ITEM *initial_item;
 
47
 
 
48
static void on_key_enter(void)
 
49
{
 
50
        ITEM *item = current_item(menu);
 
51
        if (item) {
 
52
                struct card *card = item_userptr(item);
 
53
                if (card->device_name) {
 
54
                        if (select_card_by_name(card->device_name))
 
55
                                list_widget.close();
 
56
                } else {
 
57
                        create_device_name_form();
 
58
                }
 
59
        }
 
60
}
 
61
 
 
62
static void on_menu_key(int key)
 
63
{
 
64
        static const struct {
 
65
                int key;
 
66
                int request;
 
67
        } key_map[] = {
 
68
                { KEY_DOWN, REQ_DOWN_ITEM },
 
69
                { KEY_UP, REQ_UP_ITEM },
 
70
                { KEY_HOME, REQ_FIRST_ITEM },
 
71
                { KEY_NPAGE, REQ_SCR_DPAGE },
 
72
                { KEY_PPAGE, REQ_SCR_UPAGE },
 
73
                { KEY_BEG, REQ_FIRST_ITEM },
 
74
                { KEY_END, REQ_LAST_ITEM },
 
75
        };
 
76
        unsigned int i;
 
77
 
 
78
        for (i = 0; i < ARRAY_SIZE(key_map); ++i)
 
79
                if (key_map[i].key == key) {
 
80
                        menu_driver(menu, key_map[i].request);
 
81
                        break;
 
82
                }
 
83
}
 
84
 
 
85
static void on_handle_key(int key)
 
86
{
 
87
        switch (key) {
 
88
        case 27:
 
89
        case KEY_CANCEL:
 
90
        case 'q':
 
91
        case 'Q':
 
92
                list_widget.close();
 
93
                break;
 
94
        case 10:
 
95
        case 13:
 
96
        case KEY_ENTER:
 
97
                on_key_enter();
 
98
                break;
 
99
        default:
 
100
                on_menu_key(key);
 
101
                break;
 
102
        }
 
103
}
 
104
 
 
105
static bool create(void)
 
106
{
 
107
        int rows, columns;
 
108
        const char *title;
 
109
 
 
110
        if (screen_lines < 3 || screen_cols < 10) {
 
111
                beep();
 
112
                list_widget.close();
 
113
                return FALSE;
 
114
        }
 
115
        scale_menu(menu, &rows, &columns);
 
116
        rows += 2;
 
117
        columns += 2;
 
118
        if (rows > screen_lines)
 
119
                rows = screen_lines;
 
120
        if (columns > screen_cols)
 
121
                columns = screen_cols;
 
122
 
 
123
        widget_init(&list_widget, rows, columns, SCREEN_CENTER, SCREEN_CENTER,
 
124
                    attr_menu, WIDGET_BORDER | WIDGET_SUBWINDOW);
 
125
 
 
126
        title = _("Sound Card");
 
127
        mvwprintw(list_widget.window, 0, (columns - 2 - get_mbs_width(title)) / 2, " %s ", title);
 
128
        set_menu_win(menu, list_widget.window);
 
129
        set_menu_sub(menu, list_widget.subwindow);
 
130
        return TRUE;
 
131
}
 
132
 
 
133
static void on_window_size_changed(void)
 
134
{
 
135
        unpost_menu(menu);
 
136
        if (!create())
 
137
                return;
 
138
        post_menu(menu);
 
139
}
 
140
 
 
141
static void on_close(void)
 
142
{
 
143
        unsigned int i;
 
144
        struct card *card, *next_card;
 
145
 
 
146
        unpost_menu(menu);
 
147
        free_menu(menu);
 
148
        for (i = 0; items[i]; ++i)
 
149
                free_item(items[i]);
 
150
        free(items);
 
151
        for (card = first_card.next; card; card = next_card) {
 
152
                next_card = card->next;
 
153
                free(card->indexstr);
 
154
                free(card->name);
 
155
                free(card->device_name);
 
156
                free(card);
 
157
        }
 
158
        widget_free(&list_widget);
 
159
}
 
160
 
 
161
void close_card_select_list(void)
 
162
{
 
163
        on_close();
 
164
}
 
165
 
 
166
static struct widget list_widget = {
 
167
        .handle_key = on_handle_key,
 
168
        .window_size_changed = on_window_size_changed,
 
169
        .close = on_close,
 
170
};
 
171
 
 
172
static int get_cards(void)
 
173
{
 
174
        int count, number, err;
 
175
        snd_ctl_t *ctl;
 
176
        snd_ctl_card_info_t *info;
 
177
        char buf[16];
 
178
        struct card *card, *prev_card;
 
179
 
 
180
        first_card.indexstr = "-";
 
181
        first_card.name = _("(default)");
 
182
        first_card.device_name = "default";
 
183
        count = 1;
 
184
 
 
185
        snd_ctl_card_info_alloca(&info);
 
186
        prev_card = &first_card;
 
187
        number = -1;
 
188
        for (;;) {
 
189
                err = snd_card_next(&number);
 
190
                if (err < 0)
 
191
                        fatal_alsa_error(_("cannot enumerate sound cards"), err);
 
192
                if (number < 0)
 
193
                        break;
 
194
                sprintf(buf, "hw:%d", number);
 
195
                err = snd_ctl_open(&ctl, buf, 0);
 
196
                if (err < 0)
 
197
                        continue;
 
198
                err = snd_ctl_card_info(ctl, info);
 
199
                snd_ctl_close(ctl);
 
200
                if (err < 0)
 
201
                        continue;
 
202
                card = ccalloc(1, sizeof *card);
 
203
                sprintf(buf, "%d", number);
 
204
                card->indexstr = cstrdup(buf);
 
205
                card->name = cstrdup(snd_ctl_card_info_get_name(info));
 
206
                sprintf(buf, "hw:%d", number);
 
207
                card->device_name = cstrdup(buf);
 
208
                prev_card->next = card;
 
209
                prev_card = card;
 
210
                ++count;
 
211
        }
 
212
 
 
213
        card = ccalloc(1, sizeof *card);
 
214
        card->indexstr = cstrdup(" ");
 
215
        card->name = cstrdup(_("enter device name..."));
 
216
        prev_card->next = card;
 
217
        ++count;
 
218
 
 
219
        return count;
 
220
}
 
221
 
 
222
static void create_list_items(int cards)
 
223
{
 
224
        int i;
 
225
        struct card *card;
 
226
        ITEM *item;
 
227
 
 
228
        initial_item = NULL;
 
229
        items = ccalloc(cards + 1, sizeof(ITEM*));
 
230
        i = 0;
 
231
        for (card = &first_card; card; card = card->next) {
 
232
                item = new_item(card->indexstr, card->name);
 
233
                if (!item)
 
234
                        fatal_error("cannot create menu item");
 
235
                set_item_userptr(item, card);
 
236
                items[i++] = item;
 
237
                if (!initial_item &&
 
238
                    mixer_device_name &&
 
239
                    (!card->device_name ||
 
240
                     !strcmp(card->device_name, mixer_device_name)))
 
241
                        initial_item = item;
 
242
        }
 
243
        assert(i == cards);
 
244
}
 
245
 
 
246
void create_card_select_list(void)
 
247
{
 
248
        int cards;
 
249
 
 
250
        cards = get_cards();
 
251
        create_list_items(cards);
 
252
 
 
253
        menu = new_menu(items);
 
254
        if (!menu)
 
255
                fatal_error("cannot create menu");
 
256
        set_menu_fore(menu, attr_menu_selected);
 
257
        set_menu_back(menu, attr_menu);
 
258
        set_menu_mark(menu, NULL);
 
259
        if (initial_item)
 
260
                set_current_item(menu, initial_item);
 
261
        set_menu_spacing(menu, 2, 1, 1);
 
262
        menu_opts_on(menu, O_SHOWDESC);
 
263
 
 
264
        if (!create())
 
265
                return;
 
266
 
 
267
        post_menu(menu);
 
268
}