Collection of tools useful for audio production
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.

164 lines
5.2KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Simple JACK Audio Meter
  4. # Copyright (C) 2012 Filipe Coelho <falktx@gmail.com>
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # 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 COPYING file
  17. # Imports (Global)
  18. from PyQt4.QtCore import Qt
  19. from PyQt4.QtGui import QApplication, QWidget
  20. # Imports (Custom Stuff)
  21. from digitalpeakmeter import DigitalPeakMeter
  22. from jacklib_helpers import *
  23. from shared import *
  24. global x_port1, x_port2, need_reconnect
  25. x_port1 = 0.0
  26. x_port2 = 0.0
  27. need_reconnect = False
  28. client = None
  29. port_1 = None
  30. port_2 = None
  31. def process_callback(nframes, arg):
  32. global x_port1, x_port2
  33. p_out1 = translate_audio_port_buffer(jacklib.port_get_buffer(port_1, nframes))
  34. p_out2 = translate_audio_port_buffer(jacklib.port_get_buffer(port_2, nframes))
  35. for i in range(nframes):
  36. if (abs(p_out1[i]) > x_port1):
  37. x_port1 = abs(p_out1[i])
  38. if (abs(p_out2[i]) > x_port2):
  39. x_port2 = abs(p_out2[i])
  40. return 0
  41. def port_callback(port_a, port_b, connect_yesno, arg):
  42. global need_reconnect
  43. need_reconnect = True
  44. return 0
  45. def session_callback(event, arg):
  46. if (WINDOWS):
  47. filepath = os.path.join(sys.argv[0])
  48. else:
  49. if (sys.argv[0].startswith("/")):
  50. filepath = "jack_meter"
  51. else:
  52. filepath = os.path.join(sys.path[0], "jackmeter.py")
  53. event.command_line = str(filepath).encode("ascii")
  54. jacklib.session_reply(client, event)
  55. if (event.type == jacklib.JackSessionSaveAndQuit):
  56. app.quit()
  57. #jacklib.session_event_free(event)
  58. def reconnect_inputs():
  59. play_port_1 = jacklib.port_by_name(client, "system:playback_1")
  60. play_port_2 = jacklib.port_by_name(client, "system:playback_2")
  61. list_port_1 = c_char_p_p_to_list(jacklib.port_get_all_connections(client, play_port_1))
  62. list_port_2 = c_char_p_p_to_list(jacklib.port_get_all_connections(client, play_port_2))
  63. client_name = str(jacklib.get_client_name(client), encoding="ascii")
  64. for port in list_port_1:
  65. this_port = jacklib.port_by_name(client, port)
  66. if (bool(jacklib.port_is_mine(client, this_port)) == False and bool(jacklib.port_connected_to(port_1, port)) == False):
  67. jacklib.connect(client, port, "%s:in1" % (client_name))
  68. for port in list_port_2:
  69. this_port = jacklib.port_by_name(client, port)
  70. if (bool(jacklib.port_is_mine(client, this_port)) == False and bool(jacklib.port_connected_to(port_2, port)) == False):
  71. jacklib.connect(client, port, "%s:in2" % (client_name))
  72. global need_reconnect
  73. need_reconnect = False
  74. class MeterW(DigitalPeakMeter):
  75. def __init__(self, parent=None):
  76. DigitalPeakMeter.__init__(self, parent)
  77. client_name = str(jacklib.get_client_name(client), encoding="ascii")
  78. self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint);
  79. self.setWindowTitle(client_name)
  80. self.setChannels(2)
  81. self.setOrientation(self.VERTICAL)
  82. self.setSmoothRelease(1)
  83. self.displayMeter(1, 0.0)
  84. self.displayMeter(2, 0.0)
  85. refresh = float(jacklib.get_buffer_size(client))/jacklib.get_sample_rate(client)*1000
  86. self.setRefreshRate(refresh if (refresh > 25) else 25)
  87. self.m_peakTimerId = self.startTimer(refresh if (refresh > 50) else 50)
  88. def timerEvent(self, event):
  89. if (event.timerId() == self.m_peakTimerId):
  90. global x_port1, x_port2, need_reconnect
  91. self.displayMeter(1, x_port1)
  92. self.displayMeter(2, x_port2)
  93. x_port1 = 0.0
  94. x_port2 = 0.0
  95. if (need_reconnect):
  96. reconnect_inputs()
  97. QWidget.timerEvent(self, event)
  98. #--------------- main ------------------
  99. if __name__ == '__main__':
  100. # App initialization
  101. app = QApplication(sys.argv)
  102. # JACK initialization
  103. jack_status = jacklib.jack_status_t(0)
  104. client = jacklib.client_open_uuid("M", jacklib.JackSessionID, jacklib.pointer(jack_status), "")
  105. if not client:
  106. QMessageBox.critical(None, app.translate("XYControllerW", "Error"), app.translate("XYControllerW", "Could not connect to JACK, possible errors:\n%s" % (get_jack_status_error_string(jack_status))))
  107. sys.exit(1)
  108. port_1 = jacklib.port_register(client, "in1", jacklib.JACK_DEFAULT_AUDIO_TYPE, jacklib.JackPortIsInput, 0)
  109. port_2 = jacklib.port_register(client, "in2", jacklib.JACK_DEFAULT_AUDIO_TYPE, jacklib.JackPortIsInput, 0)
  110. jacklib.set_process_callback(client, process_callback, None)
  111. jacklib.set_port_connect_callback(client, port_callback, None)
  112. jacklib.set_session_callback(client, session_callback, None)
  113. jacklib.activate(client)
  114. reconnect_inputs()
  115. # Show GUI
  116. gui = MeterW()
  117. gui.resize(70, 600)
  118. gui.show()
  119. set_up_signals(gui)
  120. # App-Loop
  121. ret = app.exec_()
  122. jacklib.deactivate(client)
  123. jacklib.client_close(client)
  124. sys.exit(ret)