audiopy revision b7d1d63f00603acda29741e369c327f048571aed
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
92a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawpops up.  Here are the options:
102a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
112a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    --headphones[={0,1}]
122a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    -p[={0,1}]
132a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        Set the headphones output device.  With no value, it toggles the
142a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        headphone device.  With a value, 0 turns the headphones off and 1
152a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        turns the headphones on.
162a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
172a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    --speaker[={0,1}]
182a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    -s[={0,1}]
192a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        Set the speaker output device.  Value semantics are the same as
202a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        above.
212a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
222a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    --lineout[={0,1}]
232a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    -l[={0,1}]
242a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        Set the line out output device.  Value semantics are the same as
252a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        above.
262a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
272a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    --help
282a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    -h
292a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        Print this message and exit.
302a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
312a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw"""
322a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
332a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawimport sys
342a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawfrom Tkinter import *
352a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawimport sunaudiodev
362a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawfrom SUNAUDIODEV import *
372a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
382a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw# Milliseconds between interrupt checks
392a06084ed51d06cdea9544b5ab02586d300dec83Barry WarsawKEEPALIVE_TIMER = 500
402a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
412a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
422a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
432a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawclass MainWindow:
442a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    def __init__(self):
452a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__tkroot = tkroot = Tk(className='Pynche')
462a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        tkroot.withdraw()
472a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # create the menubar
482a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        menubar = Menu(tkroot)
492a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        #
502a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # File menu
512a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        #
522a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        filemenu = Menu(menubar, tearoff=0)
532a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        filemenu.add_command(label='Quit',
542a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                             command=self.__quit,
552a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                             accelerator='Alt-Q',
562a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                             underline=0)
572a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        #
582a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # Tie them together
592a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        #
602a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        menubar.add_cascade(label='File',
612a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                            menu=filemenu,
622a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                            underline=0)
632a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # now create the top level window
642a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root = self.__root = Toplevel(tkroot, class_='Audiopy', menu=menubar)
652a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root.protocol('WM_DELETE_WINDOW', self.__quit)
662a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root.title('Audiopy')
672a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root.iconname('Audiopy')
682a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
692a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root.bind('<Alt-q>', self.__quit)
702a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root.bind('<Alt-Q>', self.__quit)
712a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        #
722a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # Open up the audio control device and query for the current output
732a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # device
742a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__devctl = sunaudiodev.open('control')
752a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        info = self.__devctl.getinfo()
762a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        #
77b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        # where does input come from?
78b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        frame = Frame(root, bd=1, relief=RAISED)
79b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        frame.grid(row=0, column=0)
80b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        label = Label(frame, text='Input From:')
81b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        label.grid(row=0, column=0, sticky=E)
82b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__micvar = IntVar()
83b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        btn = Checkbutton(frame,
84b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          text='Microphone',
85b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          variable=self.__micvar,
86b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          onvalue=MICROPHONE,
87b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          command=self.__pushtodev,
88b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          underline=0)
89b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        btn.grid(row=0, column=1, sticky=W)
90b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        root.bind('<Alt-m>', self.__mic)
91b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        root.bind('<Alt-M>', self.__mic)
92b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__lineinvar = IntVar()
93b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        btn = Checkbutton(frame,
94b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          text='Line In',
95b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          variable=self.__lineinvar,
96b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          onvalue=LINE_IN,
97b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          command=self.__pushtodev,
98b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          underline=5)
99b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        btn.grid(row=1, column=1, sticky=W)
100b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        root.bind('<Alt-i>', self.__linein)
101b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        root.bind('<Alt-I>', self.__linein)
102b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__cdvar = IntVar()
103b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        btn = Checkbutton(frame,
104b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          text='CD',
105b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          variable=self.__cdvar,
106b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          onvalue=CD,
107b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          command=self.__pushtodev,
108b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          underline=0)
109b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        btn.grid(row=2, column=1, sticky=W)
110b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        root.bind('<Alt-c>', self.__cd)
111b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        root.bind('<Alt-C>', self.__cd)
112b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        #
113b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        # where does output go to?
114b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        frame = Frame(root, bd=1, relief=RAISED)
115b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        frame.grid(row=1, column=0)
116b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        label = Label(frame, text='Output To:')
1172a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        label.grid(row=0, column=0, sticky=E)
1182a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__spkvar = IntVar()
119b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        btn = Checkbutton(frame,
1202a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                          text='Speaker',
1212a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                          variable=self.__spkvar,
1222a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                          onvalue=SPEAKER,
123b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          command=self.__pushtodev,
1242a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                          underline=0)
1252a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        btn.grid(row=0, column=1, sticky=W)
1262a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root.bind('<Alt-s>', self.__speaker)
1272a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root.bind('<Alt-S>', self.__speaker)
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)
1382a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__linevar = IntVar()
139b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        btn = Checkbutton(frame,
1402a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                          variable=self.__linevar,
1412a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                          onvalue=LINE_OUT,
142b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          text='Line Out',
143b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                          command=self.__pushtodev,
1442a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                          underline=0)
1452a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        btn.grid(row=2, column=1, sticky=W)
1462a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root.bind('<Alt-l>', self.__lineout)
1472a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        root.bind('<Alt-L>', self.__lineout)
148b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        #
149b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        # do we need to poll for changes?
150b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__needtopoll = 1
151b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        try:
152b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            fd = self.__devctl.fileno()
153b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            self.__needtopoll = 0
154b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        except AttributeError:
155b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            pass
156b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        else:
157b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            import struct
158b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            import fcntl
159b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            import signal
160b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            import FCNTL
161b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            import STROPTS
162b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            # set up the signal handler
163b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            signal.signal(signal.SIGPOLL, self.__update)
164b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            fcntl.ioctl(fd, STROPTS.I_SETSIG, STROPTS.S_MSG)
165b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            self.__update()
166b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        
1672a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    def __quit(self, event=None):
1682a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__devctl.close()
1692a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__root.quit()
1702a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
1712a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    def __keepalive(self):
1722a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # Exercise the Python interpreter regularly so keyboard interrupts get
1732a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # through.
1742a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__tkroot.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
175b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        if self.__needtopoll:
176b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            self.__update()
177b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw
178b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw    def __update(self, num=None, frame=None):
1792a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # We have to poll because the device could have changed state and the
1802a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # underlying module does not support the SIGPOLL notification
1812a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # interface.
1822a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        info = self.__devctl.getinfo()
1832a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__spkvar.set(info.o_port & SPEAKER)
1842a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__headvar.set(info.o_port & HEADPHONE)
1852a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__linevar.set(info.o_port & LINE_OUT)
186b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__micvar.set(info.i_port & MICROPHONE)
187b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__lineinvar.set(info.i_port & LINE_IN)
188b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__cdvar.set(info.i_port & CD)
1892a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
190b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw    def __pushtodev(self, event=None):
1912a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        info = self.__devctl.getinfo()
1922a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        info.o_port = self.__spkvar.get() + \
1932a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                      self.__headvar.get() + \
1942a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                      self.__linevar.get()
195b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        info.i_port = self.__micvar.get() + \
196b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                      self.__lineinvar.get() + \
197b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw                      self.__cdvar.get()
1982a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__devctl.setinfo(info)
1992a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2002a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    def __getset(self, var, onvalue):
2012a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        if var.get():
2022a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            var.set(0)
2032a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        else:
2042a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            var.set(onvalue)
205b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__pushtodev()
206b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw
207b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw    def __mic(self, event=None):
208b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__getset(self.__micvar, MICROPHONE)
209b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw
210b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw    def __linein(self, event=None):
211b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__getset(self.__lineinvar, LINE_IN)
212b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw
213b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw    def __cd(self, event=None):
214b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        self.__getset(self.__cdvar, CD)
2152a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2162a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    def __speaker(self, event=None):
2172a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__getset(self.__spkvar, SPEAKER)
2182a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2192a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    def __headphones(self, event=None):
2202a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__getset(self.__headvar, HEADPHONE)
2212a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2222a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    def __lineout(self, event=None):
2232a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__getset(self.__linevar, LINE_OUT)
2242a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2252a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    def start(self):
2262a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__keepalive()
2272a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        self.__tkroot.mainloop()
2282a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2292a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2302a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2312a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawdef usage(msg='', code=1):
2322a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    print __doc__
2332a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    print msg
2342a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    sys.exit(code)
2352a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2362a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2372a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawdef main():
2382a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    if len(sys.argv) == 1:
2392a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # GUI
2402a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        w = MainWindow()
241b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        try:
242b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            w.start()
243b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw        except KeyboardInterrupt:
244b7d1d63f00603acda29741e369c327f048571aedBarry Warsaw            pass
2452a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        return
2462a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
2472a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    # command line
2482a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    sval = None
2492a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    hval = None
2502a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    lval = None
2512a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    for arg in sys.argv[1:]:
2522a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        if arg in ('-h', '--help'):
2532a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            usage(code=0)
2542a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # SPEAKER
2552a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        elif arg in ('-s', '--speaker'):
2562a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            sval = -1
2572a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        elif arg[:3] == '-s=':
2582a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            try:
2592a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                sval = int(arg[3:])
2602a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            except ValueError:
2612a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                pass
2622a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            if sval <> 0 and sval <> 1:
2632a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                usage('Invalid option: ' + arg)
2642a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        elif arg[:10] == '--speaker=':
2652a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            try:
2662a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                sval = int(arg[10:])
2672a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            except ValueError:
2682a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                pass
2692a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            if sval <> 0 and sval <> 1:
2702a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                usage('Invalid option: ' + arg)
2712a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # HEADPHONES
2722a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        elif arg in ('-p', '--headphones'):
2732a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            hval = -1
2742a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        elif arg[:3] == '-p=':
2752a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            try:
2762a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                hval = int(arg[3:])
2772a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            except ValueError:
2782a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                pass
2792a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            if hval <> 0 and hval <> 1:
2802a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                usage('Invalid option: ' + arg)
2812a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        elif arg[:13] == '--headphones=':
2822a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            try:
2832a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                hval = int(arg[130:])
2842a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            except ValueError:
2852a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                pass
2862a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            if hval <> 0 and hval <> 1:
2872a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                usage('Invalid option: ' + arg)
2882a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        # LINEOUT
2892a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        elif arg in ('-l', '--lineout'):
2902a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            lval = -1
2912a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        elif arg[:3] == '-l=':
2922a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            try:
2932a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                lval = int(arg[3:])
2942a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            except ValueError:
2952a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                pass
2962a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            if lval <> 0 and lval <> 1:
2972a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                usage('Invalid option: ' + arg)
2982a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        elif arg[:10] == '--lineout=':
2992a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            try:
3002a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                lval = int(arg[10:])
3012a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            except ValueError:
3022a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                pass
3032a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            if lval <> 0 and lval <> 1:
3042a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                usage('Invalid option: ' + arg)
3052a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        else:
3062a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            usage('Invalid option: ' + arg)
3072a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    # now set the values
3082a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    try:
3092a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        devctl = sunaudiodev.open('control')
3102a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        info = devctl.getinfo()
3112a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        if sval is not None:
3122a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            if sval == -1:
3132a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                if info.o_port & SPEAKER:
3142a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                    sval = 0
3152a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                else:
3162a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                    sval = SPEAKER
3172a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            else:
3182a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                sval = sval * SPEAKER
3192a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        else:
3202a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            sval = info.o_port & SPEAKER
3212a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        if hval is not None:
3222a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            if hval == -1:
3232a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                if info.o_port & HEADPHONE:
3242a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                    hval = 0
3252a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                else:
3262a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                    hval = HEADPHONE
3272a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            else:
3282a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                hval = hval * HEADPHONE
3292a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        else:
3302a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            hval = info.o_port & HEADPHONE
3312a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        if lval is not None:
3322a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            if lval == -1:
3332a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                if info.o_port & LINE_OUT:
3342a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                    lval = 0
3352a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                else:
3362a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                    lval = LINE_OUT
3372a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            else:
3382a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw                lval = lval * LINE_OUT
3392a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        else:
3402a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            lval = info.o_port & LINE_OUT
3412a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        info.o_port = sval + hval + lval
3422a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        devctl.setinfo(info)
3432a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    finally:
3442a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw        devctl.close()
3452a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw            
3462a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
3472a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw
3482a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsawif __name__ == '__main__':
3492a06084ed51d06cdea9544b5ab02586d300dec83Barry Warsaw    main()
350