Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 1 | #! /usr/bin/env python |
| 2 | |
Barry Warsaw | d81d534 | 1998-11-18 03:28:45 +0000 | [diff] [blame] | 3 | """audiopy -- a program to control the Solaris audio device. |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 4 | |
Barry Warsaw | 8860405 | 1998-12-14 21:36:40 +0000 | [diff] [blame] | 5 | Contact: Barry Warsaw |
Barry Warsaw | d81d534 | 1998-11-18 03:28:45 +0000 | [diff] [blame] | 6 | Email: bwarsaw@python.org |
| 7 | Version: %(__version__)s |
Barry Warsaw | f79b7e2 | 1998-11-18 00:27:14 +0000 | [diff] [blame] | 8 | |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 9 | When no arguments are given, this pops up a graphical window which lets you |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 10 | choose the audio input and output devices, and set the output volume. |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 11 | |
| 12 | This program can be driven via the command line, and when done so, no window |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 13 | pops up. Most options have the general form: |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 14 | |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 15 | --device[={0,1}] |
| 16 | -d[={0,1}] |
| 17 | Set the I/O device. With no value, it toggles the specified device. |
| 18 | With a value, 0 turns the device off and 1 turns the device on. |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 19 | |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 20 | The list of devices and their short options are: |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 21 | |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 22 | (input) |
| 23 | microphone -- m |
| 24 | linein -- i |
| 25 | cd -- c |
| 26 | |
| 27 | (output) |
| 28 | headphones -- p |
| 29 | speaker -- s |
| 30 | lineout -- o |
| 31 | |
| 32 | Other options are: |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 33 | |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 34 | --gain volume |
| 35 | -g volume |
| 36 | Sets the output gain to the specified volume, which must be an integer |
| 37 | in the range [%(MIN_GAIN)s..%(MAX_GAIN)s] |
| 38 | |
Barry Warsaw | 3febc24 | 1998-11-01 07:10:51 +0000 | [diff] [blame] | 39 | --version |
| 40 | -v |
| 41 | Print the version number and exit. |
| 42 | |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 43 | --help |
| 44 | -h |
| 45 | Print this message and exit. |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 46 | """ |
| 47 | |
| 48 | import sys |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 49 | import os |
Barry Warsaw | d8d179d | 1999-09-22 15:45:51 +0000 | [diff] [blame] | 50 | import errno |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 51 | import sunaudiodev |
| 52 | from SUNAUDIODEV import * |
| 53 | |
| 54 | # Milliseconds between interrupt checks |
| 55 | KEEPALIVE_TIMER = 500 |
| 56 | |
Barry Warsaw | 772d696 | 1999-08-18 20:17:42 +0000 | [diff] [blame] | 57 | __version__ = '1.1' |
Barry Warsaw | 3febc24 | 1998-11-01 07:10:51 +0000 | [diff] [blame] | 58 | |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 59 | |
| 60 | |
| 61 | class MainWindow: |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 62 | def __init__(self, device): |
Barry Warsaw | 9ade9dd | 1998-11-01 07:13:14 +0000 | [diff] [blame] | 63 | from Tkinter import * |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 64 | self.__helpwin = None |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 65 | self.__devctl = device |
| 66 | info = device.getinfo() |
| 67 | # |
Barry Warsaw | 3febc24 | 1998-11-01 07:10:51 +0000 | [diff] [blame] | 68 | self.__tkroot = tkroot = Tk(className='Audiopy') |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 69 | tkroot.withdraw() |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 70 | # create the menubar |
| 71 | menubar = Menu(tkroot) |
| 72 | filemenu = Menu(menubar, tearoff=0) |
| 73 | filemenu.add_command(label='Quit', |
| 74 | command=self.__quit, |
| 75 | accelerator='Alt-Q', |
| 76 | underline=0) |
| 77 | helpmenu = Menu(menubar, name='help', tearoff=0) |
| 78 | helpmenu.add_command(label='About Audiopy...', |
| 79 | command=self.__popup_about, |
| 80 | underline=0) |
| 81 | helpmenu.add_command(label='Help...', |
| 82 | command=self.__popup_using, |
| 83 | underline=0) |
| 84 | menubar.add_cascade(label='File', |
| 85 | menu=filemenu, |
| 86 | underline=0) |
| 87 | menubar.add_cascade(label='Help', |
| 88 | menu=helpmenu, |
| 89 | underline=0) |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 90 | # now create the top level window |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 91 | root = self.__root = Toplevel(tkroot, class_='Audiopy', menu=menubar) |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 92 | root.protocol('WM_DELETE_WINDOW', self.__quit) |
Barry Warsaw | 3febc24 | 1998-11-01 07:10:51 +0000 | [diff] [blame] | 93 | root.title('audiopy ' + __version__) |
| 94 | root.iconname('audiopy ' + __version__) |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 95 | root.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive) |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 96 | # |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 97 | buttons = [] |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 98 | # |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 99 | # where does input come from? |
| 100 | frame = Frame(root, bd=1, relief=RAISED) |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 101 | frame.grid(row=1, column=0, sticky='NSEW') |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 102 | label = Label(frame, text='Input From:') |
| 103 | label.grid(row=0, column=0, sticky=E) |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 104 | self.__inputvar = IntVar() |
Barry Warsaw | 441abb4 | 1998-11-02 22:48:56 +0000 | [diff] [blame] | 105 | ## |
| 106 | btn = Radiobutton(frame, |
| 107 | text='None', |
| 108 | variable=self.__inputvar, |
| 109 | value=0, |
| 110 | command=self.__pushtodev, |
| 111 | underline=0) |
| 112 | btn.grid(row=0, column=1, sticky=W) |
| 113 | root.bind('<Alt-n>', self.__none) |
| 114 | root.bind('<Alt-N>', self.__none) |
| 115 | if not info.i_avail_ports & MICROPHONE: |
| 116 | btn.configure(state=DISABLED) |
| 117 | buttons.append(btn) |
| 118 | ## |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 119 | btn = Radiobutton(frame, |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 120 | text='Microphone', |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 121 | variable=self.__inputvar, |
| 122 | value=MICROPHONE, |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 123 | command=self.__pushtodev, |
| 124 | underline=0) |
Barry Warsaw | 441abb4 | 1998-11-02 22:48:56 +0000 | [diff] [blame] | 125 | btn.grid(row=1, column=1, sticky=W) |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 126 | root.bind('<Alt-m>', self.__mic) |
| 127 | root.bind('<Alt-M>', self.__mic) |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 128 | if not info.i_avail_ports & MICROPHONE: |
| 129 | btn.configure(state=DISABLED) |
| 130 | buttons.append(btn) |
| 131 | ## |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 132 | btn = Radiobutton(frame, |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 133 | text='Line In', |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 134 | variable=self.__inputvar, |
| 135 | value=LINE_IN, |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 136 | command=self.__pushtodev, |
| 137 | underline=5) |
Barry Warsaw | 441abb4 | 1998-11-02 22:48:56 +0000 | [diff] [blame] | 138 | btn.grid(row=2, column=1, sticky=W) |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 139 | root.bind('<Alt-i>', self.__linein) |
| 140 | root.bind('<Alt-I>', self.__linein) |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 141 | if not info.i_avail_ports & LINE_IN: |
| 142 | btn.configure(state=DISABLED) |
| 143 | buttons.append(btn) |
Barry Warsaw | d55049a | 1998-11-01 07:17:24 +0000 | [diff] [blame] | 144 | ## if SUNAUDIODEV was built on an older version of Solaris, the CD |
| 145 | ## input device won't exist |
| 146 | try: |
| 147 | btn = Radiobutton(frame, |
| 148 | text='CD', |
| 149 | variable=self.__inputvar, |
| 150 | value=CD, |
| 151 | command=self.__pushtodev, |
| 152 | underline=0) |
Barry Warsaw | 441abb4 | 1998-11-02 22:48:56 +0000 | [diff] [blame] | 153 | btn.grid(row=3, column=1, sticky=W) |
Barry Warsaw | d55049a | 1998-11-01 07:17:24 +0000 | [diff] [blame] | 154 | root.bind('<Alt-c>', self.__cd) |
| 155 | root.bind('<Alt-C>', self.__cd) |
| 156 | if not info.i_avail_ports & CD: |
| 157 | btn.configure(state=DISABLED) |
| 158 | buttons.append(btn) |
| 159 | except NameError: |
| 160 | pass |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 161 | # |
| 162 | # where does output go to? |
| 163 | frame = Frame(root, bd=1, relief=RAISED) |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 164 | frame.grid(row=2, column=0, sticky='NSEW') |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 165 | label = Label(frame, text='Output To:') |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 166 | label.grid(row=0, column=0, sticky=E) |
| 167 | self.__spkvar = IntVar() |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 168 | btn = Checkbutton(frame, |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 169 | text='Speaker', |
| 170 | variable=self.__spkvar, |
| 171 | onvalue=SPEAKER, |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 172 | command=self.__pushtodev, |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 173 | underline=0) |
| 174 | btn.grid(row=0, column=1, sticky=W) |
| 175 | root.bind('<Alt-s>', self.__speaker) |
| 176 | root.bind('<Alt-S>', self.__speaker) |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 177 | if not info.o_avail_ports & SPEAKER: |
| 178 | btn.configure(state=DISABLED) |
| 179 | buttons.append(btn) |
| 180 | ## |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 181 | self.__headvar = IntVar() |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 182 | btn = Checkbutton(frame, |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 183 | text='Headphones', |
| 184 | variable=self.__headvar, |
| 185 | onvalue=HEADPHONE, |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 186 | command=self.__pushtodev, |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 187 | underline=4) |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 188 | btn.grid(row=1, column=1, sticky=W) |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 189 | root.bind('<Alt-p>', self.__headphones) |
| 190 | root.bind('<Alt-P>', self.__headphones) |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 191 | if not info.o_avail_ports & HEADPHONE: |
| 192 | btn.configure(state=DISABLED) |
| 193 | buttons.append(btn) |
| 194 | ## |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 195 | self.__linevar = IntVar() |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 196 | btn = Checkbutton(frame, |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 197 | variable=self.__linevar, |
| 198 | onvalue=LINE_OUT, |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 199 | text='Line Out', |
| 200 | command=self.__pushtodev, |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 201 | underline=0) |
| 202 | btn.grid(row=2, column=1, sticky=W) |
| 203 | root.bind('<Alt-l>', self.__lineout) |
| 204 | root.bind('<Alt-L>', self.__lineout) |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 205 | if not info.o_avail_ports & LINE_OUT: |
| 206 | btn.configure(state=DISABLED) |
| 207 | buttons.append(btn) |
| 208 | # |
| 209 | # Fix up widths |
| 210 | widest = 0 |
| 211 | for b in buttons: |
| 212 | width = b['width'] |
| 213 | if width > widest: |
| 214 | widest = width |
| 215 | for b in buttons: |
| 216 | b.configure(width=widest) |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 217 | # root bindings |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 218 | root.bind('<Alt-q>', self.__quit) |
| 219 | root.bind('<Alt-Q>', self.__quit) |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 220 | # |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 221 | # Volume |
| 222 | frame = Frame(root, bd=1, relief=RAISED) |
| 223 | frame.grid(row=3, column=0, sticky='NSEW') |
| 224 | label = Label(frame, text='Output Volume:') |
| 225 | label.grid(row=0, column=0, sticky=W) |
| 226 | self.__scalevar = IntVar() |
| 227 | self.__scale = Scale(frame, |
| 228 | orient=HORIZONTAL, |
| 229 | from_=MIN_GAIN, |
| 230 | to=MAX_GAIN, |
| 231 | length=200, |
| 232 | variable=self.__scalevar, |
| 233 | command=self.__volume) |
| 234 | self.__scale.grid(row=1, column=0, sticky=EW) |
| 235 | # |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 236 | # do we need to poll for changes? |
| 237 | self.__needtopoll = 1 |
| 238 | try: |
| 239 | fd = self.__devctl.fileno() |
| 240 | self.__needtopoll = 0 |
| 241 | except AttributeError: |
| 242 | pass |
| 243 | else: |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 244 | import fcntl |
| 245 | import signal |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 246 | import STROPTS |
| 247 | # set up the signal handler |
| 248 | signal.signal(signal.SIGPOLL, self.__update) |
| 249 | fcntl.ioctl(fd, STROPTS.I_SETSIG, STROPTS.S_MSG) |
| 250 | self.__update() |
| 251 | |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 252 | def __quit(self, event=None): |
| 253 | self.__devctl.close() |
| 254 | self.__root.quit() |
| 255 | |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 256 | def __popup_about(self, event=None): |
| 257 | import tkMessageBox |
| 258 | tkMessageBox.showinfo('About Audiopy ' + __version__, |
| 259 | '''\ |
| 260 | Audiopy %s |
| 261 | Control the Solaris audio device |
| 262 | |
Barry Warsaw | 8860405 | 1998-12-14 21:36:40 +0000 | [diff] [blame] | 263 | For information |
| 264 | Contact: Barry A. Warsaw |
| 265 | Email: bwarsaw@python.org''' % __version__) |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 266 | |
| 267 | def __popup_using(self, event=None): |
| 268 | if not self.__helpwin: |
| 269 | self.__helpwin = Helpwin(self.__tkroot, self.__quit) |
| 270 | self.__helpwin.deiconify() |
| 271 | |
| 272 | |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 273 | def __keepalive(self): |
| 274 | # Exercise the Python interpreter regularly so keyboard interrupts get |
| 275 | # through. |
| 276 | self.__tkroot.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive) |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 277 | if self.__needtopoll: |
| 278 | self.__update() |
| 279 | |
| 280 | def __update(self, num=None, frame=None): |
Barry Warsaw | 772d696 | 1999-08-18 20:17:42 +0000 | [diff] [blame] | 281 | # It's possible (although I have never seen it) to get an interrupted |
| 282 | # system call during the getinfo() call. If so, and we're polling, |
| 283 | # don't sweat it because we'll come around again later. Otherwise, |
| 284 | # we'll give it a couple of tries and then give up until next time. |
| 285 | tries = 0 |
| 286 | while 1: |
| 287 | try: |
| 288 | info = self.__devctl.getinfo() |
| 289 | break |
| 290 | except sunaudiodev.error: |
| 291 | if self.__needtopoll or tries > 3: |
| 292 | return |
| 293 | tries = tries + 1 |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 294 | # input |
| 295 | self.__inputvar.set(info.i_port) |
| 296 | # output |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 297 | self.__spkvar.set(info.o_port & SPEAKER) |
| 298 | self.__headvar.set(info.o_port & HEADPHONE) |
| 299 | self.__linevar.set(info.o_port & LINE_OUT) |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 300 | # volume |
| 301 | self.__scalevar.set(info.o_gain) |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 302 | |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 303 | def __pushtodev(self, event=None): |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 304 | info = self.__devctl.getinfo() |
| 305 | info.o_port = self.__spkvar.get() + \ |
| 306 | self.__headvar.get() + \ |
| 307 | self.__linevar.get() |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 308 | info.i_port = self.__inputvar.get() |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 309 | info.o_gain = self.__scalevar.get() |
Barry Warsaw | bc9476e | 2000-03-29 21:05:53 +0000 | [diff] [blame] | 310 | try: |
| 311 | self.__devctl.setinfo(info) |
| 312 | except sunaudiodev.error, msg: |
| 313 | # TBD: what to do? it's probably temporary. |
| 314 | pass |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 315 | |
| 316 | def __getset(self, var, onvalue): |
Barry Warsaw | 441abb4 | 1998-11-02 22:48:56 +0000 | [diff] [blame] | 317 | if var.get() == onvalue: |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 318 | var.set(0) |
| 319 | else: |
| 320 | var.set(onvalue) |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 321 | self.__pushtodev() |
| 322 | |
Barry Warsaw | 441abb4 | 1998-11-02 22:48:56 +0000 | [diff] [blame] | 323 | def __none(self, event=None): |
| 324 | self.__inputvar.set(0) |
| 325 | self.__pushtodev() |
| 326 | |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 327 | def __mic(self, event=None): |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 328 | self.__getset(self.__inputvar, MICROPHONE) |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 329 | |
| 330 | def __linein(self, event=None): |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 331 | self.__getset(self.__inputvar, LINE_IN) |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 332 | |
| 333 | def __cd(self, event=None): |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 334 | self.__getset(self.__inputvar, CD) |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 335 | |
| 336 | def __speaker(self, event=None): |
| 337 | self.__getset(self.__spkvar, SPEAKER) |
| 338 | |
| 339 | def __headphones(self, event=None): |
| 340 | self.__getset(self.__headvar, HEADPHONE) |
| 341 | |
| 342 | def __lineout(self, event=None): |
| 343 | self.__getset(self.__linevar, LINE_OUT) |
| 344 | |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 345 | def __volume(self, event=None): |
| 346 | self.__pushtodev() |
| 347 | |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 348 | def start(self): |
| 349 | self.__keepalive() |
| 350 | self.__tkroot.mainloop() |
| 351 | |
| 352 | |
| 353 | |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 354 | class Helpwin: |
| 355 | def __init__(self, master, quitfunc): |
| 356 | from Tkinter import * |
| 357 | self.__root = root = Toplevel(master, class_='Audiopy') |
| 358 | root.protocol('WM_DELETE_WINDOW', self.__withdraw) |
| 359 | root.title('Audiopy Help Window') |
| 360 | root.iconname('Audiopy Help Window') |
| 361 | root.bind('<Alt-q>', quitfunc) |
| 362 | root.bind('<Alt-Q>', quitfunc) |
| 363 | root.bind('<Alt-w>', self.__withdraw) |
| 364 | root.bind('<Alt-W>', self.__withdraw) |
| 365 | |
| 366 | # more elaborate help is available in the README file |
| 367 | readmefile = os.path.join(sys.path[0], 'README') |
| 368 | try: |
| 369 | fp = None |
| 370 | try: |
| 371 | fp = open(readmefile) |
| 372 | contents = fp.read() |
| 373 | # wax the last page, it contains Emacs cruft |
Walter Dörwald | aaab30e | 2002-09-11 20:36:02 +0000 | [diff] [blame] | 374 | i = contents.rfind('\f') |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 375 | if i > 0: |
Walter Dörwald | aaab30e | 2002-09-11 20:36:02 +0000 | [diff] [blame] | 376 | contents = contents[:i].rstrip() |
Barry Warsaw | f622a33 | 1998-12-03 19:32:38 +0000 | [diff] [blame] | 377 | finally: |
| 378 | if fp: |
| 379 | fp.close() |
| 380 | except IOError: |
| 381 | sys.stderr.write("Couldn't open audiopy's README, " |
| 382 | 'using docstring instead.\n') |
| 383 | contents = __doc__ % globals() |
| 384 | |
| 385 | self.__text = text = Text(root, relief=SUNKEN, |
| 386 | width=80, height=24) |
| 387 | text.insert(0.0, contents) |
| 388 | scrollbar = Scrollbar(root) |
| 389 | scrollbar.pack(fill=Y, side=RIGHT) |
| 390 | text.pack(fill=BOTH, expand=YES) |
| 391 | text.configure(yscrollcommand=(scrollbar, 'set')) |
| 392 | scrollbar.configure(command=(text, 'yview')) |
| 393 | |
| 394 | def __withdraw(self, event=None): |
| 395 | self.__root.withdraw() |
| 396 | |
| 397 | def deiconify(self): |
| 398 | self.__root.deiconify() |
| 399 | |
| 400 | |
| 401 | |
| 402 | |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 403 | def usage(code, msg=''): |
Barry Warsaw | d81d534 | 1998-11-18 03:28:45 +0000 | [diff] [blame] | 404 | print __doc__ % globals() |
Barry Warsaw | 2858b43 | 1998-11-18 03:32:43 +0000 | [diff] [blame] | 405 | if msg: |
| 406 | print msg |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 407 | sys.exit(code) |
| 408 | |
| 409 | |
| 410 | def main(): |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 411 | # |
| 412 | # Open up the audio control device and query for the current output |
| 413 | # device |
| 414 | device = sunaudiodev.open('control') |
| 415 | |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 416 | if len(sys.argv) == 1: |
| 417 | # GUI |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 418 | w = MainWindow(device) |
Barry Warsaw | b7d1d63 | 1998-10-30 23:45:41 +0000 | [diff] [blame] | 419 | try: |
| 420 | w.start() |
| 421 | except KeyboardInterrupt: |
| 422 | pass |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 423 | return |
| 424 | |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 425 | # spec: LONG OPT, SHORT OPT, 0=input,1=output, MASK |
Barry Warsaw | d55049a | 1998-11-01 07:17:24 +0000 | [diff] [blame] | 426 | options = [('--microphone', '-m', 0, MICROPHONE), |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 427 | ('--linein', '-i', 0, LINE_IN), |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 428 | ('--headphones', '-p', 1, HEADPHONE), |
| 429 | ('--speaker', '-s', 1, SPEAKER), |
| 430 | ('--lineout', '-o', 1, LINE_OUT), |
Barry Warsaw | d55049a | 1998-11-01 07:17:24 +0000 | [diff] [blame] | 431 | ] |
| 432 | # See the comment above about `CD' |
| 433 | try: |
| 434 | options.append(('--cd', '-c', 0, CD)) |
| 435 | except NameError: |
| 436 | pass |
| 437 | |
Barry Warsaw | 2c8b35b | 1998-10-31 00:25:14 +0000 | [diff] [blame] | 438 | info = device.getinfo() |
| 439 | # first get the existing values |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 440 | i = 0 |
| 441 | while i < len(sys.argv)-1: |
| 442 | i = i + 1 |
| 443 | arg = sys.argv[i] |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 444 | if arg in ('-h', '--help'): |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 445 | usage(0) |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 446 | # does not return |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 447 | elif arg in ('-g', '--gain'): |
| 448 | gainspec = '<missing>' |
| 449 | try: |
| 450 | gainspec = sys.argv[i+1] |
| 451 | gain = int(gainspec) |
| 452 | except (ValueError, IndexError): |
| 453 | usage(1, 'Bad gain specification: ' + gainspec) |
| 454 | info.o_gain = gain |
| 455 | i = i + 1 |
| 456 | continue |
Barry Warsaw | 3febc24 | 1998-11-01 07:10:51 +0000 | [diff] [blame] | 457 | elif arg in ('-v', '--version'): |
Barry Warsaw | d81d534 | 1998-11-18 03:28:45 +0000 | [diff] [blame] | 458 | print '''\ |
| 459 | audiopy -- a program to control the Solaris audio device. |
Barry Warsaw | 8860405 | 1998-12-14 21:36:40 +0000 | [diff] [blame] | 460 | Contact: Barry Warsaw |
Barry Warsaw | d81d534 | 1998-11-18 03:28:45 +0000 | [diff] [blame] | 461 | Email: bwarsaw@python.org |
| 462 | Version: %s''' % __version__ |
Barry Warsaw | 3febc24 | 1998-11-01 07:10:51 +0000 | [diff] [blame] | 463 | sys.exit(0) |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 464 | for long, short, io, mask in options: |
| 465 | if arg in (long, short): |
| 466 | # toggle the option |
| 467 | if io == 0: |
| 468 | info.i_port = info.i_port ^ mask |
| 469 | else: |
| 470 | info.o_port = info.o_port ^ mask |
| 471 | break |
| 472 | val = None |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 473 | try: |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 474 | if arg[:len(long)+1] == long+'=': |
| 475 | val = int(arg[len(long)+1:]) |
| 476 | elif arg[:len(short)+1] == short+'=': |
| 477 | val = int(arg[len(short)+1:]) |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 478 | except ValueError: |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 479 | usage(1, msg='Invalid option: ' + arg) |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 480 | # does not return |
| 481 | if val == 0: |
| 482 | if io == 0: |
| 483 | info.i_port = info.i_port & ~mask |
| 484 | else: |
| 485 | info.o_port = info.o_port & ~mask |
| 486 | break |
| 487 | elif val == 1: |
| 488 | if io == 0: |
| 489 | info.i_port = info.i_port | mask |
| 490 | else: |
| 491 | info.o_port = info.o_port | mask |
| 492 | break |
| 493 | # else keep trying next option |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 494 | else: |
Barry Warsaw | a4b055f | 1999-04-28 19:32:46 +0000 | [diff] [blame] | 495 | usage(1, msg='Invalid option: ' + arg) |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 496 | # now set the values |
Barry Warsaw | d8d179d | 1999-09-22 15:45:51 +0000 | [diff] [blame] | 497 | try: |
| 498 | device.setinfo(info) |
| 499 | except sunaudiodev.error, (code, msg): |
Barry Warsaw | c4eb6a6 | 1999-10-07 20:00:01 +0000 | [diff] [blame] | 500 | if code <> errno.EINVAL: |
| 501 | raise |
Barry Warsaw | e77ec17 | 1998-11-01 07:03:55 +0000 | [diff] [blame] | 502 | device.close() |
Barry Warsaw | 2a06084 | 1998-10-30 18:21:52 +0000 | [diff] [blame] | 503 | |
| 504 | |
| 505 | |
| 506 | if __name__ == '__main__': |
| 507 | main() |