[proaudio] [1773] media-sound/boodler-2.0.3-r1 add docs, pyqt4 gui, ~amd64 kw, misc fixes.

[ Thread Index | Date Index | More lists.tuxfamily.org/proaudio Archives ]


Revision: 1773
Author:   gavlee
Date:     2010-10-22 07:26:34 +0200 (Fri, 22 Oct 2010)
Log Message:
-----------
media-sound/boodler-2.0.3-r1 add docs, pyqt4 gui, ~amd64 kw, misc fixes.

Modified Paths:
--------------
    trunk/overlays/proaudio/media-sound/boodler/ChangeLog
    trunk/overlays/proaudio/media-sound/boodler/Manifest

Added Paths:
-----------
    trunk/overlays/proaudio/media-sound/boodler/boodler-2.0.3-r1.ebuild
    trunk/overlays/proaudio/media-sound/boodler/files/boodle-ui-qt.py

Modified: trunk/overlays/proaudio/media-sound/boodler/ChangeLog
===================================================================
--- trunk/overlays/proaudio/media-sound/boodler/ChangeLog	2010-10-21 19:43:03 UTC (rev 1772)
+++ trunk/overlays/proaudio/media-sound/boodler/ChangeLog	2010-10-22 05:26:34 UTC (rev 1773)
@@ -2,6 +2,14 @@
 # Copyright 1999-2010 Gentoo Foundation; Distributed under the GPL v2
 # $Header: $
 
+*boodler-2.0.3-r1 (22 Oct 2010)
+
+  22 Oct 2010; Gavin Pryke <gavinlee303@xxxxxxxxxxxxxx>
+  +boodler-2.0.3-r1.ebuild, +files/boodle-ui-qt.py:
+  add ~amd64 keyword. add coreaudio and doc USE flags. include a pyqt4 gui with
+  USE=qt4. work around selection of default audio driver. remove python inherit
+  as distutils is already inherited.
+
 *boodler-2.0.3 (15 Oct 2010)
 
   15 Oct 2010; Gavin Pryke <gavinlee303@xxxxxxxxxxxxxx>

Modified: trunk/overlays/proaudio/media-sound/boodler/Manifest
===================================================================
--- trunk/overlays/proaudio/media-sound/boodler/Manifest	2010-10-21 19:43:03 UTC (rev 1772)
+++ trunk/overlays/proaudio/media-sound/boodler/Manifest	2010-10-22 05:26:34 UTC (rev 1773)
@@ -1,3 +1,4 @@
+AUX boodle-ui-qt.py 12114 RMD160 b233bfcd8a51b129dd0d2466f08b126a41077894 SHA1 bf8402a5ce0480f93bdc9ac1bb6596adab8a3db7 SHA256 b2a0ea4dc175e7e175671bfca48bafe44a0bd37801babcd7e23e492ad34130a4
 AUX boodler 2156 RMD160 3f14fe314d6d4f3dc05d566a710a9348825eb358 SHA1 5442b4abfc45054f7395afa16e1b359704bccf5e SHA256 b2f5fbc14dc152e78fdaca0b23020a8df03956c1987ce379df8cf082937177a1
 DIST Boodler-2.0.2.tar.gz 303617 RMD160 2d0577027bfb6cfb295e6d1eaf54fb3dcea4a56b SHA1 a153f58b3b39763a7876bbd28632a05134bbf522 SHA256 94a687d4ce854fc0d7749da6953d0f17efbcd00ad30359299f4d478f6b8e5197
 DIST Boodler-2.0.3.tar.gz 306478 RMD160 3499e5894a7fe457b3aafaaadebbc1063223e019 SHA1 1f543d4a09930fe33e680f1d6cf986abf07fd29e SHA256 fe432e35737aa14e3595930df05f85ecd24ba0278365c34c4028192c20a06088
