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