From patchwork Sun Jan 25 11:34:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Takashi Sakamoto X-Patchwork-Id: 5701151 Return-Path: X-Original-To: patchwork-alsa-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 80C8C9F2ED for ; Sun, 25 Jan 2015 11:39:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DDB062011B for ; Sun, 25 Jan 2015 11:39:54 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.kernel.org (Postfix) with ESMTP id CC6D5201F2 for ; Sun, 25 Jan 2015 11:39:52 +0000 (UTC) Received: by alsa0.perex.cz (Postfix, from userid 1000) id 0DD6B2604BA; Sun, 25 Jan 2015 12:39:52 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,NO_DNS_FOR_FROM, UNPARSEABLE_RELAY autolearn=no version=3.3.1 Received: from alsa0.perex.cz (localhost [IPv6:::1]) by alsa0.perex.cz (Postfix) with ESMTP id 121C12604BC; Sun, 25 Jan 2015 12:35:34 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 3544B2604B8; Sun, 25 Jan 2015 12:35:31 +0100 (CET) Received: from smtp302.phy.lolipop.jp (smtp302.phy.lolipop.jp [210.157.22.85]) by alsa0.perex.cz (Postfix) with ESMTP id A333C260453 for ; Sun, 25 Jan 2015 12:35:04 +0100 (CET) Received: from smtp302.phy.lolipop.lan (HELO smtp302.phy.lolipop.jp) (172.17.1.85) (smtp-auth username m12129643-o-takashi, mechanism plain) by smtp302.phy.lolipop.jp (qpsmtpd/0.82) with ESMTPA; Sun, 25 Jan 2015 20:35:00 +0900 Received: from 127.0.0.1 (127.0.0.1) by smtp302.phy.lolipop.jp (LOLIPOP-Fsecure); Sun, 25 Jan 2015 20:34:35 +0900 (JST) X-Virus-Status: clean(LOLIPOP-Fsecure) From: Takashi Sakamoto To: clemens@ladisch.de, tiwai@suse.de, perex@perex.cz Date: Sun, 25 Jan 2015 20:34:34 +0900 Message-Id: <1422185674-16431-14-git-send-email-o-takashi@sakamocchi.jp> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1422185674-16431-1-git-send-email-o-takashi@sakamocchi.jp> References: <1422185674-16431-1-git-send-email-o-takashi@sakamocchi.jp> Cc: alsa-devel@alsa-project.org, linux1394-devel@lists.sourceforge.net, ffado-devel@lists.sf.net Subject: [alsa-devel] [PATCH 13/13] libhinawa: add sample scripts X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP This commit adds some sample scripts written by Python 2/3. In Python, PyGObject is required for GObject Introspection library. There're three scripts, using Gtk+, Qt4 and Qt5. Each of them require python bindings as: - PyGObject - PyQt4 - PyQt5 I note that most of methods in libhinawa require 32bit array as its method arguments. In Python, 'array' module is useful but the actual width of the array element depents on machine architecture. Please refer to sample scripts to solve this issue. Signed-off-by: Takashi Sakamoto --- libhinawa/README | 10 +++ libhinawa/samples/gtk3.py | 190 ++++++++++++++++++++++++++++++++++++++++++ libhinawa/samples/qt4.py | 206 ++++++++++++++++++++++++++++++++++++++++++++++ libhinawa/samples/qt5.py | 192 ++++++++++++++++++++++++++++++++++++++++++ libhinawa/samples/run.sh | 15 ++++ 5 files changed, 613 insertions(+) create mode 100755 libhinawa/samples/gtk3.py create mode 100755 libhinawa/samples/qt4.py create mode 100755 libhinawa/samples/qt5.py create mode 100755 libhinawa/samples/run.sh diff --git a/libhinawa/README b/libhinawa/README index 42d31f5..4e3c92c 100644 --- a/libhinawa/README +++ b/libhinawa/README @@ -18,3 +18,13 @@ How to refer document $ ./configure --enable-gtk-doc $ make $ make install + +How to test +(needless to install) + $ ./autogen.sh + $ ./configure + $ make + $ ./samples/run.sh [gtk|qt4|qt5] +gtk - PyGObject is required. +qt4 - PyQt4 is required (also test python2). +qt5 - PyQt5 is required. diff --git a/libhinawa/samples/gtk3.py b/libhinawa/samples/gtk3.py new file mode 100755 index 0000000..41a817e --- /dev/null +++ b/libhinawa/samples/gtk3.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python3 + +import sys + +# Gtk+3 gir +from gi.repository import Gtk + +# Hinawa-1.0 gir +from gi.repository import Hinawa + +from array import array + +# helper function +def get_array(): + # The width with 'L' parameter is depending on environment. + arr = array('L') + if arr.itemsize is not 4: + arr = array('I') + return arr + +# query sound devices +index = -1 +while True: + try: + index = Hinawa.UnitQuery.get_sibling(index) + except Exception as e: + break + break + +# no fw sound devices are detected. +if index == -1: + print('No sound FireWire devices found.') + sys.exit() + +# get unit type +try: + unit_type = Hinawa.UnitQuery.get_unit_type(index) +except Exception as e: + print(e) + sys.exit() + +# create sound unit +def handle_lock_status(snd_unit, status): + if status: + print("streaming is locked."); + else: + print("streaming is unlocked."); +if unit_type == 1: + snd_unit = Hinawa.SndDice() +elif unit_type == 2: + snd_unit = Hinawa.SndEfw() +elif unit_type == 3 or unit_type == 4: + snd_unit = Hinawa.SndUnit() +path = "hw:{0}".format(index) +try: + snd_unit.open(path) +except Exception as e: + print(e) + sys.exit() +print('Sound device info:') +print(' type:\t{0}'.format(snd_unit.get_property("type"))) +print(' card:\t{0}'.format(snd_unit.get_property("card"))) +print(' device:\t{0}'.format(snd_unit.get_property("device"))) +print(' GUID:\t{0:016x}'.format(snd_unit.get_property("guid"))) +snd_unit.connect("lock-status", handle_lock_status) + +# create FireWire unit +def handle_bus_update(snd_unit): + print(snd_unit.get_property('generation')) +snd_unit.connect("bus-update", handle_bus_update) + +# start listening +try: + snd_unit.listen() +except Exception as e: + print(e) + sys.exit() + +# create firewire responder +resp = Hinawa.FwResp() +def handle_request(resp, tcode, req_frame): + print('Requested with tcode {0}:'.format(tcode)) + for i in range(len(req_frame)): + print(' [{0:02d}]: 0x{1:08x}'.format(i, req_frame[i])) + # Return no data for the response frame + return None +try: + resp.register(snd_unit, 0xfffff0000d00, 0x100) + resp.connect('requested', handle_request) +except Exception as e: + print(e) + sys.exit() + +# create firewire requester +req = Hinawa.FwReq() + +# Fireworks/BeBoB/OXFW supports FCP and some AV/C commands +if snd_unit.get_property('type') is not 1: + request = bytes([0x01, 0xff, 0x19, 0x00, 0xff, 0xff, 0xff, 0xff]) + try: + response = snd_unit.fcp_transact(request) + except Exception as e: + print(e) + sys.exit() + print('FCP Response:') + for i in range(len(response)): + print(' [{0:02d}]: 0x{1:02x}'.format(i, response[i])) + +# Echo Fireworks Transaction +if snd_unit.get_property("type") is 2: + args = get_array() + args.append(5) + try: + params = snd_unit.transact(6, 1, args) + except Exception as e: + print(e) + sys.exit() + print('Echo Fireworks Transaction Response:') + for i in range(len(params)): + print(" [{0:02d}]: {1:08x}".format(i, params[i])) + +# Dice notification +def handle_notification(self, message): + print("Dice Notification: {0:08x}".format(message)) +if snd_unit.get_property('type') is 1: + snd_unit.connect('notified', handle_notification) + args = get_array() + args.append(0x0000030c) + try: + # The address of clock in Impact Twin + snd_unit.transact(0xffffe0000074, args, 0x00000020) + except Exception as e: + print(e) + sys.exit() + +# GUI +class Sample(Gtk.Window): + + def __init__(self): + Gtk.Window.__init__(self, title="Hinawa-1.0 gir sample") + self.set_border_width(20) + + vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) + self.add(vbox) + + topbox = Gtk.Box(spacing=10) + vbox.pack_start(topbox, True, True, 0) + + button = Gtk.Button("transact") + button.connect("clicked", self.on_click_transact) + topbox.pack_start(button, True, True, 0) + + button = Gtk.Button("_Close", use_underline=True) + button.connect("clicked", self.on_click_close) + topbox.pack_start(button, True, True, 0) + + bottombox = Gtk.Box(spacing=10) + vbox.pack_start(bottombox, True, True, 0) + + self.entry = Gtk.Entry() + self.entry.set_text("0xfffff0000980") + bottombox.pack_start(self.entry, True, True, 0) + + self.label = Gtk.Label("result") + self.label.set_text("0x00000000") + bottombox.pack_start(self.label, True, True, 0) + + def on_click_transact(self, button): + try: + addr = int(self.entry.get_text(), 16) + val = snd_unit.read_transact(addr, 1) + except Exception as e: + print(e) + return + + self.label.set_text('0x{0:08x}'.format(val[0])) + print(self.label.get_text()) + + def on_click_close(self, button): + print("Closing application") + Gtk.main_quit() + +# Main logic +win = Sample() +win.connect("delete-event", Gtk.main_quit) +win.show_all() + +Gtk.main() + +sys.exit() diff --git a/libhinawa/samples/qt4.py b/libhinawa/samples/qt4.py new file mode 100755 index 0000000..43611a1 --- /dev/null +++ b/libhinawa/samples/qt4.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python2 + +import sys + +# PyQt4 is not released for python3, sigh... +# The combination of Python2 and Qt4 has a disadvantage for QString. +# This forces interpretor to handle QString as usual unicode string. +import sip +sip.setapi('QString', 2) +from PyQt4.QtCore import Qt +from PyQt4.QtGui import QApplication, QWidget, QHBoxLayout, QVBoxLayout +from PyQt4.QtGui import QToolButton, QGroupBox, QLineEdit, QLabel + +# Hinawa-1.0 gir +from gi.repository import Hinawa + +from array import array + +# helper function +def get_array(): + # The width with 'L' parameter is depending on environment. + arr = array('L') + if arr.itemsize is not 4: + arr = array('I') + return arr + +# query sound devices +index = -1 +while True: + try: + index = Hinawa.UnitQuery.get_sibling(index) + except Exception as e: + break + break + +# no fw sound devices are detected. +if index == -1: + print('No sound FireWire devices found.') + sys.exit() + +# get unit type +try: + unit_type = Hinawa.UnitQuery.get_unit_type(index) +except Exception as e: + print(e) + sys.exit() + +# create sound unit +def handle_lock_status(snd_unit, status): + if status: + print("streaming is locked."); + else: + print("streaming is unlocked."); +if unit_type == 1: + snd_unit = Hinawa.SndDice() +elif unit_type == 2: + snd_unit = Hinawa.SndEfw() +elif unit_type == 3 or unit_type == 4: + snd_unit = Hinawa.SndUnit() +path = "hw:{0}".format(index) +try: + snd_unit.open(path) +except Exception as e: + print(e) + sys.exit() +print('Sound device info:') +print(' type:\t{0}'.format(snd_unit.get_property("type"))) +print(' card:\t{0}'.format(snd_unit.get_property("card"))) +print(' device:\t{0}'.format(snd_unit.get_property("device"))) +print(' GUID:\t{0:016x}'.format(snd_unit.get_property("guid"))) +snd_unit.connect("lock-status", handle_lock_status) + +# create FireWire unit +def handle_bus_update(snd_unit): + print(snd_unit.get_property('generation')) +snd_unit.connect("bus-update", handle_bus_update) + +# start listening +try: + snd_unit.listen() +except Exception as e: + print(e) + sys.exit() + +# create firewire responder +resp = Hinawa.FwResp() +def handle_request(resp, tcode, req_frame): + print('Requested with tcode {0}:'.format(tcode)) + for i in range(len(req_frame)): + print(' [{0:02d}]: 0x{1:08x}'.format(i, req_frame[i])) + # Return no data for the response frame + return None +try: + resp.register(snd_unit, 0xfffff0000d00, 0x100) + resp.connect('requested', handle_request) +except Exception as e: + print(e) + sys.exit() + +# create firewire requester +req = Hinawa.FwReq() + +# Fireworks/BeBoB/OXFW supports FCP and some AV/C commands +if snd_unit.get_property('type') is not 1: + request = bytearray(8) + request[0] = 0x01 + request[1] = 0xff + request[2] = 0x19 + request[3] = 0x00 + request[4] = 0xff + request[5] = 0xff + request[6] = 0xff + request[7] = 0xff + + try: + response = snd_unit.fcp_transact(request) + except Exception as e: + print(e) + sys.exit() + print('FCP Response:') + for i in range(len(response)): + print(' [{0:02d}]: 0x{1:02x}'.format(i, ord(response[i]))) + +# Echo Fireworks Transaction +if snd_unit.get_property("type") is 2: + args = get_array() + args.append(5) + try: + params = snd_unit.transact(6, 1, args) + except Exception as e: + print(e) + sys.exit() + print('Echo Fireworks Transaction Response:') + for i in range(len(params)): + print(" [{0:02d}]: {1:08x}".format(i, params[i])) + +# Dice notification +def handle_notification(self, message): + print("Dice Notification: {0:08x}".format(message)) +if snd_unit.get_property('type') is 1: + snd_unit.connect('notified', handle_notification) + args = get_array() + args.append(0x0000030c) + try: + # The address of clock in Impact Twin + snd_unit.transact(0xffffe0000074, args, 0x00000020) + except Exception as e: + print(e) + sys.exit() + +# GUI +class Sample(QWidget): + def __init__(self, parent=None): + super(Sample, self).__init__(parent) + + self.setWindowTitle("Hinawa-1.0 gir sample with PyQt4") + + layout = QVBoxLayout() + self.setLayout(layout) + + top_grp = QGroupBox(self) + top_layout = QHBoxLayout() + top_grp.setLayout(top_layout) + layout.addWidget(top_grp) + + buttom_grp = QGroupBox(self) + buttom_layout = QHBoxLayout() + buttom_grp.setLayout(buttom_layout) + layout.addWidget(buttom_grp) + + button = QToolButton(top_grp) + button.setText('transact') + top_layout.addWidget(button) + button.clicked.connect(self.transact) + + close = QToolButton(top_grp) + close.setText('close') + top_layout.addWidget(close) + close.clicked.connect(app.quit) + + self.addr = QLineEdit(buttom_grp) + self.addr.setText('0xfffff0000980') + buttom_layout.addWidget(self.addr) + + self.value = QLabel(buttom_grp) + self.value.setText('00000000') + buttom_layout.addWidget(self.value) + + def transact(self, val): + try: + addr = int(self.addr.text(), 16) + val = req.read(snd_unit, addr, 1) + except Exception as e: + print(e) + return + + self.value.setText('0x{0:08x}'.format(val[0])) + print(self.value.text()) + +app = QApplication(sys.argv) +sample = Sample() + +sample.show() +app.exec_() + +sys.exit() diff --git a/libhinawa/samples/qt5.py b/libhinawa/samples/qt5.py new file mode 100755 index 0000000..ffe528b --- /dev/null +++ b/libhinawa/samples/qt5.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 + +import sys + +# Qt5 python binding +from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout +from PyQt5.QtWidgets import QToolButton, QGroupBox, QLineEdit, QLabel + +# Hinawa-1.0 gir +from gi.repository import Hinawa + +from array import array + +# helper function +def get_array(): + # The width with 'L' parameter is depending on environment. + arr = array('L') + if arr.itemsize is not 4: + arr = array('I') + return arr + +# query sound devices +index = -1 +while True: + try: + index = Hinawa.UnitQuery.get_sibling(index) + except Exception as e: + break + break + +# no fw sound devices are detected. +if index == -1: + print('No sound FireWire devices found.') + sys.exit() + +# get unit type +try: + unit_type = Hinawa.UnitQuery.get_unit_type(index) +except Exception as e: + print(e) + sys.exit() + +# create sound unit +def handle_lock_status(snd_unit, status): + if status: + print("streaming is locked."); + else: + print("streaming is unlocked."); +if unit_type == 1: + snd_unit = Hinawa.SndDice() +elif unit_type == 2: + snd_unit = Hinawa.SndEfw() +elif unit_type == 3 or unit_type == 4: + snd_unit = Hinawa.SndUnit() +path = "hw:{0}".format(index) +try: + snd_unit.open(path) +except Exception as e: + print(e) + sys.exit() +print('Sound device info:') +print(' type:\t{0}'.format(snd_unit.get_property("type"))) +print(' card:\t{0}'.format(snd_unit.get_property("card"))) +print(' device:\t{0}'.format(snd_unit.get_property("device"))) +print(' GUID:\t{0:016x}'.format(snd_unit.get_property("guid"))) +snd_unit.connect("lock-status", handle_lock_status) + +# create FireWire unit +def handle_bus_update(snd_unit): + print(snd_unit.get_property('generation')) +snd_unit.connect("bus-update", handle_bus_update) + +# start listening +try: + snd_unit.listen() +except Exception as e: + print(e) + sys.exit() + +# create firewire responder +resp = Hinawa.FwResp() +def handle_request(resp, tcode, req_frame): + print('Requested with tcode {0}:'.format(tcode)) + for i in range(len(req_frame)): + print(' [{0:02d}]: 0x{1:08x}'.format(i, req_frame[i])) + # Return no data for the response frame + return None +try: + resp.register(snd_unit, 0xfffff0000d00, 0x100) + resp.connect('requested', handle_request) +except Exception as e: + print(e) + sys.exit() + +# create firewire requester +req = Hinawa.FwReq() + +# Fireworks/BeBoB/OXFW supports FCP and some AV/C commands +if snd_unit.get_property('type') is not 1: + request = bytes([0x01, 0xff, 0x19, 0x00, 0xff, 0xff, 0xff, 0xff]) + try: + response = snd_unit.fcp_transact(request) + except Exception as e: + print(e) + sys.exit() + print('FCP Response:') + for i in range(len(response)): + print(' [{0:02d}]: 0x{1:02x}'.format(i, response[i])) + +# Echo Fireworks Transaction +if snd_unit.get_property("type") is 2: + args = get_array() + args.append(5) + try: + params = snd_unit.transact(6, 1, args) + except Exception as e: + print(e) + sys.exit() + print('Echo Fireworks Transaction Response:') + for i in range(len(params)): + print(" [{0:02d}]: {1:08x}".format(i, params[i])) + +# Dice notification +def handle_notification(self, message): + print("Dice Notification: {0:08x}".format(message)) +if snd_unit.get_property('type') is 1: + snd_unit.connect('notified', handle_notification) + args = get_array() + args.append(0x0000030c) + try: + # The address of clock in Impact Twin + snd_unit.transact(0xffffe0000074, args, 0x00000020) + except Exception as e: + print(e) + sys.exit() + +# GUI +class Sample(QWidget): + def __init__(self, parent=None): + super(Sample, self).__init__(parent) + + self.setWindowTitle("Hinawa-1.0 gir sample with PyQt5") + + layout = QVBoxLayout() + self.setLayout(layout) + + top_grp = QGroupBox(self) + top_layout = QHBoxLayout() + top_grp.setLayout(top_layout) + layout.addWidget(top_grp) + + buttom_grp = QGroupBox(self) + buttom_layout = QHBoxLayout() + buttom_grp.setLayout(buttom_layout) + layout.addWidget(buttom_grp) + + button = QToolButton(top_grp) + button.setText('transact') + top_layout.addWidget(button) + button.clicked.connect(self.transact) + + close = QToolButton(top_grp) + close.setText('close') + top_layout.addWidget(close) + close.clicked.connect(app.quit) + + self.addr = QLineEdit(buttom_grp) + self.addr.setText('0xfffff0000980') + buttom_layout.addWidget(self.addr) + + self.value = QLabel(buttom_grp) + self.value.setText('00000000') + buttom_layout.addWidget(self.value) + + def transact(self, val): + try: + addr = int(self.addr.text(), 16) + val = req.read(snd_unit, addr, 1) + except Exception as e: + print(e) + return + + self.value.setText('0x{0:08x}'.format(val[0])) + print(self.value.text()) + +app = QApplication(sys.argv) +sample = Sample() + +sample.show() +app.exec() + +sys.exit() diff --git a/libhinawa/samples/run.sh b/libhinawa/samples/run.sh new file mode 100755 index 0000000..8db3abc --- /dev/null +++ b/libhinawa/samples/run.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# NOTE: +# Current working directory should be in root of this repository. + +export LD_LIBRARY_PATH=src/.libs/:/usr/lib:/lib +export GI_TYPELIB_PATH=src/:/usr/lib/girepository-1.0 + +if [[ $1 == 'qt4' ]] ; then + ./samples/qt4.py +elif [[ $1 == 'qt5' ]] ; then + ./samples/qt5.py +elif [[ $1 == 'gtk' ]] ; then + ./samples/gtk3.py +fi