@@ -2,4 +3,5 @@
 EBUILD boodler-2.0.2.ebuild 1647 RMD160 597802fd10303055a77bf1f2cb0ed7fd48504b02 SHA1 fbef618c802ec9323a8e72bf87487727e348bc09 SHA256 521d5270b7bdadd73849d3e29d9e2036cd58b43d4d7b984c364bd9d148eab5d5
+EBUILD boodler-2.0.3-r1.ebuild 3507 RMD160 44fdfbf5e6dc4303f03443d59f68c3574001cf51 SHA1 5876d4c9ee9debdc810fa7b0c0cdeb5749723411 SHA256 70c8cb81be0d68f4a658b5c442fe592abcdfc247bf05395ebca421082b6b2ae1
 EBUILD boodler-2.0.3.ebuild 1977 RMD160 78d123848f328faebffd460abbf34a4839383e5c SHA1 1ac8e96111be945a46507a7cebe5ac533440929e SHA256 ab3ce6546a7a1e54eff9eacee8bf5dd6b182dfe8313742676e42aa3cc285ddd3
-MISC ChangeLog 556 RMD160 6119fd0b97141353903a4fa720226507a88c624f SHA1 9c805e3ee3b52def6ac01d079fdbea7c17da2b36 SHA256 ac4502e83ed91585f5f5615125d970c978c3b590b5b4b41071eeaf8545db25f5
+MISC ChangeLog 895 RMD160 238c949be565723daf7d33ec156352ff60f507f0 SHA1 f3ceac163b6a4c4610bf4a52adab369e1cc6f6ff SHA256 453fcc1a0f4a8530d97a13b9c5748a18f314722d8aeb42a19f42c654d57705bd
 MISC metadata.xml 457 RMD160 035f8f3790a1a312b132650bca012e2db915a57d SHA1 2098a41f73f85e1b3e75e10cb494117df2cb7587 SHA256 723b7bd3d0f84f5193ad64b625597ba2f9dc5c7d250a8b636b8cada6ad5f682b

