audiopy revision 2c8b35bdd25b0946d4ea35e74a1e20ccd4679325
12a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw#! /usr/bin/env python 22a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 32a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw"""Program to control the Solaris audio device. 42a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 52a06084ed51d06cdea9544b5ab02586d300dec83Barry WarsawWhen no arguments are given, this pops up a graphical window which lets you 62a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawchoose which audio output device you want sound to go to. 72a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 82a06084ed51d06cdea9544b5ab02586d300dec83Barry WarsawThis program can be driven via the command line, and when done so, no window 92c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsawpops up. Options have the general form: 102a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 112c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw --device[={0,1}] 122c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw -d[={0,1}] 132c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw Set the I/O device. With no value, it toggles the specified device. 142c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw With a value, 0 turns the device off and 1 turns the device on. 152a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 162c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry WarsawThe list of devices and their short options are: 172a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 182c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw (input) 192c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw microphone -- m 202c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw linein -- i 212c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw cd -- c 222c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw 232c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw (output) 242c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw headphones -- p 252c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw speaker -- s 262c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw lineout -- o 272c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw 282c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry WarsawOther options are: 292a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 302a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw --help 312a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw -h 322a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw Print this message and exit. 332a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 342a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw""" 352a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 362a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawimport sys 372a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawfrom Tkinter import * 382a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawimport sunaudiodev 392a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawfrom SUNAUDIODEV import * 402a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 412a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw# Milliseconds between interrupt checks 422a06084ed51d06cdea9544b5ab02586d300dec83Barry WarsawKEEPALIVE_TIMER = 500 432a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 442a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 452a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 462a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawclass MainWindow: 472c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw def __init__(self, device): 482c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw self.__devctl = device 492c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw info = device.getinfo() 502c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw # 512a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__tkroot = tkroot = Tk(className='Pynche') 522a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw tkroot.withdraw() 532a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # now create the top level window 542c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw root = self.__root = Toplevel(tkroot, class_='Audiopy') 552a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw root.protocol('WM_DELETE_WINDOW', self.__quit) 562a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw root.title('Audiopy') 572a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw root.iconname('Audiopy') 582a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw root.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive) 592a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # 602c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw buttons = [] 612a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # 62b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw # where does input come from? 63b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw frame = Frame(root, bd=1, relief=RAISED) 64b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw frame.grid(row=0, column=0) 65b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw label = Label(frame, text='Input From:') 66b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw label.grid(row=0, column=0, sticky=E) 67b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__micvar = IntVar() 68b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw btn = Checkbutton(frame, 69b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw text='Microphone', 70b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw variable=self.__micvar, 71b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw onvalue=MICROPHONE, 72b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw command=self.__pushtodev, 73b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw underline=0) 74b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw btn.grid(row=0, column=1, sticky=W) 75b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw root.bind('<Alt-m>', self.__mic) 76b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw root.bind('<Alt-M>', self.__mic) 772c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw if not info.i_avail_ports & MICROPHONE: 782c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw btn.configure(state=DISABLED) 792c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw buttons.append(btn) 802c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw ## 81b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__lineinvar = IntVar() 82b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw btn = Checkbutton(frame, 83b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw text='Line In', 84b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw variable=self.__lineinvar, 85b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw onvalue=LINE_IN, 86b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw command=self.__pushtodev, 87b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw underline=5) 88b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw btn.grid(row=1, column=1, sticky=W) 89b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw root.bind('<Alt-i>', self.__linein) 90b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw root.bind('<Alt-I>', self.__linein) 912c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw if not info.i_avail_ports & LINE_IN: 922c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw btn.configure(state=DISABLED) 932c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw buttons.append(btn) 942c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw ## 95b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__cdvar = IntVar() 96b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw btn = Checkbutton(frame, 97b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw text='CD', 98b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw variable=self.__cdvar, 99b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw onvalue=CD, 100b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw command=self.__pushtodev, 101b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw underline=0) 102b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw btn.grid(row=2, column=1, sticky=W) 103b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw root.bind('<Alt-c>', self.__cd) 104b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw root.bind('<Alt-C>', self.__cd) 1052c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw if not info.i_avail_ports & CD: 1062c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw btn.configure(state=DISABLED) 1072c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw buttons.append(btn) 108b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw # 109b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw # where does output go to? 110b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw frame = Frame(root, bd=1, relief=RAISED) 111b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw frame.grid(row=1, column=0) 112b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw label = Label(frame, text='Output To:') 1132a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw label.grid(row=0, column=0, sticky=E) 1142a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__spkvar = IntVar() 115b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw btn = Checkbutton(frame, 1162a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw text='Speaker', 1172a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw variable=self.__spkvar, 1182a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw onvalue=SPEAKER, 119b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw command=self.__pushtodev, 1202a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw underline=0) 1212a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw btn.grid(row=0, column=1, sticky=W) 1222a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw root.bind('<Alt-s>', self.__speaker) 1232a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw root.bind('<Alt-S>', self.__speaker) 1242c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw if not info.o_avail_ports & SPEAKER: 1252c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw btn.configure(state=DISABLED) 1262c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw buttons.append(btn) 1272c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw ## 1282a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__headvar = IntVar() 129b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw btn = Checkbutton(frame, 1302a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw text='Headphones', 1312a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw variable=self.__headvar, 1322a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw onvalue=HEADPHONE, 133b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw command=self.__pushtodev, 1342a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw underline=0) 1352a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw btn.grid(row=1, column=1, sticky=W) 1362a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw root.bind('<Alt-h>', self.__headphones) 1372a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw root.bind('<Alt-H>', self.__headphones) 1382c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw if not info.o_avail_ports & HEADPHONE: 1392c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw btn.configure(state=DISABLED) 1402c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw buttons.append(btn) 1412c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw ## 1422a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__linevar = IntVar() 143b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw btn = Checkbutton(frame, 1442a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw variable=self.__linevar, 1452a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw onvalue=LINE_OUT, 146b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw text='Line Out', 147b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw command=self.__pushtodev, 1482a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw underline=0) 1492a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw btn.grid(row=2, column=1, sticky=W) 1502a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw root.bind('<Alt-l>', self.__lineout) 1512a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw root.bind('<Alt-L>', self.__lineout) 1522c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw if not info.o_avail_ports & LINE_OUT: 1532c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw btn.configure(state=DISABLED) 1542c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw buttons.append(btn) 1552c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw # 1562c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw # Fix up widths 1572c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw widest = 0 1582c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw for b in buttons: 1592c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw width = b['width'] 1602c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw if width > widest: 1612c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw widest = width 1622c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw for b in buttons: 1632c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw b.configure(width=widest) 1642c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw # 1652c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw # Add quit button 1662c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw frame = Frame(root) 1672c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw frame.grid(row=2, column=0, sticky='EW', ipady=5) 1682c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw btn = Button(frame, 1692c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw text='Quit', 1702c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw command=self.__quit, 1712c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw underline=0) 1722c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw btn.pack(expand=YES) 1732c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw root.bind('<Alt-q>', self.__quit) 1742c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw root.bind('<Alt-Q>', self.__quit) 175b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw # 176b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw # do we need to poll for changes? 177b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__needtopoll = 1 178b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw try: 179b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw fd = self.__devctl.fileno() 180b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__needtopoll = 0 181b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw except AttributeError: 182b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw pass 183b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw else: 184b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw import struct 185b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw import fcntl 186b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw import signal 187b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw import FCNTL 188b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw import STROPTS 189b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw # set up the signal handler 190b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw signal.signal(signal.SIGPOLL, self.__update) 191b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw fcntl.ioctl(fd, STROPTS.I_SETSIG, STROPTS.S_MSG) 192b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__update() 193b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw 1942a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw def __quit(self, event=None): 1952a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__devctl.close() 1962a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__root.quit() 1972a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 1982a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw def __keepalive(self): 1992a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # Exercise the Python interpreter regularly so keyboard interrupts get 2002a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # through. 2012a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__tkroot.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive) 202b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw if self.__needtopoll: 203b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__update() 204b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw 205b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw def __update(self, num=None, frame=None): 2062a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # We have to poll because the device could have changed state and the 2072a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # underlying module does not support the SIGPOLL notification 2082a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # interface. 2092a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw info = self.__devctl.getinfo() 2102a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__spkvar.set(info.o_port & SPEAKER) 2112a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__headvar.set(info.o_port & HEADPHONE) 2122a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__linevar.set(info.o_port & LINE_OUT) 213b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__micvar.set(info.i_port & MICROPHONE) 214b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__lineinvar.set(info.i_port & LINE_IN) 215b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__cdvar.set(info.i_port & CD) 2162a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 217b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw def __pushtodev(self, event=None): 2182a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw info = self.__devctl.getinfo() 2192a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw info.o_port = self.__spkvar.get() + \ 2202a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__headvar.get() + \ 2212a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__linevar.get() 222b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw info.i_port = self.__micvar.get() + \ 223b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__lineinvar.get() + \ 224b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__cdvar.get() 2252a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__devctl.setinfo(info) 2262a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2272a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw def __getset(self, var, onvalue): 2282a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if var.get(): 2292a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw var.set(0) 2302a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 2312a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw var.set(onvalue) 232b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__pushtodev() 233b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw 234b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw def __mic(self, event=None): 235b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__getset(self.__micvar, MICROPHONE) 236b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw 237b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw def __linein(self, event=None): 238b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__getset(self.__lineinvar, LINE_IN) 239b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw 240b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw def __cd(self, event=None): 2412c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw print 'pre:', self.__cdvar.get() 242b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw self.__getset(self.__cdvar, CD) 2432c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw print 'post:', self.__cdvar.get() 2442a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2452a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw def __speaker(self, event=None): 2462a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__getset(self.__spkvar, SPEAKER) 2472a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2482a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw def __headphones(self, event=None): 2492a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__getset(self.__headvar, HEADPHONE) 2502a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2512a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw def __lineout(self, event=None): 2522a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__getset(self.__linevar, LINE_OUT) 2532a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2542a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw def start(self): 2552a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__keepalive() 2562a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw self.__tkroot.mainloop() 2572a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2582a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2592a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2602a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawdef usage(msg='', code=1): 2612a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw print __doc__ 2622a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw print msg 2632a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw sys.exit(code) 2642a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2652a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2662a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawdef main(): 2672c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw # 2682c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw # Open up the audio control device and query for the current output 2692c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw # device 2702c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw device = sunaudiodev.open('control') 2712c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw 2722a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if len(sys.argv) == 1: 2732a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # GUI 2742c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw w = MainWindow(device) 275b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw try: 276b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw w.start() 277b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw except KeyboardInterrupt: 278b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw pass 2792a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw return 2802a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 2812c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw # spec: LONG OPT, SHORT OPT, 0=input,1=output, MASK 2822c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw options = (('--microphone', '-m', 0, MICROPHONE), 2832c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw ('--linein', '-i', 0, LINE_IN), 2842c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw ('--cd', '-c', 0, CD), 2852c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw ('--headphones', '-p', 1, HEADPHONE), 2862c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw ('--speaker', '-s', 1, SPEAKER), 2872c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw ('--lineout', '-o', 1, LINE_OUT), 2882c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw ) 2892c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw values = [] 2902c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw info = device.getinfo() 2912c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw # first get the existing values 2922c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw for long, short, io, mask in options: 2932c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw if io == 0: 2942c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw flags = info.i_port 2952c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw else: 2962c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw flags = info.o_port 2972c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw values.append(flags & mask) 2982c8b35bdd25b0946d4ea35e74a1e20ccd4679325Barry Warsaw 2992a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw sval = None 3002a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw hval = None 3012a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw lval = None 3022a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw for arg in sys.argv[1:]: 3032a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if arg in ('-h', '--help'): 3042a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw usage(code=0) 3052a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # SPEAKER 3062a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw elif arg in ('-s', '--speaker'): 3072a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw sval = -1 3082a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw elif arg[:3] == '-s=': 3092a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw try: 3102a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw sval = int(arg[3:]) 3112a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw except ValueError: 3122a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw pass 3132a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if sval <> 0 and sval <> 1: 3142a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw usage('Invalid option: ' + arg) 3152a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw elif arg[:10] == '--speaker=': 3162a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw try: 3172a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw sval = int(arg[10:]) 3182a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw except ValueError: 3192a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw pass 3202a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if sval <> 0 and sval <> 1: 3212a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw usage('Invalid option: ' + arg) 3222a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # HEADPHONES 3232a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw elif arg in ('-p', '--headphones'): 3242a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw hval = -1 3252a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw elif arg[:3] == '-p=': 3262a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw try: 3272a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw hval = int(arg[3:]) 3282a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw except ValueError: 3292a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw pass 3302a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if hval <> 0 and hval <> 1: 3312a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw usage('Invalid option: ' + arg) 3322a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw elif arg[:13] == '--headphones=': 3332a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw try: 3342a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw hval = int(arg[130:]) 3352a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw except ValueError: 3362a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw pass 3372a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if hval <> 0 and hval <> 1: 3382a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw usage('Invalid option: ' + arg) 3392a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # LINEOUT 3402a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw elif arg in ('-l', '--lineout'): 3412a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw lval = -1 3422a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw elif arg[:3] == '-l=': 3432a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw try: 3442a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw lval = int(arg[3:]) 3452a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw except ValueError: 3462a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw pass 3472a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if lval <> 0 and lval <> 1: 3482a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw usage('Invalid option: ' + arg) 3492a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw elif arg[:10] == '--lineout=': 3502a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw try: 3512a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw lval = int(arg[10:]) 3522a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw except ValueError: 3532a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw pass 3542a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if lval <> 0 and lval <> 1: 3552a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw usage('Invalid option: ' + arg) 3562a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 3572a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw usage('Invalid option: ' + arg) 3582a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw # now set the values 3592a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw try: 3602a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw devctl = sunaudiodev.open('control') 3612a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw info = devctl.getinfo() 3622a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if sval is not None: 3632a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if sval == -1: 3642a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if info.o_port & SPEAKER: 3652a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw sval = 0 3662a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 3672a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw sval = SPEAKER 3682a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 3692a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw sval = sval * SPEAKER 3702a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 3712a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw sval = info.o_port & SPEAKER 3722a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if hval is not None: 3732a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if hval == -1: 3742a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if info.o_port & HEADPHONE: 3752a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw hval = 0 3762a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 3772a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw hval = HEADPHONE 3782a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 3792a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw hval = hval * HEADPHONE 3802a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 3812a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw hval = info.o_port & HEADPHONE 3822a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if lval is not None: 3832a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if lval == -1: 3842a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw if info.o_port & LINE_OUT: 3852a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw lval = 0 3862a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 3872a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw lval = LINE_OUT 3882a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 3892a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw lval = lval * LINE_OUT 3902a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw else: 3912a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw lval = info.o_port & LINE_OUT 3922a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw info.o_port = sval + hval + lval 3932a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw devctl.setinfo(info) 3942a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw finally: 3952a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw devctl.close() 3962a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 3972a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 3982a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw 3992a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawif __name__ == '__main__': 4002a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw main() 401