From 4ec14a08b68a2a3a68dea71d0ed55a49fa2e0935 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 19 Feb 2012 11:57:49 +0000 Subject: [PATCH] Added render tool; added jacklib_helpers.py --- Makefile | 15 +- src/icons/16x16/document-open.png | Bin 0 -> 702 bytes src/icons/16x16/media-playback-stop.png | Bin 0 -> 499 bytes src/icons/16x16/media-record.png | Bin 0 -> 697 bytes src/icons/48x48/media-record.png | Bin 0 -> 2907 bytes src/icons/icons.qrc | 4 + src/jacklib.py | 1 - src/jacklib_helpers.py | 55 +++ src/logs.py | 2 +- src/render.py | 305 ++++++++++++++++ src/shared.py | 9 +- src/ui/render.ui | 439 ++++++++++++++++++++++++ 12 files changed, 821 insertions(+), 9 deletions(-) create mode 100644 src/icons/16x16/document-open.png create mode 100644 src/icons/16x16/media-playback-stop.png create mode 100644 src/icons/16x16/media-record.png create mode 100644 src/icons/48x48/media-record.png create mode 100644 src/jacklib_helpers.py create mode 100644 src/render.py create mode 100644 src/ui/render.ui diff --git a/Makefile b/Makefile index 1323064..8cdaff8 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,8 @@ # Created by falkTX # -PYUIC = pyuic4 -PYRCC = pyrcc4 +PYUIC = pyuic4 --pyqt3-wrapper +PYRCC = pyrcc4 -py3 all: build @@ -14,21 +14,24 @@ build: UI RES LANG UI: tools tools: \ - src/ui_logs.py + src/ui_logs.py src/ui_render.py src/ui_logs.py: src/ui/logs.ui - $(PYUIC) -w -o src/ui_logs.py $< + $(PYUIC) -o src/ui_logs.py $< + +src/ui_render.py: src/ui/render.ui + $(PYUIC) -o src/ui_render.py $< RES: src/icons_rc.py src/icons_rc.py: src/icons/icons.qrc - $(PYRCC) -py3 -o src/icons_rc.py $< + $(PYRCC) -o src/icons_rc.py $< LANG: # pylupdate4 -verbose src/lang/lang.pro # lrelease src/lang/lang.pro clean: - rm -f *~ src/*~ src/*.pyc src/*.so src/ui_*.py src/icons_rc.py + rm -f *~ src/*~ src/*.pyc src/*.dll src/*.so src/ui_*.py src/icons_rc.py distclean: clean diff --git a/src/icons/16x16/document-open.png b/src/icons/16x16/document-open.png new file mode 100644 index 0000000000000000000000000000000000000000..530940ce5949b9ab47fd3c11ec1c572fe770d700 GIT binary patch literal 702 zcmV;v0zv(WP)MGyo9QLT$KgOac`Q*uT+@j?idKq>?;%33<-=I7FpS5eW0USt~k zW6owO%#@%SlIdm^>eS4w6xRk?!#{HqpWdDCBOB%mKc4rT_kEx5JLfPdb`Y6F)_+Kj ziHX_Cwu?M%_rQ@$N^BS2`FY4>N1tpn%b2{(2*s^N-n_E1f?zO+HDY;b34XsHcDsE8 z*uWV@2^1O|@^pR36MB)ae>ciql8YZgUh)7Ge3%=ot#Px(g#|P$9}JN}I2?*7zXzMmhOW*| zSlZg~%4)?@;1_nu1c7MCCz>`l4?wm%(SuMf_VQGB9-?%wy%H@|_=;fKlLgPH3ltxiAs-0OJMG5DHg zE1%LL4C9awhQXgOkeZy4CLd~FOrpjxj%q?n@LWP~@!(=XIap4G89MVn{634J>~Wf8rELe+};b~l+!aq1-16Sc&>sC`ntH;MZlvyd05!IG{wB1PGS zbGNNgq(tdf(o{V-eBl~czSctLnc=RrM4hCx-m<6rr&e$Mft+FiOn%4EBbcV?>@H}Y zyPzg5ZXve*-9qKd^PXb3Ia6EBER kPJ3dFdZ?Gr>`OlX2PQF=il;%MR{#J207*qoM6N<$g7rT`rT_o{ literal 0 HcmV?d00001 diff --git a/src/icons/16x16/media-playback-stop.png b/src/icons/16x16/media-playback-stop.png new file mode 100644 index 0000000000000000000000000000000000000000..180280e8ba359d2a4389e93284454cf943b27dbd GIT binary patch literal 499 zcmVMzCV_|S* zE^l&Yo9;Xs0004UNklyX+scBW;@{ixB;GHteD? zi4zVk%KMm2d+-vpg@ZO1m$9PhNBs_CwvU6gp6B-T^cklp z%LPGv>rmBAl^Q-iHLBFjq4KSMp<&gV+w9V!%@Z9SXtBdK^=89D1o6}c7u@qo%qL%H z-gxGm4LpU2vNw&#BOe&P>Cq!4LGwb5O`~jC4;H!Q9m5r89H7`jk)mm{$oi2~!WHh& zq+HUVf=iBBAfd||l~Br&N1K?GJ(kHa#W>SIO3XgxNJ>$aM>IXMj535U#3;~1b3iGQ zVp#4kxJ)p@Fe6O#7nUi8QVbk!=#sF+43ms8$qbOt!J&90^LD|k@{A_sUnv@of|<7k zaaER6UeF|@gCDNR;wnUtIm>NkSffps7)?xvDjD47oYjZrT8_$_3?+8hV}T5L<0#h} p&_s}e?F9KS7v-XS=mdoU?jMapX0!E+{+R#(002ovPDHLkV1o6$+0Fm} literal 0 HcmV?d00001 diff --git a/src/icons/16x16/media-record.png b/src/icons/16x16/media-record.png new file mode 100644 index 0000000000000000000000000000000000000000..4819a0c7605f215940607006f731b9dfa70605dd GIT binary patch literal 697 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 literal 0 HcmV?d00001 diff --git a/src/icons/icons.qrc b/src/icons/icons.qrc index fe86639..45b070e 100644 --- a/src/icons/icons.qrc +++ b/src/icons/icons.qrc @@ -1,6 +1,10 @@ + 16x16/document-open.png 16x16/edit-delete.png + 16x16/media-record.png + 16x16/media-playback-stop.png 16x16/window-close.png + 48x48/media-record.png diff --git a/src/jacklib.py b/src/jacklib.py index f0ebaa4..9f299a8 100644 --- a/src/jacklib.py +++ b/src/jacklib.py @@ -781,7 +781,6 @@ def midi_get_lost_event_count(port_buffer): # Session - def set_timebase_callback(client, session_callback, arg): jacklib.jack_set_timebase_callback.argtypes = [POINTER(jack_client_t), JackSessionCallback, c_void_p] jacklib.jack_set_timebase_callback.restype = c_int diff --git a/src/jacklib_helpers.py b/src/jacklib_helpers.py new file mode 100644 index 0000000..548807f --- /dev/null +++ b/src/jacklib_helpers.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Helper functions for extra jacklib functionality +# Copyright (C) 2012 Filipe Coelho +# +# 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 +# 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. +# +# For a full copy of the GNU General Public License see the COPYING file + +import jacklib + +def get_jack_status_error_string(c_status): + status = c_status.value + error_string = "" + + if (status & jacklib.JackFailure): + error_string += "Overall operation failed;\n" + if (status & jacklib.JackInvalidOption): + error_string += "The operation contained an invalid or unsupported option;\n" + if (status & jacklib.JackNameNotUnique): + error_string += "The desired client name was not unique;\n" + if (status & jacklib.JackServerStarted): + error_string += "The JACK server was started as a result of this operation;\n" + if (status & jacklib.JackServerFailed): + error_string += "Unable to connect to the JACK server;\n" + if (status & jacklib.JackServerError): + error_string += "Communication error with the JACK server;\n" + if (status & jacklib.JackNoSuchClient): + error_string += "Requested client does not exist;\n" + if (status & jacklib.JackLoadFailure): + error_string += "Unable to load internal client;\n" + if (status & jacklib.JackInitFailure): + error_string += "Unable to initialize client;\n" + if (status & jacklib.JackShmFailure): + error_string += "Unable to access shared memory;\n" + if (status & jacklib.JackVersionError): + error_string += "Client's protocol version does not match;\n" + if (status & jacklib.JackBackendError): + error_string += "Backend Error;\n" + if (status & jacklib.JackClientZombie): + error_string += "Client is being shutdown against its will;\n" + + if (error_string): + error_string = error_string.strip().rsplit(";", 1)[0]+"." + + return error_string diff --git a/src/logs.py b/src/logs.py index 01033b1..6f43fad 100644 --- a/src/logs.py +++ b/src/logs.py @@ -215,7 +215,7 @@ class LogsReadThread(QThread): if (self.LOG_FILE_LADISH): self.log_ladish_file.close() -# Class Window +# Logs Window class LogsW(QDialog, ui_logs.Ui_LogsW): LOG_PATH = os.path.join(HOME, ".log") diff --git a/src/render.py b/src/render.py new file mode 100644 index 0000000..6b8bb93 --- /dev/null +++ b/src/render.py @@ -0,0 +1,305 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# JACK-Capture frontend, with freewheel and transport support +# Copyright (C) 2012 Filipe Coelho +# +# 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 +# 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. +# +# For a full copy of the GNU General Public License see the COPYING file + +# Imports (Global) +from PyQt4.QtCore import pyqtSlot, Qt, QProcess, QTime, QTimer, SIGNAL, SLOT +from PyQt4.QtGui import QDialog +from time import sleep + +# Imports (Custom Stuff) +import ui_render +from shared import * +from jacklib_helpers import * + +global jack_client +jack_client = None + +# Render Window +class RenderW(QDialog, ui_render.Ui_RenderW): + def __init__(self, parent, flags): + QDialog.__init__(self, parent, flags) + self.setupUi(self) + + # ------------------------------------------------------------- + # Get JACK client and base information + + global jack_client + if (jack_client): + self.m_jack_client = jack_client + self.m_closeClient = False + else: + self.m_jack_client = jacklib.client_open("Render-Dialog", jacklib.JackNoStartServer, None) + self.m_closeClient = True + + self.m_buffer_size = jacklib.get_buffer_size(self.m_jack_client) + for i in range(self.cb_buffer_size.count()): + if (int(self.cb_buffer_size.itemText(i)) == self.m_buffer_size): + self.cb_buffer_size.setCurrentIndex(i) + + self.m_sample_rate = jacklib.get_sample_rate(self.m_jack_client) + + # ------------------------------------------------------------- + # Internal stuff + + self.m_max_time = 180 + self.m_last_time = 0 + self.m_freewheel = False + + self.m_timer = QTimer(self) + self.m_process = QProcess(self) + + # ------------------------------------------------------------- + # Set-up GUI stuff + + # Get List of formats + self.m_process.start("jack_capture", ["-pf"]) + self.m_process.waitForFinished() + + formats = str(self.m_process.readAllStandardOutput(), encoding="ascii").split(" ") + for i in range(len(formats)-1): + self.cb_format.addItem(formats[i]) + if (formats[i] == "wav"): + self.cb_format.setCurrentIndex(i) + + self.cb_depth.setCurrentIndex(4) #Float + self.rb_stereo.setChecked(True) + + self.te_end.setTime(QTime(0, 3, 0)) + self.progressBar.setMinimum(0) + self.progressBar.setMaximum(0) + self.progressBar.setValue(0) + + self.b_render.setIcon(getIcon("media-record")) + self.b_stop.setIcon(getIcon("media-playback-stop")) + self.b_close.setIcon(getIcon("window-close")) + self.b_open.setIcon(getIcon("document-open")) + self.b_stop.setVisible(False) + self.le_folder.setText(HOME) + + # ------------------------------------------------------------- + # Set-up connections + + self.connect(self.b_render, SIGNAL("clicked()"), SLOT("slot_renderStart()")) + self.connect(self.b_stop, SIGNAL("clicked()"), SLOT("slot_renderStop()")) + self.connect(self.b_open, SIGNAL("clicked()"), SLOT("slot_getAndSetPath()")) + self.connect(self.b_now_start, SIGNAL("clicked()"), SLOT("slot_setStartNow()")) + self.connect(self.b_now_end, SIGNAL("clicked()"), SLOT("slot_setEndNow()")) + self.connect(self.te_start, SIGNAL("timeChanged(const QTime)"), SLOT("slot_updateStartTime(const QTime)")) + self.connect(self.te_end, SIGNAL("timeChanged(const QTime)"), SLOT("slot_updateEndTime(const QTime)")) + self.connect(self.m_timer, SIGNAL("timeout()"), SLOT("slot_updateProgressbar()")) + + @pyqtSlot() + def slot_renderStart(self): + if (os.path.exists(self.le_folder.text()) == False): + QMessageBox.warning(self, self.tr("Warning"), self.tr("The selected directory does not exist. Please choose a valid one.")) + return + + self.group_render.setEnabled(False) + self.group_time.setEnabled(False) + self.group_encoding.setEnabled(False) + self.b_render.setVisible(False) + self.b_stop.setVisible(True) + self.b_close.setEnabled(False) + + self.m_freewheel = (self.cb_render_mode.currentIndex() == 1) + new_buffer_size = int(self.cb_buffer_size.currentText()) + + time_start = self.te_start.time() + time_end = self.te_end.time() + min_time = (time_start.hour()*3600)+(time_start.minute()*60)+(time_start.second()) + max_time = (time_end.hour()*3600)+(time_end.minute()*60)+(time_end.second()) + self.m_max_time = max_time + + self.progressBar.setMinimum(min_time) + self.progressBar.setMaximum(max_time) + self.progressBar.setValue(min_time) + self.progressBar.update() + + if (self.m_freewheel): + self.m_timer.setInterval(100) + else: + self.m_timer.setInterval(500) + + arguments = [] + + # Bit depth + arguments.append("-b") + arguments.append(self.cb_depth.currentText()) + + # Channels + arguments.append("-c") + if (self.rb_mono.isChecked()): + arguments.append("1") + elif (self.rb_stereo.isChecked()): + arguments.append("2") + else: + arguments.append(str(self.sb_channels.value())) + + # Format + arguments.append("-f") + arguments.append(self.cb_format.currentText()) + + # Controlled by transport + arguments.append("-jt") + + # Silent mode + arguments.append("-dc") + arguments.append("-s") + + # Change current directory + os.chdir(self.le_folder.text()) + + if (new_buffer_size != jacklib.get_buffer_size(self.m_jack_client)): + print("NOTICE: buffer size changed before render") + jacklib.set_buffer_size(self.m_jack_client, new_buffer_size) + + if (jacklib.transport_query(self.m_jack_client, None) > jacklib.JackTransportStopped): # >TransportStopped is rolling/starting + jacklib.transport_stop(self.m_jack_client) + + jacklib.transport_locate(self.m_jack_client, min_time*self.m_sample_rate) + self.m_last_time = -1 + + self.m_process.start("jack_capture", arguments) + self.m_process.waitForStarted() + + if (self.m_freewheel): + sleep(1) + print("NOTICE: rendering in freewheel mode") + jacklib.set_freewheel(jack_client, 1) + + self.m_timer.start() + jacklib.transport_start(self.m_jack_client) + + @pyqtSlot() + def slot_renderStop(self): + jacklib.transport_stop(self.m_jack_client) + + if (self.m_freewheel): + jacklib.set_freewheel(self.m_jack_client, 0) + + sleep(1) + + self.m_process.close() + self.m_timer.stop() + + self.group_render.setEnabled(True) + self.group_time.setEnabled(True) + self.group_encoding.setEnabled(True) + self.b_render.setVisible(True) + self.b_stop.setVisible(False) + self.b_close.setEnabled(True) + + self.progressBar.setMinimum(0) + self.progressBar.setMaximum(0) + self.progressBar.setValue(0) + self.progressBar.update() + + # Restore buffer size + new_buffer_size = jacklib.get_buffer_size(self.m_jack_client) + if (new_buffer_size != self.m_buffer_size): + jacklib.set_buffer_size(self.m_jack_client, new_buffer_size) + + @pyqtSlot() + def slot_getAndSetPath(self): + getAndSetPath(self, self.le_folder.text(), self.le_folder) + + @pyqtSlot() + def slot_setStartNow(self): + time = jacklib.get_current_transport_frame(self.m_jack_client)/self.m_sample_rate + secs = time % 60 + mins = (time / 60) % 60 + hrs = (time / 3600) % 60 + self.te_start.setTime(QTime(hrs, mins, secs)) + + @pyqtSlot() + def slot_setEndNow(self): + time = jacklib.get_current_transport_frame(self.m_jack_client)/self.m_sample_rate + secs = time % 60 + mins = (time / 60) % 60 + hrs = (time / 3600) % 60 + self.te_end.setTime(QTime(hrs, mins, secs)) + + @pyqtSlot(QTime) + def slot_updateStartTime(self, time): + if (time >= self.te_end.time()): + self.te_end.setTime(time) + self.b_render.setEnabled(False) + else: + self.b_render.setEnabled(True) + + @pyqtSlot(QTime) + def slot_updateEndTime(self, time): + if (time <= self.te_start.time()): + time = self.te_start.setTime(time) + self.b_render.setEnabled(False) + else: + self.b_render.setEnabled(True) + + @pyqtSlot() + def slot_updateProgressbar(self): + time = jacklib.get_current_transport_frame(self.m_jack_client)/self.m_sample_rate + self.progressBar.setValue(time) + + if (time > self.m_max_time or (self.m_last_time > time and self.m_freewheel == False)): + self.slot_renderStop() + + self.m_last_time = time + + def closeEvent(self, event): + if (self.m_closeClient): + jacklib.client_close(self.m_jack_client) + QDialog.closeEvent(self, event) + +# ------------------------------------------------------------- +# Allow to use this as a standalone app +if __name__ == '__main__': + + # Additional imports + import sys + from PyQt4.QtGui import QApplication + + # App initialization + app = QApplication(sys.argv) + + for iPATH in PATH: + if os.path.exists(os.path.join(iPATH, "jack_capture")): + break + else: + QMessageBox.critical(None, app.translate("RenderW", "Error"), app.translate("RenderW", "The 'jack_capture' application is not available.\nIs not possible to render without it!")) + sys.exit(1) + + jack_status = jacklib.jack_status_t(0) + jack_client = jacklib.client_open("Render", jacklib.JackNoStartServer, jacklib.pointer(jack_status)) + + if not jack_client: + QMessageBox.critical(None, app.translate("RenderW", "Error"), app.translate("RenderW", "Could not connect to JACK, possible errors:\n%s" % (get_jack_status_error_string(jack_status)))) + sys.exit(1) + + # Show GUI + gui = RenderW(None, Qt.WindowFlags()) + gui.setWindowIcon(getIcon("media-record", 48)) + gui.show() + + # App-Loop + ret = app.exec_() + + if (jack_client): + jacklib.client_close(jack_client) + + # Exit properly + sys.exit(ret) diff --git a/src/shared.py b/src/shared.py index 1bb1112..6c671b6 100644 --- a/src/shared.py +++ b/src/shared.py @@ -19,7 +19,7 @@ # Imports (Global) import os from PyQt4.QtCore import qDebug, qWarning -from PyQt4.QtGui import QIcon +from PyQt4.QtGui import QIcon, QMessageBox, QFileDialog # Small integrity tests HOME = os.getenv("HOME") @@ -41,3 +41,10 @@ else: # Get Icon from user theme, using our own as backup (Oxygen) def getIcon(icon, size=16): return QIcon.fromTheme(icon, QIcon(":/%ix%i/%s.png" % (size, size, icon))) + +# QLineEdit and QPushButtom combo +def getAndSetPath(self, currentPath, lineEdit): + newPath = QFileDialog.getExistingDirectory(self, self.tr("Set Path"), currentPath, QFileDialog.ShowDirsOnly) + if (newPath): + lineEdit.setText(newPath) + return newPath diff --git a/src/ui/render.ui b/src/ui/render.ui new file mode 100644 index 0000000..a4bd62c --- /dev/null +++ b/src/ui/render.ui @@ -0,0 +1,439 @@ + + + RenderW + + + + 0 + 0 + 585 + 332 + + + + Render + + + + + + + + 24 + + + + + + + &Render + + + + :/16x16/media-record.png:/16x16/media-record.png + + + + + + + &Stop + + + + :/16x16/media-playback-stop.png:/16x16/media-playback-stop.png + + + + + + + &Close + + + + :/16x16/window-close.png:/16x16/window-close.png + + + + + + + + + Qt::Horizontal + + + + + + + Render Options + + + + + + Render &Mode: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + cb_render_mode + + + + + + + + Realtime + + + + + Freewheel + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 275 + 20 + + + + + + + + &Buffer Size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + cb_buffer_size + + + + + + + true + + + + 32 + + + + + 64 + + + + + 128 + + + + + 256 + + + + + 512 + + + + + 1024 + + + + + 2048 + + + + + 4096 + + + + + 8192 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 275 + 20 + + + + + + + + Output folder: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + :/16x16/document-open.png:/16x16/document-open.png + + + + + + + + + + + + Time + + + + + + &Start Time: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + te_start + + + + + + + hh:mm:ss + + + + + + + &End Time: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + te_end + + + + + + + hh:mm:ss + + + + + + + now + + + + + + + now + + + + + + + + + + Encoding + + + + + + &Format: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + cb_format + + + + + + + + + + false + + + ... + + + + + + + Bit &Depth: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + cb_depth + + + + + + + + 8 + + + + + 16 + + + + + 24 + + + + + 32 + + + + + Float + + + + + + + + Mono + + + + + + + Stereo + + + + + + + Outro: + + + + + + + false + + + 1 + + + + + + + + + + + + + + b_close + clicked() + RenderW + close() + + + 465 + 343 + + + 258 + 183 + + + + + rb_outro + toggled(bool) + sb_channels + setEnabled(bool) + + + 405 + 259 + + + 484 + 255 + + + + +