Added: trunk/overlays/proaudio/media-sound/boodler/boodler-2.0.3-r1.ebuild
===================================================================
--- trunk/overlays/proaudio/media-sound/boodler/boodler-2.0.3-r1.ebuild	                        (rev 0)
+++ trunk/overlays/proaudio/media-sound/boodler/boodler-2.0.3-r1.ebuild	2010-10-22 05:26:34 UTC (rev 1773)
@@ -0,0 +1,117 @@
+# Copyright 1999-2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI=2
+
+PYTHON_DEPEND="2:2.4"
+
+inherit distutils bash-completion
+
+MY_P="Boodler-${PV}"
+
+DESCRIPTION="Tool for creating soundscapes -- continuous, infinitely varying streams of sound"
+HOMEPAGE="http://boodler.org/";
+SRC_URI="http://boodler.org/dl/${MY_P}.tar.gz";
+LICENSE="LGPL-2 GPL-2 public-domain"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="alsa bash-completion coreaudio doc esd intmath jack lame pulseaudio qt4 shout vorbis"
+
+RESTRICT="mirror"
+
+DEPEND="alsa? ( >=media-libs/alsa-lib-1.0.17a )
+	esd? ( >=media-sound/esound-0.2.41 )
+	jack? ( >=media-libs/bio2jack-0.9 )
+	lame? ( >=media-sound/lame-3.98.2-r1 )
+	pulseaudio? ( >=media-sound/pulseaudio-0.9.9 )
+	shout? ( >=media-libs/libshout-2.1 )
+	vorbis? ( >=media-libs/libvorbis-1.2.1_rc1-r2 )"
+RDEPEND="${DEPEND}
+	qt4? ( >=dev-python/PyQt4-4.7.3[X] )"
+
+S="${WORKDIR}/${MY_P}"
+
+pkg_setup() {
+	if use shout && ! use vorbis ; then
+		eerror "To have shout support, you also need to build boodler with"
+		eerror "USE=\"vorbis\"!"
+		die
+	fi
+}
+
+src_prepare() {
+	local defdriver
+	local with
+	local without
+
+	# set up a default audio driver (not daemon) according to USE flags.
+	# it does not appear to work in setup.cfg so there is a workaround below.
+	if use coreaudio ; then
+		defdriver=macosx
+	elif use alsa ; then
+		defdriver=alsa
+	else
+		defdriver=oss
+	fi
+
+	# this ugly code enables/disables the output drivers
+	# oss seems to be needed for boodler.py --list-drivers to work
+	with="${with}oss,"
+	use alsa && with="${with}alsa," || without="${without}alsa,"
+	use coreaudio && with="${with}macosx,osxaq," \
+		|| without="${without}macosx,osxaq,"
+	use esd && with="${with}esd," || without="${without}esd,"
+	use jack && with="${with}jackb," || without="${without}jackb,"
+	use lame && with="${with}lame," || without="${without}lame,"
+	use pulseaudio && with="${with}pulse," || without="${without}pulse,"
+	use shout && with="${with}shout," || without="${without}shout,"
+	use vorbis && with="${with}vorbis," || without="${without}vorbis,"
+
+	# move the original setup.cfg out of the way as a backup to check syntax
+	mv "${S}/setup.cfg" "${T}/setup.cfg.original" || die "setup.cfg not found"
+
+	# fill the setup.cfg with the values
+	cat > "${S}/setup.cfg" <<-EOF
+		[build_scripts]
+		default_driver=${defdriver}
+		[build_ext]
+		with-drivers=${with}
+		without-drivers=${without}
+		intmath=$(use intmath && echo 1 || echo 0)
+	EOF
+
+	# workaround for default-driver in setup.cfg not functioning
+	$(PYTHON) setup.py build_scripts \
+		--default-driver ${defdriver} \
+		|| die "$(PYTHON) setup.py build_scripts failed"
+
+	# fix boodle-ui-qt.py shebang
+	if use qt4 ; then
+		cp "${FILESDIR}/boodle-ui-qt.py" "${T}/boodle-ui-qt.py" \
+			|| die "cp ${FILESDIR}/boodle-ui-qt.py ${T}/boodle-ui-qt.py failed"
+		python_convert_shebangs $(python_get_version) "${T}/boodle-ui-qt.py"
+	fi
+}
+
+src_install() {
+	distutils_src_install
+
+	# a bash completion addon script downloaded from the official site
+	# http://boodler.org/dl/etc/bash_completion.d/boodler
+	dobashcompletion "${FILESDIR}/boodler"
+
+	# a pyqt4 gui addon for boodler downloaded from the official site
+	# http://boodler.org/dl/etc/boodle-ui-qt.py
+	if use qt4 ; then
+		dobin "${T}/boodle-ui-qt.py" || die "boodle-ui-qt.py not found"
+	fi
+
+	# docs, better include them as boodler is not the most intuitive to use for
+	# new users
+	if use doc ; then
+		pushd doc || die "doc dir not found"
+		dohtml -r *
+		popd
+	fi
+}

