Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
8.4KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla host code
  4. # Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License as
  8. # published by the Free Software Foundation; either version 2 of
  9. # the License, or any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the doc/GPL.txt file.
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Config)
  19. from carla_config import *
  20. # ------------------------------------------------------------------------------------------------------------
  21. # Imports (Global)
  22. if config_UseQt5:
  23. from PyQt5.QtCore import pyqtSlot
  24. from PyQt5.QtGui import QFontMetrics
  25. from PyQt5.QtWidgets import QDialog
  26. else:
  27. from PyQt4.QtCore import pyqtSlot
  28. from PyQt4.QtGui import QDialog, QFontMetrics
  29. # ------------------------------------------------------------------------------------------------------------
  30. # Imports (Custom)
  31. from carla_shared import *
  32. import ui_carla_panel_time
  33. # ------------------------------------------------------------------------------------------------------------
  34. # Time Panel
  35. class CarlaPanelTime(QDialog):
  36. def __init__(self, host, parent):
  37. QDialog.__init__(self, parent)
  38. self.host = host
  39. self.ui = ui_carla_panel_time.Ui_Dialog()
  40. self.ui.setupUi(self)
  41. if False:
  42. # kdevelop likes this :)
  43. host = CarlaHostNull()
  44. self.host = host
  45. # ----------------------------------------------------------------------------------------------------
  46. # Internal stuff
  47. self.fLastTransportBPM = 0.0
  48. self.fLastTransportFrame = 0
  49. self.fLastTransportState = False
  50. self.fSampleRate = 0.0
  51. self.ui.l_time_frame.setMinimumWidth(QFontMetrics(self.ui.l_time_frame.font()).width("000'000'000") + 3)
  52. self.ui.l_time_clock.setMinimumWidth(QFontMetrics(self.ui.l_time_clock.font()).width("00:00:00") + 3)
  53. self.ui.l_time_bbt.setMinimumWidth(QFontMetrics(self.ui.l_time_bbt.font()).width("000|00|0000") + 3)
  54. # ----------------------------------------------------------------------------------------------------
  55. # Disable buttons if plugin
  56. if host.isPlugin:
  57. self.ui.b_play.setEnabled(False)
  58. self.ui.b_stop.setEnabled(False)
  59. self.ui.b_backwards.setEnabled(False)
  60. self.ui.b_forwards.setEnabled(False)
  61. self.ui.cb_transport_link.setEnabled(False)
  62. self.ui.dsb_bpm.setEnabled(False)
  63. # ----------------------------------------------------------------------------------------------------
  64. # Connect actions to functions
  65. self.ui.b_play.clicked.connect(self.slot_transportPlayPause)
  66. self.ui.b_stop.clicked.connect(self.slot_transportStop)
  67. self.ui.b_backwards.clicked.connect(self.slot_transportBackwards)
  68. self.ui.b_forwards.clicked.connect(self.slot_transportForwards)
  69. self.ui.cb_transport_jack.clicked.connect(self.slot_transportJackEnabled)
  70. self.ui.cb_transport_link.clicked.connect(self.slot_transportLinkEnabled)
  71. host.EngineStartedCallback.connect(self.slot_handleEngineStartedCallback)
  72. host.SampleRateChangedCallback.connect(self.slot_handleSampleRateChangedCallback)
  73. # --------------------------------------------------------------------------------------------------------
  74. # Button actions
  75. @pyqtSlot(bool)
  76. def slot_transportPlayPause(self, toggled):
  77. if self.host.isPlugin or not self.host.is_engine_running():
  78. return
  79. if toggled:
  80. self.host.transport_play()
  81. else:
  82. self.host.transport_pause()
  83. self.refreshTransport()
  84. @pyqtSlot()
  85. def slot_transportStop(self):
  86. if self.host.isPlugin or not self.host.is_engine_running():
  87. return
  88. self.host.transport_pause()
  89. self.host.transport_relocate(0)
  90. self.refreshTransport()
  91. @pyqtSlot()
  92. def slot_transportBackwards(self):
  93. if self.host.isPlugin or not self.host.is_engine_running():
  94. return
  95. newFrame = self.host.get_current_transport_frame() - 100000
  96. if newFrame < 0:
  97. newFrame = 0
  98. self.host.transport_relocate(newFrame)
  99. @pyqtSlot()
  100. def slot_transportForwards(self):
  101. if self.fSampleRate == 0.0 or self.host.isPlugin or not self.host.is_engine_running():
  102. return
  103. newFrame = self.host.get_current_transport_frame() + int(self.fSampleRate*2.5)
  104. self.host.transport_relocate(newFrame)
  105. @pyqtSlot(bool)
  106. def slot_transportJackEnabled(self, clicked):
  107. if not self.host.is_engine_running():
  108. return
  109. mode = ENGINE_TRANSPORT_MODE_JACK if clicked else ENGINE_TRANSPORT_MODE_INTERNAL
  110. extra = ":link:" if self.ui.cb_transport_link.isChecked() else ""
  111. self.host.set_engine_option(ENGINE_OPTION_TRANSPORT_MODE, mode, extra)
  112. @pyqtSlot(bool)
  113. def slot_transportLinkEnabled(self, clicked):
  114. if not self.host.is_engine_running():
  115. return
  116. mode = ENGINE_TRANSPORT_MODE_JACK if self.ui.cb_transport_jack.isChecked() else ENGINE_TRANSPORT_MODE_INTERNAL
  117. extra = ":link:" if clicked else ""
  118. self.host.set_engine_option(ENGINE_OPTION_TRANSPORT_MODE, mode, extra)
  119. def showEvent(self, event):
  120. self.refreshTransport(True)
  121. QDialog.showEvent(self, event)
  122. def refreshTransport(self, forced = False):
  123. if not self.isVisible():
  124. return
  125. if self.fSampleRate == 0.0 or not self.host.is_engine_running():
  126. return
  127. timeInfo = self.host.get_transport_info()
  128. playing = timeInfo['playing']
  129. frame = timeInfo['frame']
  130. bpm = timeInfo['bpm']
  131. if playing != self.fLastTransportState or forced:
  132. if playing:
  133. icon = getIcon("media-playback-pause")
  134. self.ui.b_play.setChecked(True)
  135. self.ui.b_play.setIcon(icon)
  136. #self.ui.b_play.setText(self.tr("&Pause"))
  137. else:
  138. icon = getIcon("media-playback-start")
  139. self.ui.b_play.setChecked(False)
  140. self.ui.b_play.setIcon(icon)
  141. #self.ui.b_play.setText(self.tr("&Play"))
  142. self.fLastTransportState = playing
  143. if frame != self.fLastTransportFrame or forced:
  144. self.fLastTransportFrame = frame
  145. time = frame / self.fSampleRate
  146. secs = time % 60
  147. mins = (time / 60) % 60
  148. hrs = (time / 3600) % 60
  149. self.ui.l_time_clock.setText("%02i:%02i:%02i" % (hrs, mins, secs))
  150. frame1 = frame % 1000
  151. frame2 = (frame / 1000) % 1000
  152. frame3 = (frame / 1000000) % 1000
  153. self.ui.l_time_frame.setText("%03i'%03i'%03i" % (frame3, frame2, frame1))
  154. bar = timeInfo['bar']
  155. beat = timeInfo['beat']
  156. tick = timeInfo['tick']
  157. self.ui.l_time_bbt.setText("%03i|%02i|%04i" % (bar, beat, tick))
  158. if bpm != self.fLastTransportBPM or forced:
  159. self.fLastTransportBPM = bpm
  160. if bpm > 0.0:
  161. self.ui.dsb_bpm.setValue(bpm)
  162. self.ui.dsb_bpm.setStyleSheet("")
  163. else:
  164. self.ui.dsb_bpm.setStyleSheet("QDoubleSpinBox { color: palette(mid); }")
  165. # --------------------------------------------------------------------------------------------------------
  166. # Engine callbacks
  167. @pyqtSlot(int, int, str)
  168. def slot_handleEngineStartedCallback(self, processMode, transportMode, driverName):
  169. self.fSampleRate = self.host.get_sample_rate()
  170. self.refreshTransport(True)
  171. self.ui.cb_transport_jack.setEnabled(driverName == "JACK")
  172. self.ui.cb_transport_jack.setChecked(transportMode == ENGINE_TRANSPORT_MODE_JACK)
  173. @pyqtSlot(float)
  174. def slot_handleSampleRateChangedCallback(self, newSampleRate):
  175. self.fSampleRate = newSampleRate
  176. self.refreshTransport(True)
  177. # ------------------------------------------------------------------------------------------------------------