blob: 3e6d88ab6aa0a387133e44fc41f15593e8b26d66 [file] [log] [blame]
#! /usr/bin/env python
"""Program to control the Solaris audio device.
When no arguments are given, this pops up a graphical window which lets you
choose which audio output device you want sound to go to.
This program can be driven via the command line, and when done so, no window
pops up. Here are the options:
--headphones[={0,1}]
-p[={0,1}]
Set the headphones output device. With no value, it toggles the
headphone device. With a value, 0 turns the headphones off and 1
turns the headphones on.
--speaker[={0,1}]
-s[={0,1}]
Set the speaker output device. Value semantics are the same as
above.
--lineout[={0,1}]
-l[={0,1}]
Set the line out output device. Value semantics are the same as
above.
--help
-h
Print this message and exit.
"""
import sys
from Tkinter import *
import sunaudiodev
from SUNAUDIODEV import *
# Milliseconds between interrupt checks
KEEPALIVE_TIMER = 500
class MainWindow:
def __init__(self):
self.__tkroot = tkroot = Tk(className='Pynche')
tkroot.withdraw()
# create the menubar
menubar = Menu(tkroot)
#
# File menu
#
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label='Quit',
command=self.__quit,
accelerator='Alt-Q',
underline=0)
#
# Tie them together
#
menubar.add_cascade(label='File',
menu=filemenu,
underline=0)
# now create the top level window
root = self.__root = Toplevel(tkroot, class_='Audiopy', menu=menubar)
root.protocol('WM_DELETE_WINDOW', self.__quit)
root.title('Audiopy')
root.iconname('Audiopy')
root.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
root.bind('<Alt-q>', self.__quit)
root.bind('<Alt-Q>', self.__quit)
#
# Open up the audio control device and query for the current output
# device
self.__devctl = sunaudiodev.open('control')
info = self.__devctl.getinfo()
#
# create the speaker/headphone radio button
label = Label(root, text='Output to:')
label.grid(row=0, column=0, sticky=E)
self.__spkvar = IntVar()
btn = Checkbutton(root,
text='Speaker',
variable=self.__spkvar,
onvalue=SPEAKER,
command=self.__outputto,
underline=0)
btn.grid(row=0, column=1, sticky=W)
root.bind('<Alt-s>', self.__speaker)
root.bind('<Alt-S>', self.__speaker)
self.__headvar = IntVar()
btn = Checkbutton(root,
text='Headphones',
variable=self.__headvar,
onvalue=HEADPHONE,
command=self.__outputto,
underline=0)
btn.grid(row=1, column=1, sticky=W)
root.bind('<Alt-h>', self.__headphones)
root.bind('<Alt-H>', self.__headphones)
self.__linevar = IntVar()
btn = Checkbutton(root,
variable=self.__linevar,
onvalue=LINE_OUT,
text='Line out',
command=self.__outputto,
underline=0)
btn.grid(row=2, column=1, sticky=W)
root.bind('<Alt-l>', self.__lineout)
root.bind('<Alt-L>', self.__lineout)
def __quit(self, event=None):
self.__devctl.close()
self.__root.quit()
def __keepalive(self):
# Exercise the Python interpreter regularly so keyboard interrupts get
# through.
self.__tkroot.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
#
# We have to poll because the device could have changed state and the
# underlying module does not support the SIGPOLL notification
# interface.
info = self.__devctl.getinfo()
self.__spkvar.set(info.o_port & SPEAKER)
self.__headvar.set(info.o_port & HEADPHONE)
self.__linevar.set(info.o_port & LINE_OUT)
def __outputto(self, event=None):
info = self.__devctl.getinfo()
info.o_port = self.__spkvar.get() + \
self.__headvar.get() + \
self.__linevar.get()
self.__devctl.setinfo(info)
def __getset(self, var, onvalue):
if var.get():
var.set(0)
else:
var.set(onvalue)
self.__outputto()
def __speaker(self, event=None):
self.__getset(self.__spkvar, SPEAKER)
def __headphones(self, event=None):
self.__getset(self.__headvar, HEADPHONE)
def __lineout(self, event=None):
self.__getset(self.__linevar, LINE_OUT)
def start(self):
self.__keepalive()
self.__tkroot.mainloop()
def usage(msg='', code=1):
print __doc__
print msg
sys.exit(code)
def main():
if len(sys.argv) == 1:
# GUI
w = MainWindow()
w.start()
return
# command line
sval = None
hval = None
lval = None
for arg in sys.argv[1:]:
if arg in ('-h', '--help'):
usage(code=0)
# SPEAKER
elif arg in ('-s', '--speaker'):
sval = -1
elif arg[:3] == '-s=':
try:
sval = int(arg[3:])
except ValueError:
pass
if sval <> 0 and sval <> 1:
usage('Invalid option: ' + arg)
elif arg[:10] == '--speaker=':
try:
sval = int(arg[10:])
except ValueError:
pass
if sval <> 0 and sval <> 1:
usage('Invalid option: ' + arg)
# HEADPHONES
elif arg in ('-p', '--headphones'):
hval = -1
elif arg[:3] == '-p=':
try:
hval = int(arg[3:])
except ValueError:
pass
if hval <> 0 and hval <> 1:
usage('Invalid option: ' + arg)
elif arg[:13] == '--headphones=':
try:
hval = int(arg[130:])
except ValueError:
pass
if hval <> 0 and hval <> 1:
usage('Invalid option: ' + arg)
# LINEOUT
elif arg in ('-l', '--lineout'):
lval = -1
elif arg[:3] == '-l=':
try:
lval = int(arg[3:])
except ValueError:
pass
if lval <> 0 and lval <> 1:
usage('Invalid option: ' + arg)
elif arg[:10] == '--lineout=':
try:
lval = int(arg[10:])
except ValueError:
pass
if lval <> 0 and lval <> 1:
usage('Invalid option: ' + arg)
else:
usage('Invalid option: ' + arg)
# now set the values
try:
devctl = sunaudiodev.open('control')
info = devctl.getinfo()
if sval is not None:
if sval == -1:
if info.o_port & SPEAKER:
sval = 0
else:
sval = SPEAKER
else:
sval = sval * SPEAKER
else:
sval = info.o_port & SPEAKER
if hval is not None:
if hval == -1:
if info.o_port & HEADPHONE:
hval = 0
else:
hval = HEADPHONE
else:
hval = hval * HEADPHONE
else:
hval = info.o_port & HEADPHONE
if lval is not None:
if lval == -1:
if info.o_port & LINE_OUT:
lval = 0
else:
lval = LINE_OUT
else:
lval = lval * LINE_OUT
else:
lval = info.o_port & LINE_OUT
info.o_port = sval + hval + lval
devctl.setinfo(info)
finally:
devctl.close()
if __name__ == '__main__':
main()