pyalsa-1.0.26/0000755000000000000000000000000012022061452013021 5ustar rootroot00000000000000pyalsa-1.0.26/test/0000755000000000000000000000000012022061452014000 5ustar rootroot00000000000000pyalsa-1.0.26/test/seqtest2.py0000664000000000000000000000277512022053131016134 0ustar rootroot00000000000000#! /usr/bin/python # Sample code for pyalsa Sequencer binding # by Aldrin Martoq # version 2008012401 (UTC: 1201153962 secs since the epoch) # # This code is in the public domain, # use it as base for creating your pyalsa # sequencer application. import sys sys.path.insert(0, '../pyalsa') import alsaseq import time from alsamemdebug import debuginit, debug, debugdone debuginit() seq = alsaseq.Sequencer() def dump(event): print "event: %s" % event print " ", for attr in alsaseq.SeqEvent.__dict__: if attr.startswith('is_'): t = event.__getattribute__(attr) if t: print "%s" % attr, print data = event.get_data() print " data=%s" % data print "sequencer: %s" % seq port_id = seq.create_simple_port('hola', alsaseq.SEQ_PORT_TYPE_APPLICATION, alsaseq.SEQ_PORT_CAP_SUBS_READ | alsaseq.SEQ_PORT_CAP_READ | alsaseq.SEQ_PORT_CAP_WRITE | alsaseq.SEQ_PORT_CAP_SUBS_WRITE ) print "portid: %d" % port_id c=-2 wait = 5000 while True: if c == -1: src = (alsaseq.SEQ_CLIENT_SYSTEM,alsaseq.SEQ_PORT_SYSTEM_ANNOUNCE) dest = (seq.client_id, port_id) print 'connecting %s -> %s' % (src, dest) seq.connect_ports(src, dest) if c == 5: break print 'waiting %s...' % wait events = seq.receive_events(wait) for event in events: c = 0 dump(event) del event c += 1 debug([seq]) debugdone() pyalsa-1.0.26/test/hctltest2.py0000775000000000000000000000361612022053131016274 0ustar rootroot00000000000000#! /usr/bin/python # -*- Python -*- import sys sys.path.insert(0, '../pyalsa') del sys import select import alsahcontrol def parse_event_mask(events): if events == 0: return 'None' if events == alsahcontrol.event_mask_remove: return 'Removed' s = '' for i in alsahcontrol.event_mask.keys(): if events & alsahcontrol.event_mask[i]: s += '%s ' % i return s[:-1] def event_callback(element, events): info = alsahcontrol.Info(element) value = alsahcontrol.Value(element) print 'CALLBACK (DEF)! [%s] %s:%i' % (parse_event_mask(events), element.name, element.index) print ' ', value.get_tuple(info.type, info.count) class MyElementEvent: def callback(self, element, events): info = alsahcontrol.Info(element) value = alsahcontrol.Value(element) print 'CALLBACK (CLASS)! [%s] %s:%i' % (parse_event_mask(events), element.name, element.index) print ' ', value.get_tuple(info.type, info.count) hctl = alsahcontrol.HControl(mode=alsahcontrol.open_mode['NONBLOCK']) list = hctl.list() element1 = alsahcontrol.Element(hctl, list[0][1:]) element1.set_callback(event_callback) element2 = alsahcontrol.Element(hctl, list[1][1:]) element2.set_callback(MyElementEvent()) nelementid = (alsahcontrol.interface_id['MIXER'], 0, 0, "Z Test Volume", 1) try: hctl.element_remove(nelementid) except IOError: pass hctl.element_new(alsahcontrol.element_type['INTEGER'], nelementid, 2, 0, 100, 1) hctl.element_unlock(nelementid) # handleEvents() must be here to update internal alsa-lib's element list hctl.handle_events() element3 = alsahcontrol.Element(hctl, nelementid) element3.set_callback(event_callback) print 'Watching (DEF): %s,%i' % (element1.name, element1.index) print 'Watching (CLASS): %s,%i' % (element2.name, element2.index) print 'Watching (DEF): %s,%i' % (element3.name, element3.index) poller = select.poll() hctl.register_poll(poller) while True: poller.poll() print 'Poll OK!' hctl.handle_events() pyalsa-1.0.26/test/seqtest3.py0000664000000000000000000000353112022053131016124 0ustar rootroot00000000000000#! /usr/bin/python # Sample code for pyalsa Sequencer binding # by Aldrin Martoq # version 2008012401 (UTC: 1201153962 secs since the epoch) # # This code is in the public domain, # use it as base for creating your pyalsa # sequencer application. import sys sys.path.insert(0, '../pyalsa') from alsaseq import * import time from alsamemdebug import debuginit, debug, debugdone debuginit() def findmidiport(): for connections in seq.connection_list(): cname, cid, ports = connections # skip midi through if cname == 'Midi Through': continue for port in ports: pname, pid, pconns = port pinfo = seq.get_port_info(pid, cid) type = pinfo['type'] caps = pinfo['capability'] if type & SEQ_PORT_TYPE_MIDI_GENERIC and caps & (SEQ_PORT_CAP_WRITE): print "Using port: %s:%s" % (cname, pname) return (cid, pid) print "No midi port found -- install timidity or other software synth for testing!" sys.exit(0) # create sequencer seq = Sequencer() # find midi port cid, pid = findmidiport() # create a queue queue = seq.create_queue() seq.start_queue(queue) tempo, ppq = seq.queue_tempo(queue) print "tempo: %d ppq: %d" % (tempo, ppq) # play notes: DO RE MI FA SOL LA notes = [0x40, 0x42, 0x44, 0x45, 0x47, 0x49] event = SeqEvent(SEQ_EVENT_NOTE) for note in notes: event.dest = (cid, pid) event.queue = queue event.time += ppq event.set_data({'note.note' : note, 'note.velocity' : 64, 'note.duration' : ppq , 'note.off_velocity' : 64}) print 'event: %s %s' % (event, event.get_data()) seq.output_event(event) seq.drain_output() seq.sync_output_queue() # stop queue and delete queue seq.stop_queue(queue) seq.delete_queue(queue) debug([seq]) # close sequencer del seq debugdone() pyalsa-1.0.26/test/hctltest1.py0000775000000000000000000000350212022053131016265 0ustar rootroot00000000000000#! /usr/bin/python # -*- Python -*- import sys sys.path.insert(0, '../pyalsa') del sys import alsahcontrol def info(element): info = alsahcontrol.Info(element) enumerated = alsahcontrol.element_type['ENUMERATED'] integer = alsahcontrol.element_type['INTEGER'] integer64 = alsahcontrol.element_type['INTEGER64'] for a in dir(info): if a.startswith('__'): continue if a in ['items', 'item_names'] and info.type != enumerated: continue if a in ['min', 'max', 'step'] and info.type != integer: continue if a in ['min64', 'max64', 'step64'] and info.type != integer64: continue extra = '' if a == 'type': extra = ' (%s)' % alsahcontrol.element_type_name[info.type] print ' %s: %s%s' % (a, getattr(info, a), extra) def value(element): info = alsahcontrol.Info(element) value = alsahcontrol.Value(element) for a in dir(value): if a.startswith('__'): continue print ' %s: %s' % (a, getattr(value, a)) values = value.get_tuple(info.type, info.count) print ' Values: ', values value.set_tuple(info.type, values) value.read() if info.is_writable: value.write() print 'interface_id:' print ' ', alsahcontrol.interface_id print 'interface_name:' print ' ', alsahcontrol.interface_name print 'element_type:' print ' ', alsahcontrol.element_type print 'element_type_name:' print ' ', alsahcontrol.element_type_name print 'event_class:' print ' ', alsahcontrol.event_class print 'event_mask:' print ' ', alsahcontrol.event_mask print 'event_mask_remove:', alsahcontrol.event_mask_remove print ' ', alsahcontrol.open_mode print 'event_mask_remove:', alsahcontrol.open_mode hctl = alsahcontrol.HControl() print 'Count: ', hctl.count list = hctl.list() print 'List:' print list for l in list: print '*****' element1 = alsahcontrol.Element(hctl, l[1:]) info(element1) print '-----' value(element1) del hctl pyalsa-1.0.26/test/alsamemdebug.py0000664000000000000000000000072712022053131017003 0ustar rootroot00000000000000#! /usr/bin/python # -*- Python -*- import sys import gc def debuginit(): gc.set_debug(gc.DEBUG_LEAK | gc.DEBUG_STATS) print "GC DEBUG: init." def debug(what): from sys import getrefcount from gc import get_referrers for o in what: if getrefcount(o) - 3 != 1 or \ len(get_referrers(o)) - 2 != 1: print 'GD DEBUG LEAK:', o, hex(id(o)), type(o), getrefcount(o)-3, len(get_referrers(o))-2 def debugdone(): gc.collect() print "GC DEBUG LEAK done." None pyalsa-1.0.26/test/seqtest1.py0000664000000000000000000001374312022053131016130 0ustar rootroot00000000000000#! /usr/bin/python # Sample code for pyalsa Sequencer binding # by Aldrin Martoq # version 2008012401 (UTC: 1201153962 secs since the epoch) # # This code is in the public domain, # use it as base for creating your pyalsa # sequencer application. import sys sys.path.insert(0, '../pyalsa') del sys from alsamemdebug import debuginit, debug, debugdone import alsaseq def dump_portinfo(dict): def dl(dict, key): if dict.has_key(key): return "'" + str(dict[key]) + "'" return "N/A" def da(dict, key, search): tmp = None if dict.has_key(key): for k in search: if k & dict[key]: if tmp == None: tmp = str(search[k]) else: tmp += " " + str(search[k]) if tmp == None: tmp = "UNKNOWN(%d)" % (dict[key]) else: tmp = "N/A" return tmp return "name=%s capability=%s type=%s" % (dl(dict, 'name'), da(dict, 'capability', alsaseq._dportcap), da(dict, 'type', alsaseq._dporttype)) def dump_list(connections, simple=True): for clientports in connections: clientname, clientid, portlist = clientports print " client: %3d %s" % (clientid, clientname), if not simple: clientinfo = sequencer.get_client_info(clientid) print "\t[%s]" % clientinfo else: print for port in portlist: portname, portid, connections = port print " port: %3d:%-2d +-%s" % (clientid, portid, portname), if not simple: portinfo = sequencer.get_port_info(portid, clientid) print "\t[%s]" % (dump_portinfo(portinfo)) else: print readconn, writeconn = connections for c,p,i in readconn: if not simple: print " connection to: %d:%d %s" % (c,p, i) else: print " connection to: %d:%d" % (c,p) for c,p,i in writeconn: if not simple: print " connection to: %d:%d %s" % (c,p, i) else: print " connection to: %d:%d" % (c,p) debuginit() print "01:Creating Sequencer ==============================" sequencer = alsaseq.Sequencer() # other examples: # sequencer = alsaseq.Sequencer("hw", "myfancyapplication", alsaseq.SEQ_OPEN_INPUT, alsaseq.SEQ_BLOCK) # sequencer = alsaseq.Sequencer(clientname='python-test', streams=alsaseq.SEQ_OPEN_OUTPUT) print " sequencer: %s" % sequencer print " name: %s" % sequencer.name print " clientname: %s" % sequencer.clientname print " streams: %d (%s)" % (sequencer.streams, str(sequencer.streams)) print " mode: %d (%s)" % (sequencer.mode, str(sequencer.mode)) print " client_id: %s" % sequencer.client_id print print "02:Changing some parameters ========================" sequencer.clientname = 'pepito' sequencer.mode = alsaseq.SEQ_BLOCK print " clientname: %s" % sequencer.clientname print " mode: %d (%s)" % (sequencer.mode, str(sequencer.mode)) print print "03:Creating simple port ============================" port_id = sequencer.create_simple_port("myport", alsaseq.SEQ_PORT_TYPE_APPLICATION,alsaseq.SEQ_PORT_CAP_WRITE | alsaseq.SEQ_PORT_CAP_SUBS_WRITE) print " port_id: %s" % port_id print print "04:Getting port info ===============================" port_info = sequencer.get_port_info(port_id) print " --> %s" % dump_portinfo(port_info) print " --> %s" % port_info print print "05:Retrieving clients and connections (as list) ====" connections = sequencer.connection_list() print " %s" % (connections) print print "06:Retrieving clients and connections (detailed) ===" connections = sequencer.connection_list() dump_list(connections, False) print print "07:Connecting 'arbitrary' ports... =================" source = (alsaseq.SEQ_CLIENT_SYSTEM, alsaseq.SEQ_PORT_SYSTEM_ANNOUNCE) dest = (sequencer.client_id, port_id) print "%s ---> %s" % (str(source), str(dest)) sequencer.connect_ports(source, dest) print print "08:Retrieving clients and connections (simple) =====" connections = sequencer.connection_list() dump_list(connections) print print "09:Disconnecting previous 'arbitrary' port =========" print "%s -X-> %s" % (str(source), str(dest)) sequencer.disconnect_ports(source, dest) print print "10:Retrieving clients and connections (simple) =====" connections = sequencer.connection_list() dump_list(connections) print print "11:Listing known streams constants =================" print "%s" % alsaseq._dstreams.values() print print "12:Listing known mode constants ====================" print "%s" % alsaseq._dmode.values() print print "13:Listing known queue constants ===================" print "%s" % alsaseq._dqueue.values() print print "14:Listing known client type constants =============" print "%s" % alsaseq._dclienttype.values() print print "15:Listing known port caps constants ===============" print "%s" % alsaseq._dportcap.values() print print "16:Listing known port types constants ==============" print "%s" % alsaseq._dporttype.values() print print "17:Listing known event type constants ==============" print "%s" % alsaseq._deventtype.values() print print "18:Listing known event timestamp constants =========" print "%s" % alsaseq._deventtimestamp.values() print print "19:Listing known event timemode constants ==========" print "%s" % alsaseq._deventtimemode.values() print print "20:Listing known client addresses constants ========" print "%s" % alsaseq._dclient.values() print print "21:Listing known port addresses constants ==========" print "%s" % alsaseq._dport.values() print print "98:Removing sequencer ==============================" debug([sequencer]) del sequencer print print "99:Listing sequencer (using new one) ===============" dump_list(alsaseq.Sequencer().connection_list()) print debugdone() print "seqtest1.py done." pyalsa-1.0.26/test/ctltest1.py0000775000000000000000000000074712022053131016125 0ustar rootroot00000000000000#! /usr/bin/python # -*- Python -*- import sys sys.path.insert(0, '../pyalsa') del sys import alsacontrol ctl = alsacontrol.Control() print 'Card info:', ctl.card_info() try: print 'Hwdep devices:', ctl.hwdep_devices() except IOError, msg: print 'No hwdep devices:', msg try: print 'PCM devices:', ctl.pcm_devices() except IOError, msg: print 'No PCM devices:', msg try: print 'Rawmidi devices:', ctl.rawmidi_devices() except IOError, msg: print 'No rawmidi devices:', msg pyalsa-1.0.26/test/mixertest1.py0000775000000000000000000000506112022053131016461 0ustar rootroot00000000000000#! /usr/bin/python # -*- Python -*- import sys sys.path.insert(0, '../pyalsa') del sys from alsamemdebug import debuginit, debug, debugdone import alsamixer def print_elem(e): direction = ["playback", "capture"] print "Mixer Element '%s:%i':" % (e.name, e.index) print ' is_active: %s' % e.is_active print ' is_enumerated: %s' % e.is_enumerated print ' has_common_volume: %s' % e.has_common_volume print ' has_common_switch: %s' % e.has_common_switch print ' has_capture_switch_exclusive: %s' % e.has_capture_switch_exclusive if e.has_switch(True): print ' getCaptureGroup: %s' % e.get_capture_group for capture in [False, True]: print ' is_%s_mono: %s' % (direction[capture], e.is_mono(capture)) print ' has_%s_volume: %s' % (direction[capture], e.has_volume(capture)) if e.has_volume(capture): print ' get_%s_volume_range: %s' % (direction[capture], e.get_volume_range(capture)) print ' get_%s_volume_range_dB: %s' % (direction[capture], e.get_volume_range_dB(capture)) print ' get_%s_volume_tuple: %s' % (direction[capture], e.get_volume_tuple(capture)) print ' get_%s_volume_array: %s' % (direction[capture], e.get_volume_array(capture)) vrange = e.get_volume_range(capture) if vrange: for vol in range(vrange[0], vrange[1]+1): print ' vol %i == %idB' % (vol, e.ask_volume_dB(vol, capture)) dbrange = e.get_volume_range_dB(capture) if dbrange: for vol in range(dbrange[0], dbrange[1]+1): print ' dBvol %i == %i' % (vol, e.ask_dB_volume(vol, -1, capture)) print ' has_%s_switch: %s' % (direction[capture], e.has_switch(capture)) if e.has_switch(capture): print ' get_%s_switch_tuple: %s' % (direction[capture], e.get_switch_tuple(capture)) for channel in range(alsamixer.channel_id['LAST']+1): if e.has_channel(channel, capture): print ' has_%s_channel%s: %s' % (direction[capture], channel, alsamixer.channel_name[channel]) debuginit() print 'channel_id:' print alsamixer.channel_id print 'channel_name:' print alsamixer.channel_name print 'regopt_abstracts:' print alsamixer.regopt_abstract print 'event_mask:' print alsamixer.event_mask print 'event_mask_remove:', alsamixer.event_mask_remove mixer = alsamixer.Mixer() mixer.attach() mixer.load() print 'Element Count:', mixer.count print 'Elements:' print mixer.list() element = alsamixer.Element(mixer, "PCM") element.set_volume_array([128, 128]) print_elem(element) element.set_volume_tuple([127, 127]) print_elem(element) print_elem(alsamixer.Element(mixer, "Off-hook")) debug([element]) del element debug([mixer]) del mixer debugdone() pyalsa-1.0.26/test/cardtest1.py0000775000000000000000000000070012022053131016241 0ustar rootroot00000000000000#! /usr/bin/python # -*- Python -*- import sys sys.path.insert(0, '../pyalsa') del sys import alsacard print 'asoundlibVersion:', alsacard.asoundlib_version() print 'cardLoad:', alsacard.card_load(0) print 'cardList:', alsacard.card_list() print 'deviceNameHint for all cards:' print alsacard.device_name_hint(-1, "pcm") for card in alsacard.card_list(): print 'deviceNameHint for card #%i:' % card print alsacard.device_name_hint(card, "pcm") pyalsa-1.0.26/test/mixertest2.py0000775000000000000000000000216112022053131016460 0ustar rootroot00000000000000#! /usr/bin/python # -*- Python -*- import sys sys.path.insert(0, '../pyalsa') del sys import alsamixer import select def parse_event_mask(events): if events == 0: return 'None' if events == alsamixer.event_mask_remove: return 'Removed' s = '' for i in alsamixer.event_mask.keys(): if events & alsamixer.event_mask[i]: s += '%s ' % i return s[:-1] def event_callback(element, events): print 'CALLBACK (DEF)! [%s] %s:%i' % (parse_event_mask(events), element.name, element.index) print ' ', element.get_volume_tuple(), element.get_switch_tuple() class MyElementEvent: def callback(self, element, events): print 'CALLBACK (CLASS)! [%s] %s:%i' % (parse_event_mask(events), element.name, element.index) print ' ', element.get_volume_tuple(), element.get_switch_tuple() mixer = alsamixer.Mixer() mixer.attach() mixer.load() element1 = alsamixer.Element(mixer, "Front") element1.set_callback(event_callback) element2 = alsamixer.Element(mixer, "PCM") element2.set_callback(MyElementEvent()) poller = select.poll() mixer.register_poll(poller) while True: poller.poll() print 'Poll OK!' mixer.handle_events() pyalsa-1.0.26/pyalsa/0000755000000000000000000000000012022061452014312 5ustar rootroot00000000000000pyalsa-1.0.26/pyalsa/alsacard.c0000664000000000000000000001412712022053131016232 0ustar rootroot00000000000000/* * Python binding for the ALSA library - card management * Copyright (c) 2007 by Jaroslav Kysela * * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "Python.h" #include "structmember.h" #include "frameobject.h" #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif #include "sys/poll.h" #include "stdlib.h" #include "alsa/asoundlib.h" #ifndef Py_RETURN_NONE #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None #endif #ifndef Py_RETURN_TRUE #define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True #endif #ifndef Py_RETURN_FALSE #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False #endif static PyObject *module; /* * */ PyDoc_STRVAR(asoundlib_version__doc__, "asoundlib_version() -- Return asoundlib version string."); static PyObject * asoundlib_version(PyObject *self, PyObject *args) { return Py_BuildValue("s", snd_asoundlib_version()); } PyDoc_STRVAR(card_load__doc__, "card_load([card]) -- Load driver for given card."); static PyObject * card_load(PyObject *self, PyObject *args, PyObject *kwds) { int card = 0; static char * kwlist[] = { "card", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &card)) Py_RETURN_NONE; return Py_BuildValue("i", snd_card_load(card)); } PyDoc_STRVAR(card_list__doc__, "card_list() -- Get a card number list in tuple."); static PyObject * card_list(PyObject *self, PyObject *args) { PyObject *t; int size = 0, i = -1, res; t = PyTuple_New(0); if (!t) return NULL; while (1) { res = snd_card_next(&i); if (res) { Py_DECREF(t); return PyErr_Format(PyExc_IOError, "Cannot get next card: %s", snd_strerror(res)); } if (i < 0) break; size++; if (_PyTuple_Resize(&t, size)) return NULL; PyTuple_SET_ITEM(t, size - 1, PyInt_FromLong(i)); } return t; } PyDoc_STRVAR(card_get_index__doc__, "card_get_index(name) -- Get card index using ID string."); static PyObject * card_get_index(PyObject *self, PyObject *args, PyObject *kwds) { char *card; static char * kwlist[] = { "name", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &card)) Py_RETURN_NONE; return Py_BuildValue("i", snd_card_get_index(card)); } PyDoc_STRVAR(card_get_name__doc__, "card_get_name(card) -- Get card name string using card index."); static PyObject * card_get_name(PyObject *self, PyObject *args, PyObject *kwds) { int card, res; char *str; static char * kwlist[] = { "card", NULL }; PyObject *t; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &card)) Py_RETURN_NONE; res = snd_card_get_name(card, &str); if (res) return PyErr_Format(PyExc_IOError, "Cannot get card name: %s", snd_strerror(res)); t = Py_BuildValue("s", str); free(str); return t; } PyDoc_STRVAR(card_get_longname__doc__, "card_get_longname(card) -- Get long card name string using card index."); static PyObject * card_get_longname(PyObject *self, PyObject *args, PyObject *kwds) { int card, res; char *str; static char * kwlist[] = { "card", NULL }; PyObject *t; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &card)) Py_RETURN_NONE; res = snd_card_get_longname(card, &str); if (res) return PyErr_Format(PyExc_IOError, "Cannot get card longname: %s", snd_strerror(res)); t = Py_BuildValue("s", str); free(str); return t; } PyDoc_STRVAR(device_name_hint__doc__, "device_name_hint(card, interface) -- Get device name hints."); static PyObject * device_name_hint(PyObject *self, PyObject *args, PyObject *kwds) { int card, res; char *iface, **hint; void **hints; static char * kwlist[] = { "card", "interface", NULL }; static char * ids[] = { "NAME", "DESC", "IOID", NULL }; PyObject *l, *d, *v; char **id, *str; if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, &card, &iface)) Py_RETURN_NONE; res = snd_device_name_hint(card, iface, &hints); if (res) return PyErr_Format(PyExc_IOError, "Cannot get card longname: %s", snd_strerror(res)); l = PyList_New(0); hint = (char **)hints; while (*hint) { d = PyDict_New(); if (d == NULL) goto err1; id = ids; while (*id) { str = snd_device_name_get_hint(*hint, *id); if (str == NULL) break; v = PyString_FromString(str); free(str); if (v == NULL) goto err1; if (PyDict_SetItemString(d, *id, v)) goto err1; id++; } if (PyList_Append(l, d)) goto err1; hint++; } snd_device_name_free_hint(hints); return l; err1: Py_XDECREF(d); Py_XDECREF(l); snd_device_name_free_hint(hints); return NULL; } /* * */ static PyMethodDef pyalsacardparse_methods[] = { {"asoundlib_version", (PyCFunction)asoundlib_version, METH_NOARGS, asoundlib_version__doc__}, {"card_load", (PyCFunction)card_load, METH_VARARGS|METH_KEYWORDS, card_load__doc__}, {"card_list", (PyCFunction)card_list, METH_NOARGS, card_list__doc__}, {"card_get_index", (PyCFunction)card_get_index, METH_VARARGS|METH_KEYWORDS, card_get_index__doc__}, {"card_get_name", (PyCFunction)card_get_name, METH_VARARGS|METH_KEYWORDS, card_get_name__doc__}, {"card_get_longname", (PyCFunction)card_get_longname, METH_VARARGS|METH_KEYWORDS, card_get_longname__doc__}, {"device_name_hint", (PyCFunction)device_name_hint, METH_VARARGS|METH_KEYWORDS, device_name_hint__doc__}, {NULL} }; PyMODINIT_FUNC initalsacard(void) { module = Py_InitModule3("alsacard", pyalsacardparse_methods, "libasound alsacard wrapper"); if (module == NULL) return; if (PyErr_Occurred()) Py_FatalError("Cannot initialize module alsacard"); } pyalsa-1.0.26/pyalsa/alsacontrol.c0000664000000000000000000001712612022053131017003 0ustar rootroot00000000000000/* * Python binding for the ALSA library - Universal Control Layer * Copyright (c) 2007 by Jaroslav Kysela * * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "Python.h" #include "structmember.h" #include "frameobject.h" #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif #include "stdlib.h" #include "alsa/asoundlib.h" #ifndef Py_RETURN_NONE #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None #endif #ifndef Py_RETURN_TRUE #define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True #endif #ifndef Py_RETURN_FALSE #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False #endif static PyObject *module; #if 0 static PyObject *buildin; #endif /* * */ #define PYCTL(v) (((v) == Py_None) ? NULL : \ ((struct pyalsacontrol *)(v))) struct pyalsacontrol { PyObject_HEAD snd_ctl_t *handle; }; static inline PyObject *get_bool(int val) { if (val) { Py_INCREF(Py_True); return Py_True; } else { Py_INCREF(Py_False); return Py_False; } } PyDoc_STRVAR(cardinfo__doc__, "card_info() -- Return a dictionary with card specific information."); static PyObject * pyalsacontrol_cardinfo(struct pyalsacontrol *self, PyObject *args) { snd_ctl_card_info_t *info; PyObject *d; snd_ctl_card_info_alloca(&info); int err = snd_ctl_card_info(self->handle, info); if (err < 0) { PyErr_Format(PyExc_IOError, "Control card info error: %s", strerror(-err)); return NULL; } d = PyDict_New(); if (d) { PyDict_SetItem(d, PyString_FromString("card"), PyInt_FromLong(snd_ctl_card_info_get_card(info))); PyDict_SetItem(d, PyString_FromString("id"), PyString_FromString(snd_ctl_card_info_get_id(info))); PyDict_SetItem(d, PyString_FromString("driver"), PyString_FromString(snd_ctl_card_info_get_driver(info))); PyDict_SetItem(d, PyString_FromString("name"), PyString_FromString(snd_ctl_card_info_get_driver(info))); PyDict_SetItem(d, PyString_FromString("longname"), PyString_FromString(snd_ctl_card_info_get_longname(info))); PyDict_SetItem(d, PyString_FromString("mixername"), PyString_FromString(snd_ctl_card_info_get_mixername(info))); PyDict_SetItem(d, PyString_FromString("components"), PyString_FromString(snd_ctl_card_info_get_components(info))); } return d; } static PyObject * devices(struct pyalsacontrol *self, PyObject *args, int (*fcn)(snd_ctl_t *, int *)) { int dev, err, size = 0; PyObject *t; dev = -1; t = PyTuple_New(size); do { err = fcn(self->handle, &dev); if (err < 0) { PyErr_Format(PyExc_IOError, "Control hwdep_next_device error: %s", strerror(-err)); Py_DECREF(t); return NULL; } if (dev >= 0) { _PyTuple_Resize(&t, ++size); if (t) PyTuple_SetItem(t, size-1, PyInt_FromLong(dev)); } } while (dev >= 0); return t; } PyDoc_STRVAR(hwdepdevices__doc__, "hwdep_devices() -- Return a tuple with available hwdep devices."); static PyObject * pyalsacontrol_hwdepdevices(struct pyalsacontrol *self, PyObject *args) { return devices(self, args, snd_ctl_hwdep_next_device); } PyDoc_STRVAR(pcmdevices__doc__, "pcm_devices() -- Return a tuple with available PCM devices."); static PyObject * pyalsacontrol_pcmdevices(struct pyalsacontrol *self, PyObject *args) { return devices(self, args, snd_ctl_pcm_next_device); } PyDoc_STRVAR(rawmididevices__doc__, "rawmidi_devices() -- Return a tuple with available RawMidi devices."); static PyObject * pyalsacontrol_rawmididevices(struct pyalsacontrol *self, PyObject *args) { return devices(self, args, snd_ctl_rawmidi_next_device); } PyDoc_STRVAR(alsacontrolinit__doc__, "Control([name='default'],[mode=0])\n" " -- Open an ALSA Control device.\n"); static int pyalsacontrol_init(struct pyalsacontrol *pyctl, PyObject *args, PyObject *kwds) { char *name = "default"; int mode = 0, err; static char * kwlist[] = { "name", "mode", NULL }; pyctl->handle = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|si", kwlist, &name, &mode)) return -1; err = snd_ctl_open(&pyctl->handle, name, mode); if (err < 0) { PyErr_Format(PyExc_IOError, "Control open error: %s", strerror(-err)); return -1; } return 0; } static void pyalsacontrol_dealloc(struct pyalsacontrol *self) { if (self->handle != NULL) snd_ctl_close(self->handle); self->ob_type->tp_free(self); } static PyGetSetDef pyalsacontrol_getseters[] = { {NULL} }; static PyMethodDef pyalsacontrol_methods[] = { {"card_info", (PyCFunction)pyalsacontrol_cardinfo, METH_NOARGS, cardinfo__doc__}, {"hwdep_devices",(PyCFunction)pyalsacontrol_hwdepdevices, METH_NOARGS, hwdepdevices__doc__}, {"pcm_devices", (PyCFunction)pyalsacontrol_pcmdevices, METH_NOARGS, pcmdevices__doc__}, {"rawmidi_devices",(PyCFunction)pyalsacontrol_rawmididevices, METH_NOARGS, rawmididevices__doc__}, {NULL} }; static PyTypeObject pyalsacontrol_type = { PyObject_HEAD_INIT(0) tp_name: "alsacontrol.Control", tp_basicsize: sizeof(struct pyalsacontrol), tp_dealloc: (destructor)pyalsacontrol_dealloc, tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, tp_doc: alsacontrolinit__doc__, tp_getset: pyalsacontrol_getseters, tp_init: (initproc)pyalsacontrol_init, tp_alloc: PyType_GenericAlloc, tp_new: PyType_GenericNew, tp_free: PyObject_Del, tp_methods: pyalsacontrol_methods, }; /* * */ static PyMethodDef pyalsacontrolparse_methods[] = { {NULL} }; PyMODINIT_FUNC initalsacontrol(void) { PyObject *d, *d1, *l1, *o; int i; if (PyType_Ready(&pyalsacontrol_type) < 0) return; module = Py_InitModule3("alsacontrol", pyalsacontrolparse_methods, "libasound control wrapper"); if (module == NULL) return; #if 0 buildin = PyImport_AddModule("__buildin__"); if (buildin == NULL) return; if (PyObject_SetAttrString(module, "__buildins__", buildin) < 0) return; #endif Py_INCREF(&pyalsacontrol_type); PyModule_AddObject(module, "Control", (PyObject *)&pyalsacontrol_type); d = PyModule_GetDict(module); /* ---- */ d1 = PyDict_New(); #define add_space1(pname, name) { \ o = PyInt_FromLong(SND_CTL_ELEM_IFACE_##name); \ PyDict_SetItemString(d1, pname, o); \ Py_DECREF(o); } add_space1("CARD", CARD); add_space1("HWDEP", HWDEP); add_space1("MIXER", MIXER); add_space1("PCM", PCM); add_space1("RAWMIDI", RAWMIDI); add_space1("TIMER", TIMER); add_space1("SEQUENCER", SEQUENCER); add_space1("LAST", LAST); PyDict_SetItemString(d, "interface_id", d1); Py_DECREF(d1); /* ---- */ l1 = PyList_New(0); for (i = 0; i <= SND_CTL_ELEM_IFACE_LAST; i++) { o = PyString_FromString(snd_ctl_elem_iface_name(i)); PyList_Append(l1, o); Py_DECREF(o); } PyDict_SetItemString(d, "interface_name", l1); Py_DECREF(l1); /* ---- */ d1 = PyDict_New(); #define add_space5(pname, name) { \ o = PyInt_FromLong(SND_CTL_##name); \ PyDict_SetItemString(d1, pname, o); \ Py_DECREF(o); } add_space5("NONBLOCK", NONBLOCK); add_space5("ASYNC", ASYNC); add_space5("READONLY", READONLY); PyDict_SetItemString(d, "open_mode", d1); Py_DECREF(d1); /* ---- */ if (PyErr_Occurred()) Py_FatalError("Cannot initialize module alsacontrol"); } pyalsa-1.0.26/pyalsa/__init__.py0000664000000000000000000000000012022053131016406 0ustar rootroot00000000000000pyalsa-1.0.26/pyalsa/alsaseq.c0000664000000000000000000032222112022053131016106 0ustar rootroot00000000000000/* * Python binding for the ALSA library - sequencer * Copyright (c) 2008 by Aldrin Martoq * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "Python.h" #include #include ////////////////////////////////////////////////////////////////////////////// // some helper #define go here... ////////////////////////////////////////////////////////////////////////////// /* temporal debug (will be deleted in last patch, promise!) */ #if 1 #define ddebug(x, args...) fprintf(stderr, x "\n",##args); #else #define ddebug(x, args...) #endif /* checks if passed argument is an integer and can't be deleted. returns -1 if fails and raises TypeError or AttributeError. */ #define SETCHECKPYINT(attr, val) \ if (val == NULL) { \ PyErr_SetString(PyExc_AttributeError, \ "attribute " attr " can't be deleted!"); \ return -1; \ } \ if (!PyInt_Check(val)) { \ PyErr_SetString(PyExc_TypeError, \ "integer value expected for " attr); \ return -1; \ } /* checks if passed argument is a string and can't be deleted. returns -1 if fails and raises TypeError or AttributeError. */ #define SETCHECKPYSTR(attr, val) \ if (val == NULL) { \ PyErr_SetString(PyExc_AttributeError, \ "attribute " attr " can't be deleted!"); \ return -1; \ } \ if (!PyString_Check(val)) { \ PyErr_SetString(PyExc_TypeError, \ "string value expected for " attr); \ return -1; \ } /* checks if passed argument is a list and can't be deleted. returns -1 if fails and raises TypeError or AttributeError. */ #define SETCHECKPYLIST(attr, val) \ if (val == NULL) { \ PyErr_SetString(PyExc_AttributeError, \ "attribute " attr " can't be deleted!"); \ return -1; \ } \ if (!PyList_Check(val)) { \ PyErr_SetString(PyExc_TypeError, \ "list value expected for " attr); \ return -1; \ } /* frees only if pointer is not NULL. */ #define FREECHECKED(name, pointer) \ if (pointer != NULL) { \ free(pointer); \ pointer = NULL; \ } /* raises SequencerError with the specified string */ #define RAISESTR(str, args...) \ PyErr_Format(SequencerError, str,##args); /* raises SequencerError with the specified string and appends the alsaaudio error as string */ #define RAISESND(ret, str, args...) \ PyErr_Format(SequencerError, str ": %s",##args, snd_strerror(ret)); /* the C variable of a constant dict */ #define TDICT(subtype) _dictPYALSASEQ_CONST_##subtype /* the C enumeration of a constant dict */ #define TTYPE(subtype) PYALSASEQ_CONST_##subtype /* defines constant dict by type */ #define TCONSTDICT(subtype) \ static PyObject * TDICT(subtype); /* adds constant dict to module */ #define TCONSTDICTADD(module, subtype, name) \ _dictPYALSASEQ_CONST_##subtype = PyDict_New(); \ if (TDICT(subtype) == NULL) { \ return; \ } \ if (PyModule_AddObject(module, name, TDICT(subtype)) < 0) { \ return; \ } /* creates a typed constant and add it to the module and dictionary */ #define TCONSTADD(module, subtype, name, value) { \ PyObject *tmp = \ Constant_create(name, value, TTYPE(subtype)); \ if (tmp == NULL) { \ return; \ } \ if (PyModule_AddObject(module, name, tmp) < 0) { \ return; \ } \ PyDict_SetItem(TDICT(subtype), PyInt_FromLong(value), tmp); \ } #define TCONSTRETURN(subtype, value) { \ PyObject *key = PyInt_FromLong(value); \ ConstantObject *constantObject = (ConstantObject *) \ PyDict_GetItem(TDICT(subtype), key); \ if (constantObject == NULL) { \ return key; \ } else { \ Py_DECREF(key); \ Py_INCREF(constantObject); \ return (PyObject *)constantObject; \ } \ } #define TCONSTASSIGN(subtype, value, param) { \ PyObject *key = PyInt_FromLong(value); \ ConstantObject *constantObject = (ConstantObject *) \ PyDict_GetItem(TDICT(subtype), key); \ if (constantObject == NULL) { \ param = key; \ } else { \ Py_DECREF(key); \ Py_INCREF(constantObject); \ param = (PyObject *)constantObject; \ } \ } /* num protocol support for binary Constant operations */ #define NUMPROTOCOL2(name, oper) \ static PyObject * \ Constant_##name (PyObject *v, PyObject *w) { \ int type = 0; \ long val = 0; \ /* both have to be a int */ \ if (!PyInt_Check(v) || !PyInt_Check(w)) { \ Py_INCREF(Py_NotImplemented); \ return Py_NotImplemented; \ } \ val = PyInt_AS_LONG(v) oper PyInt_AS_LONG(w); \ /* always asume left will be the type */ \ if (PyObject_TypeCheck(v, &ConstantType)) { \ type = ((ConstantObject *) v)->type; \ } else if (PyObject_TypeCheck(w, &ConstantType)) { \ type = ((ConstantObject *) w)->type; \ } \ PyObject *self = Constant_create(#oper, val, type); \ return self; \ } /* num protocol support for unary Constant operations */ #define NUMPROTOCOL1(name, oper) \ static PyObject * \ Constant_##name (PyObject *v) { \ int type = 0; \ long val = 0; \ if (!PyInt_Check(v)) { \ Py_INCREF(Py_NotImplemented); \ return Py_NotImplemented; \ } \ val = oper PyInt_AS_LONG(v); \ if (PyObject_TypeCheck(v, &ConstantType)) { \ type = ((ConstantObject *) v)->type; \ } \ PyObject *self = Constant_create(#oper, val, type); \ return self; \ } /* sets the object into the dict */ #define SETDICTOBJ(name, object) \ PyDict_SetItemString(dict, name, object) /* sets a integer into the dict */ #define SETDICTINT(name, value) \ PyDict_SetItemString(dict, name, PyInt_FromLong(value)) /* sets note info dict (used by SeqEvent_get_data) */ #define SETDICT_NOTE3 { \ snd_seq_ev_note_t *data = &(event->data.note); \ SETDICTINT("note.channel", data->channel); \ SETDICTINT("note.note", data->note); \ SETDICTINT("note.velocity", data->velocity); \ } /* sets note info dict (used by SeqEvent_get_data) */ #define SETDICT_NOTE5 { \ snd_seq_ev_note_t *data = &(event->data.note); \ SETDICTINT("note.channel", data->channel); \ SETDICTINT("note.note", data->note); \ SETDICTINT("note.velocity", data->velocity); \ SETDICTINT("note.off_velocity", data->off_velocity); \ SETDICTINT("note.duration", data->duration); \ } /* sets control info dict (used by SeqEvent_get_data) */ #define SETDICT_CTRL1 { \ snd_seq_ev_ctrl_t *data = &(event->data.control); \ SETDICTINT("control.value", data->value); \ } /* sets control info dict (used by SeqEvent_get_data) */ #define SETDICT_CTRL2 { \ snd_seq_ev_ctrl_t *data = &(event->data.control); \ SETDICTINT("control.channel", data->channel); \ SETDICTINT("control.value", data->value); \ } /* sets control info dict (used by SeqEvent_get_data) */ #define SETDICT_CTRL3 { \ snd_seq_ev_ctrl_t *data = &(event->data.control); \ SETDICTINT("control.channel", data->channel); \ SETDICTINT("control.param", data->param); \ SETDICTINT("control.value", data->value); \ } /* sets queue info dict (used by SeqEvent_get_data) */ #define SETDICT_QUEU1 { \ snd_seq_ev_queue_control_t *data = &(event->data.queue); \ SETDICTINT("queue.queue", data->queue); \ } /* sets addr info dict (used by SeqEvent_get_data) */ #define SETDICT_ADDR1 { \ snd_seq_addr_t *data = &(event->data.addr); \ SETDICTINT("addr.client", data->client); \ } /* sets addr info dict (used by SeqEvent_get_data) */ #define SETDICT_ADDR2 { \ snd_seq_addr_t *data = &(event->data.addr); \ SETDICTINT("addr.client", data->client); \ SETDICTINT("addr.port", data->port); \ } /* sets connect info dict (used by SeqEvent_get_data) */ #define SETDICT_CONN4 { \ snd_seq_connect_t *data = &(event->data.connect); \ SETDICTINT("connect.sender.client", data->sender.client); \ SETDICTINT("connect.sender.port", data->sender.port); \ SETDICTINT("connect.dest.client", data->dest.client); \ SETDICTINT("connect.dest.port", data->dest.port); \ } /* sets result info dict (used by SeqEvent_get_data) */ #define SETDICT_RESU2 { \ snd_seq_result_t *data = &(event->data.result); \ SETDICTINT("result.event", data->event); \ SETDICTINT("result.result", data->result); \ } /* sets ext info dict (used by SeqEvent_get_data) */ #define SETDICT_EXT { \ snd_seq_ev_ext_t *data = &(event->data.ext); \ PyObject *list = PyList_New(data->len); \ int i = 0; \ unsigned char *t = (unsigned char *) data->ptr; \ for (i = 0; i < data->len; i++) { \ PyList_SetItem(list, i, PyInt_FromLong(t[i])); \ } \ SETDICTOBJ("ext", list); \ } /* gets integer from python param */ #define GETDICTINT(name, param) { \ PyObject *value = PyDict_GetItemString(dict, name); \ if (value != NULL) { \ if (!PyInt_Check(value)) { \ PyErr_SetString(PyExc_TypeError, name " must be a integer"); \ return NULL; \ } \ param = PyInt_AsLong(value); \ } \ } /* gets float from python param */ #define GETDICTFLOAT(name, param1, param2) { \ PyObject *value = PyDict_GetItemString(dict, name); \ if (value != NULL) { \ if (PyInt_Check(value)) { \ param2 = 0; \ param1 = PyInt_AsLong(value); \ } else if (PyFloat_Check(value)) { \ double d = PyFloat_AsDouble(value); \ unsigned int i = d; \ d -= i; \ param2 = d * 1000000; \ param1 = i; \ } else { \ PyErr_SetString(PyExc_TypeError, \ name " must be a integer or float"); \ return NULL; \ } \ } \ } /* gets ext data from python list */ #define GETDICTEXT(name) { \ PyObject *list = PyDict_GetItemString(dict, name); \ if (list != NULL) { \ if (!PyList_Check(list)) { \ PyErr_SetString(PyExc_TypeError, \ name " must be a list of integers"); \ return NULL; \ } \ FREECHECKED("buff", self->buff); \ int len = PyList_Size(list); \ self->event->data.ext.len = len; \ if (len > 0) { \ int i; \ for (i = 0; i < len; i++) { \ PyObject *item = PyList_GetItem(list, i); \ if (!PyInt_Check(item)) { \ PyErr_SetString(PyExc_TypeError, \ name " must be a list of integers"); \ self->event->data.ext.len = 0; \ return NULL; \ } \ } \ self->buff = malloc(len); \ if (self->buff == NULL) { \ PyErr_SetString(PyExc_TypeError, \ name " no memory"); \ self->event->data.ext.len = 0; \ return NULL; \ } \ for (i = 0; i < len; i++) { \ PyObject *item = PyList_GetItem(list, i); \ self->buff[i] = PyInt_AsLong(item); \ } \ self->event->data.ext.ptr = self->buff; \ } \ } \ } ////////////////////////////////////////////////////////////////////////////// // alsaseq.Constant implementation ////////////////////////////////////////////////////////////////////////////// /* alsaseq.Constant->type enumeration */ enum { PYALSASEQ_CONST_STREAMS, PYALSASEQ_CONST_MODE, PYALSASEQ_CONST_QUEUE, PYALSASEQ_CONST_CLIENT_TYPE, PYALSASEQ_CONST_PORT_CAP, PYALSASEQ_CONST_PORT_TYPE, PYALSASEQ_CONST_EVENT_TYPE, PYALSASEQ_CONST_EVENT_TIMESTAMP, PYALSASEQ_CONST_EVENT_TIMEMODE, PYALSASEQ_CONST_ADDR_CLIENT, PYALSASEQ_CONST_ADDR_PORT, }; // constants dictionaries TCONSTDICT(STREAMS); TCONSTDICT(MODE); TCONSTDICT(QUEUE); TCONSTDICT(CLIENT_TYPE); TCONSTDICT(PORT_CAP); TCONSTDICT(PORT_TYPE); TCONSTDICT(EVENT_TYPE); TCONSTDICT(EVENT_TIMESTAMP); TCONSTDICT(EVENT_TIMEMODE); TCONSTDICT(ADDR_CLIENT); TCONSTDICT(ADDR_PORT); /** alsaseq.Constant __doc__ */ PyDoc_STRVAR(Constant__doc__, "Constant() -> Constant object\n" "\n" "Represents one of the many integer constants from the\n" "libasound sequencer API.\n" "\n" "This class serves the following purposes:\n" " a. wrap the SND_SEQ* constants to a python int;\n" " b. provide a string representation of the constant;\n" "\n" "For a), this class is a subclass of the python int. Example:\n" " >>> import alsaseq\n" " >>> print alsaseq.SEQ_EVENT_NOTE\n" " 5\n" " >>> event = alsaseq.SeqEvent(alsaseq.SEQ_EVENT_NOTE)\n" " >>> print event.queue\n" " 253\n" " >>> print event.dest\n" " (0, 0)\n" "\n" "For b), you can get the name of the constant by calling the appropiate\n" "method (__str__ or __repr__). Example:\n" " >>> print str(event.queue), repr(event.queue)\n" " SEQ_QUEUE_DIRECT SEQ_QUEUE_DIRECT(0xfd)\n" " >>> print str(event.dest)\n" " (SEQ_CLIENT_SYSTEM(0x0), SEQ_PORT_SYSTEM_TIMER(0x0))\n" "\n" "This class implements some of the bitwise operations from the\n" "Python number protocol." ); /** alsaseq.Constant object structure type */ typedef struct { PyObject_HEAD ; /* value of constant */ unsigned long int value; /* name of constant */ const char *name; /* type of constant */ int type; } ConstantObject; /** alsaseq.Constant type (initialized later...) */ static PyTypeObject ConstantType; /** alsaseq.Constant internal create */ static PyObject * Constant_create(const char *name, long value, int type) { ConstantObject *self = PyObject_New(ConstantObject, &ConstantType); if (self == NULL) { return NULL; } self->value = value; self->name = name; self->type = type; return (PyObject *)self; } /** alsaseq.Constant tp_repr */ static PyObject * Constant_repr(ConstantObject *self) { return PyString_FromFormat("%s(0x%x)", self->name, (unsigned int)self->value); } /** alsaseq.Constant tp_str */ static PyObject * Constant_str(ConstantObject *self) { return PyString_FromFormat("%s", self->name); } /** alsaseq.Constant Number protocol support (note: not all ops supported) */ NUMPROTOCOL2(Add, +) NUMPROTOCOL2(Subtract, -) NUMPROTOCOL2(Xor, ^) NUMPROTOCOL2(Or, |) NUMPROTOCOL2(And, &) NUMPROTOCOL1(Invert, ~) /** alsaseq.Constant number protocol methods */ static PyNumberMethods Constant_as_number = { nb_add: (binaryfunc)Constant_Add, nb_subtract: (binaryfunc)Constant_Subtract, nb_xor: (binaryfunc)Constant_Xor, nb_or: (binaryfunc)Constant_Or, nb_and: (binaryfunc)Constant_And, nb_invert: (unaryfunc)Constant_Invert }; /** alsaseq.Constant type */ static PyTypeObject ConstantType = { PyObject_HEAD_INIT(NULL) tp_name: "alsaseq.Constant", tp_base: &PyInt_Type, tp_basicsize: sizeof(ConstantObject), tp_flags: Py_TPFLAGS_HAVE_GETCHARBUFFER | Py_TPFLAGS_HAVE_CLASS | Py_TPFLAGS_CHECKTYPES, tp_doc: Constant__doc__, tp_as_number: &Constant_as_number, tp_free: PyObject_Del, tp_str: (reprfunc)Constant_str, tp_repr: (reprfunc)Constant_repr }; ////////////////////////////////////////////////////////////////////////////// // alsaseq.SequencerError implementation ////////////////////////////////////////////////////////////////////////////// /** alsaseq.SequencerError instance (initialized in initalsaseq) */ static PyObject *SequencerError; ////////////////////////////////////////////////////////////////////////////// // alsaseq.SeqEvent implementation ////////////////////////////////////////////////////////////////////////////// /** alsaseq.SeqEvent __doc__ */ PyDoc_STRVAR(SeqEvent__doc__, "SeqEvent(type[, timestamp[,timemode]]) -> SeqEvent object\n" "\n" "Creates an Alsa Sequencer Event object. The type must be one of the\n" "alsaseq.SEQ_EVENT_* constants. The timestamp specifies if tick (midi)\n" "or real time is used, must be alsaseq.SEQ_TIME_STAMP_TICK or\n" "alsaseq.SEQ_TIME_STAMP_REAL. The timemode specifies if the time will\n" "be absolute or relative, must be alsaseq.SEQ_TIME_MODE_ABS or\n" "alsaseq.SEQ_TIME_MODE_REL.\n" "\n" "The timestamp and timemode defaults to SEQ_TIME_STAMP_TICK and\n" "SEQ_TIME_MODE_ABS when they are not specified.\n" "\n" "SeqEvent objects are received or sent using a Sequencer object. The\n" "data of the event can be set or retrieved using the set_data() or\n" "get_data() methods; both use a dictionary. The rest of properties of\n" "a SeqEvent can be accesed and changed using the SeqEvent attributes.\n" "\n" "The attributes and defaults values are:\n" "type -- event type.\n" "timestamp -- tick(midi) or real(nanoseconds). Default: SEQ_TIME_STAMP_TICK.\n" "timemode -- relative or absolute. Default: SEQ_TIME_MODE_ABS.\n" "queue -- queue id. Default: SEQ_QUEUE_DIRECT\n" "time -- time of this event. Default: 0.\n" "source -- source address tuple (client,port). Default: (0, 0).\n" "dest -- dest address tuple (client, port). Default: (0, 0).\n" "\n" "There are dictionaries available as attributes, that contains\n" "alsaseq.SEQ* constants that can be used for each attribute:\n" "_dtype -- event type constants.\n" "_dtimestamp -- event timestamp constants.\n" "_dtimemode -- event timemode constants.\n" "_dqueue -- queue id's.\n" "_dclient -- client address (for source an dest).\n" "_dport -- port address (for source an dest).\n" ); /** alsaseq.SeqEvent object structure type */ typedef struct { PyObject_HEAD ; /* alsa event */ snd_seq_event_t *event; /* pointer copied/created from/for variable length events */ unsigned char *buff; } SeqEventObject; /** alsaseq.SeqEvent type (initialized later...) */ static PyTypeObject SeqEventType; /** internal use: set type and update flags based on event type */ static int _SeqEvent_set_type(SeqEventObject *self, long type) { self->event->type = type; /* clean previous buff... */ FREECHECKED("buff", self->buff); memset(&(self->event->data), '\0', sizeof(self->event->data)); /* update flags */ if (snd_seq_ev_is_variable_type(self->event)) { snd_seq_ev_set_variable(self->event, 0, NULL); } else if (snd_seq_ev_is_varusr_type(self->event)) { snd_seq_ev_set_varusr(self->event, 0, NULL); } else if (snd_seq_ev_is_fixed_type(self->event)) { snd_seq_ev_set_fixed(self->event); } else { PyErr_SetString(PyExc_ValueError, "Invalid value for type; " "use one of alsaseq.SEQ_EVENT_* constants."); return -1; } return 0; } /** internal use: set timestamp flag */ static int _SeqEvent_set_timestamp(SeqEventObject *self, long timestamp) { if (timestamp == SND_SEQ_TIME_STAMP_TICK) { self->event->flags &= ~(SND_SEQ_TIME_STAMP_MASK); self->event->flags |= SND_SEQ_TIME_STAMP_TICK; } else if (timestamp == SND_SEQ_TIME_STAMP_REAL) { self->event->flags &= ~(SND_SEQ_TIME_STAMP_MASK); self->event->flags |= SND_SEQ_TIME_STAMP_REAL; } else { PyErr_SetString(PyExc_ValueError, "Invalid value for timestamp; " "use alsaseq.SEQ_TIME_STAMP_TICK or " "alsaseq.SEQ_TIME_STAMP_REAL."); return -1; } return 0; } /** internal use: set timemode flag */ static int _SeqEvent_set_timemode(SeqEventObject *self, long timemode) { if (timemode == SND_SEQ_TIME_MODE_ABS) { self->event->flags &= ~(SND_SEQ_TIME_MODE_MASK); self->event->flags |= SND_SEQ_TIME_MODE_ABS; } else if (timemode == SND_SEQ_TIME_MODE_REL) { self->event->flags &= ~(SND_SEQ_TIME_MODE_MASK); self->event->flags |= SND_SEQ_TIME_MODE_REL; } else { PyErr_SetString(PyExc_ValueError, "Invalid value for timemode; " "use alsaseq.SEQ_TIME_MODE_ABS or " "alsaseq.SEQ_TIME_MODE_REL."); return -1; } return 0; } /** alsaseq.SeqEvent tp_init */ static int SeqEvent_init(SeqEventObject *self, PyObject *args, PyObject *kwds) { int type = 0; int timestamp = SND_SEQ_TIME_STAMP_TICK; int timemode = SND_SEQ_TIME_MODE_ABS; char *kwlist [] = {"type", "timestamp", "timemode", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwlist, &type, ×tamp, &timemode)) { return -1; } if (_SeqEvent_set_type(self, type) !=0 ) { return -1; } if (_SeqEvent_set_timestamp(self, timestamp) != 0) { return -1; } if (_SeqEvent_set_timemode(self, timemode) != 0) { return -1; } snd_seq_ev_set_direct(self->event); snd_seq_ev_set_subs(self->event); return 0; } /** internal use: create a alsaseq.SeqEvent from a snd_seq_event_t structure */ static PyObject * SeqEvent_create(snd_seq_event_t *event) { SeqEventObject *self = PyObject_New(SeqEventObject, &SeqEventType); if (self == NULL) { return NULL; } self->event = malloc(sizeof(snd_seq_event_t)); if (self->event == NULL) { PyObject_Del(self); return PyErr_NoMemory(); } memcpy(self->event, event, sizeof(snd_seq_event_t)); if (snd_seq_ev_is_variable_type(self->event)) { self->buff = malloc(self->event->data.ext.len); if (self->buff == NULL) { PyObject_Del(self); return PyErr_NoMemory(); } memcpy(self->buff, self->event->data.ext.ptr, self->event->data.ext.len); self->event->data.ext.ptr = self->buff; } else { self->buff = NULL; } return (PyObject *) self; } /** alsaseq.SeqEvent tp_new */ static PyObject * SeqEvent_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { SeqEventObject *self; self = (SeqEventObject *)type->tp_alloc(type, 0); self->event = malloc(sizeof(snd_seq_event_t)); if (self->event == NULL) { type->tp_free(self); return PyErr_NoMemory(); } snd_seq_ev_clear(self->event); self->buff = NULL; return (PyObject *) self; } /** alsaseq.SeqEvent tp_dealloc */ static void SeqEvent_dealloc(SeqEventObject *self) { FREECHECKED("event", self->event); FREECHECKED("buff", self->buff); self->ob_type->tp_free(self); } /** alsaseq.SeqEvent type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_type__doc__, "type -> Constant object\n" "\n" "The type of this alsaseq.SeqEvent; Use one of the\n" "alsaseq.SEQ_EVENT_* constants.\n\n" "Note: changing a SeqEvent type will *ERASE* AND *CLEAN* its data!!" ); /** alsaseq.SeqEvent type attribute: tp_getset getter() */ static PyObject * SeqEvent_get_type(SeqEventObject *self) { TCONSTRETURN(EVENT_TYPE, self->event->type); } /** alsaseq.SeqEvent type attribute: tp_getset setter() */ static int SeqEvent_set_type(SeqEventObject *self, PyObject *val) { SETCHECKPYINT("type", val); return _SeqEvent_set_type(self, PyInt_AsLong(val)); } /** alsaseq.SeqEvent tag attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_tag__doc__, "tag -> int\n" "\n" "The tag of this alsaseq.SeqEvent (range:0-255)." ); /** alsaseq.SeqEvent tag attribute: tp_getset getter() */ static PyObject * SeqEvent_get_tag(SeqEventObject *self) { return PyInt_FromLong(self->event->tag); } /** alsaseq.SeqEvent tag attribute: tp_getset setter() */ static int SeqEvent_set_tag(SeqEventObject *self, PyObject *val) { long tag; SETCHECKPYINT("tag", val); tag = PyInt_AsLong(val); if (tag < 0 || tag > 255) { PyErr_Format(PyExc_ValueError, "invalid value '%ld'; allowed range: 0 - 255", tag); return -1; } self->event->tag = tag; return 0; } /** alsaseq.seqEvent timestamp attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_timestamp__doc__, "timestamp -> Constant object\n" "\n" "The time stamp flag of this alsaseq.SeqEvent;\n" "use alsaseq.SEQ_TIME_STAMP_TICK or alsaseq.SEQ_TIME_STAMP_REAL." ); /** alsaseq.SeqEvent timestamp attribute: tp_getset getter() */ static PyObject * SeqEvent_get_timestamp(SeqEventObject *self) { if (snd_seq_ev_is_tick(self->event)) { TCONSTRETURN(EVENT_TIMESTAMP, SND_SEQ_TIME_STAMP_TICK); } else if (snd_seq_ev_is_real(self->event)) { TCONSTRETURN(EVENT_TIMESTAMP, SND_SEQ_TIME_STAMP_REAL); } /* should never get here ... */ return NULL; } /** alsaseq.SeqEvent timestamp attribute: tp_getset setter() */ static int SeqEvent_set_timestamp(SeqEventObject *self, PyObject *val) { SETCHECKPYINT("timestamp", val); return _SeqEvent_set_timestamp(self, PyInt_AsLong(val)); } /** alsaseq.SeqEvent timemode attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_timemode__doc__, "timemode -> Constant object\n" "\n" "The time mode flag of this alsaseq.SeqEvent;\n" "use alsaseq.SEQ_TIME_MODE_ABS or alsaseq.SEQ_TIME_MODE_REL." ); /** alsaseq.SeqEvent timemode attribute: tp_getset getter() */ static PyObject * SeqEvent_get_timemode(SeqEventObject *self) { if (snd_seq_ev_is_abstime(self->event)) { TCONSTRETURN(EVENT_TIMEMODE, SND_SEQ_TIME_MODE_ABS); } else if (snd_seq_ev_is_reltime(self->event)) { TCONSTRETURN(EVENT_TIMEMODE, SND_SEQ_TIME_MODE_REL); } /* should never get here ... */ return NULL; } /** alsaseq.SeqEvent timemode attribute: tp_getset setter() */ static int SeqEvent_set_timemode(SeqEventObject *self, PyObject *val) { SETCHECKPYINT("timemode", val); return _SeqEvent_set_timemode(self, PyInt_AsLong(val)); } /** alsaseq.SeqEvent queue attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_queue__doc__, "queue -> int\n" "\n" "The send queue id of this alsaseq.SeqEvent." ); /** alsaseq.SeqEvent queue: tp_getset getter() */ static PyObject * SeqEvent_get_queue(SeqEventObject *self) { TCONSTRETURN(QUEUE, self->event->queue); } /** alsaseq.SeqEvent queue attribute: tp_getset setter() */ static int SeqEvent_set_queue(SeqEventObject *self, PyObject *val) { SETCHECKPYINT("queue", val); self->event->queue = PyInt_AsLong(val); return 0; } /** alsaseq.SeqEvent time attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_time__doc__, "time -> int or float\n" "\n" "The send time of this alsaseq.SeqEvent.\n" "If the timestamp of the SeqEvent is SEQ_TIME_STAMP_TICK, an\n" "integer value is used which represents the midi tick time; \n" "if the timestamp is SEQ_TIME_STAMP_REAL, a float value is used\n" "which represents seconds the same way Python time module.\n" ); /** alsaseq.SeqEvent time attribute: tp_getset getter() */ static PyObject * SeqEvent_get_time(SeqEventObject *self) { if (snd_seq_ev_is_real(self->event)) { double time = self->event->time.time.tv_sec; time += self->event->time.time.tv_nsec / 1000000000.0; return PyFloat_FromDouble(time); } else if (snd_seq_ev_is_tick(self->event)) { long tick = self->event->time.tick; return PyInt_FromLong(tick); } /* should never get here... */ return NULL; } /** alsaseq.SeqEvent time attribute: tp_getset setter() */ static int SeqEvent_set_time(SeqEventObject *self, PyObject *val) { int is_int = PyInt_Check(val); int is_float = PyFloat_Check(val); if (!(is_int || is_float)) { PyErr_Format(PyExc_TypeError, "integer or float expected"); return -1; } if (snd_seq_ev_is_real(self->event)) { if (is_int) { double time = PyInt_AsLong(val); self->event->time.time.tv_sec = time; self->event->time.time.tv_nsec = 0; } else { double time = PyFloat_AsDouble(val); self->event->time.time.tv_sec = (unsigned int)time; time -= self->event->time.time.tv_sec; self->event->time.time.tv_nsec = time * 1000000000; } } else if (snd_seq_ev_is_tick(self->event)) { if (is_int) { self->event->time.tick = PyInt_AsLong(val); } else { self->event->time.tick = PyFloat_AsDouble(val); } } else { /* should never get here... */ return -1; } return 0; } /** alsaseq.SeqEvent source attribute: __doc __ */ PyDoc_STRVAR(SeqEvent_source__doc__, "source -> tuple (client_id, port_id)\n" "\n" "Tuple representing the send source address of this alsaseq.SeqEvent.\n" "The tuple is (client_id, port_id). If the client or port id are known,\n" "the appropiate constant may be used, otherwise integers are expected." ); /** alsaseq.SeqEvent source attribute: tp_getset getter() */ static PyObject * SeqEvent_get_source(SeqEventObject *self) { int source_client = self->event->source.client; int source_port = self->event->source.port; PyObject *client, *port; PyObject *tuple = PyTuple_New(2); TCONSTASSIGN(ADDR_CLIENT, source_client, client); TCONSTASSIGN(ADDR_PORT, source_port, port); PyTuple_SetItem(tuple, 0, client); PyTuple_SetItem(tuple, 1, port); return tuple; } /** alsaseq.SeqEvent source attribute: tp_getset setter() */ static int SeqEvent_set_source(SeqEventObject *self, PyObject *val) { PyObject *client; PyObject *port; if (!PyTuple_Check(val) || PyTuple_Size(val) != 2) { PyErr_SetString(PyExc_TypeError, "expected tuple (client,port)"); return -1; } client = PyTuple_GetItem(val, 0); port = PyTuple_GetItem(val, 1); SETCHECKPYINT("source client", client); SETCHECKPYINT("source port", port); self->event->source.client = PyInt_AsLong(client); self->event->source.port = PyInt_AsLong(port); return 0; } /** alsaseq.SeqEvent dest attribute: __doc __ */ PyDoc_STRVAR(SeqEvent_dest__doc__, "dest -> tuple (client_id, port_id)\n" "\n" "Tuple representing the destination address of this alsaseq.SeqEvent.\n" "The tuple is (client_id, port_id). If the client or port id are known,\n" "the appropiate constant may be used, otherwise integers are expected." ); /** alsaseq.SeqEvent dest attribute: tp_getset getter() */ static PyObject * SeqEvent_get_dest(SeqEventObject *self) { int dest_client = self->event->dest.client; int dest_port = self->event->dest.port; PyObject *client, *port; PyObject *tuple = PyTuple_New(2); TCONSTASSIGN(ADDR_CLIENT, dest_client, client); TCONSTASSIGN(ADDR_PORT, dest_port, port); PyTuple_SetItem(tuple, 0, client); PyTuple_SetItem(tuple, 1, port); return tuple; } /** alsaseq.SeqEvent dest attribute: tp_getset setter() */ static int SeqEvent_set_dest(SeqEventObject *self, PyObject *val) { PyObject *client; PyObject *port; if (!PyTuple_Check(val) || PyTuple_Size(val) != 2) { PyErr_SetString(PyExc_TypeError, "expected tuple (client,port)"); return -1; } client = PyTuple_GetItem(val, 0); port = PyTuple_GetItem(val, 1); SETCHECKPYINT("dest client", client); SETCHECKPYINT("dest port", port); self->event->dest.client = PyInt_AsLong(client); self->event->dest.port = PyInt_AsLong(port); return 0; } /** alsaseq.SeqEvent is_result_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_result_type__doc__, "is_result_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type result (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_result_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_result_type(SeqEventObject *self) { if (snd_seq_ev_is_result_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_note_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_note_type__doc__, "is_note_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type note (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_note_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_note_type(SeqEventObject *self) { if (snd_seq_ev_is_note_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_control_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_control_type__doc__, "is_control_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type control (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_note_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_control_type(SeqEventObject *self) { if (snd_seq_ev_is_control_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_channel_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_channel_type__doc__, "is_channel_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type channel (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_channel_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_channel_type(SeqEventObject *self) { if (snd_seq_ev_is_channel_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_queue_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_queue_type__doc__, "is_queue_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is a queue event (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_queue_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_queue_type(SeqEventObject *self) { if (snd_seq_ev_is_queue_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_message_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_message_type__doc__, "is_message_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type message (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_message_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_message_type(SeqEventObject *self) { if (snd_seq_ev_is_message_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_subscribe_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_subscribe_type__doc__, "is_subscribe_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type subscribe (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_subscribe_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_subscribe_type(SeqEventObject *self) { if (snd_seq_ev_is_subscribe_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_sample_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_sample_type__doc__, "is_sample_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type sample (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_sample_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_sample_type(SeqEventObject *self) { if (snd_seq_ev_is_sample_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_user_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_user_type__doc__, "is_user_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type user (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_user_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_user_type(SeqEventObject *self) { if (snd_seq_ev_is_user_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_instr_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_instr_type__doc__, "is_instr_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type instr (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_instr_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_instr_type(SeqEventObject *self) { if (snd_seq_ev_is_instr_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_fixed_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_fixed_type__doc__, "is_fixed_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type fixed (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_fixed_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_fixed_type(SeqEventObject *self) { if (snd_seq_ev_is_fixed_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_variable_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_variable_type__doc__, "is_variable_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type variable (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_variable_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_variable_type(SeqEventObject *self) { if (snd_seq_ev_is_variable_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_varusr_type attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_varusr_type__doc__, "is_message_type -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is of type varusr (True) or not\n" "(False). Note: read-only attribute." ); /** alsaseq.SeqEvent is_varusr_type attribute: tp_getset getter() */ static PyObject * SeqEvent_is_varusr_type(SeqEventObject *self) { if (snd_seq_ev_is_varusr_type(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_reserved attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_reserved__doc__, "is_reserved -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is reserved (True) or not (False).\n" "Note: read-only attribute." ); /** alsaseq.SeqEvent is_reserved attribute: tp_getset getter() */ static PyObject * SeqEvent_is_reserved(SeqEventObject *self) { if (snd_seq_ev_is_reserved(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_prior attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_prior__doc__, "is_prior -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is prior (True) or not (False).\n" "Note: read-only attribute." ); /** alsaseq.SeqEvent is_prior attribute: tp_getset getter() */ static PyObject * SeqEvent_is_prior(SeqEventObject *self) { if (snd_seq_ev_is_prior(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_fixed attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_fixed__doc__, "is_fixed -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is fixed (True) or not (False).\n" "Note: read-only attribute." ); /** alsaseq.SeqEvent is_fixed attribute: tp_getset getter() */ static PyObject * SeqEvent_is_fixed(SeqEventObject *self) { if (snd_seq_ev_is_fixed(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_variable attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_variable__doc__, "is_variable -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is variable (True) or not (False).\n" "Note: read-only attribute." ); /** alsaseq.SeqEvent is_variable attribute: tp_getset getter() */ static PyObject * SeqEvent_is_variable(SeqEventObject *self) { if (snd_seq_ev_is_variable(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_varusr attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_varusr__doc__, "is_varusr -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is varusr (True) or not (False).\n" "Note: read-only attribute." ); /** alsaseq.SeqEvent is_varusr attribute: tp_getset getter() */ static PyObject * SeqEvent_is_varusr(SeqEventObject *self) { if (snd_seq_ev_is_varusr(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_tick attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_tick__doc__, "is_tick -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is tick timed (True) or not (False).\n" "Note: read-only attribute." ); /** alsaseq.SeqEvent is_tick attribute: tp_getset getter() */ static PyObject * SeqEvent_is_tick(SeqEventObject *self) { if (snd_seq_ev_is_tick(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_real attribute: __doc__ */ PyDoc_STRVAR(SeqEvent_is_real__doc__, "is_real -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is real timed (True) or not (False).\n" "Note: read-only attribute." ); /** alsaseq.SeqEvent is_real attribute: tp_getset getter() */ static PyObject * SeqEvent_is_real(SeqEventObject *self) { if (snd_seq_ev_is_real(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_abstime attribute: __doc__ */ const char SeqEvent_is_abstime__doc__ [] = "is_abstime -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is abstime timed (True) or not\n" "(False). Note: read-only attribute." ; /** alsaseq.SeqEvent is_abstime attribute: tp_getset getter() */ static PyObject * SeqEvent_is_abstime(SeqEventObject *self) { if (snd_seq_ev_is_abstime(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_reltime attribute: __doc__ */ const char SeqEvent_is_reltime__doc__ [] = "is_reltime -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is a reltime timed (True) or not\n" "(False). Note: read-only attribute." ; /** alsaseq.SeqEvent is_reltime attribute: tp_getset getter() */ static PyObject * SeqEvent_is_reltime(SeqEventObject *self) { if (snd_seq_ev_is_reltime(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent is_direct attribute: __doc__ */ const char SeqEvent_is_direct__doc__ [] = "is_direct -> boolean\n" "\n" "Indicates if this alsaseq.SeqEvent is sent directly (True) or not\n" "(False). Note: read-only attribute." ; /** alsaseq.SeqEvent is_direct attribute: tp_getset getter() */ static PyObject * SeqEvent_is_direct(SeqEventObject *self) { if (snd_seq_ev_is_direct(self->event)) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } /** alsaseq.SeqEvent _dtype attribute: __doc__ */ const char SeqEvent__dtype__doc__ [] = "_dtype -> dictionary\n" "\n" "Dictionary will available event type constants." ; /** alsaseq.Seqevent _dtype attribute: tp_getset getter() */ static PyObject * SeqEvent__dtype(SeqEventObject *self) { Py_INCREF(_dictPYALSASEQ_CONST_EVENT_TYPE); return _dictPYALSASEQ_CONST_EVENT_TYPE; } /** alsaseq.SeqEvent _dtimestamp attribute: __doc__ */ const char SeqEvent__dtimestamp__doc__ [] = "_dtimestamp -> dictionary\n" "\n" "Dictionary will available event timestamp constants." ; /** alsaseq.Seqevent _dtimestamp attribute: tp_getset getter() */ static PyObject * SeqEvent__dtimestamp(SeqEventObject *self) { Py_INCREF(_dictPYALSASEQ_CONST_EVENT_TIMESTAMP); return _dictPYALSASEQ_CONST_EVENT_TIMESTAMP; } /** alsaseq.SeqEvent _dtimemode attribute: __doc__ */ const char SeqEvent__dtimemode__doc__ [] = "_dtimemode -> dictionary\n" "\n" "Dictionary of available event timemode constants." ; /** alsaseq.Seqevent _dtimemode attribute: tp_getset getter() */ static PyObject * SeqEvent__dtimemode(SeqEventObject *self) { Py_INCREF(_dictPYALSASEQ_CONST_EVENT_TIMEMODE); return _dictPYALSASEQ_CONST_EVENT_TIMEMODE; } /** alsaseq.SeqEvent _dqueue attribute: __doc__ */ const char SeqEvent__dqueue__doc__ [] = "_dqueue -> dictionary\n" "\n" "Dictionary of known queue id constants." ; /** alsaseq.Seqevent _dqueue attribute: tp_getset getter() */ static PyObject * SeqEvent__dqueue(SeqEventObject *self) { Py_INCREF(_dictPYALSASEQ_CONST_QUEUE); return _dictPYALSASEQ_CONST_QUEUE; } /** alsaseq.SeqEvent _dclient attribute: __doc__ */ const char SeqEvent__dclient__doc__ [] = "_dclient -> dictionary\n" "\n" "Dictionary of known client addresses constants." ; /** alsaseq.Seqevent _dclient attribute: tp_getset getter() */ static PyObject * SeqEvent__dclient(SeqEventObject *self) { Py_INCREF(TDICT(ADDR_CLIENT)); return TDICT(ADDR_CLIENT); } /** alsaseq.SeqEvent _dport attribute: __doc__ */ const char SeqEvent__dport__doc__ [] = "_dport -> dictionary\n" "\n" "Dictionary of known port addresses constants." ; /** alsaseq.Seqevent _dport attribute: tp_getset getter() */ static PyObject * SeqEvent__dport(SeqEventObject *self) { Py_INCREF(TDICT(ADDR_PORT)); return TDICT(ADDR_PORT); } /** alsaseq.SeqEvent tp_getset list */ static PyGetSetDef SeqEvent_getset[] = { {"type", (getter) SeqEvent_get_type, (setter) SeqEvent_set_type, (char *) SeqEvent_type__doc__, NULL}, {"timestamp", (getter) SeqEvent_get_timestamp, (setter) SeqEvent_set_timestamp, (char *) SeqEvent_timestamp__doc__, NULL}, {"timemode", (getter) SeqEvent_get_timemode, (setter) SeqEvent_set_timemode, (char *) SeqEvent_timemode__doc__, NULL}, {"tag", (getter) SeqEvent_get_tag, (setter) SeqEvent_set_tag, (char *) SeqEvent_tag__doc__, NULL}, {"queue", (getter) SeqEvent_get_queue, (setter) SeqEvent_set_queue, (char *) SeqEvent_queue__doc__, NULL}, {"time", (getter) SeqEvent_get_time, (setter) SeqEvent_set_time, (char *) SeqEvent_time__doc__, NULL}, {"source", (getter) SeqEvent_get_source, (setter) SeqEvent_set_source, (char *) SeqEvent_source__doc__, NULL}, {"dest", (getter) SeqEvent_get_dest, (setter) SeqEvent_set_dest, (char *) SeqEvent_dest__doc__, NULL}, {"is_result_type", (getter) SeqEvent_is_result_type, NULL, (char *) SeqEvent_is_result_type__doc__, NULL}, {"is_note_type", (getter) SeqEvent_is_note_type, NULL, (char *) SeqEvent_is_note_type__doc__, NULL}, {"is_control_type", (getter) SeqEvent_is_control_type, NULL, (char *) SeqEvent_is_control_type__doc__, NULL}, {"is_channel_type", (getter) SeqEvent_is_channel_type, NULL, (char *) SeqEvent_is_channel_type__doc__, NULL}, {"is_queue_type", (getter) SeqEvent_is_queue_type, NULL, (char *) SeqEvent_is_queue_type__doc__, NULL}, {"is_message_type", (getter) SeqEvent_is_message_type, NULL, (char *) SeqEvent_is_message_type__doc__, NULL}, {"is_subscribe_type", (getter) SeqEvent_is_subscribe_type, NULL, (char *) SeqEvent_is_subscribe_type__doc__, NULL}, {"is_sample_type", (getter) SeqEvent_is_sample_type, NULL, (char *) SeqEvent_is_sample_type__doc__, NULL}, {"is_user_type", (getter) SeqEvent_is_user_type, NULL, (char *) SeqEvent_is_user_type__doc__, NULL}, {"is_instr_type", (getter) SeqEvent_is_instr_type, NULL, (char *) SeqEvent_is_instr_type__doc__, NULL}, {"is_fixed_type", (getter) SeqEvent_is_fixed_type, NULL, (char *) SeqEvent_is_fixed_type__doc__, NULL}, {"is_variable_type", (getter) SeqEvent_is_variable_type, NULL, (char *) SeqEvent_is_variable_type__doc__, NULL}, {"is_varusr_type", (getter) SeqEvent_is_varusr_type, NULL, (char *) SeqEvent_is_varusr_type__doc__, NULL}, {"is_reserved", (getter) SeqEvent_is_reserved, NULL, (char *) SeqEvent_is_reserved__doc__, NULL}, {"is_prior", (getter) SeqEvent_is_prior, NULL, (char *) SeqEvent_is_prior__doc__, NULL}, {"is_fixed", (getter) SeqEvent_is_fixed, NULL, (char *) SeqEvent_is_fixed__doc__, NULL}, {"is_variable", (getter) SeqEvent_is_variable, NULL, (char *) SeqEvent_is_variable__doc__, NULL}, {"is_varusr", (getter) SeqEvent_is_varusr, NULL, (char *) SeqEvent_is_varusr__doc__, NULL}, {"is_tick", (getter) SeqEvent_is_tick, NULL, (char *) SeqEvent_is_tick__doc__, NULL}, {"is_real", (getter) SeqEvent_is_real, NULL, (char *) SeqEvent_is_real__doc__, NULL}, {"is_abstime", (getter) SeqEvent_is_abstime, NULL, (char *) SeqEvent_is_abstime__doc__, NULL}, {"is_reltime", (getter) SeqEvent_is_reltime, NULL, (char *) SeqEvent_is_reltime__doc__, NULL}, {"is_direct", (getter) SeqEvent_is_direct, NULL, (char *) SeqEvent_is_direct__doc__, NULL}, {"_dtype", (getter) SeqEvent__dtype, NULL, (char *) SeqEvent__dtype__doc__, NULL}, {"_dtimestamp", (getter) SeqEvent__dtimestamp, NULL, (char *) SeqEvent__dtimestamp__doc__, NULL}, {"_dtimemode", (getter) SeqEvent__dtimemode, NULL, (char *) SeqEvent__dtimemode__doc__, NULL}, {"_dqueue", (getter) SeqEvent__dqueue, NULL, (char *) SeqEvent__dqueue__doc__, NULL}, {"_dclient", (getter) SeqEvent__dclient, NULL, (char *) SeqEvent__dclient__doc__, NULL}, {"_dport", (getter) SeqEvent__dport, NULL, (char *) SeqEvent__dport__doc__, NULL}, {NULL} }; /** alsaseq.SeqEvent tp_repr */ static PyObject * SeqEvent_repr(SeqEventObject *self) { PyObject *key = PyInt_FromLong(self->event->type); ConstantObject *constObject = (ConstantObject *) PyDict_GetItem(TDICT(EVENT_TYPE), key); const char *typestr = "UNKNOWN"; const char *timemode = ""; unsigned int dtime = 0; unsigned int ntime = 0; Py_DECREF(key); if (constObject != NULL) { typestr = constObject->name; } if (snd_seq_ev_is_real(self->event)) { timemode = "real"; dtime = self->event->time.time.tv_sec; ntime += self->event->time.time.tv_nsec / 1000000000.0; } else { timemode = "tick"; dtime = self->event->time.tick; } return PyString_FromFormat("", typestr, self->event->type, self->event->flags, self->event->tag, self->event->queue, timemode, dtime, ntime, (self->event->source).client, (self->event->source).port, (self->event->dest).client, (self->event->dest).port, self); } /** alsaseq.SeqEvent get_data() method: __doc__ */ PyDoc_STRVAR(SeqEvent_get_data__doc__, "get_data() -> dict\n" "\n" "Returns a new dictionary with the data of this SeqEvent.\n" "Changes to the returned dictionary will not change this SeqEvent data,\n" "for changing an event data use the set_data() method.\n" "\n" "The dictionary items are key: value; where key is the name of the\n" "data structure from alsa API and value is an integer or a list of them.\n" "\n" "The following name of structures are available:\n" " 'note.channel' -> int\n" " 'note.note' -> int\n" " 'note.velocity' -> int\n" " 'note.off_velocity' -> int\n" " 'note.duration' -> int\n" " 'control.channel' -> int\n" " 'control.value' -> int\n" " 'control.param' -> int\n" " 'queue.queue' -> int\n" " 'addr.client' -> int\n" " 'addr.port' -> int\n" " 'connect.sender.client' -> int\n" " 'connect.sender.port' -> int\n" " 'connect.dest.client' -> int\n" " 'connect.dest.port' -> int\n" " 'result.event' -> int\n" " 'result.result' -> int\n" " 'ext' -> list of int with sysex or variable data\n" "\n" "The exact items returned dependens on the event type of this SeqEvent.\n" "For a control event, only 'control.*' may be returned; for a sysex \n" "event, only 'ext' may be returned; for a note event, only 'note.*' may \n" "be returned and so on." ); /** alsaseq.SeqEvent get_data() method */ static PyObject * SeqEvent_get_data(SeqEventObject *self, PyObject *args) { PyObject *dict = PyDict_New(); snd_seq_event_t *event = self->event; switch (event->type) { case SND_SEQ_EVENT_SYSTEM: case SND_SEQ_EVENT_RESULT: SETDICT_RESU2; break; case SND_SEQ_EVENT_NOTE: SETDICT_NOTE5; break; case SND_SEQ_EVENT_NOTEON: case SND_SEQ_EVENT_NOTEOFF: case SND_SEQ_EVENT_KEYPRESS: SETDICT_NOTE3; break; case SND_SEQ_EVENT_CONTROLLER: SETDICT_CTRL3; break; case SND_SEQ_EVENT_PGMCHANGE: case SND_SEQ_EVENT_CHANPRESS: case SND_SEQ_EVENT_PITCHBEND: SETDICT_CTRL2; break; case SND_SEQ_EVENT_CONTROL14: case SND_SEQ_EVENT_NONREGPARAM: case SND_SEQ_EVENT_REGPARAM: SETDICT_CTRL3; break; case SND_SEQ_EVENT_SONGPOS: case SND_SEQ_EVENT_SONGSEL: case SND_SEQ_EVENT_QFRAME: case SND_SEQ_EVENT_TIMESIGN: case SND_SEQ_EVENT_KEYSIGN: SETDICT_CTRL1; break; case SND_SEQ_EVENT_START: case SND_SEQ_EVENT_CONTINUE: case SND_SEQ_EVENT_STOP: case SND_SEQ_EVENT_SETPOS_TICK: case SND_SEQ_EVENT_TEMPO: SETDICT_QUEU1; break; case SND_SEQ_EVENT_CLOCK: case SND_SEQ_EVENT_TICK: break; case SND_SEQ_EVENT_QUEUE_SKEW: SETDICT_QUEU1; break; case SND_SEQ_EVENT_TUNE_REQUEST: case SND_SEQ_EVENT_RESET: case SND_SEQ_EVENT_SENSING: break; case SND_SEQ_EVENT_CLIENT_START: case SND_SEQ_EVENT_CLIENT_EXIT: case SND_SEQ_EVENT_CLIENT_CHANGE: SETDICT_ADDR1; break; case SND_SEQ_EVENT_PORT_START: case SND_SEQ_EVENT_PORT_EXIT: case SND_SEQ_EVENT_PORT_CHANGE: SETDICT_ADDR2; break; case SND_SEQ_EVENT_PORT_SUBSCRIBED: case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: SETDICT_CONN4; break; case SND_SEQ_EVENT_SYSEX: SETDICT_EXT; break; } return dict; } /** alsaseq.SeqEvent set_data() method: __doc__ */ PyDoc_STRVAR(SeqEvent_set_data__doc__, "set_data(dict)" "\n" "Changes the data of this SeqEvent, updating internal data structure \n" "from the given dictionary.\n" "\n" "The dictionary items should be the same as described in the get_data() \n" "method and be the appropiate for this SeqEvent type.\n" "\n" "This method does not check if a given structure correspond to is valid \n" "for this SeqEvent type; so setting the 'control.param' or the 'ext' \n" "structures for a NOTE SeqEvent may change another data structure \n" "or will simple have no effect once sent." ); /** alsaseq.SeqEvent set_data() method */ static PyObject * SeqEvent_set_data(SeqEventObject *self, PyObject *args) { PyObject *dict = NULL; snd_seq_event_t *event = self->event; if (!PyArg_ParseTuple(args, "O", &dict)) { return NULL; } if (!PyDict_Check(dict)) { PyErr_SetString(PyExc_TypeError, "must be a dictionary"); return NULL; } GETDICTINT("note.channel", event->data.note.channel); GETDICTINT("note.note", event->data.note.note); GETDICTINT("note.velocity", event->data.note.velocity); GETDICTINT("note.off_velocity", event->data.note.off_velocity); GETDICTINT("note.duration", event->data.note.duration); GETDICTINT("control.channel", event->data.control.channel); GETDICTINT("control.param", event->data.control.param); GETDICTINT("control.value", event->data.control.value); GETDICTEXT("ext"); GETDICTINT("queue.queue", event->data.queue.queue); GETDICTINT("queue.param.value", event->data.queue.param.value); GETDICTINT("addr.client", event->data.addr.client); GETDICTINT("addr.port", event->data.addr.port); GETDICTINT("connect.sender.client", event->data.connect.sender.client); GETDICTINT("connect.sender.port", event->data.connect.sender.port); GETDICTINT("connect.dest.client", event->data.connect.dest.client); GETDICTINT("connect.dest.port", event->data.connect.dest.port); GETDICTINT("result.event", event->data.result.event); GETDICTINT("result.result", event->data.result.result); Py_RETURN_NONE; } /** alsaseq.SeqEvent tp_methods */ static PyMethodDef SeqEvent_methods[] = { {"get_data", (PyCFunction) SeqEvent_get_data, METH_VARARGS, SeqEvent_get_data__doc__}, {"set_data", (PyCFunction) SeqEvent_set_data, METH_VARARGS, SeqEvent_set_data__doc__}, {NULL} }; /** alsaseq.SeEvent type */ static PyTypeObject SeqEventType = { PyObject_HEAD_INIT(NULL) tp_name: "alsaseq.SeqEvent", tp_basicsize: sizeof(SeqEventObject), tp_dealloc: (destructor) SeqEvent_dealloc, tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, tp_doc: SeqEvent__doc__, tp_init: (initproc)SeqEvent_init, tp_new : SeqEvent_new, tp_alloc: PyType_GenericAlloc, tp_free: PyObject_Del, tp_methods: SeqEvent_methods, tp_getset: SeqEvent_getset, tp_repr: (reprfunc)SeqEvent_repr, }; ////////////////////////////////////////////////////////////////////////////// // alsaseq.Sequencer implementation ////////////////////////////////////////////////////////////////////////////// /** alsaseq.Sequencer __doc__ */ PyDoc_STRVAR(Sequencer__doc__, "Sequencer([name, clientname, streams, mode, maxreceiveevents]) " "-> Sequencer object\n" "\n" "Creates and opens an ALSA sequencer. The features of the Sequencer are:\n" "- send/receive events (as SeqEvent objects)\n" "- create ports\n" "- list all ALSA clients and their port connections\n" "- connect/disconnect arbitrary ports\n" "- create and control queues\n" "- get info about a port or a client\n" "\n" "The name must correspond to the special ALSA name (for example: 'hw'); \n" "if not specified, 'default' is used. The clientname is the name of this \n" "client; if not specified, 'pyalsa-PID' is used.\n" "\n" "The streams specifies if you want to receive, send or both; use \n" "SEQ_OPEN_INPUT, SEQ_OPEN_OUTPUT or SEQ_OPEN_DUPLEX. If not specified, \n" "SEQ_OPEN_DUPLEX is used." "\n" "The mode specifies if this client should block or not, use SEQ_BLOCK or \n" "SEQ_NONBLOCK. If not specified, SEQ_NONBLOCK is used." "\n" "The maxreceiveevents is a number that represents how many SeqEvent \n" "objects are returned by the receive() method. If not specified, the \n" "default is 4. \n" "\n" "There is no method for closing the sequencer, it will remain open as \n" "long as the Sequencer object exists. For closing the sequencer you \n" "must explicitly del() the returned object." ); /** alsaseq.Sequencer object structure type */ typedef struct { PyObject_HEAD /* streams */ int streams; /* mode */ int mode; /* alsa handler */ snd_seq_t *handle; /* max fd's */ int receive_max; /* receive poll fd's */ struct pollfd *receive_fds; /* max events for returning in receive_events() */ int receive_max_events; /* remaining bytes from input */ int receive_bytes; } SequencerObject; /** alsaseq.Sequencer type (initialized later...) */ static PyTypeObject SequencerType; /** alsaseq.Sequencer: tp_init */ static int Sequencer_init(SequencerObject *self, PyObject *args, PyObject *kwds) { int ret; /* defaults */ char *name = "default"; char *clientname = NULL; char tmpclientname[1024]; self->streams = SND_SEQ_OPEN_DUPLEX; self->mode = SND_SEQ_NONBLOCK; int maxreceiveevents = 4; char *kwlist[] = { "name", "clientname", "streams", "mode", "maxreceiveevents", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssiii", kwlist, &name, &clientname, &self->streams, &self->mode, &maxreceiveevents)) { return -1; } if (clientname == NULL) { tmpclientname[0] = 0; sprintf(tmpclientname, "pyalsa-%d", getpid()); clientname = tmpclientname; } self->receive_fds = NULL; self->receive_max = 0; self->receive_bytes = 0; self->receive_max_events = maxreceiveevents; ret = snd_seq_open(&(self->handle), name, self->streams, self->mode); if (ret < 0) { RAISESND(ret, "Failed to create sequencer"); return -1; } ret = snd_seq_set_client_name(self->handle, clientname); if (ret < 0) { RAISESND(ret, "Failed to set client name"); return -1; } return 0; } /** alsaseq.Sequencer: tp_dealloc */ static void Sequencer_dealloc(SequencerObject *self) { FREECHECKED("receive_fds", self->receive_fds); if (self->handle) { snd_seq_close(self->handle); self->handle = NULL; } self->ob_type->tp_free(self); } /** alsaseq.Sequencer name attribute: __doc__ */ PyDoc_STRVAR(Sequencer_name__doc__, "name -> string\n" "\n" "The alsa device name of this alsaseq.Sequencer.\n" "Note: read-only attribute." ); /** alsaseq.Sequencer name attribute: tp_getset getter() */ static PyObject * Sequencer_get_name(SequencerObject *self) { return PyString_FromString(snd_seq_name(self->handle)); } /** alsaseq.Sequencer clientname attribute: __doc__ */ PyDoc_STRVAR(Sequencer_clientname__doc__, "clientname -> string\n" "\n" "The client name of this alsaseq.Sequencer\n" ); /** alsaseq.Sequencer clientname attribute: tp_getset getter() */ static PyObject * Sequencer_get_clientname(SequencerObject *self) { snd_seq_client_info_t *cinfo; snd_seq_client_info_alloca(&cinfo); snd_seq_get_client_info(self->handle, cinfo); return PyString_FromString(snd_seq_client_info_get_name(cinfo)); } /** alsaseq.Sequencer clientname attribute: tp_getset setter() */ static int Sequencer_set_clientname(SequencerObject *self, PyObject *val) { char *buff; SETCHECKPYSTR("clientname", val); buff = PyString_AsString(val); snd_seq_set_client_name(self->handle, PyString_AsString(val)); return 0; } /** alsaseq.Sequencer streams attribute: __doc__ */ PyDoc_STRVAR(Sequencer_streams__doc__, "streams -> Constant object\n" "\n" "The streams of this alsaseq.Sequencer. Posible values:\n" "alsaseq.SEQ_OPEN_OUTPUT, alsaseq.SEQ_OPEN_INPUT, \n" "alsaseq.SEQ_OPEN_DUPLEX.\n" "Note: read-only attribute." ); /** alsaseq.Sequencer streams attribute: tp_getset getter() */ static PyObject * Sequencer_get_streams(SequencerObject *self) { TCONSTRETURN(STREAMS, self->streams); } /** alsaseq.Sequencer mode attribute: __doc__ */ PyDoc_STRVAR(Sequencer_mode__doc__, "mode -> Constant object\n" "\n" "The blocking mode of this alsaseq.Sequencer. Use\n" "alsaseq.SEQ_BLOCK, alsaseq.SEQ_NONBLOCK." ); /** alsaseq.Sequencer mode attribute: tp_getset getter() */ static PyObject *Sequencer_get_mode(SequencerObject *self) { TCONSTRETURN(MODE, self->mode); } /** alsaseq.Sequencer mode attribute: tp_getset setter() */ static int Sequencer_set_mode(SequencerObject *self, PyObject *val) { int ret, mode; SETCHECKPYINT("mode", val); mode = (int) PyInt_AsLong(val); if (mode != 0 && mode != SND_SEQ_NONBLOCK) { PyErr_SetString(PyExc_ValueError, "Invalid value for mode."); return -1; } ret = snd_seq_nonblock(self->handle, mode); if (ret == 0) { self->mode = mode; } else { RAISESND(ret, "Failed to set mode"); return -1; } return 0; } /** alsaseq.Sequencer client_id attribute: __doc__ */ PyDoc_STRVAR(Sequencer_client_id__doc__, "client_id -> int\n" "\n" "The client id of this alsaseq.Sequencer.\n" "Note: read-only attribute." ); /** alsaseq.Sequencer client_id attribute: tp_getset getter() */ static PyObject * Sequencer_get_client_id(SequencerObject *self) { snd_seq_client_info_t *cinfo; snd_seq_client_info_alloca(&cinfo); snd_seq_get_client_info(self->handle, cinfo); return PyInt_FromLong(snd_seq_client_info_get_client(cinfo)); } /** alsaseq.Sequencer: tp_getset list*/ static PyGetSetDef Sequencer_getset[] = { {"name", (getter) Sequencer_get_name, NULL, (char *) Sequencer_name__doc__, NULL}, {"clientname", (getter) Sequencer_get_clientname, (setter) Sequencer_set_clientname, (char *) Sequencer_clientname__doc__, NULL}, {"streams", (getter) Sequencer_get_streams, NULL, (char *) Sequencer_streams__doc__, NULL}, {"mode", (getter) Sequencer_get_mode, (setter) Sequencer_set_mode, (char *) Sequencer_mode__doc__, NULL}, {"client_id", (getter) Sequencer_get_client_id, NULL, (char *) Sequencer_client_id__doc__, NULL}, {NULL} }; /** alsaseq.Sequencer: tp_repr */ static PyObject * Sequencer_repr(SequencerObject *self) { snd_seq_client_info_t *cinfo; snd_seq_client_info_alloca(&cinfo); snd_seq_get_client_info(self->handle, cinfo); return PyString_FromFormat("", snd_seq_name(self->handle), snd_seq_client_info_get_client(cinfo), snd_seq_client_info_get_name(cinfo), self->streams, self->mode, self ); } /** alsaseq.Sequencer create_simple_port() method: __doc__ */ PyDoc_STRVAR(Sequencer_create_simple_port__doc__, "create_simple_port(name, type, caps=0) -> int" "\n" "Creates a port for receiving or sending events.\n" "\n" "Parameters:\n" " name -- name of the port\n" " type -- type of port (use one of the alsaseq.SEQ_PORT_TYPE_*\n" " constants)\n" " caps -- capabilites of the port (use bitwise alsaseq.SEQ_PORT_CAP_*\n" " constants). Default=0\n" "Returns:\n" " the port id.\n" "Raises:\n" " TypeError: if an invalid type was used in a parameter\n" " ValueError: if an invalid value was used in a parameter\n" " SequencerError: if ALSA can't create the port" ); /** alsaseq.Sequencer create_simple_port() method */ static PyObject * Sequencer_create_simple_port(SequencerObject *self, PyObject *args, PyObject *kwds) { char *name; unsigned int type; unsigned int caps=0; char *kwlist[] = { "name", "type", "caps", NULL }; int port; if (!PyArg_ParseTupleAndKeywords(args, kwds, "sI|I", kwlist, &name, &type, &caps)) { return NULL; } port = snd_seq_create_simple_port(self->handle, name, caps, type); if (port < 0) { RAISESND(port, "Failed to create simple port"); return NULL; } return PyInt_FromLong(port); } /** alsaseq.Sequencer connection_list() method: __doc__ */ PyDoc_STRVAR(Sequencer_connection_list__doc__, "connection_list() -> list\n" "\n" "List all clients and their ports connections.\n" "\n" "Returns:\n" " (list) a list of tuples: client_name, client_id, port_list:.\n" " client_name -- the client's name.\n" " client_id -- the client's id.\n" " port_list -- a list of tuples: port_name, port_id, connection_list:\n" " port_name -- the name of the port.\n" " port_id -- the port id.\n" " connection_list -- a list of tuples: read_conn, write_conn:\n" " read_conn -- a list of (client_id, port_id, info) tuples this\n" " port is connected to (sends events);\n" " info is the same of the get_connect_info() method.\n" " write_conn -- a list of (client_id, port_id, info) tuples this\n" " port is connected from (receives events);\n" " info is the same of the get_connect_info() method.\n" ); static PyObject * _query_connections_list(snd_seq_t *handle, snd_seq_query_subscribe_t *query, int type) { PyObject *list = PyList_New(0); int index = 0; long tmplong; snd_seq_query_subscribe_set_type(query, type); snd_seq_query_subscribe_set_index(query, index); while (snd_seq_query_port_subscribers(handle, query) >= 0) { const snd_seq_addr_t *addr = snd_seq_query_subscribe_get_addr(query); PyObject *dict = PyDict_New(); tmplong = snd_seq_query_subscribe_get_queue(query); PyDict_SetItemString(dict, "queue", PyInt_FromLong(tmplong)); tmplong = snd_seq_query_subscribe_get_exclusive(query); PyDict_SetItemString(dict, "exclusive", PyInt_FromLong(tmplong)); tmplong = snd_seq_query_subscribe_get_time_update(query); PyDict_SetItemString(dict, "time_update", PyInt_FromLong(tmplong)); tmplong = snd_seq_query_subscribe_get_time_real(query); PyDict_SetItemString(dict, "time_real", PyInt_FromLong(tmplong)); PyObject *tuple = PyTuple_New(3); PyTuple_SetItem(tuple, 0, PyInt_FromLong(addr->client)); PyTuple_SetItem(tuple, 1, PyInt_FromLong(addr->port)); PyTuple_SetItem(tuple, 2, dict); PyList_Append(list, tuple); snd_seq_query_subscribe_set_index(query, ++index); } return list; } static PyObject * _query_connections(snd_seq_t *handle, const snd_seq_addr_t *addr) { snd_seq_query_subscribe_t *query; snd_seq_query_subscribe_alloca(&query); snd_seq_query_subscribe_set_root(query, addr); // create tuple for read,write lists PyObject *tuple = PyTuple_New(2); PyObject *readlist = _query_connections_list(handle, query, SND_SEQ_QUERY_SUBS_READ); PyObject *writelist = _query_connections_list(handle, query, SND_SEQ_QUERY_SUBS_WRITE); PyTuple_SetItem(tuple, 0, readlist); PyTuple_SetItem(tuple, 1, writelist); return tuple; } /** alsaseq.Sequencer connection_list() method */ static PyObject * Sequencer_connection_list(SequencerObject *self, PyObject *args) { snd_seq_client_info_t *cinfo; snd_seq_port_info_t *pinfo; PyObject *client, *port, *name; PyObject *list = PyList_New(0); if (list == NULL) { return NULL; } snd_seq_client_info_alloca(&cinfo); snd_seq_port_info_alloca(&pinfo); snd_seq_client_info_set_client(cinfo, -1); while (snd_seq_query_next_client(self->handle, cinfo) >= 0) { /* reset query info */ snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo)); snd_seq_port_info_set_port(pinfo, -1); /* create tuple for client info */ PyObject *tuple = PyTuple_New(3); PyObject *portlist = PyList_New(0); name = PyString_FromFormat("%s", snd_seq_client_info_get_name(cinfo)); client = PyInt_FromLong(snd_seq_client_info_get_client(cinfo)); PyTuple_SetItem(tuple, 0, name); PyTuple_SetItem(tuple, 1, client); while (snd_seq_query_next_port(self->handle, pinfo) >= 0) { /* create tuple for port info */ PyObject *porttuple = PyTuple_New(3); name = PyString_FromFormat("%s", snd_seq_port_info_get_name(pinfo)); port = PyInt_FromLong(snd_seq_port_info_get_port(pinfo)); PyTuple_SetItem(porttuple, 0, name); PyTuple_SetItem(porttuple, 1, port); /* create tuple for read,write connections */ PyObject *conntuple = _query_connections(self->handle, snd_seq_port_info_get_addr(pinfo)); PyTuple_SetItem(porttuple, 2, conntuple); PyList_Append(portlist, porttuple); } PyTuple_SetItem(tuple, 2, portlist); /* append list of port tuples */ PyList_Append(list, tuple); } return list; } /** alsaseq.Sequencer get_client_info() method: __doc__ */ PyDoc_STRVAR(Sequencer_get_client_info__doc__, "get_client_info(client_id = self.client_id) -> dictionary\n" "\n" "Retrieve info about an existing client.\n" "\n" "Parameters:\n" " client_id -- the client id (defaults to: self.client_id)\n" "Returns:\n" " (dict) a dictionary with the following values:\n" " id -- id of client.\n" " type -- type of client (SEQ_USER_CLIENT or SEQ_KERNEL_CLIENT).\n" " name -- name of client.\n" " broadcast_filter -- broadcast filter flag of client as int.\n" " error_bounce -- error bounce of client as int.\n" " event_filter -- event filter of client as string.\n" " num_ports -- number of opened ports of client.\n" " event_lost -- number of lost events of client.\n" "Raises:\n" " SequencerError: ALSA error occurred." ); /** alsaseq.Sequencer get_client_info() method */ static PyObject * Sequencer_get_client_info(SequencerObject *self, PyObject *args, PyObject *kwds) { snd_seq_client_info_t *cinfo; int client_id = -1; int ret; PyObject *tmpobj; long tmplong; const char * tmpchar; char *kwlist[] = { "client_id", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &client_id)) { return NULL; } snd_seq_client_info_alloca(&cinfo); if (client_id == -1) { ret = snd_seq_get_client_info(self->handle, cinfo); if (ret < 0) { RAISESND(ret, "Failed to retrieve client info for self.client_id"); return NULL; } client_id = snd_seq_client_info_get_client(cinfo); } else { ret = snd_seq_get_any_client_info(self->handle, client_id, cinfo); if (ret < 0) { RAISESND(ret, "Failed to retrieve client info for '%d'", client_id); return NULL; } } PyObject *dict = PyDict_New(); if (dict == NULL) { return NULL; } TCONSTASSIGN(ADDR_CLIENT, client_id, tmpobj); PyDict_SetItemString(dict, "id", tmpobj); tmplong = snd_seq_client_info_get_type(cinfo); TCONSTASSIGN(CLIENT_TYPE, tmplong, tmpobj); PyDict_SetItemString(dict, "type", tmpobj); tmpchar = snd_seq_client_info_get_name(cinfo); tmpchar = (tmpchar == NULL ? "" : tmpchar); PyDict_SetItemString(dict, "name", PyString_FromString(tmpchar)); tmplong = snd_seq_client_info_get_broadcast_filter(cinfo); PyDict_SetItemString(dict, "broadcast_filter", PyInt_FromLong(tmplong)); tmplong = snd_seq_client_info_get_error_bounce(cinfo); PyDict_SetItemString(dict, "error_bounce", PyInt_FromLong(tmplong)); tmpchar = (const char *)snd_seq_client_info_get_event_filter(cinfo); tmpchar = (tmpchar == NULL ? "" : tmpchar); PyDict_SetItemString(dict, "event_filter", PyString_FromString(tmpchar)); tmplong = snd_seq_client_info_get_num_ports(cinfo); PyDict_SetItemString(dict, "num_ports", PyInt_FromLong(tmplong)); tmplong = snd_seq_client_info_get_event_lost(cinfo); PyDict_SetItemString(dict, "event_lost", PyInt_FromLong(tmplong)); return dict; } /** alsaseq.Sequencer get_port_info() method: __doc__ */ PyDoc_STRVAR(Sequencer_get_port_info__doc__, "get_port_info(port_id, client_id = self.client_id) -> dictionary\n" "\n" "Retrieve info about an existing client's port.\n" "\n" "Parameters:\n" " port_id -- the port id\n" " client_id -- the client id (defaults to: self.client_id)\n" "Returns:\n" " (dict) a dictionary with the following values:\n" " name -- the port name\n" " type -- the port type bit flags\n" " capability -- the port capability bit flags as integer\n" "Raises:\n" " SequencerError: ALSA error occurred." ); /** alsaseq.Sequencer get_port_info() method */ static PyObject * Sequencer_get_port_info(SequencerObject *self, PyObject *args, PyObject *kwds) { snd_seq_port_info_t *pinfo; snd_seq_client_info_t *cinfo; int port_id; int client_id; const char *tmpchar; long tmplong; int ret; char *kwlist[] = { "port_id", "client_id", NULL }; snd_seq_client_info_alloca(&cinfo); ret = snd_seq_get_client_info(self->handle, cinfo); if (ret < 0) { RAISESND(ret, "Failed to determine self.client_id"); return NULL; } client_id = snd_seq_client_info_get_client(cinfo); if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwlist, &port_id, &client_id)) { return NULL; } PyObject *dict = PyDict_New(); if (dict == NULL) { return NULL; } snd_seq_port_info_alloca(&pinfo); ret = snd_seq_get_any_port_info(self->handle, client_id, port_id, pinfo); if (ret < 0) { RAISESND(ret, "Failed to get port info for %d:%d", client_id, port_id); return NULL; } tmpchar = snd_seq_port_info_get_name(pinfo); tmpchar = (tmpchar == NULL ? "" : tmpchar); PyDict_SetItemString(dict, "name", PyString_FromString(tmpchar)); tmplong = snd_seq_port_info_get_capability(pinfo); PyDict_SetItemString(dict, "capability", PyInt_FromLong(tmplong)); tmplong = snd_seq_port_info_get_type(pinfo); PyDict_SetItemString(dict, "type", PyInt_FromLong(tmplong)); return dict; } /** alsaseq.Sequencer connect_ports() method: __doc__ */ PyDoc_STRVAR(Sequencer_connect_ports__doc__, "connect_ports(srcaddr,dstaddr,queue,exclusive,time_update,time_real)\n" "\n" "Connect the ports specified by srcaddr and dstaddr.\n" "\n" "Parameters:\n" " srcaddr -- (tuple) the (client_id, port_id) tuple for the source\n" " port (the port sending events)\n" " dstaddr -- (tuple) the (client_id, port_id) tuple for the destination\n" " port (the port receiveng events)\n" " queue -- the queue of the connection.\n" " If not specified, defaults to 0.\n" " exclusive -- 1 if the connection is exclusive, 0 otherwise.\n" " If not specified, defaults to 0.\n" " time_update -- 1 if the connection should update time, 0 otherwise.\n" " If not specified, defaults to 0.\n" " time_real -- 1 if the update time is in real, 0 if is in tick.\n" " If not specified, defaults to 0.\n" "Raises:\n" " SequenceError: if ALSA can't connect the ports" ); /** alsaseq.Sequencer connect_ports() method */ static PyObject * Sequencer_connect_ports(SequencerObject *self, PyObject *args) { snd_seq_addr_t sender, dest; snd_seq_port_subscribe_t *sinfo; int ret; int queue = 0; int exclusive = 0; int time_update = 0; int time_real = 0; if (!PyArg_ParseTuple(args, "(BB)(BB)|iiii", &(sender.client), &(sender.port), &(dest.client), &(dest.port), &queue, &exclusive, &time_update, &time_real)) { return NULL; } snd_seq_port_subscribe_alloca(&sinfo); snd_seq_port_subscribe_set_sender(sinfo, &sender); snd_seq_port_subscribe_set_dest(sinfo, &dest); snd_seq_port_subscribe_set_queue(sinfo, queue); snd_seq_port_subscribe_set_exclusive(sinfo, exclusive); snd_seq_port_subscribe_set_time_update(sinfo, time_update); snd_seq_port_subscribe_set_time_real(sinfo, time_real); ret = snd_seq_subscribe_port(self->handle, sinfo); if (ret < 0) { RAISESND(ret, "Failed to connect ports %d:%d -> %d:%d", sender.client, sender.port, dest.client, dest.port); return NULL; } Py_RETURN_NONE; } /** alsaseq.Sequencer disconnect_ports() method: __doc__ */ PyDoc_STRVAR(Sequencer_disconnect_ports__doc__, "disconnect_ports(srcaddr, destaddr)\n" "\n" "Disconnect the ports specified by srcaddr and dstaddr.\n" "\n" "Parameters:\n" " srcaddr -- (tuple) the client_id, port_id tuple for the source\n" " port (the port sending events)\n" " dstaddr -- (tuple) the client_id, port_id tuple for the destination\n" " port (the port receiveng events)\n" "Raises:\n" " SequenceError: if ALSA can't disconnect the port" ); /** alsaseq.Sequencer disconnect_ports() method */ static PyObject * Sequencer_disconnect_ports(SequencerObject *self, PyObject *args) { snd_seq_addr_t sender, dest; snd_seq_port_subscribe_t *sinfo; int ret; if (!PyArg_ParseTuple(args, "(BB)(BB)", &(sender.client), &(sender.port), &(dest.client), &(dest.port))) { return NULL; } snd_seq_port_subscribe_alloca(&sinfo); snd_seq_port_subscribe_set_sender(sinfo, &sender); snd_seq_port_subscribe_set_dest(sinfo, &dest); ret = snd_seq_unsubscribe_port(self->handle, sinfo); if (ret < 0) { RAISESND(ret, "Failed to disconnect ports: %d:%d --> %d:%d", sender.client, sender.port, dest.client, dest.port); return NULL; } Py_RETURN_NONE; } /** alsaseq.Sequencer get_connect_info() method: __doc__ */ PyDoc_STRVAR(Sequencer_get_connect_info__doc__, "get_connect_info(srcaddr, dstaddr) -> dictionary\n" "\n" "Retrieve the subscribe info of the specified connection.\n" "\n" "Parameters:\n" " srcaddr -- (tuple) the client_id, port_id tuple for the source\n" " port (the port sending events)\n" " dstaddr -- (tuple) the client_id, port_id tuple for the destination\n" " port (the port receiveng events)\n" "Returns:\n" " (dict) a dictionary with the following values:\n" " queue -- \n" " exclusive -- \n" " time_update -- \n" " time_real --- \n" "Raises:\n" " SequenceError: if ALSA can't retrieve the connection or the\n" " connection doesn't exists." ); static PyObject* Sequencer_get_connect_info(SequencerObject *self, PyObject *args) { snd_seq_addr_t sender, dest; snd_seq_port_subscribe_t *sinfo; int ret; long tmplong; if (!PyArg_ParseTuple(args, "(BB)(BB)", &(sender.client), &(sender.port), &(dest.client), &(dest.port))) { return NULL; } snd_seq_port_subscribe_alloca(&sinfo); snd_seq_port_subscribe_set_sender(sinfo, &sender); snd_seq_port_subscribe_set_dest(sinfo, &dest); ret = snd_seq_get_port_subscription(self->handle, sinfo); if (ret < 0) { RAISESND(ret, "Failed to get port subscript: %d:%d --> %d:%d", sender.client, sender.port, dest.client, dest.port); return NULL; } PyObject *dict = PyDict_New(); tmplong = snd_seq_port_subscribe_get_queue(sinfo); PyDict_SetItemString(dict, "queue", PyInt_FromLong(tmplong)); tmplong = snd_seq_port_subscribe_get_exclusive(sinfo); PyDict_SetItemString(dict, "exclusive", PyInt_FromLong(tmplong)); tmplong = snd_seq_port_subscribe_get_time_update(sinfo); PyDict_SetItemString(dict, "time_update", PyInt_FromLong(tmplong)); tmplong = snd_seq_port_subscribe_get_time_real(sinfo); PyDict_SetItemString(dict, "time_real", PyInt_FromLong(tmplong)); return dict; } /** alsaseq.Sequencer receive_events() method: __doc__ */ PyDoc_STRVAR(Sequencer_receive_events__doc__, "receive_events(timeout = 0, maxevents = self.receive_maxevents) -> list\n" "\n" "Receive events.\n" "\n" "Parameters:\n" " timeout -- (int) time for wating for events in miliseconds\n" " maxevents -- (int) max events to be returned\n" "Returns:\n" " (list) a list of alsaseq.SeqEvent objects\n" "Raises:\n" " TypeError: if an invalid type was used in a parameter\n" " SequencerError: if ALSA error occurs." ); /** alsaseq.Sequencer receive_events() method */ static PyObject * Sequencer_receive_events(SequencerObject *self, PyObject *args, PyObject *kwds) { int maxevents = self->receive_max_events; snd_seq_event_t *event = NULL; int timeout = 0; int ret; char *kwlist[] = {"timeout", "maxevents", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, &timeout, &maxevents)) { return NULL; } if (self->receive_fds == NULL) { self->receive_max = snd_seq_poll_descriptors_count(self->handle, POLLOUT); self->receive_fds = malloc(sizeof(struct pollfd) * self->receive_max); } PyObject *list = PyList_New(0); if (list == NULL) { return NULL; } if (self->receive_bytes <= 0 && timeout != 0) { snd_seq_poll_descriptors(self->handle, self->receive_fds, self->receive_max, POLLIN); Py_BEGIN_ALLOW_THREADS; ret = poll(self->receive_fds, self->receive_max, timeout); Py_END_ALLOW_THREADS; if (ret == 0) { return list; } else if (ret < 0) { RAISESTR("Failed to poll from receive: %s", strerror(-ret)); return NULL; } } do { ret = snd_seq_event_input(self->handle, &event); self->receive_bytes = ret; if (ret < 0) { if (ret != -EAGAIN) { } break; } PyObject *SeqEventObject = SeqEvent_create(event); if (SeqEventObject == NULL) { RAISESTR("Error creating event!"); return NULL; } PyList_Append(list, SeqEventObject); maxevents --; } while (maxevents > 0 && ret > 0); return list; } /** alsaseq.Sequencer output_event() method: __doc__ */ PyDoc_STRVAR(Sequencer_output_event__doc__, "output_event(event)\n" "\n" "Put the the given event in the outputbuffer. This actually will enqueue\n" "the event, to make sure it's sent, use the drain_output() method.\n" "\n" "Parameters:\n" " event -- a SeqEvent object\n" "Raises:\n" " SequencerError: if ALSA can't send the event" ); /** alsaseq.Sequencer output_event() method */ static PyObject * Sequencer_output_event(SequencerObject *self, PyObject *args, PyObject *kwds) { SeqEventObject *seqevent; char *kwlist[] = {"event", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &seqevent)) { return NULL; } if (!PyObject_TypeCheck(seqevent, &SeqEventType)) { PyErr_SetString(PyExc_TypeError, "alsaseq.SeqEvent expected"); return NULL; } snd_seq_event_output(self->handle, seqevent->event); Py_RETURN_NONE; } /** alsaseq.Sequencer drain_output() method: __doc__ */ PyDoc_STRVAR(Sequencer_drain_output__doc__, "drain_output()\n" "\n" "Drain the output, making sure all events int the buffer are sent.\n" "The events sent may remain unprocessed, to make sure they are\n" "processed, call the sync_output_queue() method.\n" "\n" "Raises:\n" " SequencerError: if ALSA can't drain the output" ); /** alsaseq.Sequencer drain_output() method */ static PyObject *Sequencer_drain_output(SequencerObject *self, PyObject *args) { int ret; ret = snd_seq_drain_output(self->handle); if (ret < 0) { RAISESND(ret, "Failed to drain output"); return NULL; } Py_RETURN_NONE; } /** alsaseq.Sequencer sync_output_queue() method: __doc__ */ PyDoc_STRVAR(Sequencer_sync_output_queue__doc__, "sync_output_queue()\n" "\n" "Waits until all events of this clients are processed.\n" "\n" "Raises:\n" " SequencerError: if an ALSA error occurs." ); /** alsaseq.Sequencer sync_output_queue() method */ static PyObject * Sequencer_sync_output_queue(SequencerObject *self, PyObject *args) { int ret; ret = snd_seq_sync_output_queue(self->handle); if (ret < 0) { RAISESND(ret, "Failed to sync output queue"); return NULL; } Py_RETURN_NONE; } /** alsaseq.Sequencer parse_address() method: __doc__ */ PyDoc_STRVAR(Sequencer_parse_address__doc__, "parse_address(string) -> tuple\n" "\n" "Parses the given string as an ALSA client:port. You can use client,\n" "port id's or names.\n" "\n" "Parameters:\n" " string -- the address in the format client:port.\n" "Returns:\n" " the tuple (client_id, port_id).\n" "Raises:\n" " SequencerError: if ALSA can't parse the given address" ); /** alsaseq.Sequencer parse_address() method */ static PyObject * Sequencer_parse_address(SequencerObject *self, PyObject *args) { snd_seq_addr_t addr; char *str = NULL; int ret; if (!PyArg_ParseTuple(args, "s", &(str))) { return NULL; } ret = snd_seq_parse_address(self->handle, &addr, str); if (ret < 0) { RAISESND(ret, "Invalid client:port specification '%s'", str); return NULL; } PyObject *tuple = PyTuple_New(2); PyTuple_SetItem(tuple, 0, PyInt_FromLong(addr.client)); PyTuple_SetItem(tuple, 1, PyInt_FromLong(addr.port)); return tuple; } /** alsaseq.Sequencer create_queue() method: __doc__ */ PyDoc_STRVAR(Sequencer_create_queue__doc__, "create_queue(name=None)-> int\n" "\n" "Creates a queue with the optional given name.\n" "\n" "Parameters:\n" " name -- the name of the queue.\n" "Returns:\n" " the queue id.\n" "Raises:\n" " SequencerError: if ALSA can't create the queue" ); /** alsaseq.Sequencer create_queue() method */ static PyObject * Sequencer_create_queue(SequencerObject *self, PyObject *args, PyObject *kwds) { char *kwlist[] = {"name", NULL}; char *queue_name = NULL; int ret; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &queue_name)) { return NULL; } if (queue_name != NULL) { ret = snd_seq_alloc_named_queue(self->handle, queue_name); } else { ret = snd_seq_alloc_queue(self->handle); } if (ret < 0) { RAISESND(ret, "Failed to create queue"); return NULL; } return PyInt_FromLong(ret); } /** alsaseq.Sequencer delete_queue() method: __doc__ */ PyDoc_STRVAR(Sequencer_delete_queue__doc__, "delete_queue(queue)\n" "\n" "Deletes (frees) a queue.\n" "\n" "Parameters:\n" " queue -- the queue id.\n" "Raises:\n" " SequencerError: if ALSA can't delete the queue." ); /** alsaseq.Sequencer delete_queue() method */ static PyObject * Sequencer_delete_queue(SequencerObject *self, PyObject *args, PyObject *kwds) { char *kwlist[] = {"queue", NULL}; int queue_id; int ret; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &queue_id)) { return NULL; } ret = snd_seq_free_queue(self->handle, queue_id); if (ret < 0) { RAISESND(ret, "Failed to create queue"); return NULL; } Py_RETURN_NONE; } /** alsaseq.Sequencer queue_tempo() method: __doc__ */ PyDoc_STRVAR(Sequencer_queue_tempo__doc__, "queue_tempo(queue, tempo=None, ppq=None) -> tuple" "\n" "Query and changes the queue tempo. For querying (not changing) the queue\n" "tempo, pass only the queue id.\n" "\n" "Parameters:\n" " queue -- the queue id.\n" " tempo -- the new queue tempo or None for keeping the current tempo.\n" " ppq -- the new queue ppq or None for keeping the current tempo.\n" "Returns:\n" " a tuple (tempo, ppq) with the current or changed tempo.\n" "Raises:\n" " SequencerError: if ALSA can't change the queue tempo or an invalid\n" " queue was specified." ); /** alsaseq.Sequencer queue_tempo() method */ static PyObject * Sequencer_queue_tempo(SequencerObject *self, PyObject *args, PyObject *kwds) { char *kwlist[] = {"queue", "tempo", "ppq", NULL}; int queueid, tempo=-1, ppq=-1; int ret; snd_seq_queue_tempo_t *queue_tempo; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwlist, &queueid, &tempo, &ppq)) { return NULL; } snd_seq_queue_tempo_alloca(&queue_tempo); ret = snd_seq_get_queue_tempo(self->handle, queueid, queue_tempo); if (ret < 0) { RAISESND(ret, "Failed to retrieve current queue tempo"); return NULL; } if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwlist, &queueid, &tempo, &ppq)) { return NULL; } if (tempo != -1) { snd_seq_queue_tempo_set_tempo(queue_tempo, tempo); } if (ppq != -1) { snd_seq_queue_tempo_set_ppq(queue_tempo, ppq); } if (tempo != -1 && ppq != -1) { ret = snd_seq_set_queue_tempo(self->handle, queueid, queue_tempo); if (ret < 0) { RAISESND(ret, "Failed to set queue tempo"); return NULL; } } tempo = snd_seq_queue_tempo_get_tempo(queue_tempo); ppq = snd_seq_queue_tempo_get_ppq(queue_tempo); PyObject *tuple = PyTuple_New(2); PyTuple_SetItem(tuple, 0, PyInt_FromLong(tempo)); PyTuple_SetItem(tuple, 1, PyInt_FromLong(ppq)); return tuple; } /** alsaseq.Sequencer start_queue() method: __doc__ */ PyDoc_STRVAR(Sequencer_start_queue__doc__, "start_queue(queue)\n" "\n" "Starts the specified queue.\n" "\n" "Parameters:\n" " queue -- the queue id.\n" "Raises:\n" " SequencerError: if ALSA can't start the queue." ); /** alsaseq.Sequencer start_queue() method */ static PyObject * Sequencer_start_queue(SequencerObject *self, PyObject *args, PyObject *kwds) { char *kwlist[] = {"queue", NULL}; int queueid; int ret; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &queueid)) { return NULL; } ret = snd_seq_start_queue(self->handle, queueid, NULL); if (ret < 0) { RAISESND(ret, "Failed to start queue"); return NULL; } Py_RETURN_NONE; } /** alsaseq.Sequencer stop_queue() method: __doc__ */ PyDoc_STRVAR(Sequencer_stop_queue__doc__, "stop_queue(queue)\n" "\n" "Stops the specified queue.\n" "\n" "Parameters:\n" " queue -- the queue id.\n" "Raises:\n" " SequencerError: if ALSA can't stop the queue." ); /** alsaseq.Sequencer stop_queue() method */ static PyObject * Sequencer_stop_queue(SequencerObject *self, PyObject *args, PyObject *kwds) { char *kwlist[] = {"queue", NULL}; int queueid; int ret; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &queueid)) { return NULL; } ret = snd_seq_stop_queue(self->handle, queueid, NULL); if (ret < 0) { RAISESND(ret, "Failed to stop queue"); return NULL; } Py_RETURN_NONE; } PyDoc_STRVAR(Sequencer_registerpoll__doc__, "register_poll(pollObj, input=False, output=False) -- Register poll file descriptors."); static PyObject * Sequencer_registerpoll(SequencerObject *self, PyObject *args, PyObject *kwds) { PyObject *pollObj, *reg, *t; struct pollfd *pfd; int i, count; int input = 0; int output = 0; int mode = POLLIN|POLLOUT; static char * kwlist[] = { "pollObj", "input", "output", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwlist, &pollObj, &input, &output)) return NULL; if (input && !output) mode = POLLIN; else if (!input && output) mode = POLLOUT; count = snd_seq_poll_descriptors_count(self->handle, mode); if (count <= 0) Py_RETURN_NONE; pfd = alloca(sizeof(struct pollfd) * count); count = snd_seq_poll_descriptors(self->handle, pfd, count, mode); if (count <= 0) Py_RETURN_NONE; reg = PyObject_GetAttr(pollObj, PyString_InternFromString("register")); for (i = 0; i < count; i++) { t = PyTuple_New(2); if (t) { PyTuple_SET_ITEM(t, 0, PyInt_FromLong(pfd[i].fd)); PyTuple_SET_ITEM(t, 1, PyInt_FromLong(pfd[i].events)); Py_XDECREF(PyObject_CallObject(reg, t)); Py_DECREF(t); } } Py_XDECREF(reg); Py_RETURN_NONE; } /** alsaseq.Sequencer tp_methods */ static PyMethodDef Sequencer_methods[] = { {"create_simple_port", (PyCFunction) Sequencer_create_simple_port, METH_VARARGS | METH_KEYWORDS, Sequencer_create_simple_port__doc__ }, {"connection_list", (PyCFunction) Sequencer_connection_list, METH_VARARGS, Sequencer_connection_list__doc__ }, {"get_client_info", (PyCFunction) Sequencer_get_client_info, METH_VARARGS | METH_KEYWORDS, Sequencer_get_client_info__doc__ }, {"get_port_info", (PyCFunction) Sequencer_get_port_info, METH_VARARGS | METH_KEYWORDS, Sequencer_get_port_info__doc__ }, {"connect_ports", (PyCFunction) Sequencer_connect_ports, METH_VARARGS, Sequencer_connect_ports__doc__ }, {"disconnect_ports", (PyCFunction) Sequencer_disconnect_ports, METH_VARARGS, Sequencer_disconnect_ports__doc__ }, {"get_connect_info", (PyCFunction) Sequencer_get_connect_info, METH_VARARGS, Sequencer_get_connect_info__doc__}, {"receive_events", (PyCFunction) Sequencer_receive_events, METH_VARARGS | METH_KEYWORDS, Sequencer_receive_events__doc__}, {"output_event", (PyCFunction) Sequencer_output_event, METH_VARARGS | METH_KEYWORDS, Sequencer_output_event__doc__}, {"drain_output", (PyCFunction) Sequencer_drain_output, METH_VARARGS, Sequencer_drain_output__doc__}, {"sync_output_queue", (PyCFunction) Sequencer_sync_output_queue, METH_VARARGS, Sequencer_sync_output_queue__doc__}, {"parse_address", (PyCFunction) Sequencer_parse_address, METH_VARARGS, Sequencer_parse_address__doc__}, {"create_queue", (PyCFunction) Sequencer_create_queue, METH_VARARGS | METH_KEYWORDS, Sequencer_create_queue__doc__}, {"delete_queue", (PyCFunction) Sequencer_delete_queue, METH_VARARGS | METH_KEYWORDS, Sequencer_delete_queue__doc__}, {"queue_tempo", (PyCFunction) Sequencer_queue_tempo, METH_VARARGS | METH_KEYWORDS, Sequencer_queue_tempo__doc__}, {"start_queue", (PyCFunction) Sequencer_start_queue, METH_VARARGS | METH_KEYWORDS, Sequencer_start_queue__doc__}, {"stop_queue", (PyCFunction) Sequencer_stop_queue, METH_VARARGS | METH_KEYWORDS, Sequencer_stop_queue__doc__}, {"register_poll", (PyCFunction) Sequencer_registerpoll, METH_VARARGS | METH_KEYWORDS, Sequencer_registerpoll__doc__}, {NULL} }; /** alsaseq.Sequencer type */ static PyTypeObject SequencerType = { PyObject_HEAD_INIT(NULL) tp_name: "alsaseq.Sequencer", tp_basicsize: sizeof(SequencerObject), tp_dealloc: (destructor) Sequencer_dealloc, tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, tp_doc: Sequencer__doc__, tp_init: (initproc) Sequencer_init, tp_new: PyType_GenericNew, tp_alloc: PyType_GenericAlloc, tp_free: PyObject_Del, tp_repr: (reprfunc) Sequencer_repr, tp_methods: Sequencer_methods, tp_getset: Sequencer_getset }; ////////////////////////////////////////////////////////////////////////////// // alsaseq module implementation ////////////////////////////////////////////////////////////////////////////// /** alsaseq module: __doc__ */ char alsaseq__doc__ [] = "libasound alsaseq wrapper" ; /** alsaseq module methods */ static PyMethodDef alsaseq_methods[] = { { NULL }, }; PyMODINIT_FUNC initalsaseq(void) { PyObject *module; if (PyType_Ready(&ConstantType) < 0) { return; } if (PyType_Ready(&SeqEventType) < 0) { return; } if (PyType_Ready(&SequencerType) < 0) { return; } module = Py_InitModule3("alsaseq", alsaseq_methods, alsaseq__doc__); if (module == NULL) { return; } SequencerError = PyErr_NewException("alsaseq.SequencerError", NULL, NULL); if (SequencerError == NULL) { return; } Py_INCREF(SequencerError); PyModule_AddObject(module, "SequencerError", SequencerError); Py_INCREF(&SeqEventType); PyModule_AddObject(module, "SeqEvent", (PyObject *) &SeqEventType); Py_INCREF(&SequencerType); PyModule_AddObject(module, "Sequencer", (PyObject *) &SequencerType); Py_INCREF(&ConstantType); PyModule_AddObject(module, "Constant", (PyObject *) &ConstantType); /* misc constants */ PyModule_AddStringConstant(module, "SEQ_LIB_VERSION_STR", SND_LIB_VERSION_STR); /* add Constant dictionaries to module */ TCONSTDICTADD(module, STREAMS, "_dstreams"); TCONSTDICTADD(module, MODE, "_dmode"); TCONSTDICTADD(module, QUEUE, "_dqueue"); TCONSTDICTADD(module, CLIENT_TYPE, "_dclienttype"); TCONSTDICTADD(module, PORT_CAP, "_dportcap"); TCONSTDICTADD(module, PORT_TYPE, "_dporttype"); TCONSTDICTADD(module, EVENT_TYPE, "_deventtype"); TCONSTDICTADD(module, EVENT_TIMESTAMP, "_deventtimestamp"); TCONSTDICTADD(module, EVENT_TIMEMODE, "_deventtimemode"); TCONSTDICTADD(module, ADDR_CLIENT, "_dclient"); TCONSTDICTADD(module, ADDR_PORT, "_dport"); /* Sequencer streams */ TCONSTADD(module, STREAMS, "SEQ_OPEN_OUTPUT", SND_SEQ_OPEN_OUTPUT); TCONSTADD(module, STREAMS, "SEQ_OPEN_INPUT", SND_SEQ_OPEN_INPUT); TCONSTADD(module, STREAMS, "SEQ_OPEN_DUPLEX", SND_SEQ_OPEN_DUPLEX); /* Sequencer blocking mode */ TCONSTADD(module, MODE, "SEQ_BLOCK", 0); TCONSTADD(module, MODE, "SEQ_NONBLOCK", SND_SEQ_NONBLOCK); /* Known queue id */ TCONSTADD(module, QUEUE, "SEQ_QUEUE_DIRECT", SND_SEQ_QUEUE_DIRECT); /* client types */ TCONSTADD(module, CLIENT_TYPE, "SEQ_USER_CLIENT", SND_SEQ_USER_CLIENT); TCONSTADD(module, CLIENT_TYPE, "SEQ_KERNEL_CLIENT", SND_SEQ_KERNEL_CLIENT); /* Sequencer port cap */ TCONSTADD(module, PORT_CAP, "SEQ_PORT_CAP_NONE", 0); TCONSTADD(module, PORT_CAP, "SEQ_PORT_CAP_WRITE", SND_SEQ_PORT_CAP_WRITE); TCONSTADD(module, PORT_CAP, "SEQ_PORT_CAP_SYNC_WRITE", SND_SEQ_PORT_CAP_SYNC_WRITE); TCONSTADD(module, PORT_CAP, "SEQ_PORT_CAP_SYNC_READ", SND_SEQ_PORT_CAP_SYNC_READ); TCONSTADD(module, PORT_CAP, "SEQ_PORT_CAP_SUBS_WRITE", SND_SEQ_PORT_CAP_SUBS_WRITE); TCONSTADD(module, PORT_CAP, "SEQ_PORT_CAP_SUBS_READ", SND_SEQ_PORT_CAP_SUBS_READ); TCONSTADD(module, PORT_CAP, "SEQ_PORT_CAP_READ", SND_SEQ_PORT_CAP_READ); TCONSTADD(module, PORT_CAP, "SEQ_PORT_CAP_NO_EXPORT", SND_SEQ_PORT_CAP_NO_EXPORT); TCONSTADD(module, PORT_CAP, "SEQ_PORT_CAP_DUPLEX", SND_SEQ_PORT_CAP_DUPLEX); /* Sequencer port type */ TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_SYNTHESIZER", SND_SEQ_PORT_TYPE_SYNTHESIZER); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_SYNTH", SND_SEQ_PORT_TYPE_SYNTH); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_SPECIFIC", SND_SEQ_PORT_TYPE_SPECIFIC); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_SOFTWARE", SND_SEQ_PORT_TYPE_SOFTWARE); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_SAMPLE", SND_SEQ_PORT_TYPE_SAMPLE); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_PORT", SND_SEQ_PORT_TYPE_PORT); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_MIDI_XG", SND_SEQ_PORT_TYPE_MIDI_XG); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_MIDI_MT32", SND_SEQ_PORT_TYPE_MIDI_MT32); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_MIDI_GS", SND_SEQ_PORT_TYPE_MIDI_GS); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_MIDI_GM2", SND_SEQ_PORT_TYPE_MIDI_GM2); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_MIDI_GM", SND_SEQ_PORT_TYPE_MIDI_GM); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_MIDI_GENERIC", SND_SEQ_PORT_TYPE_MIDI_GENERIC); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_HARDWARE", SND_SEQ_PORT_TYPE_HARDWARE); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_DIRECT_SAMPLE", SND_SEQ_PORT_TYPE_DIRECT_SAMPLE); TCONSTADD(module, PORT_TYPE, "SEQ_PORT_TYPE_APPLICATION", SND_SEQ_PORT_TYPE_APPLICATION); /* SeqEvent event type */ TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_SYSTEM", SND_SEQ_EVENT_SYSTEM); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_RESULT", SND_SEQ_EVENT_RESULT); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_NOTE", SND_SEQ_EVENT_NOTE); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_NOTEON", SND_SEQ_EVENT_NOTEON); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_NOTEOFF", SND_SEQ_EVENT_NOTEOFF); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_KEYPRESS", SND_SEQ_EVENT_KEYPRESS); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_CONTROLLER", SND_SEQ_EVENT_CONTROLLER); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_PGMCHANGE", SND_SEQ_EVENT_PGMCHANGE); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_CHANPRESS", SND_SEQ_EVENT_CHANPRESS); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_PITCHBEND", SND_SEQ_EVENT_PITCHBEND); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_CONTROL14", SND_SEQ_EVENT_CONTROL14); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_NONREGPARAM", SND_SEQ_EVENT_NONREGPARAM); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_REGPARAM", SND_SEQ_EVENT_REGPARAM); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_SONGPOS", SND_SEQ_EVENT_SONGPOS); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_SONGSEL", SND_SEQ_EVENT_SONGSEL); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_QFRAME", SND_SEQ_EVENT_QFRAME); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_TIMESIGN", SND_SEQ_EVENT_TIMESIGN); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_KEYSIGN", SND_SEQ_EVENT_KEYSIGN); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_START", SND_SEQ_EVENT_START); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_CONTINUE", SND_SEQ_EVENT_CONTINUE); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_STOP", SND_SEQ_EVENT_STOP); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_SETPOS_TICK", SND_SEQ_EVENT_SETPOS_TICK); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_SETPOS_TIME", SND_SEQ_EVENT_SETPOS_TIME); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_TEMPO", SND_SEQ_EVENT_TEMPO); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_CLOCK", SND_SEQ_EVENT_CLOCK); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_TICK", SND_SEQ_EVENT_TICK); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_QUEUE_SKEW", SND_SEQ_EVENT_QUEUE_SKEW); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_SYNC_POS", SND_SEQ_EVENT_SYNC_POS); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_TUNE_REQUEST", SND_SEQ_EVENT_TUNE_REQUEST); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_RESET", SND_SEQ_EVENT_RESET); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_SENSING", SND_SEQ_EVENT_SENSING); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_ECHO", SND_SEQ_EVENT_ECHO); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_OSS", SND_SEQ_EVENT_OSS); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_CLIENT_START", SND_SEQ_EVENT_CLIENT_START); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_CLIENT_EXIT", SND_SEQ_EVENT_CLIENT_EXIT); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_CLIENT_CHANGE", SND_SEQ_EVENT_CLIENT_CHANGE); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_PORT_START", SND_SEQ_EVENT_PORT_START); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_PORT_EXIT", SND_SEQ_EVENT_PORT_EXIT); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_PORT_CHANGE", SND_SEQ_EVENT_PORT_CHANGE); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_PORT_SUBSCRIBED", SND_SEQ_EVENT_PORT_SUBSCRIBED); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_PORT_UNSUBSCRIBED", SND_SEQ_EVENT_PORT_UNSUBSCRIBED); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR0", SND_SEQ_EVENT_USR0); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR1", SND_SEQ_EVENT_USR1); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR2", SND_SEQ_EVENT_USR2); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR3", SND_SEQ_EVENT_USR3); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR4", SND_SEQ_EVENT_USR4); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR5", SND_SEQ_EVENT_USR5); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR6", SND_SEQ_EVENT_USR6); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR7", SND_SEQ_EVENT_USR7); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR8", SND_SEQ_EVENT_USR8); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR9", SND_SEQ_EVENT_USR9); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_SYSEX", SND_SEQ_EVENT_SYSEX); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_BOUNCE", SND_SEQ_EVENT_BOUNCE); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR_VAR0", SND_SEQ_EVENT_USR_VAR0); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR_VAR1", SND_SEQ_EVENT_USR_VAR1); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR_VAR2", SND_SEQ_EVENT_USR_VAR2); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR_VAR3", SND_SEQ_EVENT_USR_VAR3); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_USR_VAR4", SND_SEQ_EVENT_USR_VAR4); TCONSTADD(module, EVENT_TYPE, "SEQ_EVENT_NONE", SND_SEQ_EVENT_NONE); /* SeqEvent event timestamp flags */ TCONSTADD(module, EVENT_TIMESTAMP, "SEQ_TIME_STAMP_TICK", SND_SEQ_TIME_STAMP_TICK); TCONSTADD(module, EVENT_TIMESTAMP, "SEQ_TIME_STAMP_REAL", SND_SEQ_TIME_STAMP_REAL); /* SeqEvent event timemode flags */ TCONSTADD(module, EVENT_TIMEMODE, "SEQ_TIME_MODE_ABS", SND_SEQ_TIME_MODE_ABS); TCONSTADD(module, EVENT_TIMEMODE, "SEQ_TIME_MODE_REL", SND_SEQ_TIME_MODE_REL); /* SeqEvent event addresses */ TCONSTADD(module, ADDR_CLIENT, "SEQ_CLIENT_SYSTEM", SND_SEQ_CLIENT_SYSTEM); TCONSTADD(module, ADDR_CLIENT, "SEQ_ADDRESS_BROADCAST", SND_SEQ_ADDRESS_BROADCAST); TCONSTADD(module, ADDR_CLIENT, "SEQ_ADDRESS_SUBSCRIBERS", SND_SEQ_ADDRESS_SUBSCRIBERS); TCONSTADD(module, ADDR_CLIENT, "SEQ_ADDRESS_UNKNOWN", SND_SEQ_ADDRESS_UNKNOWN); TCONSTADD(module, ADDR_PORT, "SEQ_PORT_SYSTEM_TIMER", SND_SEQ_PORT_SYSTEM_TIMER); TCONSTADD(module, ADDR_PORT, "SEQ_PORT_SYSTEM_ANNOUNCE", SND_SEQ_PORT_SYSTEM_ANNOUNCE); TCONSTADD(module, ADDR_PORT, "SEQ_ADDRESS_BROADCAST", SND_SEQ_ADDRESS_BROADCAST); TCONSTADD(module, ADDR_PORT, "SEQ_ADDRESS_SUBSCRIBERS", SND_SEQ_ADDRESS_SUBSCRIBERS); TCONSTADD(module, ADDR_PORT, "SEQ_ADDRESS_UNKNOWN", SND_SEQ_ADDRESS_UNKNOWN); } pyalsa-1.0.26/pyalsa/alsahcontrol.c0000664000000000000000000012741412022053131017155 0ustar rootroot00000000000000/* * Python binding for the ALSA library - Universal Control Layer * Copyright (c) 2007 by Jaroslav Kysela * * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "Python.h" #include "structmember.h" #include "frameobject.h" #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif #include "sys/poll.h" #include "stdlib.h" #include "alsa/asoundlib.h" #ifndef Py_RETURN_NONE #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None #endif #ifndef Py_RETURN_TRUE #define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True #endif #ifndef Py_RETURN_FALSE #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False #endif static int element_callback(snd_hctl_elem_t *elem, unsigned int mask); static PyObject *module; #if 0 static PyObject *buildin; #endif static PyInterpreterState *main_interpreter; /* * */ #define PYHCTL(v) (((v) == Py_None) ? NULL : \ ((struct pyalsahcontrol *)(v))) struct pyalsahcontrol { PyObject_HEAD snd_hctl_t *handle; }; static inline PyObject *get_bool(int val) { if (val) { Py_INCREF(Py_True); return Py_True; } else { Py_INCREF(Py_False); return Py_False; } } static PyObject *id_to_python(snd_ctl_elem_id_t *id) { PyObject *v; v = PyTuple_New(6); if (v == NULL) return NULL; PyTuple_SET_ITEM(v, 0, PyInt_FromLong(snd_ctl_elem_id_get_numid(id))); PyTuple_SET_ITEM(v, 1, PyInt_FromLong(snd_ctl_elem_id_get_interface(id))); PyTuple_SET_ITEM(v, 2, PyInt_FromLong(snd_ctl_elem_id_get_device(id))); PyTuple_SET_ITEM(v, 3, PyInt_FromLong(snd_ctl_elem_id_get_subdevice(id))); PyTuple_SET_ITEM(v, 4, PyString_FromString(snd_ctl_elem_id_get_name(id))); PyTuple_SET_ITEM(v, 5, PyInt_FromLong(snd_ctl_elem_id_get_index(id))); return v; } static int parse_id(snd_ctl_elem_id_t *id, PyObject *o) { unsigned int interface, device, subdevice, index; char *name; if (!PyTuple_Check(o) || PyTuple_Size(o) != 5) { PyErr_SetString(PyExc_TypeError, "id argument tuple size error"); return -1; } if (!PyArg_ParseTuple(o, "iiisi", &interface, &device, &subdevice, &name, &index)) return -1; snd_ctl_elem_id_set_interface(id, interface); snd_ctl_elem_id_set_device(id, device); snd_ctl_elem_id_set_subdevice(id, subdevice); snd_ctl_elem_id_set_name(id, name); snd_ctl_elem_id_set_index(id, index); return 0; } typedef int (*fcn_simple)(void *, void *); static PyObject *simple_id_fcn(struct pyalsahcontrol *self, PyObject *args, void *fcn, const char *xname) { snd_ctl_elem_id_t *id; int res; snd_ctl_elem_id_alloca(&id); if (PyTuple_Check(args) && !PyTuple_Check(PyTuple_GetItem(args, 0))) { if (parse_id(id, args) < 0) return NULL; } else { if (!PyArg_ParseTuple(args, "O", &args)) return NULL; if (parse_id(id, args) < 0) return NULL; } res = ((fcn_simple)fcn)(snd_hctl_ctl(self->handle), id); if (res < 0) { PyErr_Format(PyExc_IOError, "element %s error: %s", xname, snd_strerror(-res)); return NULL; } Py_RETURN_NONE; } static PyObject * pyalsahcontrol_getcount(struct pyalsahcontrol *self, void *priv) { return PyLong_FromLong(snd_hctl_get_count(self->handle)); } static PyObject * pyalsahcontrol_getChctl(struct pyalsahcontrol *self, void *priv) { return PyInt_FromLong((long)self->handle); } PyDoc_STRVAR(handlevents__doc__, "handle_events() -- Process waiting hcontrol events (and call appropriate callbacks)."); static PyObject * pyalsahcontrol_handleevents(struct pyalsahcontrol *self, PyObject *args) { int err; Py_BEGIN_ALLOW_THREADS; err = snd_hctl_handle_events(self->handle); Py_END_ALLOW_THREADS; if (err < 0) PyErr_Format(PyExc_IOError, "HControl handle events error: %s", strerror(-err)); Py_RETURN_NONE; } PyDoc_STRVAR(registerpoll__doc__, "register_poll(pollObj) -- Register poll file descriptors."); static PyObject * pyalsahcontrol_registerpoll(struct pyalsahcontrol *self, PyObject *args) { PyObject *pollObj, *reg, *t; struct pollfd *pfd; int i, count; if (!PyArg_ParseTuple(args, "O", &pollObj)) return NULL; count = snd_hctl_poll_descriptors_count(self->handle); if (count <= 0) Py_RETURN_NONE; pfd = alloca(sizeof(struct pollfd) * count); count = snd_hctl_poll_descriptors(self->handle, pfd, count); if (count <= 0) Py_RETURN_NONE; reg = PyObject_GetAttr(pollObj, PyString_InternFromString("register")); for (i = 0; i < count; i++) { t = PyTuple_New(2); if (t) { PyTuple_SET_ITEM(t, 0, PyInt_FromLong(pfd[i].fd)); PyTuple_SET_ITEM(t, 1, PyInt_FromLong(pfd[i].events)); Py_XDECREF(PyObject_CallObject(reg, t)); Py_DECREF(t); } } Py_XDECREF(reg); Py_RETURN_NONE; } static PyObject * pyalsahcontrol_getpollfds(struct pyalsahcontrol *self, void *priv) { PyObject *l, *t; struct pollfd *pfds; int i, count; count = snd_hctl_poll_descriptors_count(self->handle); if (count < 0) { pfds_error: PyErr_Format(PyExc_IOError, "poll descriptors error: %s", snd_strerror(count)); return NULL; } pfds = alloca(sizeof(struct pollfd) * count); count = snd_hctl_poll_descriptors(self->handle, pfds, count); if (count < 0) goto pfds_error; l = PyList_New(count); if (!l) return NULL; for (i = 0; i < count; ++i) { t = PyTuple_New(2); if (t) { PyTuple_SET_ITEM(t, 0, PyInt_FromLong(pfds[i].fd)); PyTuple_SET_ITEM(t, 1, PyInt_FromLong(pfds[i].events)); PyList_SetItem(l, i, t); } } return l; } PyDoc_STRVAR(list__doc__, "list() -- Return a list (tuple) of element IDs in (numid,interface,device,subdevice,name,index) tuple."); static PyObject * pyalsahcontrol_list(struct pyalsahcontrol *self, PyObject *args) { PyObject *t, *v; int i, count; snd_hctl_elem_t *elem; snd_ctl_elem_id_t *id; snd_ctl_elem_id_alloca(&id); count = snd_hctl_get_count(self->handle); t = PyTuple_New(count); if (count == 0) return t; elem = snd_hctl_first_elem(self->handle); for (i = 0; i < count; i++) { v = NULL; if (elem) { snd_hctl_elem_get_id(elem, id); v = id_to_python(id); } if (v == NULL || elem == NULL) { v = Py_None; Py_INCREF(v); } PyTuple_SET_ITEM(t, i, v); elem = snd_hctl_elem_next(elem); } return t; } PyDoc_STRVAR(elementnew__doc__, "element_new(element_type['INTEGER'], id, count, min, max, step)\n" "element_new(element_type['INTEGER64'], id, count, min64, max64, step64)\n" "element_new(element_type['BOOLEAN'], id, count)\n" "element_new(element_type['IEC958'], id)\n" " -- Create a new hcontrol element.\n" " -- The id argument is tuple (interface, device, subdevice, name, index).\n"); static PyObject * pyalsahcontrol_elementnew(struct pyalsahcontrol *self, PyObject *args) { snd_ctl_elem_type_t type; PyObject *o; unsigned int count; long min, max, step; long long min64, max64, step64; snd_ctl_elem_id_t *id; snd_ctl_t *ctl; int res; snd_ctl_elem_id_alloca(&id); if (!PyTuple_Check(args) || PyTuple_Size(args) < 2) { PyErr_SetString(PyExc_TypeError, "wrong argument count"); return NULL; } o = PyTuple_GetItem(args, 0); if (!PyInt_Check(o)) { PyErr_SetString(PyExc_TypeError, "type argument is not integer"); return NULL; } Py_INCREF(o); type = PyInt_AsLong(o); o = PyTuple_GetItem(args, 1); if (!PyTuple_Check(o)) { PyErr_SetString(PyExc_TypeError, "id argument is not tuple"); return NULL; } switch (type) { case SND_CTL_ELEM_TYPE_INTEGER: if (!PyArg_ParseTuple(args, "iOilll", &type, &o, &count, &min, &max, &step)) return NULL; break; case SND_CTL_ELEM_TYPE_INTEGER64: if (!PyArg_ParseTuple(args, "iO|iLLL", &type, &o, &count, &min64, &max64, &step64)) return NULL; break; case SND_CTL_ELEM_TYPE_BOOLEAN: if (!PyArg_ParseTuple(args, "iOi", &type, &o, &count)) return NULL; break; case SND_CTL_ELEM_TYPE_IEC958: if (!PyArg_ParseTuple(args, "iO", &type, &o)) return NULL; break; default: PyErr_Format(PyExc_TypeError, "type %i is not supported yet", type); return NULL; } if (parse_id(id, o) < 0) return NULL; ctl = snd_hctl_ctl(self->handle); switch (type) { case SND_CTL_ELEM_TYPE_INTEGER: res = snd_ctl_elem_add_integer(ctl, id, count, min, max, step); break; case SND_CTL_ELEM_TYPE_INTEGER64: res = snd_ctl_elem_add_integer64(ctl, id, count, min64, max64, step64); break; case SND_CTL_ELEM_TYPE_BOOLEAN: res = snd_ctl_elem_add_boolean(ctl, id, count); break; case SND_CTL_ELEM_TYPE_IEC958: res = snd_ctl_elem_add_iec958(ctl, id); break; default: res = -EIO; break; } if (res < 0) { PyErr_Format(PyExc_IOError, "new element of type %i create error: %s", type, snd_strerror(-res)); return NULL; } Py_RETURN_NONE; } PyDoc_STRVAR(elementremove__doc__, "element_remove(id)\n" "element_remove(interface, device, subdevice, name, index)\n" " -- Remove element.\n"); static PyObject * pyalsahcontrol_elementremove(struct pyalsahcontrol *self, PyObject *args) { return simple_id_fcn(self, args, snd_ctl_elem_remove, "remove"); } PyDoc_STRVAR(elementlock__doc__, "element_lock(id)\n" "element_lock(interface, device, subdevice, name, index)\n" " -- Lock element.\n"); static PyObject * pyalsahcontrol_elementlock(struct pyalsahcontrol *self, PyObject *args) { return simple_id_fcn(self, args, snd_ctl_elem_lock, "lock"); } PyDoc_STRVAR(elementunlock__doc__, "element_unlock(id)\n" "element_unlock(interface, device, subdevice, name, index)\n" " -- Unlock element.\n"); static PyObject * pyalsahcontrol_elementunlock(struct pyalsahcontrol *self, PyObject *args) { return simple_id_fcn(self, args, snd_ctl_elem_unlock, "unlock"); } PyDoc_STRVAR(alsahcontrolinit__doc__, "HControl([name='default'],[mode=0])\n" " -- Open an ALSA HControl device.\n"); static int pyalsahcontrol_init(struct pyalsahcontrol *pyhctl, PyObject *args, PyObject *kwds) { char *name = "default"; int mode = 0, load = 1, err; static char * kwlist[] = { "name", "mode", "load", NULL }; pyhctl->handle = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sii", kwlist, &name, &mode, &load)) return -1; err = snd_hctl_open(&pyhctl->handle, name, mode); if (err < 0) { PyErr_Format(PyExc_IOError, "HControl open error: %s", strerror(-err)); return -1; } if (load) { err = snd_hctl_load(pyhctl->handle); if (err < 0) { snd_hctl_close(pyhctl->handle); pyhctl->handle = NULL; PyErr_Format(PyExc_IOError, "HControl load error: %s", strerror(-err)); return -1; } } return 0; } static void pyalsahcontrol_dealloc(struct pyalsahcontrol *self) { if (self->handle != NULL) snd_hctl_close(self->handle); self->ob_type->tp_free(self); } static PyGetSetDef pyalsahcontrol_getseters[] = { {"count", (getter)pyalsahcontrol_getcount, NULL, "hcontrol element count", NULL}, {"poll_fds", (getter)pyalsahcontrol_getpollfds, NULL, "list of (fd, eventbits) tuples", NULL}, {"get_C_hctl", (getter)pyalsahcontrol_getChctl, NULL, "hcontrol C pointer (internal)", NULL}, {NULL} }; static PyMethodDef pyalsahcontrol_methods[] = { {"list", (PyCFunction)pyalsahcontrol_list, METH_NOARGS, list__doc__}, {"element_new", (PyCFunction)pyalsahcontrol_elementnew, METH_VARARGS, elementnew__doc__}, {"element_remove",(PyCFunction)pyalsahcontrol_elementremove, METH_VARARGS, elementremove__doc__}, {"element_lock",(PyCFunction)pyalsahcontrol_elementlock, METH_VARARGS, elementlock__doc__}, {"element_unlock",(PyCFunction)pyalsahcontrol_elementunlock, METH_VARARGS, elementunlock__doc__}, {"handle_events",(PyCFunction)pyalsahcontrol_handleevents, METH_NOARGS, handlevents__doc__}, {"register_poll",(PyCFunction)pyalsahcontrol_registerpoll, METH_VARARGS|METH_KEYWORDS, registerpoll__doc__}, {NULL} }; static PyTypeObject pyalsahcontrol_type = { PyObject_HEAD_INIT(0) tp_name: "alsahcontrol.HControl", tp_basicsize: sizeof(struct pyalsahcontrol), tp_dealloc: (destructor)pyalsahcontrol_dealloc, tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, tp_doc: alsahcontrolinit__doc__, tp_getset: pyalsahcontrol_getseters, tp_init: (initproc)pyalsahcontrol_init, tp_alloc: PyType_GenericAlloc, tp_new: PyType_GenericNew, tp_free: PyObject_Del, tp_methods: pyalsahcontrol_methods, }; /* * hcontrol element section */ #define PYHCTLELEMENT(v) (((v) == Py_None) ? NULL : \ ((struct pyalsahcontrolelement *)(v))) struct pyalsahcontrolelement { PyObject_HEAD PyObject *pyhandle; PyObject *callback; snd_hctl_t *handle; snd_hctl_elem_t *elem; }; static PyObject * pyalsahcontrolelement_getname(struct pyalsahcontrolelement *pyhelem, void *priv) { return PyString_FromString(snd_hctl_elem_get_name(pyhelem->elem)); } typedef unsigned int (*fcn1)(void *); static PyObject * pyalsahcontrolelement_uint(struct pyalsahcontrolelement *pyhelem, void *fcn) { return PyInt_FromLong(((fcn1)fcn)(pyhelem->elem)); } static PyObject * pyalsahcontrolelement_getChelem(struct pyalsahcontrolelement *self, void *priv) { return PyInt_FromLong((long)self->elem); } PyDoc_STRVAR(elock__doc__, "lock() -- Lock this element.\n"); static PyObject * pyalsahcontrolelement_lock(struct pyalsahcontrolelement *pyhelem, PyObject *args) { snd_ctl_elem_id_t *id; int res; snd_ctl_elem_id_alloca(&id); snd_hctl_elem_get_id(pyhelem->elem, id); res = snd_ctl_elem_lock(snd_hctl_ctl(pyhelem->handle), id); if (res < 0) return PyErr_Format(PyExc_IOError, "element lock error: %s", snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(eunlock__doc__, "unlock() -- Unlock this element.\n"); static PyObject * pyalsahcontrolelement_unlock(struct pyalsahcontrolelement *pyhelem, PyObject *args) { snd_ctl_elem_id_t *id; int res; snd_ctl_elem_id_alloca(&id); snd_hctl_elem_get_id(pyhelem->elem, id); res = snd_ctl_elem_unlock(snd_hctl_ctl(pyhelem->handle), id); if (res < 0) return PyErr_Format(PyExc_IOError, "element unlock error: %s", snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(setcallback__doc__, "set_callback(callObj) -- Set callback object.\n" "Note: callObj might have callObj.callback attribute.\n"); static PyObject * pyalsahcontrolelement_setcallback(struct pyalsahcontrolelement *pyhelem, PyObject *args) { PyObject *o; if (!PyArg_ParseTuple(args, "O", &o)) return NULL; if (o == Py_None) { Py_XDECREF(pyhelem->callback); pyhelem->callback = NULL; snd_hctl_elem_set_callback(pyhelem->elem, NULL); } else { Py_INCREF(o); pyhelem->callback = o; snd_hctl_elem_set_callback_private(pyhelem->elem, pyhelem); snd_hctl_elem_set_callback(pyhelem->elem, element_callback); } Py_RETURN_NONE; } PyDoc_STRVAR(elementinit__doc__, "Element(hctl, numid)\n" "Element(hctl, interface, device, subdevice, name, index)\n" "Element(hctl, (interface, device, subdevice, name, index))\n" " -- Create a hcontrol element object.\n"); static int pyalsahcontrolelement_init(struct pyalsahcontrolelement *pyhelem, PyObject *args, PyObject *kwds) { PyObject *hctl, *first; char *name = "Default"; int numid = 0, iface = 0, device = 0, subdevice = 0, index = 0; snd_ctl_elem_id_t *id; static char *kwlist1[] = { "hctl", "interface", "device", "subdevice", "name", "index", NULL }; long helem = 0; float f = 0; snd_ctl_elem_info_t *elem_info; snd_ctl_elem_id_alloca(&id); pyhelem->pyhandle = NULL; pyhelem->handle = NULL; pyhelem->elem = NULL; if (!PyTuple_Check(args) || PyTuple_Size(args) < 2) { PyErr_SetString(PyExc_TypeError, "first argument must be alsahcontrol.HControl"); return -1; } first = PyTuple_GetItem(args, 1); if (PyFloat_Check(first)) { if (!PyArg_ParseTuple(args, "Ofi", &hctl, &f, &helem)) return -1; } else if (PyInt_Check(first)) { if (!PyArg_ParseTuple(args, "Oi", &hctl, &numid)) return -1; snd_ctl_elem_id_set_numid(id, numid); } else if (PyTuple_Check(first)) { if (!PyArg_ParseTuple(args, "OO", &hctl, &first)) return -1; if (!PyArg_ParseTuple(first, "iiis|i", &iface, &device, &subdevice, &name, &index)) return -1; goto parse1; } else { if (!PyArg_ParseTupleAndKeywords(first, kwds, "O|iiisi", kwlist1, &hctl, &iface, &device, &subdevice, &name, &index)) return -1; parse1: snd_ctl_elem_id_set_interface(id, iface); snd_ctl_elem_id_set_device(id, device); snd_ctl_elem_id_set_subdevice(id, subdevice); snd_ctl_elem_id_set_name(id, name); snd_ctl_elem_id_set_index(id, index); } if (hctl->ob_type != &pyalsahcontrol_type) { PyErr_SetString(PyExc_TypeError, "bad type for hctl argument"); return -1; } pyhelem->pyhandle = hctl; Py_INCREF(hctl); pyhelem->handle = PYHCTL(hctl)->handle; /* FIXME: Remove it when hctl find works ok !!! */ snd_ctl_elem_info_alloca(&elem_info); snd_ctl_elem_info_set_id(elem_info, id); if (snd_ctl_elem_info(snd_hctl_ctl(pyhelem->handle), elem_info) < 0) goto elem_not_found; snd_ctl_elem_info_get_id(elem_info, id); pyhelem->elem = helem > 0 ? (snd_hctl_elem_t *)helem : snd_hctl_find_elem(pyhelem->handle, id); if (pyhelem->elem == NULL) { elem_not_found: if (numid == 0) PyErr_Format(PyExc_IOError, "cannot find hcontrol element %i,%i,%i,'%s',%i", iface, device, subdevice, name, index); else PyErr_Format(PyExc_IOError, "cannot find hcontrol element numid=%i", numid); return -1; } return 0; } static void pyalsahcontrolelement_dealloc(struct pyalsahcontrolelement *self) { if (self->elem) { Py_XDECREF(self->callback); snd_hctl_elem_set_callback(self->elem, NULL); } if (self->pyhandle) { Py_XDECREF(self->pyhandle); } self->ob_type->tp_free(self); } static PyGetSetDef pyalsahcontrolelement_getseters[] = { {"numid", (getter)pyalsahcontrolelement_uint, NULL, "hcontrol element numid", snd_hctl_elem_get_numid}, {"interface", (getter)pyalsahcontrolelement_uint, NULL, "hcontrol element interface", snd_hctl_elem_get_interface}, {"device", (getter)pyalsahcontrolelement_uint, NULL, "hcontrol element device", snd_hctl_elem_get_device}, {"subdevice", (getter)pyalsahcontrolelement_uint, NULL, "hcontrol element subdevice", snd_hctl_elem_get_subdevice}, {"name", (getter)pyalsahcontrolelement_getname, NULL, "hcontrol element name", NULL}, {"index", (getter)pyalsahcontrolelement_uint, NULL, "hcontrol element index", snd_hctl_elem_get_index}, {"get_C_helem", (getter)pyalsahcontrolelement_getChelem, NULL, "hcontrol element C pointer (internal)", NULL }, {NULL} }; static PyMethodDef pyalsahcontrolelement_methods[] = { {"lock", (PyCFunction)pyalsahcontrolelement_lock, METH_NOARGS, elock__doc__}, {"unlock", (PyCFunction)pyalsahcontrolelement_unlock, METH_NOARGS, eunlock__doc__}, {"set_callback",(PyCFunction)pyalsahcontrolelement_setcallback, METH_VARARGS, setcallback__doc__}, {NULL} }; static PyTypeObject pyalsahcontrolelement_type = { PyObject_HEAD_INIT(0) tp_name: "alsahcontrol.Element", tp_basicsize: sizeof(struct pyalsahcontrolelement), tp_dealloc: (destructor)pyalsahcontrolelement_dealloc, tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, tp_doc: elementinit__doc__, tp_getset: pyalsahcontrolelement_getseters, tp_init: (initproc)pyalsahcontrolelement_init, tp_alloc: PyType_GenericAlloc, tp_new: PyType_GenericNew, tp_free: PyObject_Del, tp_methods: pyalsahcontrolelement_methods, }; /* * hcontrol info section */ #define PYHCTLINFO(v) (((v) == Py_None) ? NULL : \ ((struct pyalsahcontrolinfo *)(v))) struct pyalsahcontrolinfo { PyObject_HEAD PyObject *pyelem; snd_hctl_elem_t *elem; snd_ctl_elem_info_t *info; }; static PyObject * pyalsahcontrolinfo_element(struct pyalsahcontrolinfo *pyinfo, void *priv) { Py_INCREF(pyinfo->pyelem); return pyinfo->pyelem; } typedef int (*fcn2)(void *); static PyObject * pyalsahcontrolinfo_bool(struct pyalsahcontrolinfo *pyinfo, void *fcn) { return get_bool(((fcn2)fcn)(pyinfo->info)); } static PyObject * pyalsahcontrolinfo_getowner(struct pyalsahcontrolinfo *pyinfo, void *priv) { return PyInt_FromLong(snd_ctl_elem_info_get_owner(pyinfo->info)); } static PyObject * pyalsahcontrolinfo_getitems(struct pyalsahcontrolinfo *pyinfo, void *priv) { if (snd_ctl_elem_info_get_type(pyinfo->info) != SND_CTL_ELEM_TYPE_ENUMERATED) { PyErr_SetString(PyExc_TypeError, "element is not enumerated"); return NULL; } return PyInt_FromLong(snd_ctl_elem_info_get_items(pyinfo->info)); } typedef long (*fcn3_0)(void *); static PyObject * pyalsahcontrolinfo_long(struct pyalsahcontrolinfo *pyinfo, void *fcn) { if (snd_ctl_elem_info_get_type(pyinfo->info) != SND_CTL_ELEM_TYPE_INTEGER) { PyErr_SetString(PyExc_TypeError, "element is not integer"); return NULL; } return PyLong_FromLong(((fcn3_0)fcn)(pyinfo->info)); } typedef long long (*fcn3)(void *); static PyObject * pyalsahcontrolinfo_longlong(struct pyalsahcontrolinfo *pyinfo, void *fcn) { if (snd_ctl_elem_info_get_type(pyinfo->info) != SND_CTL_ELEM_TYPE_INTEGER64) { PyErr_SetString(PyExc_TypeError, "element is not integer64"); return NULL; } return PyLong_FromLongLong(((fcn3)fcn)(pyinfo->info)); } typedef unsigned int (*fcn4)(void *); static PyObject * pyalsahcontrolinfo_uint(struct pyalsahcontrolinfo *pyinfo, void *fcn) { return PyLong_FromLong(((fcn4)fcn)(pyinfo->info)); } typedef const char * (*fcn5)(void *); static PyObject * pyalsahcontrolinfo_str(struct pyalsahcontrolinfo *pyinfo, void *fcn) { return PyString_FromString(((fcn5)fcn)(pyinfo->info)); } static PyObject * pyalsahcontrolinfo_id(struct pyalsahcontrolinfo *pyinfo, void *priv) { snd_ctl_elem_id_t *id; snd_ctl_elem_id_alloca(&id); snd_ctl_elem_info_get_id(pyinfo->info, id); return id_to_python(id); } static PyObject * pyalsahcontrolinfo_dimensions(struct pyalsahcontrolinfo *pyinfo, void *priv) { int dims = snd_ctl_elem_info_get_dimensions(pyinfo->info); unsigned int i; PyObject *t; if (dims <= 0) Py_RETURN_NONE; t = PyTuple_New(dims); if (t == NULL) return NULL; for (i = 0; i < dims; i++) { PyTuple_SET_ITEM(t, i, PyInt_FromLong(snd_ctl_elem_info_get_dimension(pyinfo->info, i))); } return t; } static PyObject * pyalsahcontrolinfo_itemnames(struct pyalsahcontrolinfo *pyinfo, void *priv) { int items; int res; unsigned int i; PyObject *t; if (snd_ctl_elem_info_get_type(pyinfo->info) != SND_CTL_ELEM_TYPE_ENUMERATED) { PyErr_SetString(PyExc_TypeError, "element is not enumerated"); return NULL; } items = snd_ctl_elem_info_get_items(pyinfo->info); if (items <= 0) Py_RETURN_NONE; t = PyTuple_New(items); if (t == NULL) return NULL; for (i = 0; i < items; i++) { snd_ctl_elem_info_set_item(pyinfo->info, i); res = snd_hctl_elem_info(pyinfo->elem, pyinfo->info); if (res < 0) { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, i, Py_None); } else { PyTuple_SET_ITEM(t, i, PyString_FromString(snd_ctl_elem_info_get_item_name(pyinfo->info))); } } return t; } PyDoc_STRVAR(infoinit__doc__, "Info(elem)\n" " -- Create a hcontrol element info object.\n"); static int pyalsahcontrolinfo_init(struct pyalsahcontrolinfo *pyinfo, PyObject *args, PyObject *kwds) { PyObject *elem; int res; pyinfo->pyelem = NULL; pyinfo->elem = NULL; pyinfo->info = NULL; if (!PyArg_ParseTuple(args, "O", &elem)) return -1; if (elem->ob_type != &pyalsahcontrolelement_type) { PyErr_SetString(PyExc_TypeError, "bad type for element argument"); return -1; } if (snd_ctl_elem_info_malloc(&pyinfo->info)) { PyErr_SetString(PyExc_TypeError, "malloc problem"); return -1; } pyinfo->pyelem = elem; Py_INCREF(elem); pyinfo->elem = PYHCTLELEMENT(elem)->elem; res = snd_hctl_elem_info(pyinfo->elem, pyinfo->info); if (res < 0) { PyErr_Format(PyExc_IOError, "hcontrol element info problem: %s", snd_strerror(-res)); return -1; } return 0; } static void pyalsahcontrolinfo_dealloc(struct pyalsahcontrolinfo *self) { if (self->info) snd_ctl_elem_info_free(self->info); if (self->pyelem) { Py_XDECREF(self->pyelem); } self->ob_type->tp_free(self); } static PyGetSetDef pyalsahcontrolinfo_getseters[] = { {"element", (getter)pyalsahcontrolinfo_element, NULL, "hcontrol element for this info", NULL}, {"id", (getter)pyalsahcontrolinfo_id, NULL, "hcontrol element full id", snd_ctl_elem_info_get_id}, {"numid", (getter)pyalsahcontrolinfo_uint, NULL, "hcontrol element numid", snd_ctl_elem_info_get_numid}, {"interface", (getter)pyalsahcontrolinfo_uint, NULL, "hcontrol element interface", snd_ctl_elem_info_get_interface}, {"device", (getter)pyalsahcontrolinfo_uint, NULL, "hcontrol element device", snd_ctl_elem_info_get_device}, {"subdevice", (getter)pyalsahcontrolinfo_uint, NULL, "hcontrol element subdevice", snd_ctl_elem_info_get_subdevice}, {"name", (getter)pyalsahcontrolinfo_str, NULL, "hcontrol element name", snd_ctl_elem_info_get_name}, {"index", (getter)pyalsahcontrolinfo_uint, NULL, "hcontrol element index", snd_ctl_elem_info_get_index}, {"type", (getter)pyalsahcontrolinfo_uint, NULL, "hcontrol element index", snd_ctl_elem_info_get_type}, {"is_readable", (getter)pyalsahcontrolinfo_bool, NULL, "hcontrol element is readable", snd_ctl_elem_info_is_readable}, {"is_writable", (getter)pyalsahcontrolinfo_bool, NULL, "hcontrol element is writable",snd_ctl_elem_info_is_writable}, {"is_volatile", (getter)pyalsahcontrolinfo_bool, NULL, "hcontrol element is volatile",snd_ctl_elem_info_is_volatile}, {"is_inactive", (getter)pyalsahcontrolinfo_bool, NULL, "hcontrol element is inactive",snd_ctl_elem_info_is_inactive}, {"is_locked", (getter)pyalsahcontrolinfo_bool, NULL, "hcontrol element is locked",snd_ctl_elem_info_is_locked}, {"is_tlv_readable",(getter)pyalsahcontrolinfo_bool, NULL, "hcontrol element is TLV readable",snd_ctl_elem_info_is_tlv_readable}, {"is_tlv_Writable",(getter)pyalsahcontrolinfo_bool, NULL, "hcontrol element is TLV writable",snd_ctl_elem_info_is_tlv_writable}, {"is_tlv_Commandable",(getter)pyalsahcontrolinfo_bool, NULL, "hcontrol element is TLV commandable",snd_ctl_elem_info_is_tlv_commandable}, {"is_owner", (getter)pyalsahcontrolinfo_bool, NULL, "this process is owner of this hcontrol element",snd_ctl_elem_info_is_owner}, {"is_user", (getter)pyalsahcontrolinfo_bool, NULL, "hcontrol element is user element",snd_ctl_elem_info_is_user}, {"owner", (getter)pyalsahcontrolinfo_getowner, NULL, "get owner pid for this hcontrol element", NULL}, {"count", (getter)pyalsahcontrolinfo_uint, NULL, "get count of values", snd_ctl_elem_info_get_count}, {"min", (getter)pyalsahcontrolinfo_long, NULL, "get minimum limit value", snd_ctl_elem_info_get_min}, {"max", (getter)pyalsahcontrolinfo_long, NULL, "get maximum limit value", snd_ctl_elem_info_get_max}, {"step", (getter)pyalsahcontrolinfo_long, NULL, "get step value", snd_ctl_elem_info_get_step}, {"min64", (getter)pyalsahcontrolinfo_longlong, NULL, "get 64-bit minimum limit value", snd_ctl_elem_info_get_min64}, {"max64", (getter)pyalsahcontrolinfo_longlong, NULL, "get 64-bit maximum limit value", snd_ctl_elem_info_get_max64}, {"step64", (getter)pyalsahcontrolinfo_longlong, NULL, "get 64-bit step value", snd_ctl_elem_info_get_step64}, {"items", (getter)pyalsahcontrolinfo_getitems, NULL, "get count of enumerated items", NULL}, {"dimensions", (getter)pyalsahcontrolinfo_dimensions, NULL, "get hcontrol element dimensions (in tuple)", NULL}, {"item_names", (getter)pyalsahcontrolinfo_itemnames, NULL, "get enumerated item names (in tuple)", NULL}, {NULL} }; static PyMethodDef pyalsahcontrolinfo_methods[] = { {NULL} }; static PyTypeObject pyalsahcontrolinfo_type = { PyObject_HEAD_INIT(0) tp_name: "alsahcontrol.Info", tp_basicsize: sizeof(struct pyalsahcontrolinfo), tp_dealloc: (destructor)pyalsahcontrolinfo_dealloc, tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, tp_doc: infoinit__doc__, tp_getset: pyalsahcontrolinfo_getseters, tp_init: (initproc)pyalsahcontrolinfo_init, tp_alloc: PyType_GenericAlloc, tp_new: PyType_GenericNew, tp_free: PyObject_Del, tp_methods: pyalsahcontrolinfo_methods, }; /* * hcontrol value section */ #define PYHCTLVALUE(v) (((v) == Py_None) ? NULL : \ ((struct pyalsahcontrolvalue *)(v))) struct pyalsahcontrolvalue { PyObject_HEAD PyObject *pyelem; snd_hctl_elem_t *elem; snd_ctl_elem_value_t *value; }; static PyObject * pyalsahcontrolvalue_element(struct pyalsahcontrolvalue *pyvalue, void *priv) { Py_INCREF(pyvalue->pyelem); return pyvalue->pyelem; } typedef unsigned int (*fcn10)(void *); static PyObject * pyalsahcontrolvalue_uint(struct pyalsahcontrolvalue *pyvalue, void *fcn) { return PyLong_FromLong(((fcn10)fcn)(pyvalue->value)); } typedef const char * (*fcn11)(void *); static PyObject * pyalsahcontrolvalue_str(struct pyalsahcontrolvalue *pyvalue, void *fcn) { return PyString_FromString(((fcn5)fcn)(pyvalue->value)); } static PyObject * pyalsahcontrolvalue_id(struct pyalsahcontrolvalue *pyvalue, void *priv) { snd_ctl_elem_id_t *id; snd_ctl_elem_id_alloca(&id); snd_ctl_elem_value_get_id(pyvalue->value, id); return id_to_python(id); } PyDoc_STRVAR(gettuple__doc__, "get_tuple(type, count) -- Get hcontrol element values in tuple."); PyDoc_STRVAR(getarray__doc__, "get_array(type, count) -- Get hcontrol element values in array."); static PyObject * pyalsahcontrolvalue_get1(struct pyalsahcontrolvalue *self, PyObject *args, int list) { int type; long i, count; snd_aes_iec958_t *iec958; PyObject *t, *o; if (!PyArg_ParseTuple(args, "il", &type, &count)) return NULL; if (count <= 0) Py_RETURN_NONE; if (type == SND_CTL_ELEM_TYPE_IEC958) { if (count != 1) Py_RETURN_NONE; count = 3; } t = !list ? PyTuple_New(count) : PyList_New(count); if (t == NULL) return NULL; switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: for (i = 0; i < count; i++) { o = get_bool(snd_ctl_elem_value_get_boolean(self->value, i)); if (!list) PyTuple_SET_ITEM(t, i, o); else PyList_SetItem(t, i, o); } break; case SND_CTL_ELEM_TYPE_INTEGER: for (i = 0; i < count; i++) { o = PyInt_FromLong(snd_ctl_elem_value_get_integer(self->value, i)); if (!list) PyTuple_SET_ITEM(t, i, o); else PyList_SetItem(t, i, o); } break; case SND_CTL_ELEM_TYPE_INTEGER64: for (i = 0; i < count; i++) { o = PyLong_FromLongLong(snd_ctl_elem_value_get_integer64(self->value, i)); if (!list) PyTuple_SET_ITEM(t, i, o); else PyList_SetItem(t, i, o); } break; case SND_CTL_ELEM_TYPE_ENUMERATED: for (i = 0; i < count; i++) { o = PyInt_FromLong(snd_ctl_elem_value_get_enumerated(self->value, i)); if (!list) { PyTuple_SET_ITEM(t, i, o); } else { PyList_SetItem(t, i, o); } } break; case SND_CTL_ELEM_TYPE_BYTES: for (i = 0; i < count; i++) { o = PyInt_FromLong(snd_ctl_elem_value_get_byte(self->value, i)); if (!list) { PyTuple_SET_ITEM(t, i, o); } else { PyList_SetItem(t, i, o); } } break; case SND_CTL_ELEM_TYPE_IEC958: iec958 = malloc(sizeof(*iec958)); if (iec958 == NULL) { Py_DECREF(t); Py_RETURN_NONE; } snd_ctl_elem_value_get_iec958(self->value, iec958); if (!list) { PyTuple_SET_ITEM(t, 0, PyString_FromStringAndSize((char *)iec958->status, sizeof(iec958->status))); PyTuple_SET_ITEM(t, 1, PyString_FromStringAndSize((char *)iec958->subcode, sizeof(iec958->subcode))); PyTuple_SET_ITEM(t, 2, PyString_FromStringAndSize((char *)iec958->dig_subframe, sizeof(iec958->dig_subframe))); } else { PyList_SetItem(t, 0, PyString_FromStringAndSize((char *)iec958->status, sizeof(iec958->status))); PyList_SetItem(t, 1, PyString_FromStringAndSize((char *)iec958->subcode, sizeof(iec958->subcode))); PyList_SetItem(t, 2, PyString_FromStringAndSize((char *)iec958->dig_subframe, sizeof(iec958->dig_subframe))); } free(iec958); break; default: Py_DECREF(t); t = NULL; PyErr_Format(PyExc_TypeError, "Unknown hcontrol element type %i", type); break; } return t; } static PyObject * pyalsahcontrolvalue_gettuple(struct pyalsahcontrolvalue *self, PyObject *args) { return pyalsahcontrolvalue_get1(self, args, 0); } static PyObject * pyalsahcontrolvalue_getarray(struct pyalsahcontrolvalue *self, PyObject *args) { return pyalsahcontrolvalue_get1(self, args, 1); } PyDoc_STRVAR(settuple__doc__, "set_tuple(type, val) -- Set hcontrol element values from tuple."); PyDoc_STRVAR(setarray__doc__, "set_array(type, val) -- Set hcontrol element values from array."); static PyObject * pyalsahcontrolvalue_settuple(struct pyalsahcontrolvalue *self, PyObject *args) { int type, list; Py_ssize_t len; long i, count; snd_aes_iec958_t *iec958; PyObject *t, *v; char *str; if (!PyArg_ParseTuple(args, "iO", &type, &t)) return NULL; list = PyList_Check(t); if (!PyTuple_Check(t) && !list) { PyErr_SetString(PyExc_TypeError, "Tuple expected as val argument!"); return NULL; } count = !list ? PyTuple_Size(t) : PyList_Size(t); switch (type) { case SND_CTL_ELEM_TYPE_BOOLEAN: for (i = 0; i < count; i++) { v = !list ? PyTuple_GetItem(t, i) : PyList_GetItem(t, i); if (v == Py_None) continue; Py_INCREF(v); snd_ctl_elem_value_set_boolean(self->value, i, PyInt_AsLong(v)); } break; case SND_CTL_ELEM_TYPE_INTEGER: for (i = 0; i < count; i++) { v = !list ? PyTuple_GetItem(t, i) : PyList_GetItem(t, i); if (v == Py_None) continue; Py_INCREF(v); snd_ctl_elem_value_set_integer(self->value, i, PyInt_AsLong(v)); } break; case SND_CTL_ELEM_TYPE_INTEGER64: for (i = 0; i < count; i++) { v = !list ? PyTuple_GetItem(t, i) : PyList_GetItem(t, i); if (v == Py_None) continue; Py_INCREF(v); snd_ctl_elem_value_set_integer64(self->value, i, PyLong_AsLongLong(v)); } break; case SND_CTL_ELEM_TYPE_ENUMERATED: for (i = 0; i < count; i++) { v = !list ? PyTuple_GetItem(t, i) : PyList_GetItem(t, i); if (v == Py_None) continue; Py_INCREF(v); snd_ctl_elem_value_set_enumerated(self->value, i, PyInt_AsLong(v)); } break; case SND_CTL_ELEM_TYPE_BYTES: for (i = 0; i < count; i++) { v = !list ? PyTuple_GetItem(t, i) : PyList_GetItem(t, i); if (v == Py_None) continue; Py_INCREF(v); snd_ctl_elem_value_set_byte(self->value, i, PyInt_AsLong(v)); } break; case SND_CTL_ELEM_TYPE_IEC958: if (count != 3) { PyErr_SetString(PyExc_TypeError, "Tuple with len == 3 expected for IEC958 type!"); return NULL; } iec958 = calloc(1, sizeof(*iec958)); if (iec958 == NULL) { Py_DECREF(t); Py_RETURN_NONE; } len = 0; v = !list ? PyTuple_GET_ITEM(t, 0) : PyList_GetItem(t, 0); Py_INCREF(v); if (PyString_AsStringAndSize(v, &str, &len)) goto err1; if (len > sizeof(iec958->status)) len = sizeof(iec958->status); memcpy(iec958->status, str, len); len = 0; v = !list ? PyTuple_GET_ITEM(t, 1) : PyList_GetItem(t, 1); Py_INCREF(v); if (PyString_AsStringAndSize(v, &str, &len)) goto err1; if (len > sizeof(iec958->subcode)) len = sizeof(iec958->subcode); memcpy(iec958->subcode, str, len); len = 0; v = !list ? PyTuple_GET_ITEM(t, 2) : PyList_GetItem(t, 2); Py_INCREF(v); if (PyString_AsStringAndSize(v, &str, &len)) goto err1; if (len > sizeof(iec958->dig_subframe)) len = sizeof(iec958->dig_subframe); memcpy(iec958->dig_subframe, str, len); free(iec958); break; err1: PyErr_SetString(PyExc_TypeError, "Invalid tuple IEC958 type!"); free(iec958); break; default: PyErr_Format(PyExc_TypeError, "Unknown hcontrol element type %i", type); break; } Py_RETURN_NONE; } PyDoc_STRVAR(read__doc__, "read() -- Read value state.\n"); static PyObject * pyalsahcontrolvalue_read(struct pyalsahcontrolvalue *self, PyObject *args) { int res; res = snd_hctl_elem_read(self->elem, self->value); if (res < 0) return PyErr_Format(PyExc_IOError, "hcontrol element read error: %s", snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(write__doc__, "write() -- Write new value state.\n"); static PyObject * pyalsahcontrolvalue_write(struct pyalsahcontrolvalue *self, PyObject *args) { int res; res = snd_hctl_elem_write(self->elem, self->value); if (res < 0) return PyErr_Format(PyExc_IOError, "hcontrol element write error: %s", snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(valueinit__doc__, "Value(elem)\n" " -- Create a hcontrol element value object.\n" "Note: Value state is read from device!\n"); static int pyalsahcontrolvalue_init(struct pyalsahcontrolvalue *pyvalue, PyObject *args, PyObject *kwds) { PyObject *elem; int res; pyvalue->pyelem = NULL; pyvalue->elem = NULL; pyvalue->value = NULL; if (!PyArg_ParseTuple(args, "O", &elem)) return -1; if (elem->ob_type != &pyalsahcontrolelement_type) { PyErr_SetString(PyExc_TypeError, "bad type for element argument"); return -1; } if (snd_ctl_elem_value_malloc(&pyvalue->value)) { PyErr_SetString(PyExc_TypeError, "malloc problem"); return -1; } pyvalue->pyelem = elem; Py_INCREF(elem); pyvalue->elem = PYHCTLELEMENT(elem)->elem; res = snd_hctl_elem_read(pyvalue->elem, pyvalue->value); if (res < 0) { PyErr_Format(PyExc_IOError, "hcontrol element value read problem: %s", snd_strerror(-res)); return -1; } return 0; } static void pyalsahcontrolvalue_dealloc(struct pyalsahcontrolvalue *self) { if (self->value) snd_ctl_elem_value_free(self->value); if (self->pyelem) { Py_XDECREF(self->pyelem); } self->ob_type->tp_free(self); } static PyGetSetDef pyalsahcontrolvalue_getseters[] = { {"element", (getter)pyalsahcontrolvalue_element, NULL, "hcontrol element for this value", NULL}, {"id", (getter)pyalsahcontrolvalue_id, NULL, "hcontrol element full id", snd_ctl_elem_value_get_id}, {"numid", (getter)pyalsahcontrolvalue_uint, NULL, "hcontrol element numid", snd_ctl_elem_value_get_numid}, {"interface", (getter)pyalsahcontrolvalue_uint, NULL, "hcontrol element interface", snd_ctl_elem_value_get_interface}, {"device", (getter)pyalsahcontrolvalue_uint, NULL, "hcontrol element device", snd_ctl_elem_value_get_device}, {"subdevice", (getter)pyalsahcontrolvalue_uint, NULL, "hcontrol element subdevice", snd_ctl_elem_value_get_subdevice}, {"name", (getter)pyalsahcontrolvalue_str, NULL, "hcontrol element name", snd_ctl_elem_value_get_name}, {"index", (getter)pyalsahcontrolvalue_uint, NULL, "hcontrol element index", snd_ctl_elem_value_get_index}, {NULL} }; static PyMethodDef pyalsahcontrolvalue_methods[] = { {"get_tuple", (PyCFunction)pyalsahcontrolvalue_gettuple, METH_VARARGS, gettuple__doc__}, {"get_array", (PyCFunction)pyalsahcontrolvalue_getarray, METH_VARARGS, getarray__doc__}, {"set_tuple", (PyCFunction)pyalsahcontrolvalue_settuple, METH_VARARGS, settuple__doc__}, {"set_array", (PyCFunction)pyalsahcontrolvalue_settuple, METH_VARARGS, setarray__doc__}, {"read", (PyCFunction)pyalsahcontrolvalue_read, METH_NOARGS, read__doc__}, {"write", (PyCFunction)pyalsahcontrolvalue_write, METH_NOARGS, write__doc__}, {NULL} }; static PyTypeObject pyalsahcontrolvalue_type = { PyObject_HEAD_INIT(0) tp_name: "alsahcontrol.Value", tp_basicsize: sizeof(struct pyalsahcontrolvalue), tp_dealloc: (destructor)pyalsahcontrolvalue_dealloc, tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, tp_doc: valueinit__doc__, tp_getset: pyalsahcontrolvalue_getseters, tp_init: (initproc)pyalsahcontrolvalue_init, tp_alloc: PyType_GenericAlloc, tp_new: PyType_GenericNew, tp_free: PyObject_Del, tp_methods: pyalsahcontrolvalue_methods, }; /* * */ static PyMethodDef pyalsahcontrolparse_methods[] = { {NULL} }; PyMODINIT_FUNC initalsahcontrol(void) { PyObject *d, *d1, *l1, *o; int i; if (PyType_Ready(&pyalsahcontrol_type) < 0) return; if (PyType_Ready(&pyalsahcontrolelement_type) < 0) return; if (PyType_Ready(&pyalsahcontrolinfo_type) < 0) return; if (PyType_Ready(&pyalsahcontrolvalue_type) < 0) return; module = Py_InitModule3("alsahcontrol", pyalsahcontrolparse_methods, "libasound hcontrol wrapper"); if (module == NULL) return; #if 0 buildin = PyImport_AddModule("__buildin__"); if (buildin == NULL) return; if (PyObject_SetAttrString(module, "__buildins__", buildin) < 0) return; #endif Py_INCREF(&pyalsahcontrol_type); PyModule_AddObject(module, "HControl", (PyObject *)&pyalsahcontrol_type); Py_INCREF(&pyalsahcontrolelement_type); PyModule_AddObject(module, "Element", (PyObject *)&pyalsahcontrolelement_type); Py_INCREF(&pyalsahcontrolinfo_type); PyModule_AddObject(module, "Info", (PyObject *)&pyalsahcontrolinfo_type); Py_INCREF(&pyalsahcontrolvalue_type); PyModule_AddObject(module, "Value", (PyObject *)&pyalsahcontrolvalue_type); d = PyModule_GetDict(module); /* ---- */ d1 = PyDict_New(); #define add_space1(pname, name) { \ o = PyInt_FromLong(SND_CTL_ELEM_IFACE_##name); \ PyDict_SetItemString(d1, pname, o); \ Py_DECREF(o); } add_space1("CARD", CARD); add_space1("HWDEP", HWDEP); add_space1("MIXER", MIXER); add_space1("PCM", PCM); add_space1("RAWMIDI", RAWMIDI); add_space1("TIMER", TIMER); add_space1("SEQUENCER", SEQUENCER); add_space1("LAST", LAST); PyDict_SetItemString(d, "interface_id", d1); Py_DECREF(d1); /* ---- */ l1 = PyList_New(0); for (i = 0; i <= SND_CTL_ELEM_IFACE_LAST; i++) { o = PyString_FromString(snd_ctl_elem_iface_name(i)); PyList_Append(l1, o); Py_DECREF(o); } PyDict_SetItemString(d, "interface_name", l1); Py_DECREF(l1); /* ---- */ d1 = PyDict_New(); #define add_space2(pname, name) { \ o = PyInt_FromLong(SND_CTL_ELEM_TYPE_##name); \ PyDict_SetItemString(d1, pname, o); \ Py_DECREF(o); } add_space2("NONE", NONE); add_space2("BOOLEAN", BOOLEAN); add_space2("INTEGER", INTEGER); add_space2("ENUMERATED", ENUMERATED); add_space2("BYTES", BYTES); add_space2("IEC958", IEC958); add_space2("INTEGER64", INTEGER64); add_space2("LAST", LAST); PyDict_SetItemString(d, "element_type", d1); Py_DECREF(d1); /* ---- */ l1 = PyList_New(0); for (i = 0; i <= SND_CTL_ELEM_TYPE_LAST; i++) { o = PyString_FromString(snd_ctl_elem_type_name(i)); PyList_Append(l1, o); Py_DECREF(o); } PyDict_SetItemString(d, "element_type_name", l1); Py_DECREF(l1); /* ---- */ d1 = PyDict_New(); #define add_space3(pname, name) { \ o = PyInt_FromLong(SND_CTL_EVENT_##name); \ PyDict_SetItemString(d1, pname, o); \ Py_DECREF(o); } add_space3("ELEMENT", ELEM); add_space3("LAST", LAST); PyDict_SetItemString(d, "event_class", d1); Py_DECREF(d1); /* ---- */ d1 = PyDict_New(); #define add_space4(pname, name) { \ o = PyInt_FromLong(SND_CTL_EVENT_MASK_##name); \ PyDict_SetItemString(d1, pname, o); \ Py_DECREF(o); } add_space4("VALUE", VALUE); add_space4("INFO", INFO); add_space4("ADD", ADD); add_space4("TLV", TLV); PyDict_SetItemString(d, "event_mask", d1); Py_DECREF(d1); o = PyInt_FromLong(SND_CTL_EVENT_MASK_REMOVE); PyDict_SetItemString(d, "event_mask_remove", o); Py_DECREF(o); /* ---- */ d1 = PyDict_New(); #define add_space5(pname, name) { \ o = PyInt_FromLong(SND_CTL_##name); \ PyDict_SetItemString(d1, pname, o); \ Py_DECREF(o); } add_space5("NONBLOCK", NONBLOCK); add_space5("ASYNC", ASYNC); add_space5("READONLY", READONLY); PyDict_SetItemString(d, "open_mode", d1); Py_DECREF(d1); /* ---- */ main_interpreter = PyThreadState_Get()->interp; if (PyErr_Occurred()) Py_FatalError("Cannot initialize module alsahcontrol"); } /* * element event callback */ static int element_callback(snd_hctl_elem_t *elem, unsigned int mask) { PyThreadState *tstate, *origstate; struct pyalsahcontrolelement *pyhelem; PyObject *o, *t, *r; int res = 0, inside = 1; if (elem == NULL) return -EINVAL; pyhelem = snd_hctl_elem_get_callback_private(elem); if (pyhelem == NULL || pyhelem->callback == NULL) return -EINVAL; tstate = PyThreadState_New(main_interpreter); origstate = PyThreadState_Swap(tstate); o = PyObject_GetAttr(pyhelem->callback, PyString_InternFromString("callback")); if (!o) { PyErr_Clear(); o = pyhelem->callback; inside = 0; } t = PyTuple_New(2); if (t) { if (PyTuple_SET_ITEM(t, 0, (PyObject *)pyhelem)) Py_INCREF(pyhelem); PyTuple_SET_ITEM(t, 1, PyInt_FromLong(mask)); r = PyObject_CallObject(o, t); Py_DECREF(t); if (r) { if (PyInt_Check(r)) { res = PyInt_AsLong(r); } else if (r == Py_None) { res = 0; } Py_DECREF(r); } else { PyErr_Print(); PyErr_Clear(); res = -EIO; } } if (inside) { Py_DECREF(o); } PyThreadState_Swap(origstate); PyThreadState_Delete(tstate); return res; } pyalsa-1.0.26/pyalsa/alsamixer.c0000664000000000000000000011722212022053131016445 0ustar rootroot00000000000000/* * Python binding for the ALSA library - mixer * Copyright (c) 2007 by Jaroslav Kysela * * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "Python.h" #include "structmember.h" #include "frameobject.h" #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif #include "sys/poll.h" #include "stdlib.h" #include "alsa/asoundlib.h" #ifndef Py_RETURN_NONE #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None #endif #ifndef Py_RETURN_TRUE #define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True #endif #ifndef Py_RETURN_FALSE #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False #endif static int element_callback(snd_mixer_elem_t *elem, unsigned int mask); static PyObject *module; #if 0 static PyObject *buildin; #endif static PyInterpreterState *main_interpreter; /* * */ #define PYALSAMIXER(v) (((v) == Py_None) ? NULL : \ ((struct pyalsamixer *)(v))) struct pyalsamixer { PyObject_HEAD snd_mixer_t *handle; }; static inline PyObject *get_bool(int val) { if (val) { Py_INCREF(Py_True); return Py_True; } else { Py_INCREF(Py_False); return Py_False; } } static PyObject * pyalsamixer_getcount(struct pyalsamixer *self, void *priv) { return PyLong_FromLong(snd_mixer_get_count(self->handle)); } PyDoc_STRVAR(attach__doc__, "attach(card=None, [, abstract=]) -- Attach mixer to a sound card."); static PyObject * pyalsamixer_attach(struct pyalsamixer *self, PyObject *args, PyObject *kwds) { char *card = "default"; int abstract = -1, res; static char * kwlist[] = { "card", "abstract", NULL }; struct snd_mixer_selem_regopt *options = NULL, _options; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|si", kwlist, &card, &abstract)) Py_RETURN_NONE; if (abstract < 0) { res = snd_mixer_attach(self->handle, card); if (res < 0) return PyErr_Format(PyExc_RuntimeError, "Cannot attach card '%s': %s", card, snd_strerror(-res)); abstract = -1; } if (abstract >= 0) { memset(&_options, 0, sizeof(_options)); _options.ver = 1; _options.abstract = abstract; _options.device = card; options = &_options; } res = snd_mixer_selem_register(self->handle, options, NULL); if (res < 0) return PyErr_Format(PyExc_RuntimeError, "Cannot register simple mixer (abstract %i): %s", abstract, snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(load__doc__, "load() -- Load mixer elements."); static PyObject * pyalsamixer_load(struct pyalsamixer *self, PyObject *args) { int res = snd_mixer_load(self->handle); if (res < 0) return PyErr_Format(PyExc_RuntimeError, "Cannot load mixer elements: %s", snd_strerror(-res)); return Py_BuildValue("i", res); } PyDoc_STRVAR(free__doc__, "free() -- Free mixer elements and all related resources."); static PyObject * pyalsamixer_free(struct pyalsamixer *self, PyObject *args) { snd_mixer_free(self->handle); Py_RETURN_NONE; } PyDoc_STRVAR(handlevents__doc__, "handle_events() -- Process waiting mixer events (and call appropriate callbacks)."); static PyObject * pyalsamixer_handleevents(struct pyalsamixer *self, PyObject *args) { int err; Py_BEGIN_ALLOW_THREADS; err = snd_mixer_handle_events(self->handle); Py_END_ALLOW_THREADS; if (err < 0) PyErr_Format(PyExc_IOError, "Alsamixer handle events error: %s", strerror(-err)); Py_RETURN_NONE; } PyDoc_STRVAR(registerpoll__doc__, "register_poll(pollObj) -- Register poll file descriptors."); static PyObject * pyalsamixer_registerpoll(struct pyalsamixer *self, PyObject *args) { PyObject *pollObj, *reg, *t; struct pollfd *pfd; int i, count; if (!PyArg_ParseTuple(args, "O", &pollObj)) return NULL; count = snd_mixer_poll_descriptors_count(self->handle); if (count <= 0) Py_RETURN_NONE; pfd = alloca(sizeof(struct pollfd) * count); count = snd_mixer_poll_descriptors(self->handle, pfd, count); if (count <= 0) Py_RETURN_NONE; reg = PyObject_GetAttr(pollObj, PyString_InternFromString("register")); for (i = 0; i < count; i++) { t = PyTuple_New(2); if (t) { PyTuple_SET_ITEM(t, 0, PyInt_FromLong(pfd[i].fd)); PyTuple_SET_ITEM(t, 1, PyInt_FromLong(pfd[i].events)); Py_XDECREF(PyObject_CallObject(reg, t)); Py_DECREF(t); } } Py_XDECREF(reg); Py_RETURN_NONE; } static PyObject * pyalsamixer_getpollfds(struct pyalsamixer *self, void *priv) { PyObject *l, *t; struct pollfd *pfds; int i, count; count = snd_mixer_poll_descriptors_count(self->handle); if (count < 0) { pfds_error: PyErr_Format(PyExc_IOError, "poll descriptors error: %s", snd_strerror(count)); return NULL; } pfds = alloca(sizeof(struct pollfd) * count); count = snd_mixer_poll_descriptors(self->handle, pfds, count); if (count < 0) goto pfds_error; l = PyList_New(count); if (!l) return NULL; for (i = 0; i < count; ++i) { t = PyTuple_New(2); if (t) { PyTuple_SET_ITEM(t, 0, PyInt_FromLong(pfds[i].fd)); PyTuple_SET_ITEM(t, 1, PyInt_FromLong(pfds[i].events)); PyList_SetItem(l, i, t); } } return l; } PyDoc_STRVAR(list__doc__, "list() -- Return a list (tuple) of element IDs in (name,index) tuple."); static PyObject * pyalsamixer_list(struct pyalsamixer *self, PyObject *args) { PyObject *t, *v; int i, count; snd_mixer_elem_t *elem; count = snd_mixer_get_count(self->handle); t = PyTuple_New(count); if (count == 0) return t; elem = snd_mixer_first_elem(self->handle); for (i = 0; i < count; i++) { v = NULL; if (elem) { v = PyTuple_New(2); PyTuple_SET_ITEM(v, 0, PyString_FromString(snd_mixer_selem_get_name(elem))); PyTuple_SET_ITEM(v, 1, PyInt_FromLong(snd_mixer_selem_get_index(elem))); } if (v == NULL || elem == NULL) { v = Py_None; Py_INCREF(v); } PyTuple_SET_ITEM(t, i, v); elem = snd_mixer_elem_next(elem); } return t; } PyDoc_STRVAR(alsamixerinit__doc__, "Mixer([mode=0])\n" " -- Open an ALSA mixer device.\n"); static int pyalsamixer_init(struct pyalsamixer *pymix, PyObject *args, PyObject *kwds) { int mode = 0, err; static char * kwlist[] = { "mode", NULL }; pymix->handle = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &mode)) return -1; err = snd_mixer_open(&pymix->handle, mode); if (err < 0) { PyErr_Format(PyExc_IOError, "Alsamixer open error: %s", strerror(-err)); return -1; } return 0; } static void pyalsamixer_dealloc(struct pyalsamixer *self) { if (self->handle != NULL) snd_mixer_close(self->handle); self->ob_type->tp_free(self); } static PyGetSetDef pyalsamixer_getseters[] = { {"count", (getter)pyalsamixer_getcount, NULL, "mixer element count", NULL}, {"poll_fds", (getter)pyalsamixer_getpollfds, NULL, "list of (fd, eventbits) tuples", NULL}, {NULL} }; static PyMethodDef pyalsamixer_methods[] = { {"attach", (PyCFunction)pyalsamixer_attach, METH_VARARGS|METH_KEYWORDS, attach__doc__}, {"load", (PyCFunction)pyalsamixer_load, METH_NOARGS, load__doc__}, {"free", (PyCFunction)pyalsamixer_free, METH_NOARGS, free__doc__}, {"list", (PyCFunction)pyalsamixer_list, METH_NOARGS, list__doc__}, {"handle_events",(PyCFunction)pyalsamixer_handleevents, METH_NOARGS, handlevents__doc__}, {"register_poll",(PyCFunction)pyalsamixer_registerpoll, METH_VARARGS, registerpoll__doc__}, {NULL} }; static PyTypeObject pyalsamixer_type = { PyObject_HEAD_INIT(0) tp_name: "alsamixer.Mixer", tp_basicsize: sizeof(struct pyalsamixer), tp_dealloc: (destructor)pyalsamixer_dealloc, tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, tp_doc: alsamixerinit__doc__, tp_getset: pyalsamixer_getseters, tp_init: (initproc)pyalsamixer_init, tp_alloc: PyType_GenericAlloc, tp_new: PyType_GenericNew, tp_free: PyObject_Del, tp_methods: pyalsamixer_methods, }; /* * mixer element section */ #define PYALSAMIXERELEMENT(v) (((v) == Py_None) ? NULL : \ ((struct pyalsamixerelement *)(v))) struct pyalsamixerelement { PyObject_HEAD PyObject *pyhandle; PyObject *callback; snd_mixer_t *handle; snd_mixer_elem_t *elem; }; static PyObject * pyalsamixerelement_getname(struct pyalsamixerelement *pyelem, void *priv) { return PyString_FromString(snd_mixer_selem_get_name(pyelem->elem)); } static PyObject * pyalsamixerelement_getindex(struct pyalsamixerelement *pyelem, void *priv) { return PyInt_FromLong(snd_mixer_selem_get_index(pyelem->elem)); } typedef unsigned int (*fcn1)(void *); static PyObject * pyalsamixerelement_bool(struct pyalsamixerelement *pyelem, void *fcn) { int res = ((fcn1)fcn)(pyelem->elem); if (res > 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; } static PyObject * pyalsamixerelement_getcapgroup(struct pyalsamixerelement *pyelem, void *priv) { return PyInt_FromLong(snd_mixer_selem_get_capture_group(pyelem->elem)); } PyDoc_STRVAR(ismono__doc__, "is_mono([capture=False]]) -- Return if this control is mono."); static PyObject * pyalsamixerelement_ismono(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0; if (!PyArg_ParseTuple(args, "|i", &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_is_playback_mono(pyelem->elem); else res = snd_mixer_selem_is_capture_mono(pyelem->elem); if (res > 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyDoc_STRVAR(haschannel__doc__, "has_channel([channel=channel_id['MONO'], [capture=False]]) -- Return if channel exists."); static PyObject * pyalsamixerelement_haschannel(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, chn = SND_MIXER_SCHN_MONO; if (!PyArg_ParseTuple(args, "|ii", &chn, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_has_playback_channel(pyelem->elem, chn); else res = snd_mixer_selem_has_capture_channel(pyelem->elem, chn); if (res > 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; } PyDoc_STRVAR(hasvolume__doc__, "has_volume([capture=False]]) -- Return if volume exists.\n" "Note: String 'Joined' is returned when volume is joined."); static PyObject * pyalsamixerelement_hasvolume(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0; if (!PyArg_ParseTuple(args, "|i", &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_has_playback_volume(pyelem->elem); else res = snd_mixer_selem_has_capture_volume(pyelem->elem); if (res > 0) { if (dir == 0) res = snd_mixer_selem_has_playback_volume_joined(pyelem->elem); else res = snd_mixer_selem_has_capture_volume_joined(pyelem->elem); if (res > 0) return Py_BuildValue("s", "Joined"); Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } PyDoc_STRVAR(hasswitch__doc__, "has_switch([capture=False]) -- Return if switch exists." "Note: String 'Joined' is returned when switch is joined."); static PyObject * pyalsamixerelement_hasswitch(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0; if (!PyArg_ParseTuple(args, "|i", &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_has_playback_switch(pyelem->elem); else res = snd_mixer_selem_has_capture_switch(pyelem->elem); if (res > 0) { if (dir == 0) res = snd_mixer_selem_has_playback_switch_joined(pyelem->elem); else res = snd_mixer_selem_has_capture_switch_joined(pyelem->elem); if (res > 0) return Py_BuildValue("s", "Joined"); Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } PyDoc_STRVAR(askvoldB__doc__, "ask_volume_dB(value, [capture=False]]) -- Convert integer volume to dB value."); static PyObject * pyalsamixerelement_askvoldB(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0; long volume, val; if (!PyArg_ParseTuple(args, "|li", &volume, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_ask_playback_vol_dB(pyelem->elem, volume, &val); else res = snd_mixer_selem_ask_capture_vol_dB(pyelem->elem, volume, &val); if (res < 0) { PyErr_Format(PyExc_RuntimeError, "Cannot convert mixer volume (capture=%s, value=%li): %s", dir ? "True" : "False", volume, snd_strerror(-res)); Py_RETURN_NONE; } return PyInt_FromLong(val); } PyDoc_STRVAR(askdBvol__doc__, "ask_dB_volume(dBvalue, [[direction=-1], [capture=False]]) -- Convert integer volume to dB value."); static PyObject * pyalsamixerelement_askdBvol(struct pyalsamixerelement *pyelem, PyObject *args) { int res, xdir = -1, dir = 0; long dBvolume, val; if (!PyArg_ParseTuple(args, "|lii", &dBvolume, &xdir, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_ask_playback_dB_vol(pyelem->elem, dBvolume, xdir, &val); else res = snd_mixer_selem_ask_capture_dB_vol(pyelem->elem, dBvolume, xdir, &val); if (res < 0) { PyErr_Format(PyExc_RuntimeError, "Cannot convert mixer volume (capture=%s, dBvalue=%li, direction=%i): %s", dir ? "True" : "False", dBvolume, xdir, snd_strerror(-res)); Py_RETURN_NONE; } return PyInt_FromLong(val); } PyDoc_STRVAR(getvolume__doc__, "get_volume([channel=ChannelId['MONO'], [capture=False]]) -- Get volume."); static PyObject * pyalsamixerelement_getvolume(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, chn = SND_MIXER_SCHN_MONO; long val; if (!PyArg_ParseTuple(args, "|ii", &chn, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_get_playback_volume(pyelem->elem, chn, &val); else res = snd_mixer_selem_get_capture_volume(pyelem->elem, chn, &val); if (res < 0) { PyErr_Format(PyExc_RuntimeError, "Cannot get mixer volume (capture=%s, channel=%i): %s", dir ? "True" : "False", chn, snd_strerror(-res)); Py_RETURN_NONE; } return PyInt_FromLong(val); } PyDoc_STRVAR(getvolumetuple__doc__, "get_volume_tuple([capture=False]]) -- Get volume and store result to tuple."); static PyObject * pyalsamixerelement_getvolumetuple(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, i, last; long val; PyObject *t; if (!PyArg_ParseTuple(args, "|i", &dir)) return NULL; if (dir == 0) { if (snd_mixer_selem_is_playback_mono(pyelem->elem)) { t = PyTuple_New(1); if (!t) return NULL; res = snd_mixer_selem_get_playback_volume(pyelem->elem, SND_MIXER_SCHN_MONO, &val); if (res >= 0) PyTuple_SET_ITEM(t, 0, PyInt_FromLong(val)); } else { t = PyTuple_New(SND_MIXER_SCHN_LAST+1); if (!t) return NULL; for (i = last = 0; i <= SND_MIXER_SCHN_LAST; i++) { res = -1; if (snd_mixer_selem_has_playback_channel(pyelem->elem, i)) { res = snd_mixer_selem_get_playback_volume(pyelem->elem, i, &val); if (res >= 0) { while (last < i) { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, last, Py_None); last++; } PyTuple_SET_ITEM(t, i, PyInt_FromLong(val)); last++; } } } _PyTuple_Resize(&t, last); } } else { if (snd_mixer_selem_is_capture_mono(pyelem->elem)) { t = PyTuple_New(1); if (!t) return NULL; res = snd_mixer_selem_get_capture_volume(pyelem->elem, SND_MIXER_SCHN_MONO, &val); if (res >= 0) PyTuple_SET_ITEM(t, 0, PyInt_FromLong(val)); } else { t = PyTuple_New(SND_MIXER_SCHN_LAST+1); if (!t) return NULL; for (i = last = 0; i <= SND_MIXER_SCHN_LAST; i++) { res = -1; if (snd_mixer_selem_has_capture_channel(pyelem->elem, i)) { res = snd_mixer_selem_get_capture_volume(pyelem->elem, i, &val); if (res >= 0) { while (last < i) { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, last, Py_None); last++; } PyTuple_SET_ITEM(t, i, PyInt_FromLong(val)); } } } _PyTuple_Resize(&t, last); } } return t; } PyDoc_STRVAR(getvolumearray__doc__, "get_volume_array([capture=False]]) -- Get volume and store result to array."); static PyObject * pyalsamixerelement_getvolumearray(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, i, last; long val; PyObject *t, *l; if (!PyArg_ParseTuple(args, "|i", &dir)) return NULL; if (dir == 0) { if (snd_mixer_selem_is_playback_mono(pyelem->elem)) { t = PyList_New(1); if (!t) return NULL; res = snd_mixer_selem_get_playback_volume(pyelem->elem, SND_MIXER_SCHN_MONO, &val); if (res >= 0) PyList_SetItem(t, 0, PyInt_FromLong(val)); } else { t = PyList_New(SND_MIXER_SCHN_LAST+1); if (!t) return NULL; for (i = last = 0; i <= SND_MIXER_SCHN_LAST; i++) { res = -1; if (snd_mixer_selem_has_playback_channel(pyelem->elem, i)) { res = snd_mixer_selem_get_playback_volume(pyelem->elem, i, &val); if (res >= 0) { while (last < i) { Py_INCREF(Py_None); PyList_SetItem(t, last, Py_None); last++; } PyList_SetItem(t, i, PyInt_FromLong(val)); last++; } } } l = PyList_GetSlice(t, 0, last); Py_DECREF(t); t = l; } } else { if (snd_mixer_selem_is_capture_mono(pyelem->elem)) { t = PyList_New(1); if (!t) return NULL; res = snd_mixer_selem_get_capture_volume(pyelem->elem, SND_MIXER_SCHN_MONO, &val); if (res >= 0) PyList_SET_ITEM(t, 0, PyInt_FromLong(val)); } else { t = PyList_New(SND_MIXER_SCHN_LAST+1); if (!t) return NULL; for (i = last = 0; i <= SND_MIXER_SCHN_LAST; i++) { res = -1; if (snd_mixer_selem_has_capture_channel(pyelem->elem, i)) { res = snd_mixer_selem_get_capture_volume(pyelem->elem, i, &val); if (res >= 0) { while (last < i) { Py_INCREF(Py_None); PyList_SetItem(t, last, Py_None); last++; } PyList_SetItem(t, i, PyInt_FromLong(val)); } } } l = PyList_GetSlice(t, 0, last); Py_DECREF(t); t = l; } } return t; } PyDoc_STRVAR(setvolume__doc__, "set_volume(value, [channel=ChannelId['MONO'], [capture=False]]) -- Set volume."); static PyObject * pyalsamixerelement_setvolume(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, chn = SND_MIXER_SCHN_MONO; long val; if (!PyArg_ParseTuple(args, "l|ii", &val, &chn, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_set_playback_volume(pyelem->elem, chn, val); else res = snd_mixer_selem_set_capture_volume(pyelem->elem, chn, val); if (res < 0) PyErr_Format(PyExc_RuntimeError, "Cannot set mixer volume (capture=%s, channel=%i, value=%li): %s", dir ? "True" : "False", chn, val, snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(setvolumetuple__doc__, "set_volume_tuple(value, [capture=False]]) -- Set volume level from tuple."); PyDoc_STRVAR(setvolumearray__doc__, "set_volume_array(value, [capture=False]]) -- Set volume level from array."); static PyObject * pyalsamixerelement_setvolumetuple(struct pyalsamixerelement *pyelem, PyObject *args) { PyObject *t, *o; int i, res, dir = 0; long val; if (!PyArg_ParseTuple(args, "O|i", &t, &dir)) return NULL; if (!PyTuple_Check(t) && !PyList_Check(t)) return PyErr_Format(PyExc_RuntimeError, "Volume values in tuple are expected!"); if (PyTuple_Check(t)) { for (i = 0; i < PyTuple_Size(t); i++) { o = PyTuple_GetItem(t, i); if (o == Py_None) continue; if (!PyInt_Check(o)) { PyErr_Format(PyExc_RuntimeError, "Only None or Int types are expected!"); break; } val = PyInt_AsLong(o); if (dir == 0) res = snd_mixer_selem_set_playback_volume(pyelem->elem, i, val); else res = snd_mixer_selem_set_capture_volume(pyelem->elem, i, val); if (res < 0) PyErr_Format(PyExc_RuntimeError, "Cannot set mixer volume (capture=%s, channel=%i, value=%li): %s", dir ? "True" : "False", i, val, snd_strerror(-res)); } } else { for (i = 0; i < PyList_Size(t); i++) { o = PyList_GetItem(t, i); if (o == Py_None) continue; if (!PyInt_Check(o)) { PyErr_Format(PyExc_RuntimeError, "Only None or Int types are expected!"); break; } val = PyInt_AsLong(o); if (dir == 0) res = snd_mixer_selem_set_playback_volume(pyelem->elem, i, val); else res = snd_mixer_selem_set_capture_volume(pyelem->elem, i, val); if (res < 0) PyErr_Format(PyExc_RuntimeError, "Cannot set mixer volume (capture=%s, channel=%i, value=%li): %s", dir ? "True" : "False", i, val, snd_strerror(-res)); } } Py_DECREF(t); Py_RETURN_NONE; } PyDoc_STRVAR(setvolumeall__doc__, "set_volume_all(value, [capture=False]]) -- Set volume for all channels."); static PyObject * pyalsamixerelement_setvolumeall(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0; long val; if (!PyArg_ParseTuple(args, "l|i", &val, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_set_playback_volume_all(pyelem->elem, val); else res = snd_mixer_selem_set_capture_volume_all(pyelem->elem, val); if (res < 0) PyErr_Format(PyExc_RuntimeError, "Cannot set mixer volume (capture=%s, value=%li): %s", dir ? "True" : "False", val, snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(getrange__doc__, "get_volume_range([capture=False]]) -- Get volume range in (min,max) tuple."); static PyObject * pyalsamixerelement_getrange(struct pyalsamixerelement *pyelem, PyObject *args) { int dir = 0, res; long min, max; PyObject *t; if (!PyArg_ParseTuple(args, "|i", &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_get_playback_volume_range(pyelem->elem, &min, &max); else res = snd_mixer_selem_get_capture_volume_range(pyelem->elem, &min, &max); if (res < 0) return PyErr_Format(PyExc_RuntimeError, "Cannot get mixer volume range (capture=%s): %s", dir ? "True" : "False", snd_strerror(-res)); t = PyTuple_New(2); if (!t) Py_RETURN_NONE; PyTuple_SET_ITEM(t, 0, PyInt_FromLong(min)); PyTuple_SET_ITEM(t, 1, PyInt_FromLong(max)); return t; } PyDoc_STRVAR(setrange__doc__, "set_volume_range(min, max, [capture=False]]) -- Set volume range limits."); static PyObject * pyalsamixerelement_setrange(struct pyalsamixerelement *pyelem, PyObject *args) { int dir = 0, res; long min, max; if (!PyArg_ParseTuple(args, "ll|i", &min, &max, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_set_playback_volume_range(pyelem->elem, min, max); else res = snd_mixer_selem_set_capture_volume_range(pyelem->elem, min, max); if (res < 0) return PyErr_Format(PyExc_RuntimeError, "Cannot set mixer volume range (min=%li,max=%li,capture=%s): %s", min, max, dir ? "True" : "False", snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(getswitch__doc__, "get_switch([channel=ChannelId['MONO'], [capture=False]]) -- Get switch state."); static PyObject * pyalsamixerelement_getswitch(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, chn = SND_MIXER_SCHN_MONO, val; if (!PyArg_ParseTuple(args, "|ii", &chn, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_get_playback_switch(pyelem->elem, chn, &val); else res = snd_mixer_selem_get_capture_switch(pyelem->elem, chn, &val); if (res < 0) { PyErr_Format(PyExc_RuntimeError, "Cannot get mixer volume (capture=%s, channel=%i): %s", dir ? "True" : "False", chn, snd_strerror(-res)); Py_RETURN_NONE; } if (val) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } PyDoc_STRVAR(getswitchtuple__doc__, "get_switch_tuple([capture=False]]) -- Get switch state and store result to tuple."); static PyObject * pyalsamixerelement_getswitchtuple(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, i, last, val; PyObject *t; if (!PyArg_ParseTuple(args, "|i", &dir)) return NULL; if (dir == 0) { if (snd_mixer_selem_is_playback_mono(pyelem->elem)) { t = PyTuple_New(1); if (!t) return NULL; res = snd_mixer_selem_get_playback_switch(pyelem->elem, SND_MIXER_SCHN_MONO, &val); if (res >= 0) PyTuple_SET_ITEM(t, 0, get_bool(val)); } else { t = PyTuple_New(SND_MIXER_SCHN_LAST+1); if (!t) return NULL; for (i = last = 0; i <= SND_MIXER_SCHN_LAST; i++) { res = -1; if (snd_mixer_selem_has_playback_channel(pyelem->elem, i)) { res = snd_mixer_selem_get_playback_switch(pyelem->elem, i, &val); if (res >= 0) { while (last < i) { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, last, Py_None); last++; } PyTuple_SET_ITEM(t, i, get_bool(val)); last++; } } } _PyTuple_Resize(&t, last); } } else { if (snd_mixer_selem_is_capture_mono(pyelem->elem)) { t = PyTuple_New(1); if (!t) return NULL; res = snd_mixer_selem_get_capture_switch(pyelem->elem, SND_MIXER_SCHN_MONO, &val); if (res >= 0) PyTuple_SET_ITEM(t, 0, get_bool(val)); } else { t = PyTuple_New(SND_MIXER_SCHN_LAST+1); if (!t) return NULL; for (i = last = 0; i <= SND_MIXER_SCHN_LAST; i++) { res = -1; if (snd_mixer_selem_has_capture_channel(pyelem->elem, i)) { res = snd_mixer_selem_get_capture_switch(pyelem->elem, i, &val); if (res >= 0) { while (last < i) { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, last, Py_None); last++; } PyTuple_SET_ITEM(t, i, get_bool(val)); } } } _PyTuple_Resize(&t, last); } } return t; } PyDoc_STRVAR(setswitch__doc__, "set_switch(value, [channel=ChannelId['MONO'], [capture=False]]) -- Set switch state."); static PyObject * pyalsamixerelement_setswitch(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, chn = SND_MIXER_SCHN_MONO, val; if (!PyArg_ParseTuple(args, "i|ii", &val, &chn, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_set_playback_switch(pyelem->elem, chn, val); else res = snd_mixer_selem_set_capture_switch(pyelem->elem, chn, val); if (res < 0) PyErr_Format(PyExc_RuntimeError, "Cannot set mixer switch (capture=%s, channel=%i, value=%i): %s", dir ? "True" : "False", chn, val, snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(setswitchtuple__doc__, "set_switch_tuple(value, [capture=False]]) -- Set switch state from tuple."); static PyObject * pyalsamixerelement_setswitchtuple(struct pyalsamixerelement *pyelem, PyObject *args) { PyObject *t, *o; int i, res, dir = 0, val; if (!PyArg_ParseTuple(args, "O|i", &t, &dir)) return NULL; if (!PyTuple_Check(t)) return PyErr_Format(PyExc_RuntimeError, "Switch state values in tuple are expected!"); for (i = 0; i < PyTuple_Size(t); i++) { o = PyTuple_GetItem(t, i); if (o == Py_None) continue; val = PyObject_IsTrue(o); if (dir == 0) res = snd_mixer_selem_set_playback_switch(pyelem->elem, i, val); else res = snd_mixer_selem_set_capture_switch(pyelem->elem, i, val); if (res < 0) PyErr_Format(PyExc_RuntimeError, "Cannot set mixer switch (capture=%s, channel=%i, value=%i): %s", dir ? "True" : "False", i, val, snd_strerror(-res)); } Py_DECREF(t); Py_RETURN_NONE; } PyDoc_STRVAR(setswitchall__doc__, "set_switch_all(value, [capture=False]]) -- Set switch for all channels."); static PyObject * pyalsamixerelement_setswitchall(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, val; if (!PyArg_ParseTuple(args, "i|i", &val, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_set_playback_switch_all(pyelem->elem, val); else res = snd_mixer_selem_set_capture_switch_all(pyelem->elem, val); if (res < 0) PyErr_Format(PyExc_RuntimeError, "Cannot set mixer switch state (capture=%s, value=%i): %s", dir ? "True" : "False", val, snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(getvolumedb__doc__, "get_volume_dB([channel=ChannelId['MONO'], [capture=False]]) -- Get volume in dB."); static PyObject * pyalsamixerelement_getvolumedb(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, chn = SND_MIXER_SCHN_MONO; long val; if (!PyArg_ParseTuple(args, "|ii", &chn, &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_get_playback_dB(pyelem->elem, chn, &val); else res = snd_mixer_selem_get_capture_dB(pyelem->elem, chn, &val); if (res < 0) { PyErr_Format(PyExc_RuntimeError, "Cannot get mixer volume in dB (capture=%s, channel=%i): %s", dir ? "True" : "False", chn, snd_strerror(-res)); Py_RETURN_NONE; } return Py_BuildValue("i", res); } PyDoc_STRVAR(setvolumedb__doc__, "set_volume_dB(value, [channel=ChannelId['MONO'], [capture=False], [dir=0]]) -- Set volume in dB."); static PyObject * pyalsamixerelement_setvolumedb(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, dir1 = 0, chn = SND_MIXER_SCHN_MONO; long val; if (!PyArg_ParseTuple(args, "l|iii", &val, &chn, &dir, &dir1)) return NULL; if (dir == 0) res = snd_mixer_selem_set_playback_dB(pyelem->elem, chn, val, dir1); else res = snd_mixer_selem_set_capture_dB(pyelem->elem, chn, val, dir1); if (res < 0) PyErr_Format(PyExc_RuntimeError, "Cannot set mixer volume in dB (capture=%s, channel=%i, value=%li): %s", dir ? "True" : "False", chn, val, snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(setvolumealldb__doc__, "set_volume_all_dB(value, [[capture=False], [dir=0]]) -- Set volume for all channels in dB."); static PyObject * pyalsamixerelement_setvolumealldb(struct pyalsamixerelement *pyelem, PyObject *args) { int res, dir = 0, dir1 = 0; long val; if (!PyArg_ParseTuple(args, "l|ii", &val, &dir, &dir1)) return NULL; if (dir == 0) res = snd_mixer_selem_set_playback_dB_all(pyelem->elem, val, dir1); else res = snd_mixer_selem_set_capture_dB_all(pyelem->elem, val, dir1); if (res < 0) PyErr_Format(PyExc_RuntimeError, "Cannot set mixer volume in dB (capture=%s, value=%li): %s", dir ? "True" : "False", val, snd_strerror(-res)); Py_RETURN_NONE; } PyDoc_STRVAR(getrangedb__doc__, "get_volume_range_dB([capture=False]]) -- Get volume range in dB in (min,max) tuple."); static PyObject * pyalsamixerelement_getrangedb(struct pyalsamixerelement *pyelem, PyObject *args) { int dir = 0, res; long min, max; PyObject *t; if (!PyArg_ParseTuple(args, "|i", &dir)) return NULL; if (dir == 0) res = snd_mixer_selem_get_playback_dB_range(pyelem->elem, &min, &max); else res = snd_mixer_selem_get_capture_dB_range(pyelem->elem, &min, &max); if (res < 0) return PyErr_Format(PyExc_RuntimeError, "Cannot get mixer volume range in dB (capture=%s): %s", dir ? "True" : "False", snd_strerror(-res)); t = PyTuple_New(2); if (!t) Py_RETURN_NONE; PyTuple_SET_ITEM(t, 0, PyInt_FromLong(min)); PyTuple_SET_ITEM(t, 1, PyInt_FromLong(max)); return t; } PyDoc_STRVAR(setcallback__doc__, "set_callback(callObj) -- Set callback object.\n" "Note: callObj might have callObj.callback attribute.\n"); static PyObject * pyalsamixerelement_setcallback(struct pyalsamixerelement *pyelem, PyObject *args) { PyObject *o; if (!PyArg_ParseTuple(args, "O", &o)) return NULL; if (o == Py_None) { Py_XDECREF(pyelem->callback); pyelem->callback = NULL; snd_mixer_elem_set_callback(pyelem->elem, NULL); } else { Py_INCREF(o); pyelem->callback = o; snd_mixer_elem_set_callback_private(pyelem->elem, pyelem); snd_mixer_elem_set_callback(pyelem->elem, element_callback); } Py_RETURN_NONE; } PyDoc_STRVAR(elementinit__doc__, "Element(mixer, name[, index=0])\n" " -- Create a mixer element object.\n" "\n" "You may specify simple name and index like:\n" "element(mixer, \"PCM\", 0)\n"); static int pyalsamixerelement_init(struct pyalsamixerelement *pyelem, PyObject *args, PyObject *kwds) { PyObject *mixer; char *name; int index = 0; snd_mixer_selem_id_t *id; static char * kwlist[] = { "mixer", "name", "index", NULL }; snd_mixer_selem_id_alloca(&id); pyelem->pyhandle = NULL; pyelem->handle = NULL; pyelem->elem = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os|i", kwlist, &mixer, &name, &index)) return -1; if (mixer->ob_type != &pyalsamixer_type) { PyErr_SetString(PyExc_TypeError, "bad type for mixer argument"); return -1; } pyelem->pyhandle = mixer; Py_INCREF(mixer); pyelem->handle = PYALSAMIXER(mixer)->handle; snd_mixer_selem_id_set_name(id, name); snd_mixer_selem_id_set_index(id, index); pyelem->elem = snd_mixer_find_selem(pyelem->handle, id); if (pyelem->elem == NULL) { PyErr_Format(PyExc_IOError, "cannot find mixer element '%s',%i", name, index); return -1; } return 0; } static void pyalsamixerelement_dealloc(struct pyalsamixerelement *self) { if (self->elem) { Py_XDECREF(self->callback); snd_mixer_elem_set_callback(self->elem, NULL); } if (self->pyhandle) { Py_XDECREF(self->pyhandle); } self->ob_type->tp_free(self); } static PyGetSetDef pyalsamixerelement_getseters[] = { {"name", (getter)pyalsamixerelement_getname, NULL, "mixer element name", NULL}, {"index", (getter)pyalsamixerelement_getindex, NULL, "mixer element index", NULL}, {"is_active", (getter)pyalsamixerelement_bool, NULL, "element is in active status", snd_mixer_selem_is_active}, {"is_enumerated",(getter)pyalsamixerelement_bool, NULL, "element is enumerated type", snd_mixer_selem_is_enumerated}, {"has_common_volume",(getter)pyalsamixerelement_bool, NULL, "element has common volume control", snd_mixer_selem_has_common_volume}, {"has_common_switch",(getter)pyalsamixerelement_bool, NULL, "element has common switch control", snd_mixer_selem_has_common_switch}, {"has_capture_switch_exclusive", (getter)pyalsamixerelement_bool, NULL, "element has exclusive capture switch", snd_mixer_selem_has_capture_switch_exclusive}, {"get_capture_group",(getter)pyalsamixerelement_getcapgroup, NULL, "element get capture group", NULL}, {NULL} }; static PyMethodDef pyalsamixerelement_methods[] = { {"ask_volume_dB",(PyCFunction)pyalsamixerelement_askvoldB, METH_VARARGS, askvoldB__doc__}, {"ask_dB_volume",(PyCFunction)pyalsamixerelement_askdBvol, METH_VARARGS, askdBvol__doc__}, {"get_volume", (PyCFunction)pyalsamixerelement_getvolume, METH_VARARGS, getvolume__doc__}, {"get_volume", (PyCFunction)pyalsamixerelement_getvolume, METH_VARARGS, getvolume__doc__}, {"get_volume_tuple", (PyCFunction)pyalsamixerelement_getvolumetuple, METH_VARARGS,getvolumetuple__doc__}, {"get_volume_array", (PyCFunction)pyalsamixerelement_getvolumearray, METH_VARARGS,getvolumearray__doc__}, {"set_volume", (PyCFunction)pyalsamixerelement_setvolume, METH_VARARGS, setvolume__doc__}, {"set_volume_tuple", (PyCFunction)pyalsamixerelement_setvolumetuple, METH_VARARGS,setvolumetuple__doc__}, {"set_volume_array", (PyCFunction)pyalsamixerelement_setvolumetuple, METH_VARARGS,setvolumearray__doc__}, {"set_volume_all",(PyCFunction)pyalsamixerelement_setvolumeall, METH_VARARGS, setvolumeall__doc__}, {"get_volume_range", (PyCFunction)pyalsamixerelement_getrange, METH_VARARGS, getrange__doc__}, {"set_volume_range", (PyCFunction)pyalsamixerelement_setrange, METH_VARARGS, setrange__doc__}, {"get_volume_dB",(PyCFunction)pyalsamixerelement_getvolumedb, METH_VARARGS, getvolumedb__doc__}, {"set_volume_dB",(PyCFunction)pyalsamixerelement_setvolumedb, METH_VARARGS, setvolumedb__doc__}, {"set_volume_all_dB",(PyCFunction)pyalsamixerelement_setvolumealldb,METH_VARARGS, setvolumealldb__doc__}, {"get_volume_range_dB", (PyCFunction)pyalsamixerelement_getrangedb, METH_VARARGS, getrangedb__doc__}, {"get_switch", (PyCFunction)pyalsamixerelement_getswitch, METH_VARARGS, getswitch__doc__}, {"get_switch_tuple", (PyCFunction)pyalsamixerelement_getswitchtuple, METH_VARARGS,getswitchtuple__doc__}, {"set_switch", (PyCFunction)pyalsamixerelement_setswitch, METH_VARARGS, setswitch__doc__}, {"set_switch_tuple", (PyCFunction)pyalsamixerelement_setswitchtuple, METH_VARARGS,setswitchtuple__doc__}, {"set_switch_all",(PyCFunction)pyalsamixerelement_setswitchall, METH_VARARGS, setswitchall__doc__}, {"is_mono", (PyCFunction)pyalsamixerelement_ismono, METH_VARARGS, ismono__doc__}, {"has_channel", (PyCFunction)pyalsamixerelement_haschannel, METH_VARARGS, haschannel__doc__}, {"has_volume", (PyCFunction)pyalsamixerelement_hasvolume, METH_VARARGS, hasvolume__doc__}, {"has_switch", (PyCFunction)pyalsamixerelement_hasswitch, METH_VARARGS, hasswitch__doc__}, {"set_callback",(PyCFunction)pyalsamixerelement_setcallback, METH_VARARGS, setcallback__doc__}, {NULL} }; static PyTypeObject pyalsamixerelement_type = { PyObject_HEAD_INIT(0) tp_name: "alsamixer.Element", tp_basicsize: sizeof(struct pyalsamixerelement), tp_dealloc: (destructor)pyalsamixerelement_dealloc, tp_flags: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, tp_doc: elementinit__doc__, tp_getset: pyalsamixerelement_getseters, tp_init: (initproc)pyalsamixerelement_init, tp_alloc: PyType_GenericAlloc, tp_new: PyType_GenericNew, tp_free: PyObject_Del, tp_methods: pyalsamixerelement_methods, }; /* * */ static PyMethodDef pyalsamixerparse_methods[] = { {NULL} }; PyMODINIT_FUNC initalsamixer(void) { PyObject *d, *d1, *l1, *o; int i; if (PyType_Ready(&pyalsamixer_type) < 0) return; if (PyType_Ready(&pyalsamixerelement_type) < 0) return; module = Py_InitModule3("alsamixer", pyalsamixerparse_methods, "libasound mixer wrapper"); if (module == NULL) return; #if 0 buildin = PyImport_AddModule("__buildin__"); if (buildin == NULL) return; if (PyObject_SetAttrString(module, "__buildins__", buildin) < 0) return; #endif Py_INCREF(&pyalsamixer_type); PyModule_AddObject(module, "Mixer", (PyObject *)&pyalsamixer_type); Py_INCREF(&pyalsamixerelement_type); PyModule_AddObject(module, "Element", (PyObject *)&pyalsamixerelement_type); d = PyModule_GetDict(module); /* ---- */ d1 = PyDict_New(); #define add_space1(pname, name) { \ o = PyInt_FromLong(SND_MIXER_SCHN_##name); \ PyDict_SetItemString(d1, pname, o); \ Py_DECREF(o); } add_space1("UNKNOWN", UNKNOWN); add_space1("FRONT_LEFT", FRONT_LEFT); add_space1("FRONT_RIGHT", FRONT_RIGHT); add_space1("REAR_LEFT", REAR_LEFT); add_space1("REAR_RIGHT", REAR_RIGHT); add_space1("FRONT_CENTER", FRONT_CENTER); add_space1("WOOFER", WOOFER); add_space1("SIDE_LEFT", SIDE_LEFT); add_space1("SIDE_RIGHT", SIDE_RIGHT); add_space1("REAR_CENTER", REAR_CENTER); add_space1("LAST", LAST); add_space1("MONO", MONO); PyDict_SetItemString(d, "channel_id", d1); Py_DECREF(d1); /* ---- */ l1 = PyList_New(0); for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) { o = PyString_FromString(snd_mixer_selem_channel_name(i)); PyList_Append(l1, o); Py_DECREF(o); } PyDict_SetItemString(d, "channel_name", l1); Py_DECREF(l1); /* ---- */ d1 = PyDict_New(); #define add_space2(pname, name) { \ o = PyInt_FromLong(SND_MIXER_SABSTRACT_##name); \ PyDict_SetItemString(d1, pname, o); \ Py_DECREF(o); } add_space2("NONE", NONE); add_space2("BASIC", BASIC); PyDict_SetItemString(d, "regopt_abstract", d1); Py_DECREF(d1); /* ---- */ d1 = PyDict_New(); #define add_space3(pname, name) { \ o = PyInt_FromLong(SND_CTL_EVENT_MASK_##name); \ PyDict_SetItemString(d1, pname, o); \ Py_DECREF(o); } add_space3("VALUE", VALUE); add_space3("INFO", INFO); add_space3("ADD", ADD); add_space3("TLV", TLV); PyDict_SetItemString(d, "event_mask", d1); Py_DECREF(d1); o = PyInt_FromLong(SND_CTL_EVENT_MASK_REMOVE); PyDict_SetItemString(d, "event_mask_remove", o); Py_DECREF(o); /* ---- */ main_interpreter = PyThreadState_Get()->interp; if (PyErr_Occurred()) Py_FatalError("Cannot initialize module alsamixer"); } /* * element event callback */ static int element_callback(snd_mixer_elem_t *elem, unsigned int mask) { PyThreadState *tstate, *origstate; struct pyalsamixerelement *pyelem; PyObject *o, *t, *r; int res = 0, inside = 1; if (elem == NULL) return -EINVAL; pyelem = snd_mixer_elem_get_callback_private(elem); if (pyelem == NULL || pyelem->callback == NULL) return -EINVAL; tstate = PyThreadState_New(main_interpreter); origstate = PyThreadState_Swap(tstate); o = PyObject_GetAttr(pyelem->callback, PyString_InternFromString("callback")); if (!o) { PyErr_Clear(); o = pyelem->callback; inside = 0; } t = PyTuple_New(2); if (t) { if (PyTuple_SET_ITEM(t, 0, (PyObject *)pyelem)) Py_INCREF(pyelem); PyTuple_SET_ITEM(t, 1, PyInt_FromLong(mask)); r = PyObject_CallObject(o, t); Py_DECREF(t); if (r) { if (PyInt_Check(r)) { res = PyInt_AsLong(r); } else if (r == Py_None) { res = 0; } Py_DECREF(r); } else { PyErr_Print(); PyErr_Clear(); res = -EIO; } } if (inside) { Py_DECREF(o); } PyThreadState_Swap(origstate); PyThreadState_Delete(tstate); return res; } pyalsa-1.0.26/setup.py0000775000000000000000000000370412022053131014537 0ustar rootroot00000000000000#! /usr/bin/python # -*- Python -*- import os import sys try: from setuptools import setup, Extension except ImportError: from distutils.core import setup, Extension VERSION='1.0.26' if os.path.exists("version"): fp = open("version", "r") ver = fp.readline() fp.close() ver = ver[:-1] else: ver = None if ver != VERSION: fp = open("version", "w+") fp.write(VERSION + '\n') fp.close() del fp setup( name='pyalsa', version=VERSION, author="The ALSA Team", author_email='alsa-devel@alsa-project.org', ext_modules=[ Extension('pyalsa.alsacard', ['pyalsa/alsacard.c'], include_dirs=[], library_dirs=[], libraries=['asound']), Extension('pyalsa.alsacontrol', ['pyalsa/alsacontrol.c'], include_dirs=[], library_dirs=[], libraries=['asound']), Extension('pyalsa.alsahcontrol', ['pyalsa/alsahcontrol.c'], include_dirs=[], library_dirs=[], libraries=['asound']), Extension('pyalsa.alsamixer', ['pyalsa/alsamixer.c'], include_dirs=[], library_dirs=[], libraries=['asound']), Extension('pyalsa.alsaseq', ['pyalsa/alsaseq.c'], include_dirs=[], library_dirs=[], libraries=['asound']), ], packages=['pyalsa'], scripts=[] ) uname = os.uname() a = 'build/lib.%s-%s-%s' % (uname[0].lower(), uname[4], sys.version[:3]) for f in ['alsacard.so', 'alsacontrol.so', 'alsahcontrol.so', 'alsamixer.so', 'alsaseq.so']: if not os.path.exists('pyalsa/%s' % f): a = '../build/lib.%s-%s-%s/pyalsa/%s' % (uname[0].lower(), uname[4], sys.version[:3], f) print a, f os.symlink(a, 'pyalsa/%s' % f) pyalsa-1.0.26/utils/0000755000000000000000000000000012022061452014161 5ustar rootroot00000000000000pyalsa-1.0.26/utils/aplaymidi.py0000664000000000000000000003574612022053131016520 0ustar rootroot00000000000000#! /usr/bin/python # aplaymidi.py -- python port of aplaymidi # Copyright (C) 2008 Aldrin Martoq # # Based on code from aplaymidi.c from ALSA project # Copyright (C) 2004-2006 Clemens Ladisch # # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import sys sys.path.insert(0, '../pyalsa') import getopt import os import struct import alsaseq import traceback import time from alsaseq import * class SMFError(Exception): """ Exception raised for errors while reading a SMF file """ pass def errormsg(msg, *args): """ prints an error message to stderr """ sys.stderr.write(msg % args) sys.stderr.write('\n') traceback.print_exc(file=sys.stderr) def fatal(msg, *args): """ prints an error message to stderr, and dies """ errormsg(msg, *args) sys.exit(1) def init_seq(): """ opens an alsa sequencer """ try: sequencer = Sequencer(name = 'default', clientname = 'aplaymidi.py', streams = SEQ_OPEN_DUPLEX, mode = SEQ_BLOCK) return sequencer except SequencerError, e: fatal("open sequencer: %e", e) def parse_ports(sequencer, portspec): """ parses one or more port addresses from the string, separated by ',' example: 14:0,Timidity """ portlist = [] if portspec == None: return portlist ports = portspec.split(',') for port in ports: try: client, port = sequencer.parse_address(port) portlist.append((client, port)) except SequencerError, e: fatal("Failed to parse port %s - %s", port, e) return portlist def create_source_port(sequencer): try : port = sequencer.create_simple_port(name = 'aplaymidi.py', type = SEQ_PORT_TYPE_MIDI_GENERIC \ | SEQ_PORT_TYPE_APPLICATION, caps = SEQ_PORT_CAP_NONE) return port except SequencerError, e: fatal("Failed to create port - %s", e) def create_queue(sequencer): try: queue = sequencer.create_queue(name = 'aplaymidi') return queue except SequencerError, e: fatal("Failed to create queue - %s", e) def connect_ports(sequencer, port_id, ports): client_id = sequencer.client_id for client, port in ports: sequencer.connect_ports((client_id, port_id), (client, port)) def read_byte(file): """ read a single byte raises SMFError if end of file was detected """ s = file.read(1) if s == '': raise SMFError('End of file reached at position %d' % file.tell()) return struct.unpack('B', s)[0] def read_32_le(file): """ reads a little-endian 32-bit integer """ value = 0 for p in (0, 8, 16, 24): c = read_byte(file) value |= c << p return value def read_id(file): """ reads a 4-char identifier """ return file.read(4) def read_int(file, bytes): """ reads a fixed-size big-endian number """ value = 0 while bytes > 0: c = read_byte(file) value = (value << 8) | c bytes -= 1 return value def read_var(file): """ reads a variable-length number """ c = read_byte(file) value = c & 0x7f if c & 0x80: c = read_byte(file) value = (value << 7) | (c & 0x7f) if c & 0x80: c = read_byte(file) value = (value << 7) | (c & 0x7f) if c & 0x80: c = read_byte(file) value = (value << 7) | (c & 0x7f) if c & 0x80: raise SMFError('Invalid variable-length number at file position %d' % file.tell()) return value def skip(file, bytes): """ skip the specified number of bytes """ file.read(bytes) def read_track(file, chunk_len, ports, smtpe_timing): """ reads one complete track from the file """ tick = 0 last_cmd = 0 port = 0 typemap = {} typemap[0x8] = SEQ_EVENT_NOTEOFF typemap[0x9] = SEQ_EVENT_NOTEON typemap[0xa] = SEQ_EVENT_KEYPRESS typemap[0xb] = SEQ_EVENT_CONTROLLER typemap[0xc] = SEQ_EVENT_PGMCHANGE typemap[0xd] = SEQ_EVENT_CHANPRESS typemap[0xe] = SEQ_EVENT_PITCHBEND eventlist = [] track_end = file.tell() + chunk_len while file.tell() < track_end: delta_ticks = read_var(file) if delta_ticks < 0: break tick += delta_ticks c = read_byte(file) if c < 0: break if c & 0x80: cmd = c if cmd < 0xf0: last_cmd = cmd else: # running status cmd = last_cmd file.seek(file.tell() - 1) if not cmd: break s = cmd >> 4 if s >= 0x8 and s <= 0xa: event = SeqEvent(type=typemap[s]) event.dest = ports[port] event.time = tick event.set_data({'note.channel' : cmd & 0x0f, 'note.note' : read_byte(file) & 0x7f, 'note.velocity' : read_byte(file) & 0x7f }) eventlist.append(event) elif s == 0xb or s == 0xe: event = SeqEvent(type=typemap[s]) event.dest = ports[port] event.time = tick event.set_data({'control.channel' : cmd & 0x0f, 'control.param' : read_byte(file) & 0x7f, 'control.value' : read_byte(file) & 0x7f }) eventlist.append(event) elif s == 0xc or s == 0xd: event = SeqEvent(type=typemap[s]) event.dest = ports[port] event.time = tick event.set_data({'control.channel' : cmd & 0x0f, 'control.value' : read_byte(file) & 0x7f }) eventlist.append(event) elif s == 0xf: if cmd == 0xf0 or cmd == 0xf7: # sysex l = read_var(file) if l < 0: break if cmd == 0xf0: l += 1 event = SeqEvent(type=SEQ_EVENT_SYSEX) event.dest = ports[port] event.time = tick sysexdata = [] if cmd == 0xf0: sysexdata.append(0xf0) while len(sysexdata) < l: sysexdata.append(read_byte(file)) event.set_data({'ext' : sysexdata}) eventlist.append(event) elif cmd == 0xff: c = read_byte(file) l = read_var(file) if l < 0: break if c == 0x21: # port number port = read_byte() % len(ports) skip(file, l - 1) elif c == 0x2f: # end track track_endtick = tick skip(file, track_end - file.tell()) return track_endtick, eventlist elif c == 0x51: # tempo if l < 3: break if smtpe_timing: skip(file, l) else: event = SeqEvent(type=SEQ_EVENT_TEMPO) event.dest = (SEQ_CLIENT_SYSTEM, SEQ_PORT_SYSTEM_TIMER) event.time = tick tempo = read_byte(file) << 16 tempo |= read_byte(file) << 8 tempo |= read_byte(file) event.set_data({'queue.param.value' : tempo}) eventlist.append(event) skip(file, l - 3) else: # ignore all other meta events skip(file, l) else: break else: break raise SMFError('Invalid MIDI data at file position (%d)' % file.tell()) def read_smf(file, ports): """ reads an entire MIDI file """ tempo = 0 ppq = 0 tracks = [] header_len = read_int(file, 4) if header_len < 6: raise SMFError('Invalid header_len: %d' % header_len) type = read_int(file, 2) if type != 0 and type != 1: raise SMFError('Not supported type: %d' % type) num_tracks = read_int(file, 2) if num_tracks < 1 or num_tracks > 1000: raise SMFError('Invalid number of tracks: %d' % num_tracks) time_division = read_int(file, 2) if time_division < 0: raise SMFError('Invalid time division: %d' % time_division) smtpe_timing = time_division & 0x8000 if not smtpe_timing: # time division is ticks per quarter tempo = 500000 ppq = time_division else: i = 0x80 - ((time_division >>8) & 0x7f) time_division &= 0xff if i == 24: tempo = 500000 ppq = 12 * time_division elif i == 25: tempo = 400000 ppq = 10 * time_division elif i == 29: tempo = 100000000 ppq = 2997 * time_division elif i == 30: tempo = 500000 ppq = 15 * time_division else: raise SMFError('Invalid number of SMPTE frames per second (%d)' % i) # read tracks while num_tracks > 0: # search for MTrk chunk while True: id = read_id(file) chunk_len = read_int(file, 4) if chunk_len < 0 or chunk_len >= 0x10000000: raise SMFError('Invalid chunk length %d' % chunk_len) if id == 'MTrk': break skip(file, chunk_len) trackevents = read_track(file, chunk_len, ports, smtpe_timing) tracks.append(trackevents) num_tracks -= 1 return tempo, ppq, tracks def read_riff(file, ports): """ reads an entire RIFF file """ raise NotImplementedError("Sorry, I couldn't find any RIFF midi file to implement this! -- Aldrin Martoq") def play(sequencer, filename, end_delay, source_port, queue, ports): file = sys.stdin ok = None if filename != '-': try: file = open(filename, 'rb') except IOError, e: fatal("Cannot open %s - %s", filename, e) id = read_id(file) try: if id == 'MThd': ok = read_smf(file, ports) elif id == 'RIFF': ok = read_riff(file, ports) else: raise SMFError('unrecognized id') except SMFError, e: errormsg("%s is not a Standard MIDI File - %s", filename, e) # now play! tempo, ppq, tracks = ok sequencer.queue_tempo(queue, tempo, ppq) sequencer.start_queue(queue) # add all events from tracks and sort them based on track, then on time itrack = 0 allevents = [] for track in tracks: endtick, eventlist = track for event in eventlist: d = {'itrack' : itrack, 'event' : event, 'time' : event.time} allevents.append(d) itrack += 1 def compare(x, y): ret = x['time'] - y['time'] if ret == 0: ret = x['itrack'] - y['itrack'] return ret allevents.sort(compare) max_tick = allevents[-1]['time'] for d in allevents: event = d['event'] event.source = (0, 0) event.queue = queue if event.type == SEQ_EVENT_TEMPO: event.set_data({'queue.queue' : queue}) sequencer.output_event(event) # schedule queue stop at end of song event = SeqEvent(SEQ_EVENT_STOP) event.source = (0, 0) event.queue = queue event.time = max_tick event.dest = (SEQ_CLIENT_SYSTEM, SEQ_PORT_SYSTEM_TIMER) event.set_data({'queue.queue' : queue}) sequencer.output_event(event) # make sure that the sequencer sees all our events sequencer.drain_output() sequencer.sync_output_queue() time.sleep(end_delay) if file != sys.stdin: file.close() def list_ports(): sequencer = init_seq() print " Port Client name Port name"; clientports = sequencer.connection_list() for connections in clientports: clientname, clientid, connectedports = connections for port in connectedports: portname, portid, connections = port portinfo = sequencer.get_port_info(portid, clientid) type = portinfo['type'] caps = portinfo['capability'] if type & SEQ_PORT_TYPE_MIDI_GENERIC and \ caps & (SEQ_PORT_CAP_WRITE | SEQ_PORT_CAP_SUBS_WRITE): print "%3d:%-3d %-32.32s %s" % (clientid, portid, clientname, portname) def usage(): print "Usage: %s -p client:port[,...] [-d delay] midifile ...\n" \ "-h, --help this help\n" \ "-V, --version print current version\n" \ "-l, --list list all possible output ports\n" \ "-p, --port=client:port,... set port(s) to play to\n" \ "-d, --delay=seconds delay after song ends\n" % (sys.argv[0]) def version(): print "aplaymidi.py asoundlib version %s" % (SEQ_LIB_VERSION_STR) def main(): sequencer = init_seq() ports = [] end_delay = 2 try: opts, args = getopt.getopt(sys.argv[1:], "hVlp:d:", ["help", "version", "list", "port=", "delay="]) except getopt.GetoptError: usage() sys.exit(2) for o, a in opts: if o in ("-h", "--help"): usage() sys.exit(0) elif o in ("-V", "--version"): version() sys.exit(0) elif o in ("-l", "--list"): list_ports() sys.exit(0) elif o in ("-p", "--port"): ports = parse_ports(sequencer, a) elif o in ("-d", "--delay"): end_delay = int(a) if len(ports) < 1: ports = parse_ports(sequencer, os.getenv('ALSA_OUTPUT_PORTS')) if len(ports) < 1: fatal("Please specify at least one port with --port.") if len(args) < 1: fatal("Please specify a file to play.") source_port = create_source_port(sequencer) queue = create_queue(sequencer) connect_ports(sequencer, source_port, ports) for filename in args: play(sequencer, filename, end_delay, source_port, queue, ports) if __name__ == '__main__': main() pyalsa-1.0.26/utils/aconnect.py0000664000000000000000000001554412022053131016333 0ustar rootroot00000000000000#! /usr/bin/python # aconnect.py -- python port of aconnect # Copyright (C) 2008 Aldrin Martoq # # Based on code from aconnect.c from ALSA project # Copyright (C) 1999 Takashi Iwai # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import sys sys.path.insert(0, '../pyalsa') import getopt import os from alsaseq import * LIST_INPUT=1 LIST_OUTPUT=2 def errormsg(msg, *args): """ prints an error message to stderr """ sys.stderr.write(msg % args) sys.stderr.write('\n') traceback.print_exc(file=sys.stderr) def fatal(msg, *args): """ prints an error message to stderr, and dies """ errormsg(msg, *args) sys.exit(1) def init_seq(): """ opens an alsa sequencer """ try: sequencer = Sequencer(name = 'default', clientname = 'aconnect.py', streams = SEQ_OPEN_DUPLEX, mode = SEQ_BLOCK) return sequencer except SequencerError, e: fatal("open sequencer: %e", e) def usage(): print \ "aconnect - python ALSA sequencer connection manager\n" \ "Copyright (C) 1999-2000 Takashi Iwai\n" \ "Copyright (C) 2008 Aldrin Martoq \n" \ "Usage: \n" \ " * Connection/disconnection between ports\n" \ " %s [-options] sender receiver\n" \ " sender, receiver = client:port pair\n" \ " -d,--disconnect disconnect\n" \ " -e,--exclusive exclusive connection\n" \ " -r,--real # convert real-time-stamp on queue\n" \ " -t,--tick # convert tick-time-stamp on queue\n" \ " * List connected ports (no subscription action)\n" \ " %s -i|-o [-options]\n" \ " -i,--input list input (readable) ports\n" \ " -o,--output list output (writable) ports\n" \ " -l,--list list current connections of each port\n" \ " * Remove all exported connections\n" \ " -x,--removeall" \ % (sys.argv[0], sys.argv[0]) def do_list_subs(conn, text): l = [] for c, p, i in conn: s = "" if i['exclusive']: s+= "[ex]" if i['time_update']: if i['time_real']: s += "[%s:%s]" % ("real", i['queue']) else: s += "[%s:%s]" % ("tick", i['queue']) s = "%d:%d%s" % (c, p, s) l.append(s) if len(l): print "\t%s: %s" % (text, ', '.join(l)) def do_list_ports(sequencer, list_perm, list_subs): connectionlist = sequencer.connection_list() for connections in connectionlist: clientname, clientid, connectedports = connections clientinfo = sequencer.get_client_info(clientid) type = clientinfo['type'] count = [] if type == SEQ_USER_CLIENT: type = 'user' else: type = 'kernel' for port in connectedports: portname, portid, portconns = port portinfo = sequencer.get_port_info(portid, clientid) caps = portinfo['capability'] if not (caps & SEQ_PORT_CAP_NO_EXPORT): reads = SEQ_PORT_CAP_READ | SEQ_PORT_CAP_SUBS_READ write = SEQ_PORT_CAP_WRITE | SEQ_PORT_CAP_SUBS_WRITE if (list_perm & LIST_INPUT) and (caps & reads == reads): count.append(port) elif (list_perm & LIST_OUTPUT) and (caps & write == write): count.append(port) if len(count) > 0: print "client %d: '%s' [type=%s]" % (clientid, clientname, type) for port in count: portname, portid, portconns = port print " %3d '%-16s'" % (portid, portname) if list_subs: readconn, writeconn = portconns do_list_subs(readconn, "Connecting To") do_list_subs(writeconn, "Connected From") def do_unsubscribe(sequencer, args): sender = sequencer.parse_address(args[0]) dest = sequencer.parse_address(args[1]) try: sequencer.get_connect_info(sender, dest) except SequencerError: print 'No subscription is found' return try: sequencer.disconnect_ports(sender, dest) except SequencerError, e: fatal("Failed to disconnect ports %s->%s - %s", sender, dest, e) def do_subscribe(sequencer, args, queue, exclusive, convert_time, convert_real): sender = sequencer.parse_address(args[0]) dest = sequencer.parse_address(args[1]) try: sequencer.get_connect_info(sender, dest) print "Connection is already subscribed" return except SequencerError: pass sequencer.connect_ports(sender, dest, queue, exclusive, convert_time, convert_real) def main(): sequencer = init_seq() command = 'subscribe' list_perm = 0 list_subs = 0 exclusive = 0 convert_time = 0 convert_real = 0 queue = 0 try: opts, args = getopt.getopt(sys.argv[1:], "dior:t:elx", ["disconnect", "input", "output", "real=", "tick=", "exclusive", "list", "removeall"]) except getopt.GetoptError: usage() sys.exit(2) for o, a in opts: if o in ("-d", "--disconnect"): command = 'unsubscribe' elif o in ("-i", "--input"): command = 'list' list_perm |= LIST_INPUT elif o in ("-o", "--output"): command = 'list' list_perm |= LIST_OUTPUT elif o in ("-e", "--exclusive"): exclusive = 1 elif o in ("-r", "--real"): queue = int(a) convert_time = 1 convert_real = 1 elif o in ("-t", "--tick"): queue = int(a) convert_time = 1 convert_real = 0 elif o in ("-l", "--list"): list_subs = 1 elif o in ("-x", "--removeall"): command = 'removeall' if command == 'list': do_list_ports(sequencer, list_perm, list_subs) return if len(args) != 2: usage() sys.exit(2) if command == 'unsubscribe': do_unsubscribe(sequencer, args) elif command == 'subscribe': do_subscribe(sequencer, args, queue, exclusive, convert_time, convert_real) if __name__ == '__main__': main() pyalsa-1.0.26/utils/remove-user-ctl.py0000775000000000000000000000045012022053131017563 0ustar rootroot00000000000000#! /usr/bin/python # -*- Python -*- from pyalsa.alsahcontrol import HControl, Element, Info hctl = HControl(name='hw:1') list = hctl.list() for id in list: elem = Element(hctl, id[1:]) info = Info(elem) if info.is_user: print 'Removing element %s' % repr(id) hctl.element_remove(id[1:]) pyalsa-1.0.26/utils/aseqdump.py0000664000000000000000000001422612022053131016354 0ustar rootroot00000000000000#! /usr/bin/python # aseqdump.py -- python port of aplaymidi # Copyright (C) 2008 Aldrin Martoq # # Based on code from aseqdump.c, from ALSA project # Copyright (C) 2005 Clemens Ladisch # # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import sys sys.path.insert(0, '../pyalsa') import getopt import os import struct import alsaseq import traceback import time from alsaseq import * def errormsg(msg, *args): """ prints an error message to stderr """ sys.stderr.write(msg % args) sys.stderr.write('\n') traceback.print_exc(file=sys.stderr) def fatal(msg, *args): """ prints an error message to stderr, and dies """ errormsg(msg, *args) sys.exit(1) def init_seq(): """ opens an alsa sequencer """ try: sequencer = Sequencer(name = 'default', clientname = 'aseqdump.py', streams = SEQ_OPEN_DUPLEX, mode = SEQ_BLOCK) return sequencer except SequencerError, e: fatal("open sequencer: %e", e) def parse_ports(sequencer, portspec): """ parses one or more port addresses from the string, separated by ',' example: 14:0,Timidity """ portlist = [] if portspec == None: return portlist ports = portspec.split(',') for port in ports: try: client, port = sequencer.parse_address(port) portlist.append((client, port)) except SequencerError, e: fatal("Failed to parse port %s - %s", port, e) return portlist def create_source_port(sequencer): try : port = sequencer.create_simple_port(name = 'aseqdump.py', type = SEQ_PORT_TYPE_MIDI_GENERIC | SEQ_PORT_TYPE_APPLICATION, caps = SEQ_PORT_CAP_WRITE | SEQ_PORT_CAP_SUBS_WRITE) return port except SequencerError, e: fatal("Failed to create port - %s", e) def connect_ports(sequencer, port_id, ports): client_id = sequencer.client_id for client, port in ports: sequencer.connect_ports((client, port),(client_id, port_id)) def dump_event(event): print "%3d:%-3d" % ((event.source)[0], (event.source)[1]), type = event.type data = event.get_data() if type == SEQ_EVENT_NOTEON: print "Note on %2d %3d %3d" % \ (data['note.channel'], data['note.note'], data['note.velocity']) elif type == SEQ_EVENT_NOTEOFF: print "Note off %2d %3d %3d" % \ (data['note.channel'], data['note.note'], data['note.velocity']) elif type == SEQ_EVENT_KEYPRESS: print "Polyphonic aftertouch %2d %3d %3d" % \ (data['note.channel'], data['note.note'], data['note.velocity']) elif type == SEQ_EVENT_CONTROLLER: print "Control change %2d %3d %3d" % \ (data['control.channel'], data['control.param'], data['control.value']) elif type == SEQ_EVENT_PGMCHANGE: print "Program change %2d %3d" % \ (data['control.channel'], data['control.value']) else: print "Event type %d" % type def list_ports(): sequencer = init_seq() print " Port Client name Port name"; clientports = sequencer.connection_list() for connections in clientports: clientname, clientid, connectedports = connections for port in connectedports: portname, portid, connections = port portinfo = sequencer.get_port_info(portid, clientid) caps = portinfo['capability'] if caps & (SEQ_PORT_CAP_READ | SEQ_PORT_CAP_SUBS_READ): print "%3d:%-3d %-32.32s %s" % (clientid, portid, clientname, portname) def usage(): print "Usage: %s [options]\n" \ "\nAvailable options:\n" \ "-h, --help this help\n" \ "-V, --version show version\n" \ "-l, --list list input ports\n" \ "-p, --port=client:port,... source port(s)\n" \ % (sys.argv[0]) def version(): print "aseqdump.py asoundlib version %s" % (SEQ_LIB_VERSION_STR) def main(): sequencer = init_seq() ports = [] end_delay = 2 try: opts, args = getopt.getopt(sys.argv[1:], "hVlp:", ["help", "version", "list", "port="]) except getopt.GetoptError: usage() sys.exit(2) for o, a in opts: if o in ("-h", "--help"): usage() sys.exit(0) elif o in ("-V", "--version"): version() sys.exit(0) elif o in ("-l", "--list"): list_ports() sys.exit(0) elif o in ("-p", "--port"): ports = parse_ports(sequencer, a) elif o in ("-d", "--delay"): end_delay = int(a) source_port = create_source_port(sequencer) connect_ports(sequencer, source_port, ports) sequencer.mode = SEQ_NONBLOCK if len(ports) > 0: print "Waiting for data.", else: print "Waiting for data at port %d:0." % sequencer.client_id, print "Press Ctrl+C to end." print "Source_ Event_________________ Ch _Data__" while True: try: eventlist = sequencer.receive_events(timeout=10069, maxevents = 1) for event in eventlist: dump_event(event) except KeyboardInterrupt: pass break if __name__ == '__main__': main() pyalsa-1.0.26/PKG-INFO0000644000000000000000000000031712022061452014117 0ustar rootroot00000000000000Metadata-Version: 1.0 Name: pyalsa Version: 1.0.26 Summary: UNKNOWN Home-page: UNKNOWN Author: The ALSA Team Author-email: alsa-devel@alsa-project.org License: UNKNOWN Description: UNKNOWN Platform: UNKNOWN