Added: trunk/overlays/proaudio/media-sound/boodler/files/boodle-ui-qt.py
===================================================================
--- trunk/overlays/proaudio/media-sound/boodler/files/boodle-ui-qt.py	                        (rev 0)
+++ trunk/overlays/proaudio/media-sound/boodler/files/boodle-ui-qt.py	2010-10-22 05:26:34 UTC (rev 1773)
@@ -0,0 +1,316 @@
+#!/usr/bin/python
+
+# Boodler: a programmable soundscape tool
+# Designed by Andrew Plotkin <erkyrath@xxxxxxxxxx>
+# For more information, see <http://boodler.org/>
+#
+# This Python script ("boodle-ui-qt.py") is licensed under the GNU
+# Library General Public License (LGPL).
+# Author: Tuukka Hastrup <Tuukka.Hastrup@xxxxxx>
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this program. (It should be a document entitled "LGPL".) 
+# If not, see the web URL above, or write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import sys
+import subprocess
+import os, signal
+
+from boopak import collect # you'll need Boodler on Python's library path
+
+# same as in boodler.py
+if 'darwin' in sys.platform.lower():
+    Default_Relative_Data_Dir = 'Library/Application Support/Boodler'
+else:
+    Default_Relative_Data_Dir = '.boodler'
+
+basedir = None # XXX opts.basedir
+if not basedir:
+    basedir = os.environ.get('BOODLER_DATA')
+if not basedir:
+    basedir = os.path.join(os.environ.get('HOME'), Default_Relative_Data_Dir)
+
+
+# collect the list of agents
+
+l = collect.PackageCollection(basedir=basedir)
+
+pkgs = l.list_all_current_packages()
+
+agents = []
+
+for pkgname,_vers in sorted(pkgs):
+    pkg = l.load(pkgname)
+    for resname in sorted(pkg.resources.keys()):
+        res = pkg.resources.get(resname)
+        if res.get_one("boodler.use") == "agent":
+            agents += [(pkgname, resname)]
+
+
+def play(agent):
+    boodler = ["boodler.py", "%s/%s" % agent]
+    return boodler
+
+def textplay(agent):
+    print "Playing %s/%s" % agent,
+
+    pkg = l.load(agent[0])
+    res = pkg.resources.get(agent[1])
+    print '"%s"' % res.get_one("dc.title"), "... ",
+
+    sys.stdout.flush()
+
+    boodler = subprocess.Popen(play(agent), stdin=subprocess.PIPE, 
+                               stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+    try:
+        boodler.communicate()
+        if boodler.returncode == 0:
+            print "Done."
+        else:
+            print "Boodler failed with exit code %s." % boodler.returncode
+    except KeyboardInterrupt:
+        print "\nInterrupted"
+        os.kill(boodler.pid, signal.SIGTERM)
+        try:
+            boodler.wait()
+        except KeyboardInterrupt:
+            os.kill(boodler.pid, signal.SIGKILL)
+
+def textmain():
+    for agent in agents:
+        textplay(agent)
+
+def qtmain():
+    from PyQt4 import QtCore, QtGui # you'll need PyQt4 (python-qt4)
+
+    def index2rowdata(index):
+        rowdata = (index.sibling(index.row(), 0).data().toString(),
+                   index.sibling(index.row(), 1).data().toString(),
+                   index.sibling(index.row(), 2).data().toString(),
+                   )
+        
+        return rowdata
+
+    class Window(QtGui.QWidget):
+        def __init__(self, app):
+            self.boodler = None
+
+            QtGui.QWidget.__init__(self)
+
+            self.connect(app, QtCore.SIGNAL('aboutToQuit()'), self.stopPlay)
+
+            # proxy model for sorting and filtering
+            self.proxyModel = QtGui.QSortFilterProxyModel()
+            self.proxyModel.setDynamicSortFilter(True)
+            self.proxyModel.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
+            self.proxyModel.setFilterKeyColumn(2)
+
+            # widgets for now playing agent
+            self.nowPlayingGroupBox = QtGui.QGroupBox("Now playing")
+            self.nowPlayingLabel = QtGui.QLabel("Double-click a soundscape to play\n")
+            self.nowPlayingButton = QtGui.QPushButton(self.style().standardIcon(QtGui.QStyle.SP_MediaStop), "&Stop")
+            self.nowPlayingButton.setEnabled(False)
+
+            # signals for now playing agent
+            self.connect(self.nowPlayingButton, QtCore.SIGNAL('clicked()'), self.stopPlay)
+
+            # widgets for selected agent
+            self.selectedGroupBox = QtGui.QGroupBox("Selected soundscape")
+            self.selectedLabel = QtGui.QLabel("Click a soundscape to view details\n")
+            self.selectedInfoLabel = QtGui.QLabel("Internal name:\nLicense:\nSource:")
+            self.selectedButton = QtGui.QPushButton(self.style().standardIcon(QtGui.QStyle.SP_MediaPlay), "&Play")
+            self.selectedButton.setEnabled(False)
+
+            # signals for now playing agent
+            self.connect(self.selectedButton, QtCore.SIGNAL('clicked()'), self.playButtonClicked)
+
+            # view widgets
+            self.proxyGroupBox = QtGui.QGroupBox("Available soundscapes")
+
+            self.proxyView = QtGui.QTreeView()
+            self.proxyView.setRootIsDecorated(False)
+            self.proxyView.setAlternatingRowColors(True)
+            self.proxyView.setModel(self.proxyModel)
+            self.proxyView.setSortingEnabled(True)
+            self.proxyView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
+            self.proxyView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
+            self.proxyView.setAllColumnsShowFocus(True)
+
+            # filter pattern widgets
+            self.filterPatternLineEdit = QtGui.QLineEdit()
+            self.filterPatternLabel = QtGui.QLabel("F&ind:")
+            self.filterPatternLabel.setBuddy(self.filterPatternLineEdit)
+
+            # filter pattern signals
+            self.connect(self.filterPatternLineEdit,
+                    QtCore.SIGNAL('textChanged(const QString &)'),
+                    self.filterRegExpChanged)
+
+            self.connect(self.proxyView.selectionModel(), 
+                         QtCore.SIGNAL('currentRowChanged(const QModelIndex &, const QModelIndex &)'), 
+                         self.itemSelected)
+            self.connect(self.proxyView, QtCore.SIGNAL('activated(const QModelIndex &)'), self.itemActivated)
+
+            # now playing layout
+            nowPlayingLayout = QtGui.QHBoxLayout()
+            nowPlayingLayout.addWidget(self.nowPlayingButton)
+            nowPlayingLayout.addWidget(self.nowPlayingLabel, 1)
+            self.nowPlayingGroupBox.setLayout(nowPlayingLayout)
+
+            # selected layout
+            selectedLayout = QtGui.QVBoxLayout()
+            selectedLayoutH = QtGui.QHBoxLayout()
+            selectedLayoutH.addWidget(self.selectedButton)
+            selectedLayoutH.addWidget(self.selectedLabel, 1)
+            selectedLayout.addLayout(selectedLayoutH)
+            selectedLayout.addWidget(self.selectedInfoLabel)
+            self.selectedGroupBox.setLayout(selectedLayout)
+
+            # available agents layout
+            filterPatternLayout = QtGui.QHBoxLayout()
+            filterPatternLayout.addWidget(self.filterPatternLabel)
+            filterPatternLayout.addWidget(self.filterPatternLineEdit)
+
+            proxyLayout = QtGui.QVBoxLayout()
+            proxyLayout.addWidget(self.proxyView)
+            proxyLayout.addLayout(filterPatternLayout)
+            self.proxyGroupBox.setLayout(proxyLayout)
+
+            # main layout
+            mainLayout = QtGui.QVBoxLayout()
+            mainLayout.addWidget(self.nowPlayingGroupBox)
+            mainLayout.addWidget(self.selectedGroupBox)
+            mainLayout.addWidget(self.proxyGroupBox)
+            self.setLayout(mainLayout)
+
+            # set top-level window properties
+            self.setWindowTitle("Boodle UI")
+            self.resize(500, 450)
+
+            # set initial state
+            self.proxyView.sortByColumn(2, QtCore.Qt.AscendingOrder)
+            self.filterPatternLineEdit.setText("")
+
+        def setSourceModel(self, model):
+            self.proxyModel.setSourceModel(model)
+
+        def filterRegExpChanged(self):
+            regExp = QtCore.QRegExp(self.filterPatternLineEdit.text(), QtCore.Qt.CaseInsensitive, QtCore.QRegExp.Wildcard)
+            self.proxyModel.setFilterRegExp(regExp)
+
+        def itemSelected(self, currentIndex, _previousIndex):
+            if not currentIndex.isValid():
+                return # keep the latest selection, if any
+            row = index2rowdata(currentIndex)
+            self.lastSelectedRow = row
+            self.selectedButton.setEnabled(True)
+            self.updateSelected(row)
+
+        def itemActivated(self, index):
+            row = index2rowdata(index)
+            self.startPlay((str(row[0]), str(row[1])))
+            self.updateNowPlaying(row)
+
+        def playButtonClicked(self):
+            row = self.lastSelectedRow
+            self.startPlay((str(row[0]), str(row[1])))
+            self.updateNowPlaying(row)
+
+        def updateNowPlaying(self, row):
+            pkg = l.load(str(row[0]))
+            creator = pkg.metadata.get_one("dc.creator")
+            pkgtitle = pkg.metadata.get_one("dc.title")
+
+            msg = '"%s"\nby %s from "%s"' % (row[2], creator, pkgtitle)
+            self.nowPlayingLabel.setText(msg)
+
+        def updateSelected(self, row):
+            pkg = l.load(str(row[0]))
+            creator = pkg.metadata.get_one("dc.creator")
+            pkgtitle = pkg.metadata.get_one("dc.title")
+            license = pkg.metadata.get_one("dc.license")
+            source = pkg.metadata.get_one("dc.source")
+
+            msg = '"%s"\nby %s from "%s"' % (row[2], creator, pkgtitle)
+            self.selectedLabel.setText(msg)
+
+            info = 'Internal name: %s/%s' % (row[0], row[1])
+            info += '\nLicense: %s' % license
+            info += '\nSource: %s' % source
+            self.selectedInfoLabel.setText(info)
+
+        def startPlay(self, agent):
+            self.stopPlay()
+
+            self.boodler = QtCore.QProcess(self)
+            self.connect(self.boodler, QtCore.SIGNAL('error(QProcess::ProcessError)'), self.playError)
+            self.connect(self.boodler, QtCore.SIGNAL('finished(int,QProcess::ExitStatus)'), self.playFinished)
+
+            cmd = play(agent)
+            print "Launching: %s" % ' '.join(cmd)
+            self.boodler.start(cmd[0], cmd[1:])
+
+            self.nowPlayingButton.setEnabled(True)
+
+        def stopPlay(self):
+            if self.boodler:
+                self.disconnect(self.boodler, QtCore.SIGNAL('error(QProcess::ProcessError)'), self.playError)
+                self.disconnect(self.boodler, QtCore.SIGNAL('finished(int, QProcess::ExitStatus)'), self.playFinished)
+                if self.boodler.state() != QtCore.QProcess.NotRunning:
+                    self.boodler.terminate()
+                    if not self.boodler.waitForFinished(5000):
+                        self.boodler.kill()
+                self.boodler = None
+
+            self.nowPlayingButton.setEnabled(False)
+
+        def playError(self, error):
+            if error == QtCore.QProcess.FailedToStart:
+                print "Boodler failed to start: %s" % self.boodler.errorString()
+            elif error == QtCore.QProcess.Crashed:
+                print "Boodler crashed with exit code %s." % self.boodler.exitCode()
+            else:
+                print "Boodler failed with error %s." % error
+
+            self.stopPlay()
+
+        def playFinished(self, exitCode, exitStatus):
+            if exitCode != 0:
+                print self.boodler.readAllStandardError()
+                print "Boodler failed with exit code %s." % exitCode
+            else:
+                print "Boodler done playing."
+
+            self.stopPlay()
+
+    def createAgentModel(parent):
+        model = QtGui.QStandardItemModel(0, 3, parent)
+        
+        model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Package"))
+        model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("Resource"))
+        model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Title"))
+
+        def standardItem(x):
+            if x is None:
+                return QtGui.QStandardItem("")
+            else:
+                return QtGui.QStandardItem(x)
+
+        for agent in reversed(agents):
+            pkg = l.load(agent[0])
+            res = pkg.resources.get(agent[1])
+            title = res.get_one("dc.title")
+            model.appendRow(map(standardItem, [agent[0], agent[1], title]))
+
+        return model
+
+    app = QtGui.QApplication(sys.argv)
+    window = Window(app)
+    window.setSourceModel(createAgentModel(window))
+    window.show()
+    sys.exit(app.exec_())
+
+
+qtmain()


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/