qjackctl-1.0.4/PaxHeaders/CMakeLists.txt0000644000000000000000000000013214771215054015134 xustar0030 mtime=1743067692.317443163 30 atime=1743067692.317443163 30 ctime=1743067692.317443163 qjackctl-1.0.4/CMakeLists.txt0000644000175000001440000002607514771215054015136 0ustar00rncbcuserscmake_minimum_required (VERSION 3.15) project (QjackCtl VERSION 1.0.4 DESCRIPTION "JACK Audio Connection Kit - Qt GUI Interface" HOMEPAGE_URL "https://qjackctl.sourceforge.io" LANGUAGES C CXX) set (PROJECT_TITLE "${PROJECT_NAME}") string (TOLOWER "${PROJECT_TITLE}" PROJECT_NAME) set (PROJECT_COPYRIGHT "Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved.") set (PROJECT_DOMAIN "rncbc.org") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") execute_process ( COMMAND git describe --tags --dirty --abbrev=6 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_DESCRIBE_OUTPUT RESULT_VARIABLE GIT_DESCRIBE_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE) if (GIT_DESCRIBE_RESULT EQUAL 0) set (GIT_VERSION "${GIT_DESCRIBE_OUTPUT}") string (REGEX REPLACE "^[^0-9]+" "" GIT_VERSION "${GIT_VERSION}") string (REGEX REPLACE "-g" "git." GIT_VERSION "${GIT_VERSION}") string (REGEX REPLACE "[_|-]" "." GIT_VERSION "${GIT_VERSION}") execute_process ( COMMAND git rev-parse --abbrev-ref HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_REVPARSE_OUTPUT RESULT_VARIABLE GIT_REVPARSE_RESULT OUTPUT_STRIP_TRAILING_WHITESPACE) if (GIT_REVPARSE_RESULT EQUAL 0 AND NOT GIT_REVPARSE_OUTPUT STREQUAL "main") set (GIT_VERSION "${GIT_VERSION} [${GIT_REVPARSE_OUTPUT}]") endif () set (PROJECT_VERSION "${GIT_VERSION}") endif () if (CMAKE_BUILD_TYPE MATCHES "Debug") set (CONFIG_DEBUG 1) set (CONFIG_BUILD_TYPE "debug") else () set (CONFIG_DEBUG 0) set (CONFIG_BUILD_TYPE "release") set (CMAKE_BUILD_TYPE "Release") endif () set (CONFIG_PREFIX "${CMAKE_INSTALL_PREFIX}") include (GNUInstallDirs) set (CONFIG_BINDIR "${CONFIG_PREFIX}/${CMAKE_INSTALL_BINDIR}") set (CONFIG_LIBDIR "${CONFIG_PREFIX}/${CMAKE_INSTALL_LIBDIR}") set (CONFIG_DATADIR "${CONFIG_PREFIX}/${CMAKE_INSTALL_DATADIR}") set (CONFIG_MANDIR "${CONFIG_PREFIX}/${CMAKE_INSTALL_MANDIR}") # Disable system tray argument option. option (CONFIG_SYSTEM_TRAY "Enable system tray (default=yes)" 1) # Enable JACK session support. option (CONFIG_JACK_SESSION "Enable JACK session support (default=yes)" 1) # Enable JACK port aliases support. option (CONFIG_JACK_PORT_ALIASES "Enable JACK port aliases support (default=yes)" 1) # Enable JACK metadata support. option (CONFIG_JACK_METADATA "Enable JACK metadata support (default=yes)" 1) # Enable JACK MIDI support option. option (CONFIG_JACK_MIDI "Enable JACK MIDI support (default=yes)" 1) # Enable JACK CV support option. option (CONFIG_JACK_CV "Enable JACK CV support (default=yes)" 1) # Enable JACK OSC support option. option (CONFIG_JACK_OSC "Enable JACK OSC support (default=yes)" 1) # Enable JACK version support. option (CONFIG_JACK_VERSION "Enable JACK version support (default=no)" 0) # Enable ALSA sequencer support option. option (CONFIG_ALSA_SEQ "Enable ALSA/MIDI sequencer support (default=yes)" 1) # Enable PortAudio argument option. option (CONFIG_PORTAUDIO "Enable PortAudio interface (default=yes)" 1) # Enable CoreAudio argument option. option (CONFIG_COREAUDIO "Enable CoreAudio interface (default=yes)" 1) # Enable D-Bus argument option. option (CONFIG_DBUS "Enable D-Bus interface (default=yes)" 1) # Enable unique/single instance. option (CONFIG_XUNIQUE "Enable unique/single instance (default=yes)" 1) # Enable debugger stack-trace option (assumes --enable-debug). option (CONFIG_STACKTRACE "Enable debugger stack-trace (default=no)" 0) # Enable Wayland support option. option (CONFIG_WAYLAND "Enable Wayland support (EXPERIMENTAL) (default=no)" 0) # Enable Qt6 build preference. option (CONFIG_QT6 "Enable Qt6 build (default=yes)" 1) # Enable install QT DLLs for Windows targets using windeployqt. option (CONFIG_INSTALL_QT "Install Qt for MacOS and Windows targets (default=no)" 0) # Fix for new CMAKE_REQUIRED_LIBRARIES policy. if (POLICY CMP0075) cmake_policy (SET CMP0075 NEW) endif () # Check for Qt... if (CONFIG_QT6) find_package (Qt6 QUIET) if (NOT Qt6_FOUND) set (CONFIG_QT6 0) endif () endif () if (CONFIG_QT6) find_package (QT QUIET NAMES Qt6) else () find_package (QT QUIET NAMES Qt5) endif () find_package (Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui Widgets Xml Svg) if (CONFIG_XUNIQUE) find_package (Qt${QT_VERSION_MAJOR} COMPONENTS Network) if (NOT Qt${QT_VERSION_MAJOR}Network_FOUND) message (WARNING "*** QT Network library not found.") set (CONFIG_XUNIQUE 0) endif () endif () if (CONFIG_DBUS) find_package (Qt${QT_VERSION_MAJOR} COMPONENTS DBus) if (NOT Qt${QT_VERSION_MAJOR}DBus_FOUND) message (WARNING "*** QT DBus library not found.") set (CONFIG_DBUS 0) endif () endif () find_package (Qt${QT_VERSION_MAJOR}LinguistTools) include (CheckIncludeFile) include (CheckIncludeFiles) include (CheckIncludeFileCXX) include (CheckLibraryExists) include (CheckSymbolExists) # Checks for header files. if (UNIX AND NOT APPLE) check_include_files ("fcntl.h;unistd.h;signal.h" HAVE_SIGNAL_H) endif () # Find package modules include (FindPkgConfig) pkg_check_modules (JACK IMPORTED_TARGET jack>=0.100.0) if (JACK_FOUND) find_library (JACK_LIBRARY NAMES ${JACK_LIBRARIES} HINTS ${JACK_LIBDIR}) if (JACK_LIBRARY) set (CONFIG_JACK 1) set (CMAKE_REQUIRED_LIBRARIES "${JACK_LIBRARIES};${CMAKE_REQUIRED_LIBRARIES}") set (CMAKE_REQUIRED_INCLUDES "${JACK_INCLUDE_DIRS};${CMAKE_REQUIRED_INCLUDES}") else () message (FATAL_ERROR "*** JACK library not found.") set (CONFIG_JACK 0) endif () else () message (FATAL_ERROR "*** JACK package not found.") set (CONFIG_JACK 0) endif () # Check for jack/statistics.h header. check_include_file (jack/statistics.h HAVE_JACK_STATISTICS_H) if (NOT HAVE_JACK_STATISTICS_H) set (CONFIG_JACK_STATISTICS 0) else () set (CONFIG_JACK_STATISTICS 1) endif () # Check for JACK MIDI headers availability. if (CONFIG_JACK_MIDI) check_include_file (jack/midiport.h HAVE_JACK_MIDIPORT_H) if (NOT HAVE_JACK_MIDIPORT_H) set (CONFIG_JACK_MIDI 0) endif () endif () # Check for JACK session headers availability. if (CONFIG_JACK_SESSION) check_include_file (jack/session.h HAVE_JACK_SESSION_H) if (NOT HAVE_JACK_SESSION_H) set (CONFIG_JACK_SESSION 0) endif () endif () # Check for JACK metadata headers availability. if (CONFIG_JACK_METADATA) check_include_file (jack/metadata.h HAVE_JACK_METADATA_H) if (NOT HAVE_JACK_METADATA_H) set (CONFIG_JACK_METADATA 0) endif () endif () if (NOT CONFIG_JACK_METADATA) set (CONFIG_JACK_CV 0) set (CONFIG_JACK_OSC 0) endif () # Check for jack_is_realtime function. check_symbol_exists (jack_is_realtime "jack/jack.h" CONFIG_JACK_REALTIME) # Check for jack_free function. check_symbol_exists (jack_free "jack/jack.h" CONFIG_JACK_FREE) # Check for jack_set_port_rename_callback check_symbol_exists (jack_set_port_rename_callback "jack/jack.h" CONFIG_JACK_PORT_RENAME) # Check for jack_transport_query function. check_symbol_exists (jack_transport_query "jack/transport.h" CONFIG_JACK_TRANSPORT) # Check for jack_get_xrun_delayed_usecs function. check_symbol_exists (jack_get_xrun_delayed_usecs "jack/statistics.h" CONFIG_JACK_XRUN_DELAY) # Check for jack_get_max_delayed_usecs function. check_symbol_exists (jack_get_max_delayed_usecs "jack/statistics.h" CONFIG_JACK_MAX_DELAY) # Check for jack_port_get_aliases function. if (CONFIG_JACK_PORT_ALIASES) check_symbol_exists (jack_port_get_aliases "jack/jack.h" HAVE_JACK_PORT_ALIASES) if (NOT HAVE_JACK_PORT_ALIASES) set (CONFIG_JACK_PORT_ALIASES 0) endif () endif () # Check for jack_get_version_string function. if (CONFIG_JACK_VERSION) check_symbol_exists (jack_get_version_string "jack/jack.h" HAVE_JACK_VERSION) if (NOT HAVE_JACK_VERSION) set (CONFIG_JACK_VERSION 0) endif () endif () # Check for ALSA libraries. if (CONFIG_ALSA_SEQ) find_package (ALSA) if (ALSA_FOUND) set (CONFIG_ALSA_SEQ 1) set (CMAKE_REQUIRED_LIBRARIES "${ALSA_LIBRARIES};${CMAKE_REQUIRED_LIBRARIES}") set (CMAKE_REQUIRED_INCLUDES "${ALSA_INCLUDE_DIRS};${CMAKE_REQUIRED_INCLUDES}") else () message (WARNING "*** ALSA library not found.") set (CONFIG_ALSA_SEQ 0) endif () endif () # Check for PORTAUDIO libraries. if (CONFIG_PORTAUDIO) find_package (PortAudio) if (PortAudio_FOUND) set (CONFIG_PORTAUDIO 1) #set (CMAKE_REQUIRED_LIBRARIES "${PORTAUDIO_LIBRARY};${CMAKE_REQUIRED_LIBRARIES}") else () message (WARNING "*** PORTAUDIO library not found.") set (CONFIG_PORTAUDIO 0) endif () endif () if (CONFIG_COREAUDIO) if (APPLE) check_include_file ("CoreAudio/CoreAudio.h" HAVE_COREAUDIO_H) find_library(CORE_FOUNDATION_LIBRARY CoreFoundation) find_library(CORE_AUDIO_LIBRARY CoreAudio) endif () if (NOT APPLE OR NOT HAVE_COREAUDIO_H OR NOT CORE_FOUNDATION_LIBRARY OR NOT CORE_AUDIO_LIBRARY) set (CONFIG_COREAUDIO 0) endif () endif () add_subdirectory (src) # Finally check whether Qt is statically linked. if (QT_FEATURE_static) set(QT_VERSION "${QT_VERSION}-static") endif () # Configuration status macro (SHOW_OPTION text value) if (${value}) message ("${text}: yes") else () message ("${text}: no") endif () endmacro () message ("\n ${PROJECT_TITLE} ${PROJECT_VERSION} (Qt ${QT_VERSION})") message ("\n Build target . . . . . . . . . . . . . . . . . . .: ${CONFIG_BUILD_TYPE}\n") show_option (" JACK Audio Connection Kit support . . . . . . . ." CONFIG_JACK) show_option (" JACK Realtime support . . . . . . . . . . . . . ." CONFIG_JACK_REALTIME) show_option (" JACK Transport support . . . . . . . . . . . . . ." CONFIG_JACK_TRANSPORT) show_option (" JACK XRUN delay support . . . . . . . . . . . . ." CONFIG_JACK_XRUN_DELAY) show_option (" JACK Maximum scheduling delay support . . . . . ." CONFIG_JACK_MAX_DELAY) show_option (" JACK Port aliases support . . . . . . . . . . . ." CONFIG_JACK_PORT_ALIASES) show_option (" JACK Metadata support . . . . . . . . . . . . . ." CONFIG_JACK_METADATA) show_option (" JACK MIDI support . . . . . . . . . . . . . . . ." CONFIG_JACK_MIDI) show_option (" JACK CV support . . . . . . . . . . . . . . . . ." CONFIG_JACK_CV) show_option (" JACK OSC support . . . . . . . . . . . . . . . . ." CONFIG_JACK_OSC) show_option (" JACK Session support . . . . . . . . . . . . . . ." CONFIG_JACK_SESSION) show_option (" JACK Version support (JACK2) . . . . . . . . . . ." CONFIG_JACK_VERSION) show_option (" ALSA MIDI Sequencer support . . . . . . . . . . ." CONFIG_ALSA_SEQ) show_option (" System tray icon support . . . . . . . . . . . . ." CONFIG_SYSTEM_TRAY) show_option (" D-Bus interface support . . . . . . . . . . . . ." CONFIG_DBUS) show_option (" PortAudio interface support . . . . . . . . . . ." CONFIG_PORTAUDIO) show_option (" CoreAudio interface support . . . . . . . . . . ." CONFIG_COREAUDIO) message ("") show_option (" System tray icon support . . . . . . . . . . . . ." CONFIG_SYSTEM_TRAY) show_option (" Unique/Single instance support . . . . . . . . . ." CONFIG_XUNIQUE) show_option (" Debugger stack-trace (gdb) . . . . . . . . . . . ." CONFIG_STACKTRACE) show_option (" Install Qt on MacOS / Windows . . . . . . . . . ." CONFIG_INSTALL_QT) message ("\n Install prefix . . . . . . . . . . . . . . . . . .: ${CONFIG_PREFIX}\n") qjackctl-1.0.4/PaxHeaders/ChangeLog0000644000000000000000000000013214771215054014146 xustar0030 mtime=1743067692.317443163 30 atime=1743067692.317443163 30 ctime=1743067692.317443163 qjackctl-1.0.4/ChangeLog0000644000175000001440000021577214771215054014154 0ustar00rncbcusersQjackCtl - JACK Audio Connection Kit Qt GUI Interface ----------------------------------------------------- ChangeLog 1.0.4 2025-03-27 An Early Spring'25 Release. - Fixed command line parsing (QCommandLineParser/Option) to not exiting the application with a segfault when showing help and version information. - Graph: force an actual complete refresh on main View/Refresh..., especially when changing the color theme palette on-the-fly. 1.0.3 2024-10-29 An Autumn'24 Release. - Long missing D-Bus method slot added: "reset" (dbus-send --system / org.rncbc.qjackctl.reset). - Graph: Node reference positioning changed to the top-left corner, improving the base snapping-to-grid perception. - Prepping up next development cycle (Qt >= 6.8) 1.0.2 2024-09-17 An End-of-Summer'24 Release. - Graph: when visible the thumb-view may now be drag-moved over to a different corner position anytime. - Session: introducing new Save session name/directory dialog. - Connections: connector line colors are now uniquely mapped on a (readable/output) client name basis. 1.0.1 2024-08-01 A Summer'24 Release. - Graph: thumb-view repositions and resizes immediately when visible. - Graph: Implement patchbay node search functionality: adds a floating text-entry field, which appears when typing in the canvas, selecting nodes that contains the typed text (maybe regular expression). - Graph: fixed a potential use-after-free issue on canvas nodes refresh and recycle. 1.0.0 2024-06-19 An Unthinkable Release. - Making up the unthinkable (aka. v1.0.0) - Cancel button option added to close to system-tray icon message. - Graph: Introducing thumbview context-menu. 0.9.91 2024-05-01 A Spring'24 Release Candidate 2. - Prepping the unthinkable (aka. v1.0.0-rc2) - Graph: Introducing the View/Thumbview option as a whole graph thumbnail overview helper. - Updated to latest framework level (Qt >= 6.7) 0.9.90 2024-04-10 A Spring'24 Release Candidate. - Prepping the unthinkable (aka. v1.0.0-rc1) - Custom color themes are now file based (*.conf); legacy still preserved ntl. - Old generic "Portuguese" translation (pt) has been corrected to the more proper "Portuguese (Brazil)" locale (pt_BR). - Simplified and shortened the main window title. 0.9.13 2024-01-24 A Winter'24 Release. - Graph: Make the main canvas background to mid-gray, when on non-dark color themes. - Turkish (tr) translation added. - Updated copyright headers into the New Year (2024). 0.9.12 2023-09-09 An End-of-Summer'23 Release. - Setup: disable Settings parameters altogether, except frames/period (aka. buffer-size) if running in the so called 'Active' pure-client mode (eg. under PipeWire's pw-jack substitution). - Connections: Fixed an old JACK client/ports aliases malfunction, hopefully. - Graph: Ctrl+left or middle-button click-dragging for panning, is now a lot smoother, hopefully. - Graph: Click-dragging with the mouse middle-button is now used for panning only, not to start a selection anymore. - Preppings to next development cycle (Qt >= 6.6) 0.9.11 2023-06-01 A Spring'23 Release. - Graph: Soft incremental bounds constraints now imposed to all new and old nodes positioning. - Prepping into the next development cycle (with Qt >= 6.5). 0.9.10 2023-03-23 An Early-Spring'23 Release. - Setup: revert to previous settings when dismissing the dialog. - Graph: Attempt to make port labels as short as possible. - Graph: introducing touch pinch-gesture for zooming. 0.9.9 2022-12-28 An End-of-Year'22 Release. - Graph: whether to draw connectors through or around nodes is a new user preference option (cf. View > Connect Through Nodes). - Graph: Allow middle mouse button for grabbing and dragging the main canvas. - Make up visual immediate feedback connectlons. 0.9.8 2022-10-03 An Early-Autumn'22 release. - Graph: View / Repel Overlapping Nodes option added. - Avoid nagging on D-BUS error messsage windows (or bubbles) when trying to start in pure JACK client mode (Active). - Add current system user-name to the singleton/unique application instance identifier. - Graph/Connect and Disconnect keyboard shortcuts added to existing [Ins] and [Del], as [Ctrl+C] and [Ctrl+D] respectively; also added [F2] as brand new keyboard shortcut for Edit/Rename... 0.9.7 2022-04-02 A Spring'22 Release. - Main application icon is now presented in scalable format (SVG). - Migrated command line parsing to QCommandLineParser/Option (Qt >= 5.2) - Fixed translations path to be relative to application runtime. 0.9.6 2022-01-09 A Winter'22 Release. - Dropped autotools (autoconf, automake, etc.) build system. - Limit or mitigate fast auto-scrolling when moving Graph client nodes off the viewport. - Whenever possible, adopt the previous named default preset, when starting the JACK-server on premises. - Conditional fix to MacOSX and FreeBSD builds. 0.9.5 2021-10-05 An Autumn'21 Release. - Streamlined Windows and MacOSX deliverables (by Alexis Murzeau). - Korean (ko) translation added (by JungHee Lee). 0.9.4 2021-07-04 An Early-Summer'21 Release. - All builds default to Qt6 (Qt >= 6.1) where available. - CMake is now the official build system. 0.9.3 2021-05-11 A Spring'21 Release. - Graph connection lines drop-shadow eye-candy has been optimized, improving a lot on moving highly-connected nodes, especially the ones with plenty of backward-curved connections. - All packaging builds switching to CMake. - Fixed default preset/aliases switching and reloading when entering pure-client mode (ie. "Active" status). 0.9.2 2021-03-14 An End-of-Winter'21 Release. - Clock source, Self-connect mode and Server synchronous mode options are now always enabled on the Setup / Settings dialog, although only available or effective to jackd2. - Graph Disconnect now applies to selected connections or nodes only. 0.9.1 2021-02-07 A Winter'21 Release. - Graph Disconnect now applies to all selected ports and connections. - Main window is now freely resizable, while keeping all the buttons stretched to the same aspect ratio. - Warning to confirm application close is now back in business when functioning as client only (Active). - Graph items are automatically raised when created or high-lighted (incremental z-value). - Add a little but straight horizontal line-gap to the Graph connections. - Customize the Graph zoom slider widget to reset upon mouse middle-button click. - Add Clear preset button to Setup dialog. - Use default values for most preset parameters: sample rate, frames/period (aka. buffer-size), periods/buffer, realtime priority, port maximum, client timeout, word length, wait time, channel maximum. - Early preparations for the New Year develop(ment) cycle. 0.9.0 2020-12-17 A Winter'20 Release. - List only available backend drivers when JACK D-BUS is enabled. - Graph client-name / node-title aliases persistence have been hopefully fixed. - Get rid of those "JACK has crashed" red-herrings from latest Windows(tm) builds. - Early fixing to build for Qt >= 6.0.0 and comply with C++17 standard. 0.6.3 2020-07-31 A Summer'20 Release. - Clock source and Self connect restriction options have been added to Setup / Settings / Advanced (only enabled when JACK D-BUS control interface is in effect). - Added preliminary support for JACK CV signal-type ports and JACK OSC event-type ports (Graph only). - Left-clicking on the system-tray icon now simply toggles the main widget visibility, disregarding if already hidden undercover to other windows. - Graph nodes and ports are now presented with some gradient background. - Fixed Setup dialog Cancel (or close) behavior when Settings > Parameters > Frames/Period (aka. buffer- size) it's the only setting that's changed. - Early fixing to build for Qt >= 5.15.0. 0.6.2 2020-03-24 A Spring'20 Release. - A scalable (.svg) icon version has been added. - Make man page compression reproducible (after request by Jelle van der Waa, while on the Vee-Ones, thanks). - Ditching deprecated QTime methods for QElapsedTimer's (in compliance to Qt >= 5.14.0). - Bumped copyright headers into the New Year (2020). 0.6.1 2019-12-22 The Winter'19 Release. - Custom color (palette) theme editor introduced; color (palette) theme changes are now effective immediately, except on default. - Second attempt to fix the yet non-official though CMake build configuration. - When using autotools and ./configure --with-qt=..., it is also necessary to adjust the PKG_CONFIG_PATH environment variable (after a merge request by plcl aka. Pedro López-Cabanillas, while on qmidinet, thanks). 0.6.0 2019-10-17 An Autumn'19 Release. - Graph: avoid self-connecting over their own ports when client nodes are selected as a whole group; also try to match port-types in a oderly fashion when connecting multiple selected ports. - Changing current JACK buffer size from Setup dialog (cf. Settings /Frames/Period) may now take effect just immediately ;) - An 'Apply' button as been added to the Setup dialog; ask whether to restart the JACK audio server, if any settings are changed. - Added alternate yet non-official CMake build option. - Fix HiDPI display screen effective support (Qt >= 5.6). - Command line arguments (--start, --preset=[label] and --active -patchbay=[path]) are passed and take effect on the current singleton/unique application instance, when enabled and already running. - System-tray icon context menu has been refactored to be exactly the same as the main-window context menu that is re-instantiated on demand. - Make sure compiler flags comply to c++11 as standard. 0.5.9 2019-07-12 A Summer'19 Release. - Updated for the newer Qt5 translation tools (>= 5.13). - Configure updated to check for qtchooser availability. 0.5.8 2019-05-25 A Spring'19 Release. - When enabled the current default preset settings are now read from the last known JACK D-BUS configuration. - Minor update to Debian packaging control file. - Removed all the remaining leftovers of old pre-FFADO 'freebob' driver support. 0.5.7 2019-03-11 A Spring-Break'19 Release. - Graph node and port title renaming and nodes position move changes are now undo/redo-able. - Graph client and port title in-place renaming is now integrated to native aliases and JACK metadata (aka. pretty-names). - Refactored all native client/port name aliases. - Re-defined all main application UNIX signal handling. 0.5.6 2019-03-11 Pre-LAC2019 Release Frenzy. - Refactored all singleton/unique application instance setup logic away from X11/Xcb hackery. - At last, JACK freewheel mode is now being detected as to postpone any active patchbay scans as much as possible. - Removed old pre-FFADO 'freebob' driver support. - HiDPI display screen support (Qt >= 5.6). - Graph port temporary highlighting while hovering, if and only if connecting ports of same type and complementary modes. - Bumped copyright headers into the New Year (2019). 0.5.5 2018-11-23 A Black-Friday'18 Release! - Old deprecated Qt4 build support is no more. - Graph port sort options added as View / Sort menu. - System tray options now subject to current desktop environment availability. - Also disable Setup / Misc / Other / Save JACK server configuration to (.jackdrc) when JACK D-Bus interface is enabled. - Whether to use server synchronous mode option added to Setup / Settings / Parameters (only applied when JACK D-BUS interface is enabled). - Disable some Setup / Settings / Advanced parameters when JACK D-Bus interface is enabled and vice-versa. - Attempt to power-cycle JACK D-Bus service on demand; - Marked as probably useless anyway, old "H/W Monitor" option (-H) is now being ditched from Setup / Settings / Advanced tab. - Graph port/connections highlighting. 0.5.4 2018-09-24 An Early Autumn'18 Release. - Graph port-type colors are now configurable (cf. menu View > Colors. - Make Graph nodes (ie. client boxes) transparent for yet some eye-candiness ;). Also keep the (Graph) current selection across port (dis)connections. - Drawing patchbay connector lines as (bezier) curves is now a difinitive and fixed feature (as long as no more remains from the so called "Cambric explosion era" are still lurking in there). - AppStream metadata updated to be the most compliant with latest freedesktop.org specification and recommendation. - Graph auto-layout improvement for brand new node clients. - Avoid showing setup warning when no server settings have changed. - Fixed JACK D-Bus settings for MIDI driver parameter. 0.5.3 2018-07-22 A Summer'18 Release. - Portuguese (pt) translation added (by Heitor Rocha). - AppData/AppStream metadata is now settled under an all permisssive license (FSFAP). - Improved Graph rubberband add (Shift) and toggle (Ctrl) multiple (de)selections. - Added user preference option: Setup / Misc / Buttons / Replace Connections with Graph button (on main window). - Added a zoom slider control to the Graph view status bar. 0.5.2 2018-05-27 Pre-LAC2018 release frenzy hotfix. - Respect ALSA Sequencer support option also on Graph view. - Regression to new Graph node/ports sorting comparator; also fixed multiple and many port removals, most probably causing it to crash due to double-free/delete potential. - Fixed the automatic aggregation of new Graph client nodes that are split as either input or output only (ie. system, terminal, physical or otherwise non-duplex nodes). - Added View/Zoom Range mode option to Graph tool. 0.5.1 2018-05-21 Pre-LAC2018 release frenzy. - Half a decade later, recent new custom entries may now get removed from Session Infra-client list. - Some rather old, better said "Cambric explosion era", user preference options have been ditched altogether: Display / Time Format; Display / Shiny glass light effect; Display / Connections/Draw connections and patchbay lines as Bezier curves; Misc/Configure as temporary server. - A brand new and way long overdue connections Graph widget is finally introduced, only to be accessible through the context menu at this time. - Extended multi-selection is now supported on all Connections client/port lists, allowing for multiple (dis)connections at once. - Disable singleton/unique application instance setup logic when the display server platform is not X11. - A little hardening on the configure (autoconf) macro side. 0.5.0 2017-12-16 End of Autum'17 release. - Current preset is always taken into account if ever changes while the Setup dialog is hidden (eg. via context menu). - Desktop entry specification file is now finally independent from build/configure template chains. - Updated target path for freedesktop.org's AppStream metainfo file (formerly AppData). 0.4.5 2017-04-27 Pre-LAC2017 release frenzy. - On some desktop-shells, the system tray icon blinking on XRUN ocurrences, have been found responsible to excessive CPU usage, an "eye-candy" effect which is now optional as far as Setup/ Display/Blink server mode indicator goes. - Added French man page (by Olivier Humbert, thanks). - Make builds reproducible byte for byte, by getting rid of the configure build date and time stamps. 0.4.4 2016-11-14 A Fall'16 release. - Fixed an early crash when the singleton/unique application instance setup option is turned off. - Almost complete overhaul on the configure script command line options, wrt. installation directories specification, eg. --prefix, --bindir, --libdir, --datadir and --mandir. 0.4.3 2016-09-14 End of Summer'16 release. - Fix build error caused by variable length array. - Fix some tooltip spelling (patch by Jaromír Mikeš, thanks). - Translation (not) fix for the default server name "(default)". - Old "Start minimized to system tray" option returns to setup. - Dropped the --enable-qt5 from configure as found redundant given that's the build default anyway (suggestion by Guido Scholz, while for Qtractor, thanks). - Late again French (fr) translation update (by Olivier Humbert aka. trebmuh, thanks). 0.4.2 2016-04-05 Spring'16 release frenzy. - Added a brand new "Enable JACK D-BUS interface" option, split from the old common "Enable D-BUS interface" setup option which now refers to its own self D-BUS interface exclusively. - Dropped old "Start minimized to system tray" option from setup. - Add double-click action (toggle start/stop) to systray (a pull request by Joel Moberg, thanks). - Added application keywords to freedesktop.org's AppData. - System-tray icon context menu has been fixed/hacked to show up again on Plasma 5 (aka. KDE5) notification status area. - Switched column entries in the unified interface device combo- box to make it work for macosx/coreaudio again. - Blind fix to a FTBFS on macosx/coreaudio platforms, a leftover from the unified interface device selection combo-box inception, almost two years ago. - Prevent x11extras module from use on non-X11/Unix plaforms. - Late French (fr) translation update (by Olivier Humbert, thanks). 0.4.1 2015-10-28 A Fall'15 release. - Probing portaudio audio device in a separate thread (by Kjetil Matheussen, thanks). - Messages standard output capture has been improved again, now in both ways a non-blocking pipe may get. - Regression fix for invalid system-tray icon dimensions reported by some desktop environment frameworks. - New hi-res application icon (by Uttrup Renzel, Max Christian Pohle, thanks). - System tray icon red background now blinks when a XRUN occurs. - Desktop environment session shutdown/logout management has been also adapted to Qt5 framework. - Single/unique application instance control adapted to Qt5/X11. - Prefer Qt5 over Qt4 by default with configure script. - Overrideable tooltips with latency info (re. Connections JACK client/ports: patch by Xavier Mendez, thanks). - Complete rewrite of Qt4 vs. Qt5 configure builds. - French (fr) translation update (by Olivier Humbert, thanks). 0.4.0 2015-07-15 Summer'15 release frenzy. - Some windows fixes added (patch by Kjetil Matheussen, thanks). - Most advanced Setup/Settings are moved into new Setup/Advanced settings tab; limit range for the real-time priority setting, now having 6 as absolute minimum valid value (after patches by Robin Gareus, thanks). - A new top-level widget window geometry state save and restore sub-routine is now in effect. - Delayed geometry setup for widget windows upon startup has been deprecated and scrapped altogether. - Setup/settings dialog tab is going into some layout changes; also got rid of old patchbay auto-refresh timer cruft, which was previously hidden/disabled. - New socket names are now automatically inferred from selected client names while on the Patchbay widget, Socket dialog. - Fixed for some strict tests for Qt4 vs. Qt5 configure builds. - German (de) translation update (by Guido Scholz, thanks). 0.3.13 2015-03-25 Pre-LAC2015 release frenzy. - Added application description as freedesktop.org's AppData. - Setup dialog form is now modeless. - Introducing brand new active patchbay reset/disconnect-all user preference option. - Current highlighted client/port connections are now drawn with thicker connector lines. - New user preference option on whether to show the nagging 'program will keep running in the system tray' message, on main window close. - Connections lines now drawn with anti-aliasing; connections splitter handles width is now reduced. - Drop missing or non-existent patchbay definition files from the most recent used list. 0.3.12 2014-10-19 JACK Pretty-names aliasing. - JACK client/port pretty-name (metadata) support is being introduced and seamlessly integrated with old Connections client/port aliases editing (rename) (refactored from an original patch by Paul Davis, thanks). - Application close confirm warning is now raising the main window as visible and active for due top level display, especially applicable when minimized to the system tray. - Messages standard output capture has been slightly improved as for non-blocking i/o, whenever available. - Translations install directory change. - Allow the build system to include an user specified LDFLAGS. - Missing input/output-latency parameter settings now settled for the D-BUS controlled JACK server and firewire back-end driver. 0.3.11 2013-12-31 A fifth of a Jubilee. - More preparations for Qt5 configure build. - Interface device selection is now unified, by moving the old '>' pop-up menu into the customized combo-box drop-down list showing all available card/device names and descriptions (on a patch by Arnout Engelen, thanks). - Added include to shut up gcc 4.7 build failures (patch by Alexis Ballier, thanks). 0.3.10 2013-04-01 The singing swan rehersal. - Session infra-client management finally being added. - Preparations for Qt5 migration. - Transport tempo (BPM) precision display fixed to 4 digits. - Color-candy (dang old ANSI terminal?) escape sequences are now silently stripped from jackdbus messages captured log (onliner from original patch by Brendan Jones, thanks). - List ALSA device card id. string instead of device number, while on setup dialog. - Japanese (ja) translation added (by Takashi Sakamoto). 0.3.9 2012-05-18 The last of the remnants. - Killing D-BUS controlled JACK server is now made optional, cf. Setup/Misc/Stop JACK audio server on application exit. (a patch by Roland Mas, thanks). - Added include to shut up gcc 4.7 build failures. - Make(ing) -jN parallel builds now available for the masses. - A mis-quoting bug at the command line argument string may have been crippling the (unmaintained) Windows port since ever, leaving its main function to start jackd dead in the water, belly down :) now hopefully fixed (following a mail transaction with Stephane Letz and Mathias Nagorni, thanks). - Currently a JACK2-only feature, the JACK version string display at the About dialog box, must now be explicitly enabled on configure time (--enable-jack-version). - A new so called "Server Suffix" parameter option appears to rescue on the situations where QjackCtl falls short on extra, exquisite and/or esoteric command line options eg. (net)jack1/2 differences. - Fixed D-Bus Input/Output device parameter settings, filled when either interface is selected for Capture/Playback only. (probable fix for bug #3441860). - Fixed Makefile.in handling of installation directories to the configure script eg. --datadir, --localedir, --mandir. (after an original patch from h3xx, thanks). - Main window is now brought to front and (re)activated when clicking on the system tray icon instead of just hiding it. - Add current xrun count to the system tray icon tooltip, if not zero (after patch #3314633 by Colin Fletcher, thanks). 0.3.8 2011-07-01 JACK Session versioning. - Debugging stacktrace now applies to all working threads. - Session "Save" button now a drop-down menu, replacing the session save type combo-box/drop-down list selection. Also, an early session directory versioning/numbering scheme is now in place, although optional. - Probable fix to debian bug report #624198 - segfault when pressing the stop button (by Grant Adrian Diffey, after a patch from Adrian Knoth, thanks). - Desktop environment session shutdown (eg. logout) is now tapped for graceful application exit, even though the main window is active (visible) and minimizing to system tray is enabled. Both were causing first shutdown/logout attempt to abort. Not anymore, hopefully ;). - Make sure all activated patchbay definition files are in their complete and absolute directory path forms. - Connections refresh button now does an immediate and true reconstruction of all clients and their respective ports and connections, unconditionally. - Command line server start option (-s, --start) is now made independent from configuration setup option (cf. Setup/Misc/Start JACK audio server on application startup). - Now handling cable socket types properly to let patchbay definitions work correctly, whenever having sockets with the very same literal name (twisted from patch #3183467, by Karsten, thanks;). - Abrupt focus behavior when any of the keyboard modifiers (Shift, Ctrl, Alt, Caps Lock) is hit while on Connections client/port aliases editing (rename) has been fixed. - Russian (ru) translation updated (by Alexandre Prokoudine). - Added include "errno.h" alegedly missing for BSD style systems (applying patch for bug #3126091). 0.3.7 2010-11-30 JACK Session managerism. - Session widget has session save type preserved as well. - Connections and the new Messages/Status widgets now have their last open tab preserved across program run-cycles. - Connections and Patchbay widgets have been finally given up on an old feature request: an Expand All items button. - A significant UI layout has been made: the Messages and Status widgets were merged into one, giving space to the brand new Session wigdet to be easy accessible from the main panel control window. - libX11 is now being added explicitly to the build link phase, as seen necessary on some bleeding-edge distros eg. Fedora 13, Debian 6. (closing bug #3050915). - Input/Output latency options were missing but now finally enabled for the firewire back-end. - General standard dialog buttons layout is now in place. - Avoid pre-loading a stalled patchbay definition filename and its nagging error on startup (fixes bug #3017078). - Client connection retrial logic scrapped. Being a leftover from early ages, when machines were slower and JACK server startup times were longer... now, if it can't connect first time as client, it will tear down the server whether it's starting up still or not at all. (cf. Setup/Settings/Start Delay for the rescue). - Server name is finally part of the server settings presets, thanks to Fons Adriaensen for the heads-up. - As a workaround regarding issues switching jack2's backends, Robin Gareus sends us yet another D-Bus method slot: "preset", (dbus-send --system / org.rncbc.qjackctl.preset string:PRESET). Thanks again. - Another D-Bus interface slot makes it through implementation: "quit" (eg. usage: dbus-send --system / org.rncbc.qjackctl.quit). Besides, there's also these new JACK session management actions which were being overlooked as well: "load", "save", "savequit" and "savetemplate" are also available as D-Bus method slots. - Make sure that Patchbay socket names are unique when adding or copying, fixing previous patch by Dominic Sacre. - JACK version is now being shown on the About box (jack2). - Slight Connections widget behavioral change: (dis)connecting a client (from) to one single port, (dis)connections will be applied in sequence from (to) all client output ports to (from) as many input ports there are in below, one by one (satisfying a 5 year old request from Yann Orlarey, thanks:). - JACK session support is being introduced. - Ignore first XRUN occurrence option dropped from statistics. - Initial widget geometry and visibility persistence logic has been slightly revised as much to avoid crash failures due to wrong main widget hidden state. - Double-quotes are now being added to device names which include blank characters and were rendering invalid all command line invocation of the classic JACK server (eg. specially due for Portaudio device names on Windows). - Transport play (rolling) status is now being guarded to avoid backfiring from extraneous transport state changes. - General source tree layout and build configuration change. - Italian (it) translation added (by Sergio Atzori). - Post-shutdown script invocation logic slightly refactored in attempt to enforce its execution on application quit. 0.3.6 2010-03-09 Full D-Busification! - Make sure socket names are unique on each side of the Patchbay (another patch from Dominic Sacre, thanks). - A bunch of primitive D-Bus interface slots have been added, allowing shortcut access to most of main applications actions like toggling Messages, Status, Connections, Patchbay widget pop-ups, reset stats, transport and so on. New bindings are given eg. via dbus-send --system / org.rncbc.qjackctl.(main, messages, status, connections, patchbay, setup, about, reset, rewind, backward, play, pause, forward). (from an original idea from Sebastian Gutsfeld, thanks). - Patchbay snapshot now tolerates JACK client port strings that have more than one semi-colon in it, honoring just the first one exactly as everywhere else eg. Connections. (a glitch as reported by Geoff Beasley while using a2jmidid). - Most modal message dialog boxes (eg. critical errors) are now replaced by system tray icon bubble messages where available (mitigating feature request #2936455). - Comply with jackd >= 0.118.0 which nowruns in real-time mode by default; use of -R is now deprecated from the jackd command line interface options; use -r to run in non-real-time-scheduling. - A man page has beed added. - Got rid of a pretty old and never really useful "jackd-realtime" server path option--actually, it was only seen available on the now defunct old Mandrake Linux distro. - D-Bus support, as provided by org.jackaudio.service aka jackdbus, is now being introduced and used wherever available and whenever enabled. Configuring, starting, stopping and logging the JACK back-end server through the "infamous" jackdbus service is now being seamlessly exploited. - Global configuration state is now explicitly saved/committed to disk when Setup dialog changes are accepted and applied. - Server name command line option added (-n, --server-name). - Single application instance restriction option added (X11). - Setup for the netjack (slave) "net" driver has now sample-rate and frames per buffer (period size) settings disabled and/or ignored, as those are pretty much auto-detected by default; also, a new "netone" backend driver option has been introduced (as suggested by Torben Hohn). - Czech (cs) translation added (by Pavel Fric). - Fixed some main window keyboard shortcuts. Escape key now closes Connections, Patchbay, Status and Messages widgets as usual (bug #2871548). - Fixed glitch on configure portaudio support, specially when the library is not detected as available. 0.3.5 2009-09-30 Slipped away! - Late support for UTF-8 encoded client/port names. - Allow only one single patchbay connection to or from an exclusive socket (mitigating bug #2859119). - Automatic crash-dump reports, debugger stack-traces (gdb), back- traces, whatever, are being introduced as a brand new configure option (--enable-stacktrace) and default enabled on debug build targets (--enable-debug). - Probable fix on the audio connections with regard to client/port (re)name changes (an ancient bug reported by Fons Adriaensen). - Portaudio device selector is now available (after a patch handed by Torben Hohn and Stephane Letz). - A couple of primitive D-Bus interface slots have been introduced, giving the option to start/stop the jackd server from the system bus eg. via dbus-send --system / org.rncbc.qjackctl.start (.stop), (a nice addition supplied by Robin Gareus, thanks). - New command line option (-a, --active-patchbay=[path]) to specify and activate a given patchbay definition file (a simple patch sent by John Schneiderman, thanks). - Added one significant digit to DSP Load percentage status display. - Tentative support for netjack (slave) by adding the "net" driver to the existing backend driver options on the Setup/Settings section. - Converted obsolete QMessageBox forms to standard buttons. - New patchbay snapshot now raises the dirty flag and allows for the immediate salvage of patchbay definition profile. - Conditional build for JACK port aliases support (JACK >= 0.109.2). - Alternate icon sizes other than default 16x16, are now effective to the Connections widget (Setup/Dislay/Connections Window/Icon size). 0.3.4 2008-12-05 Patchbay snapshot revamp. - Introducing the very first and complete translations in-package: German (de), Spanish (es), French (fr) and Russian (ru); credits in TRANSLATORS. - At last, after years of retarded procrastination, the old infamous patchbay snapshot feature has been the subject of a almost complete rewrite and it does try to give a way better mapping of all actual and current running client/port connections, both JACK (audio, MIDI) and ALSA MIDI, of course ;) - On Setup/Settings/Parameters dialog, all device selection options are now reset to default when disabled interactively. - Grayed/disabled palette color group fix for dark color themes. - Qt Software logo update. - Fait-divers: desktop menu file touched to openSUSE conventions. - ALSA PCM devices now only listed/enumerated iif strictly compliant with the audio mode criteria (Duplex, Capture-only or Playback-only) as kindly suggested by Nedko Ardaunov. - JACK client/port aliases may now be displayed as a global user option (see Setup/Display/Connections/JACK client/port aliases). - Lighten up the connections line and highlight colors, as seen to fit best on some darker background themes. - Patchbay snapshot fixed to differentiate socket clients according to its type (Audio, MIDI or ALSA-Seq), avoiding the mess and gross mistake of hanging disparate type ports under the same client item. - JACK_DEFAULT_SERVER environment variable is now appended to the X11 unique application identifier, allowing for having multiple instances each controlling its own JACK server, besides the default one. - Due to some trouble with newer Qt >= 4.4 applications regarding font size configuration, a new global user option is now available to the rescue: Setup/Misc/Defaults/Base font size (default is no-op). 0.3.3 2008-06-07 Patchbay JACK-MIDI, file logging and X11 uniqueness. - Attempt to load Qt's own translation support and get rid of the ever warning startup message, unless built in debug mode. (transaction by Guido Scholz, while on qsynth-devel, thanks). - Messages file logging makes its first long overdue appearance, with user configurable settings in Setup/Options/Logging. - Only one application instance is now allowed to be up and running, with immediate but graceful termination upon startup iif an already running instance is detected, which will see its main widget shown up and the server started automatically (Qt/X11 platform only). - Finally, full JACK MIDI support sneaks into the patchbay; socket types now differ in Audio, MIDI and ALSA, following the very same nomenclature as found on the Connections widget tabs. - Sun driver support (by Jacob Meuser). - Delay window positioning at startup option is now being disabled, on the Setup/Misc tab, when Minimize to system tray is enabled. - Cosmetic fix: Setup/Settings tab, 'Input Device' text label was using a slightly smaller font than the rest of the application (bug#1872545, reported by Jouni Rinne). 0.3.2 2007-12-20 Patchbay heads-up with season greetings. - Patchbay port matching has been slightly extended, this time allowing for the multiple or as many-to-many connections between socket plugs, provided these are specified in proper regex form (after a patch proposed by Dave Moore, thanks). - A new option to start the program minimized when the system tray icon is enabled, is now available from Setup/Misc/Start minimized to system tray (as kindly suggested by Marc-Olivier Barre). - Regression from QSystemTrayIcon (Qt4 >= 4.2) implementation, at least on X11 environments: while the main application widget was minimized to the system-tray, closing any other top-level widget was causing the immediate and unexpected application shutdown. - Some portaudio backend settings are now being enabled, specially suited for the jackdmp flavouring. - Server mode display blinking, usually shown as the RT indicator, is now an option (Setup/Display/Blink server mode indicator when started). - Tool/child windows position and size preservation fixed. - The connections/patchbay auto-refresh option has been finally removed due to several user requests, although deprecated for quite some time now it has been the probable cause of some periodic xrun occurrences due to graph-locking in jackd (while making Geoff Beasley angry in the process:). - Messages line limit was not being checked, now honored. - Simple as it could ever be, the build executive summary report is now given on configure. - Patchbay snapshot ot its socket and port ordering back. - ALSA Sequencer support is now an optional feature on setup, preventing the annoying "MIDI patchbay will be not available" warning message, ruining window placement on Linux systems where the snd-midi-seq kernel module is not loaded or not favorable (eg. OSS) at startup (by request from Jussi Laako). - Get configure to try and detect the correct qmake location and insert it the search order, so let the qt4 tools take precedence when --with-qt option is given and older qt3 ones coexist and are found located ahead in the PATH. - The connections widget is now being properly refreshed, due to some quirk in the QTreeWidget which was preventing some items, specially the expanded ones, to disappear in the void. Meanwhile, with a hand from Stephane Letz, the client/port lookup method was changed to prevent duplicated, missing entries or worse, crashes due to weird behaved windows applications. - The xrun count stats can now be reset simply by middle clicking on the systray icon or the main window's display area (thanks to patch sent by Dominic Sacre). - An improved version of the "shiny" background image was issued. The original somehow looked like two different images put together, probably most apparent on a bright TFT screen (by Dominic Sacre). - A warning is now being issued, asking whether one wants to remove a corresponding Patchbay connection, when client/ports are being disconnected over the Connections window, thus avoiding automatic reconnection annoyance due to normal active Patchbay behavior. - The infamous "Keep child windows always on top" global option is now supposed to behave a little better when disabled, layering child windows as naturally as far the window manager dictates. - Input/Output Channel setting is now allowed to be greater than 32; the special default text is now displayed, also on Input/Output Latency and Priority settings spin-boxes. - Andreas Persson just sent a patch that makes it possible to compile and run qjackctl with Qt version 4.1. Applied without hesitation, thanks. 0.3.1a 2007-07-19 System-tray tooltip icon crash fix. - An immediate showstopper crash upon client start was irradicated, which was affecting those with the system-tray icon disabled, as is the default (thanks to Ken Ellinwood for first reporting this sloppy one). 0.3.1 2007-07-18 Shallowed bug-fix release. - The current DSP load percentage activity is now also displayed on the system-tray icon tooltip. - An illusive but nasty Connections/Patchbay item tooltip crash bug has been hopefully fixed (Qt >= 4.3). - Now using QSystemTrayIcon class facility if available (Qt4 >= 4.2) making the system-tray option available on most platforms, notably on Windows and Mac OS X. - Usage of QProcess class has been severely refactored, now using QProcess::start() instead of QProcess::startDetached(), giving much tighter control over the started jackd(mp) process. Downside is that QjackCtl lost its ability and option to leave the process detached upon quitting the application. Too bad. - A new eye-candy bit has sneaked in: server mode display, that is the RT indicator, now blinks when server/client is started/active. - Combo-box setup history has been corrected on restore, which was discarding the very initial default (factory) contents. - Now that Qt4 is accessible to open-source Windows appplications, there's some experimental stuff sneaking in for jackdmp support on win32 (http://www.grame.fr/~letz/jackdmp.html). - Connections list items were initially sorted in descending order by default. Fixed. Client items are now naturally sorted, again. 0.3.0 2007-07-10 Qt4 migration was complete. - Qt4 migration was complete. Care must be taken with this new configuration file and location: this release starts a new one from scratch and won't reuse any of the previous existing ones, although cut and paste might help if you know what you're doing :) - On a last-minute addition, the "firewire" audio backend driver option has been also included, supporting the ffado.org project which is evolving where "freebob" is leaving (thanks to Klaus Zimmermann for this one). 0.2.23 2007-07-02 JACK MIDI support debut. - JACK MIDI support is now being introduced. Connections window now has a brand new MIDI tab, the older being renamed to ALSA, as for the ALSA/MIDI sequencer conveniency. The server settings now include the MIDI driver setup option (ALSA backend only). - Application icon is now installed to ${prefix}/share/pixmaps; application desktop entry file is now included in installation; spec file (RPM) is now a bit more openSUSE compliant; initial debianization. - Invalidation of the JACK client handle is now forced right on jack_shutdown notification, preventing a most probable fatal crash due to jack_deactivate and/or jack_client_close being called after the jack_watchdog kicks in. - Default font option names were adjusted to "Sans Serif" and "Monospace", wherever available. - The "keep child windows always on top" option is not set as default anymore, because window focus behavior gets tricky on some desktop environments (eg. Mac OS X, Gnome). - Autoconf (configure) scripting gets an update. 0.2.22 2007-03-31 Long overdue but better late than never. - Fixed default settings for the freebob backend (JACK >= 0.103.0). - CPU Load status label now says correctly DSP Load. - The most recently used patchbay definitions can now be correctly selected in round-robin fashion from its drop-down list widget. - Avoid mixing JACK MIDI ports with regular audio ports on the Connections and Patchbay widgets; strictly list only audio ports. - Added 192k sample rate to setup settings drop down list (as kindly reminded by Klaus Zimmermann, thanks). - Most top-level widgets were missing the normal-widget flag, which were causing some sticky size behavior on some window managers. 0.2.21 2006-10-07 Shrinking on screen real-estate. - GPL address update. - All window captions can now be set smaller as tool-widgets. This option takes effect when child windows are kept always on top. - For the brave of heart, specially the ones brave enough to try with Stephane Letz's jackdmp, a win32 build should be now possible. - The main window button text labels are now optional (after a kind suggestion by Geoff Beasley, thanks). - Increse default maximum number of ports setting from 128 to 256. - Initial freebob backend driver support. Also changed the coreaudio backend driver command line device name/id parameter. - Closing the main window while not as an active JACK client, nor under a server running state, will just quit the whole application, even though the system-tray icon option is in effect. - The most relevant transport commands (Rewind, Play and Pause) are now made available on the main window context popup menu. - The post-shutdown script is now also being called when using the Stop button, whether the jackd server has been started internally or not. The initial hard-coded default is now on and set to `killall jackd` (as a workaround to an old request from Stephane Letz). - The main window buttons display are now optional. One can choose whether the left, right and/or transport buttons are hidden, making it for a total of six different modes for the main window presentation (after a much simpler suggestion from Paul Davis and Stephane Letz). - Added configure support for x86_64 libraries (UNTESTED). 0.2.20 2006-03-05 Featuring patchbay socket forwarding. - Server path setting now accepts custom command line parameters (after a kind suggestion from Jussi Laako). - The internal XRUN callback notification statistics and reporting has been changed to be a bit less intrusive. - Patchbay socket dialog gets some more eye-candy as icons have been added to the client and plug selection (combobox) widgets. - Connections and patchbay lines coloring has changed just slightly :) - New patchbay socket forwarding feature. Any patchbay socket can now be set to have all its connections replicated (i.e. forwarded) to another one, which will behave actively as a clone of the former. Forward connections are shown by vertical directed colored lines, and can be selected either on socket dialog or from context menu (currently experimental, only applicable to input/writable sockets). - Optional specification of alternate JACK and/or ALSA installation paths on configure time (after a patch from Lucas Brasilino, thanks). 0.2.19a 2005-11-28 MIDI aliases are back in town. - ALSA sequencer client/port name aliases are functional again; all actual MIDI sequencer client/port numerical identifier prefixes are also back in business. 0.2.19 2005-11-19 MRU patchbay selection, Mac OS X and other fixes. - Connections widget views are now properly refreshed after renaming client/ports (aliases). - Disabled system tray and ALSA sequencer support on configure time, whenever building for MacOSX as default. - Fixed the major issues with selecting an audio interface on Mac OSX; the button the right of the interface combo is now much better looking than it was before; input/output channel counts are also updated automatically now (thanks to Jesse Chappell for the patch). - Prevent the setting of the coreaudio device id on the jackd command line (-n) whenever the default interface is being selected. - The connections and patchbay windows are now allowed to have a wider connection lines frame panel; splitter width sizes are now persistent across application sessions (thanks to Filipe Tomas for the hint). - Activation toggling feedback on the patchbay widget has been fixed; additionally and as found convenient, the most recently used patchbay definitions can now be loaded immediately by selecting from a drop-down list widget, which replaces the old static patchbay name status text, and adds a lil'icon too :) - All widget captions changed to include proper application title prefix. - Attempt to bring those aging autoconf templates to date; sample SPEC file for RPM build is now being included and generated at configure time. - The current selected device is now shown with a checkmark on the device selection menu(s), while on the settings dialog. - Set to use QApplication::setMainWidget() instead of registering the traditional lastWindowClosed() signal to quit() slot, just to let the -geometry command line argument have some effect on X11. 0.2.18 2005-07-18 The mantra of bugfixes stays on. - A freezing and endless loop condition on the patchbay socket item duplication (copy) has been fixed. - Fixed output disability when messages limit option is turned off (thanks again to Wolfgang Woehl for spotting this one). 0.2.17 2005-06-17 Systemic I/O Latency settings are in. - Systemic I/O Latency settings are now featured for the alsa, oss and coreaudio backends, letting you specify the known latency of external hardware for client aware compensation purposes (thanks to Wolfgang Woehl, for the reminder). - Update on last backstage changes to the coreaudio backend options (due to Stephane Letz. Thanks). 0.2.16 2005-06-13 OSS device name selection and Mac OS X breakthrough. - ALSA sequencer client/port name changes are now properly detected on the MIDI connections widget (as noted by Chris Cannam. Thanks). - Long overdue transport buttons (rewind, backward and forward) finally landed onto the main control window, at last :). - Duplication (copy) of patchbay socket items was added. - Do not ever try to start the JACK server if there's one already found running, on which case the client-only mode of operation is then activated (as kindly suggested by Orm Finnendahl, thanks). - After several Mac OS X user requests, ALSA/MIDI sequencer support is now an option, otherwise detected at configure time and conditionally compiled in if, and only if, ALSA is found available (which has been a primordial assumption on Linux systems:). Ah, and that just makes for the blind inclusion of another backend driver option: coreaudio. - Actual OSS device selection menu now featured on setup dialog; these adds to the device selection button menus for the OSS driver settings. - Delayed geometry setup of windows upon startup was added as an optional workaround to subtle problems due to window decoration information not being available at window creation time on some window managers (as patch proposed by Dirk Jagdmann. Thanks). - Fixed some minor but rather old bug that was quitting the application abruptly, when one switches off the system tray icon while the main application widget is hidden. - Cancel is now an option when creating a new patchbay definition. - Context menus are finally littered with icons. - Minor configure and Makefile install fixes, as Debian and Mac OS X specialties. Also, install does the right thing with target file modes (thanks to Matt Flax and Ebrahim Mayat, for pointing these out). 0.2.15a 2005-02-09 Return of the paranoid. - Regression from 0.2.13, of the not so stupid pseudo-mutex guards on the connections management framework, after fixing some crash reports from Fernando Pablo Lopez-Lezcano and Dave Phillips (thanks!); it pays to be such a paranoid after all :). 0.2.15 2005-02-06 Client/port names aliasing and other minors. - JACK/ALSA client and port name aliasing (renaming) is now an optional feature for the connections window; all client/port aliases are saved on a per preset basis (as proposed for Lionstracs' Mediastation). - Server state now shown (back gain) on the system tray icon tooltip; speaking of which, tooltips are now also featured on connections, status and patchbay windows. - New actual hardware device selection menu featured on setup dialog; these new button menus are only available for the ALSA driver settings. - Server path factory default to jackd instead of jackstart; preset setup button icons are back. - Fixed rare connection port item removal/disconnection dangling pointer bug. 0.2.14 2005-01-23 More progressive optimizations. - Put a limit on XRUN callback messages and statistics report rate, preventing the potential hosing of the GUI due to a XRUN cascade storm. The maximum reasonable report rate has been fixed to be one XRUN callback occurrence per second. - Set to ignore the SIGPIPE ("Broken pipe") signal, where available, as the default handler is usually fatal when a JACK client is zombified abruptly. - All conection view items are now sorted in natural case insensitive order, not just as audio port names as was before. - Got rid of those nonsense paranoid and rather stupid pseudo-mutex guards on the connections management framework and event notifications (nuff said :). - Optional confirmation warning on audio server shutdown, if there's some audio clients still active and connected (as suggested by Sampo Savolainen). - Check for on configure time (as of JACK 0.99.42+ CVS). - "Unlock memory" server setup option was added, allowing the release of memory used by common toolkit libraries (GTK+, Qt, FLTK, Wine) that were being superfluously locked on every GUI JACK client; number of periods has now the minimum allowed value of 2; server start delay widget converted to spinbox; setup dialog layout slighly changed. - Removed stand-alone usx2y driver support. Since JACK 0.99.41+ CVS, the special "rawusb" support on the Tascam US-122/224/428 USB Audio/MIDI interface controllers have been merged and properly integrated into the regular alsa backend driver. Being still experimental, this special mode of operation is now triggered only when "hw:N,2" is specified as the alsa device name (N = soundcard index of snd-usb-usx2y module). - Messages window limit is now enforced only when the line count exceeds in one third the user configured line count maximum; if Qt 3.2.0+ is in use, the QTextView widget is otherwise set to the optimized Qt::LogText format. - XRUN status items are kept double-dashed if none has been detected. 0.2.13 2004-11-21 Retouches and minor optimizations. - Main window is now properly minimized instead of simply hidden when the system tray icon is not available nor opted in (as suggested by Florian Schmidt). - Some informational status items are now updated 10 times less frequently (e.g. CPU Load, Sample Rate, Buffer Size, Realtime Mode, etc.), lowering the CPU burden of most probably redundant status updates. - XRUN detection and statistics are being conditionally included if jack_get_xrun_delayed_usecs() is available (as of JACK 0.99.7+ CVS). - Fixed ancient bug on client shutdown event handling, which was invoking the xrun notification handler by mistake. - Support for maximum scheduling delay status added; this status relies on jack_get_max_delayed_usecs() function availability at configure time, depending on a Lee Revell's non-official JACK patch. - Patchbay Activate button is now a toggle button widget, allowing the deactivation of the current patchbay profile. - Reset-status icon has been changed to a simple red circle instead of previous one which was much like a power-switch symbol. - Preset selection has been added to the context menu. 0.2.12a 2004-10-11 Audio connections now naturally sorted. - Client port list on audio connections are now hopefully fixed for good; the sort comparison function now takes full natural order into account. 0.2.12 2004-10-08 Larger icons and font option on connections/patchbay. - Fixed some old and slow memory-leak due to redundand and repetitive call to jack_port_by_name() (discovered and solved, thanks to Jesse Chappell); some other free() and configure fixes were also applied. - Shiny display effect toggling has immediate feedback on setup dialog. - Added new usx2y driver support. - New scaled connections/patchbay icons were added; meanwhile, all inline XPM icons were removed and brainlessly converted to PNG format. - New setup options as for the connections/patchbay view apprearence: larger icon sizes and font selection are now possible, to better ease manipulation on a touchscreen (feature requested for Lionstracs' Mediastation). - Connection line width follows icon size in discrete proportion. - "Other" setup options moved to a new dialog tab, "Misc"; new extreme item values, 32 and 16 frames, added to the drop-down list of the Frames/Buffer setting (as suggested by Mark Knetch). 0.2.11 2004-09-10 Shiny display now optional and other fixes. - Fixed Input/Output channels settings, being now either enabled when the ALSA driver is selected for Capture/Playback only. - Shiny display effect: after some conservative user complaints this pure cosmetic feature is now made optional ;) 0.2.10 2004-09-04 Shiny display and curved connections. - New pre-shutdown script setup option, allowing to specify a shell-script to be run before the JACK server daemon is shutted-down. This overrides any previous shutdown script setting, which should be now moved onto the existing post-shutdown script option, as to keep old procedural behaviour. - Avoid stopping JACK prematurely with QProcess::kill() (oneliner fix); stopping JACK will now take a little bit longer, but hopefully will take the time to cleanup properly (thanks to Kjetil Matheussen). - ALSA driver Duplex mode accepts alternate Input or Output device name. - Context menu reset option is now always enabled (yet another suggestion from Sampo Savolainen). - Main display background gets shinny effect; adjusted system tray background palette color mode. - Priority and setup control is now a spinbox ranging from 0..89 (as suggested by Florian Schmidt). Same for Periods/Buffer. - Patchbay connection lines are now drawn correctly when items are scrolled out of view. Additionally, the connection lines can now be optionally drawn as bezier spline curves (big thanks to Wilfried Huss). 0.2.9 2004-07-04 Sloppy boy fixes and minor featuritis. - Patchbay socket dialog client and plug list option items are now properly escaped as regular expressions. - JACK callbacks are now internally mapped to QCustomeEvent's instead of using the traditional pipe notifications. - The system tray popup menu is now featured as a context menu on the main application window too. - The reset status option is now included in the system tray popup menu. - Server stop command button now enabled during client startup interval; this makes it possible to stop the server just in case the client can't be activated for any reason. - Top level sub-windows are now always raised and set with active focus when shown to visibility. 0.2.8 2004-04-30 System tray icon and menu option. - New option for system tray icon and menu, which is known to be effective on KDE enabled desktops; support for freedesktop.org's system tray protocol specification has been included so this maybe also effective on Gnome2. - Capture or Playback-only optional alternate device interface name may now be specified for the ALSA audio driver server settings. - Maximum number of ports setting was added to server setup. - The dash (-) is now a legal character for preset names. 0.2.7b 2004-04-05 OSS driver setup fix. - OSS driver halfduplex setup operation is now fixed, thanks to Jussi Laako. 0.2.7a 2004-04-05 Compilation fix for Qt 3.1. - QSplitter::setChildrenCollapsible call is now conditionally compiled, applied only on Qt 3.2+. 0.2.7 2004-04-04 User-interface refinements and OSS driver support. - Connections and patchbay windows horizontal layout are now user configurable via splitter widgets. - Refresh on connections window now take effect on both tabs, Audio (JACK) and MIDI (ALSA). - OSS driver support and no-mlock option added to server settings, setup dialog (as of JACK 0.95.7+). - Temporary server configuration option added, applicable to the auto-start server feature on client applications, whether the server shall exit once all clients are closed. - Server mode (RT) status display added. - Warning messages are now prompted to the user when there are any pending changes not saved nor applied while on the setup dialog. - Translation support for the default preset name "(default)". - Messages window pops up whenever a critical error message is issued. 0.2.6 2004-02-29 More work in progress. - Message window line limit is now a configurable option on setup, as is whether the command-line local configuration file gets saved at all; the first argument of the command-line configuration is stuffed to be the executable server command absolute path, when possible. - Warning message issued if ALSA sequencer is not available on startup; also if server settings are changed while client is currently active. - Server autostart magic is locally disabled by forcing the environment variable JACK_NO_START_SERVER at startup; with any luck this will maintain qjackctl's behaviour whether the JACK server is already started or not. - Makefile.cvs makes its late entrance on the build toolset. 0.2.5 2004-02-16 Server survival option and command-line wrapper feature. - New option on application exit for leaving the JACK server daemon running, surviving the parent process; the confirmation prompt on application close now features a "Terminate", "Leave" and "Cancel" button options. - New command-line wrapper feature for JACK client applications, thus giving a convenient head start for the JACK audio server as needed (as suggested by Fernando Pablo Lopez-Lezcano, of Planet CCRMA fame). - Messages, Status, Connections and Patchbay pop-up windows are not hinted as dialogs anymore and thus are not centered relative to parent main window which has become a strict Qt dialog widget behaviour (as of Qt 3.3+). - Patchbay window content changes are now properly updated, without the need for a later manual refresh to redraw stalled connection lines. - The snapshot option for creating a new patchbay definition from current actual connections now takes client and port names as regular expressions and smart enough when regarding more than two contiguous decimal digits :) - Patchbay socket list view ordering is now properly preserved; socket dialog gets plug list handling ehancements; active patchbay gets reloaded when commited and saved to file; connections redraw on socket removal has been fixed. - Server literal command-line is now saved into local configuration file (~/.jackdrc) for convenience of future auto-start client applications. - New setup option on whether all child windows are kept on top of the main window, or otherwise floating with probable taskbar entries of their own. - Setup changes that are only effective next time the program is run gets an informational message box shown to the user. 0.2.4 2004-02-01 Exclusive patchbay sockets. - Patchbay definitions may now be configured with exclusive sockets; this way, only one defined connection is allowed as soon as it's available, being all others immediatelly disconnected whenever attempted. - On the connections view, current connected client ports are now slightly highlighted (blue) whenever a client or port is selected on the opposite column (as suggested by Lawrie Abbott). - Connections and patchbay drag and drop feature is now bilateral; you can now drag and drop an item from right to left to establish the connection. 0.2.3a 2004-01-19 Time format combo-box tooltip fix. - A qt-designer copy-paste leftover has been fixed; sloppy boy I am ;) 0.2.3 2004-01-19 Tenths, hundredths, milliseconds, whatever. - Custom time format setup for all elapsed times, allowing the display of tenths, hundredths or even milliseconds instead of just hundredths of second for transport time code. 0.2.2 2004-01-16 Hundredths are back. - Transport time is now shown with hundredths of second (hh:mm:ss.dd), as it was once before but not constant zero. - Client start delay now configurable on setup; this may be of help for slow machines or unusual long server driver startups (e.g. portaudio). - Client-only mode restart has been fixed. - Messages color retouching. - Popup menus memory leak fixed. 0.2.1 2003-12-29 The fix of fixes. - Fixed jackstart/jackd command line parameter argument concatenation. - Front panel status display font can now be customized. - Some connection graph changes were being silently missed, now fixed. - Messages window fallback fix; stdout handling has been retouched to be more line buffer oriented. 0.2.0 2003-12-12 ALSA sequencer patchbay entrance. - ALSA sequencer subscription patchbay feature, complementing current audio service with a MIDI application connection graph, gracefuly included on the same front-end. - Current preset name is shown on main window caption title. New button and form icons. Messages window blankness rendering fix. - Immediate server startup option was made persistent and therefore remembered across sessions. - Standard output/error stream capture setup option. 0.1.3 2003-11-26 Server settings profile/preset feature. - Server setup settings can now be profiled, named and saved as presets. Command line preset name option and scripting argument meta-symbols are also featured for convenience (kindly suggested by Sampo Savolainen). - New configure time argument debugging support (--enable-debug). 0.1.2 2003-11-16 More work in progress. - Qmake project file (qjackctl.pro) now generated by configure (autoconf), introducing the explicit binding support to libqt-mt (multi-thread). - Main window is not hinted as a dialog anymore, giving room to the minimize button on some other window managers; application close confirm warning is now an option. - Removed deprecated settings options: temporary directory and ASIO mode; new available settings for the ALSA driver: force 16bit format, maximum input channels and output channels (as of JACK 0.90.x). - Transport time display looses static hundredth seconds decimal digits. 0.1.1a 2003-11-01 Whatever happened to OK button icons. - Restored missing OK button icons. 0.1.1 2003-10-29 Minor feature enhancements and bugfixes. - Main window display items are now made fixed in width, at least those more prone to change frequently and thus caused some display jitter. - Messages, status, connections and patchbay module windows are now reopened automagicaly on startup as they were on previous session. - New patchbay definition snapshot option from current actual connections; current active patchbay filename status indication on title. - New icons patchbay editor window and socket dialogs; own stdout/stdin is now properly captured and shown on messages log window. - Fixed an obvious patchbay connection scan freezing bug; default .xml file extension enforcement on save. 0.1.0 2003-10-22 Major user interface redesign. - Main application window complete redesign, now more like a multimedia/LCD control panel -- old main window dialog tabs are now splitted in separate pop-up windows/dialogs; big time display options. In other words, this sums up to a nice complete application rewrite. - Deprecated options for forcing aRTs and jackd daemons are no longer available; this functionality can be officially superceded by the more generic startup/shutdown script options. - Seamless support for externally started JACK server, providing a client-only mode of operation; if the JACK daemon is already started, qjackctl enters in client detached mode automagically. - Messages window font is configurable and saved across sessions (by Jack O'Quin's humble request). Some colorization has been introduced on some event messages. - Preliminary patchbay persistence feature is under way. A patchbay definition editor is already included, following an alternative socket-plug patchbay model that aliases and is a direct map to the client-port JACK connections model. The patchbay definitions are stored as text/xml files. - New post-startup script option; immediate JACK server startup command line option (as suggested by Kasper Souren). 0.0.9a 2003-10-03 Tiny bugfixes. - Startup/shutdown script options now correctly saved and restored. - Dummy driver wait parameter is now properly set on startup. - Confirmation warning on disconnecting all ports (as suggested by Robert Jonsson). 0.0.9 2003-09-25 Work in progress. - New connection port item pixmaps that distinguishes physical from logical ports. - History of most recently used values gets saved for some settings and options comboboxes widgets. - New startup and shutdown script options, intended to supersede the mess of forcing artsd and jackd itself, in a near future ;) this way, one can also include the operation of the LADCCA daemon (following a suggestion from Kasper Souren). - Connections command buttons are now shortly disabled after clicking, avoiding accidental duplicated connections. 0.0.8 2003-09-19 Preliminary transport and buffer size status control. - Transport status and control introduced (requires JACK 0.80.0+); - Statistics tab renamed to Status, where the transport state info and simple play/pause control buttons are now placed; - Buffer size status is yet another item on the list view. 0.0.7 2003-09-15 Minor bugfixes. - Inverse alphabetic ordering fixed on Connections port listing. - Verbose option added; messages view font size fix; about Qt dialog; logo pixmap retouched. - Configure script now checks for Qt 3.1.1 or greater. 0.0.6 2003-09-12 Drag-n-drop and more feature enhancements and bugfixes. - Patchbay connection user interface handling has been fairly rewritten; (features new bugs while fixing old ones ;-) - Reset XRUN statistics button added; reset time recorded on statistics; calculated latency is now shown on settings; ASIO mode disables Periods/Buffer setting (all suggestions by Lawrie Abbott). - Context popup menu introduced for port connection handling; includes new command for disconnecting all currently connected ports. - Closing the application while JACK is running, is now presented with a warning confirmation message (preventing accidental Esc key press? :). - Patchbay port lists ordering are now more numerical-friendly than ever, taking account for sub-numbering port names (following yet another suggestion from Lawrie). - Connection drag-and-drop is now featured after many, many requests. - Corrected the configure script to properly recognize Qt 3.0.1 or greater. 0.0.5 2003-09-05 Minor feature enhancements and bugfixes. - Internationalization support added; future qjackctl_${LANG}.qm translation files are located on ${prefix}/share/locale . - New dummy and portaudio driver support (as of JACK release 0.80.0+). - A couple of silent memory leak bugs have been corrected. 0.0.4 2003-08-29 Minor changes and bugfixes. - The patchbay port lists are now sorted in a more numerical friendly manner (as suggested by Steve Harris); the sort code has been "borrowed" from qjackconnect, yet again. - Patchbay port connection lines are now always visible, even if their respective connected port items aren't. - Multiple simultaneous port connections can now be handled when a client application item is selected for connection/disconnection (again, suggested by Steve Harris), replicating and extending qjackconnect's similar behaviour. - An auto-refresh option for the patchbay connections is now available, for those cases when client code just can't handle properly some callbacks. - Window positioning and sizing is now almost persistent across sessions; as before, position is saved for the minimal view mode; but now, the details dialog view mode gets its position and size independantly saved also. 0.0.3 2003-08-07 Integrated visual patchbay. - A patchbay for jack port connections is now integrated, much like the greatest Mathias Nagorni's qjackconnect (http://www.suse.de/~mana/jack.html). 0.0.2 2003-08-02 Client code features introduced. - JACK library and header files are checked on configure. - Server CPU load, sample rate and time elapsed since last XRUN detected, are now displayed on statistics. 0.0.1 2003-07-26 Initial release. qjackctl-1.0.4/PaxHeaders/LICENSE0000644000000000000000000000013214771215054013401 xustar0030 mtime=1743067692.317443163 30 atime=1743067692.317443163 30 ctime=1743067692.317443163 qjackctl-1.0.4/LICENSE0000644000175000001440000004310314771215054013372 0ustar00rncbcusers GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. qjackctl-1.0.4/PaxHeaders/README0000644000000000000000000000013214771215054013254 xustar0030 mtime=1743067692.317443163 30 atime=1743067692.317443163 30 ctime=1743067692.317443163 qjackctl-1.0.4/README0000644000175000001440000001044614771215054013251 0ustar00rncbcusersQjackCtl - JACK Audio Connection Kit Qt GUI Interface ----------------------------------------------------- QjackCtl is a simple Qt application to control the JACK sound server (http://jackaudio.org), for the Linux Audio infrastructure. Written in C++ around the Qt framework for X11, most exclusively using Qt Designer. Provides a simple GUI dialog for setting several JACK server parameters, which are properly saved between sessions, and a way control of the status of the audio server. With time, this primordial interface has become richer by including a enhanced patchbay and connection control features. Homepage: https://qjackctl.sourceforge.io http://qjackctl.sourceforge.net License: GNU General Public License (GPL) Requirements ------------ The software requirements for build and runtime are listed as follows: Mandatory: - Qt framework, C++ class library and tools for cross-platform application and UI development https://qt.io/ - JACK Audio Connection Kit https://jackaudio.org/ Optional (opted-in at build time): - ALSA, Advanced Linux Sound Architecture https://www.alsa-project.org/ Installation ------------ Unpack the tarball and in the extracted source directory: cmake [-DCMAKE_INSTALL_PREFIX=] -B build cmake --build build [--parallel ] and optionally, as root: [sudo] cmake --install build Note that the default installation path () is /usr/local . Configuration ------------- QjackCtl holds its settings and configuration state per user, in a file located as $HOME/.config/rncbc.org/QjackCtl.conf . Normally, there's no need to edit this file, as it is recreated and rewritten everytime qjackctl is run. Bugs ---- Probably plenty still, QjackCtl maybe considered on beta stage already. It has been locally tested since JACK release 0.98.0, with custom 2.4 kernels with low-latency, preemptible and capabilities enabling patches. As for 2.6 kernels, the emergence of Ingo Molnar's Realtime Preemption kernel patch it's being now recommended for your taking benefit of the realtime and low-latency audio pleasure JACK can give. Support ------- QjackCtl is open source free software. For bug reports, feature requests, discussion forums, mailling lists, or any other matter related to the development of this piece of software, please use the Sourceforge project page (https://sourceforge.net/projects/qjackctl). You can also find timely and closer contact information on my personal web site (https://www.rncbc.org). Acknowledgments --------------- QjackCtl's user interface layout (and the whole idea for that matter) was partially borrowed from origoinal Lawrie Abbott's jacko project, which was taken from wxWindow/Python into the Qt/C++ arena. Since 2003-08-06, qjackctl has been included in the awesome Planet CCRMA (http://ccrma-www.stanford.edu/planetccrma/software/) software collection. Thanks a lot Fernando! Here are some people who helped this project in one way or another, and in fair and strict alphabetic order: Alexandre Prokoudine Kasper Souren Andreas Persson Kjetil Matheussen Arnout Engelen Ken Ellinwood Austin Acton Lawrie Abbott Ben Powers Lee Revell Chris Cannam Lucas Brasilino Dan Nigrin Marc-Olivier Barre Dave Moore Mark Knecht Dave Phillips Matthias Nagorni Dirk Jagdmann Melanie Dominic Sacre Nedko Arnaudov Fernando Pablo Lopez-Lezcano Orm Finnendahl Filipe Tomas Paul Davis Florian Schmidt Robert Jonsson Fons Adriaensen Robin Gareus Geoff Beasley Roland Mas Jack O'Quin Sampo Savolainen Jacob Meuser Stephane Letz Jesse Chappell Steve Harris Joachim Deguara Taybin Rutkin John Schneiderman Wilfried Huss Jussi Laako Wolfgang Woehl Karsten Wiese A special mention should go to the translators of QjackCtl (see TRANSLATORS). Thanks to you all. -- rncbc aka Rui Nuno Capela rncbc at rncbc dot org https://www.rncbc.org qjackctl-1.0.4/PaxHeaders/TRANSLATORS0000644000000000000000000000013214771215054014133 xustar0030 mtime=1743067692.317443163 30 atime=1743067692.317443163 30 ctime=1743067692.317443163 qjackctl-1.0.4/TRANSLATORS0000644000175000001440000000141614771215054014125 0ustar00rncbcusersCzech (cs) Pavel Fric German (de) Guido Scholz Spanish (es) Adrian Pardini Daryl Hanlon French (fr) Raphaël Doursenaud Olivier Humbert Italian (it) Sergio Atzori Japanese (ja) Takashi Sakamoto Korean (ko) JungHee Lee Dutch (nl) Peter Geirnaert Portuguese (pt_BR) Heitor Rocha Russian (ru) Alexandre Prokoudine Slovak (sk) Jose Riha Turkish (tr) Orkun Arapoğlu Ukrainian (uk) Yuri Chornoivan qjackctl-1.0.4/PaxHeaders/cmake0000644000000000000000000000013214771215054013377 xustar0030 mtime=1743067692.317636622 30 atime=1743067692.317443163 30 ctime=1743067692.317636622 qjackctl-1.0.4/cmake/0000755000175000001440000000000014771215054013444 5ustar00rncbcusersqjackctl-1.0.4/cmake/PaxHeaders/FindPortAudio.cmake0000644000000000000000000000013214771215054017165 xustar0030 mtime=1743067692.317636622 30 atime=1743067692.317636622 30 ctime=1743067692.317636622 qjackctl-1.0.4/cmake/FindPortAudio.cmake0000644000175000001440000000605214771215054017160 0ustar00rncbcusers# Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. #[=======================================================================[.rst: FindPortAudio ----------- Find the PortAudio libraries Set PortAudio_ROOT cmake or environment variable to the PortAudio install root directory to use a specific PortAudio installation. IMPORTED targets ^^^^^^^^^^^^^^^^ This module defines the following :prop_tgt:`IMPORTED` target: ``PortAudio::PortAudio`` Result variables ^^^^^^^^^^^^^^^^ This module will set the following variables if found: ``PortAudio_INCLUDE_DIRS`` where to find portaudio.h, etc. ``PortAudio_LIBRARIES`` the libraries to link against to use PortAudio. ``PortAudio_FOUND`` TRUE if found #]=======================================================================] include(FindPackageHandleStandardArgs) # Use hints from pkg-config if available find_package (PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(PC_PortAudio portaudio-2.0) endif() find_package(Threads QUIET) # Look for the necessary header find_path(PortAudio_INCLUDE_DIR NAMES portaudio.h HINTS ${PC_PortAudio_INCLUDE_DIRS} ) mark_as_advanced(PortAudio_INCLUDE_DIR) # Look for the necessary library set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "") find_library(PortAudio_LIBRARY NAMES ${PC_PortAudio_LIBRARIES} portaudio NAMES_PER_DIR HINTS ${PC_PortAudio_LIBRARY_DIRS} ) mark_as_advanced(PortAudio_LIBRARY) set(PortAudio_INCLUDE_DIRS ${PortAudio_INCLUDE_DIR} CACHE PATH "PortAudio include directories") if(PC_PortAudio_FOUND) # Use pkg-config data as it might have additional transitive dependencies of portaudio # itself in case of using the static lib. set(PortAudio_LIBRARIES ${PC_PortAudio_LIBRARIES} CACHE FILEPATH "PortAudio libraries" ) find_package_handle_standard_args(PortAudio REQUIRED_VARS PortAudio_LIBRARIES PortAudio_INCLUDE_DIRS VERSION_VAR PortAudio_VERSION ) else() set(PortAudio_LIBRARIES ${PortAudio_LIBRARY} CACHE FILEPATH "PortAudio libraries" ) find_package_handle_standard_args(PortAudio REQUIRED_VARS PortAudio_LIBRARIES PortAudio_INCLUDE_DIRS) endif() if(PortAudio_FOUND) # Create the imported target if(NOT TARGET PortAudio::PortAudio) add_library(PortAudio::PortAudio UNKNOWN IMPORTED) set_target_properties(PortAudio::PortAudio PROPERTIES IMPORTED_LOCATION "${PortAudio_LIBRARY}") target_include_directories(PortAudio::PortAudio INTERFACE ${PortAudio_INCLUDE_DIRS}) target_link_libraries(PortAudio::PortAudio INTERFACE ${PortAudio_LIBRARIES}) if(WIN32 AND NOT PC_PortAudio_FOUND) # Needed when building against the static library target_link_libraries(PortAudio::PortAudio INTERFACE dsound setupapi winmm ole32 uuid) endif() if(Threads_FOUND) # Needed when building against the static library target_link_libraries(PortAudio::PortAudio INTERFACE Threads::Threads) endif() endif() else() message(STATUS "Set PortAudio_ROOT cmake or environment variable to the PortAudio install root directory to use a specific PortAudio installation.") endif() qjackctl-1.0.4/cmake/PaxHeaders/FindJack.cmake0000644000000000000000000000013214771215054016127 xustar0030 mtime=1743067692.317636622 30 atime=1743067692.317443163 30 ctime=1743067692.317636622 qjackctl-1.0.4/cmake/FindJack.cmake0000644000175000001440000000471214771215054016123 0ustar00rncbcusers# Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. #[=======================================================================[.rst: FindJack ----------- Find the Jack libraries Set Jack_ROOT cmake or environment variable to the Jack install root directory to use a specific Jack installation. IMPORTED targets ^^^^^^^^^^^^^^^^ This module defines the following :prop_tgt:`IMPORTED` target: ``Jack::Jack`` Result variables ^^^^^^^^^^^^^^^^ This module will set the following variables if found: ``Jack_INCLUDE_DIRS`` where to find Jack.h, etc. ``Jack_LIBRARIES`` the libraries to link against to use Jack. ``Jack_FOUND`` TRUE if found #]=======================================================================] if(WIN32) if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") set(JACK_DEFAULT_PATHS "C:/Program Files (x86)/JACK2;C:/Program Files/JACK2") set(JACK_DEFAULT_NAME "jack") set(JACK_DEFAULT_LIB_SUFFIX "lib32;lib") else() set(JACK_DEFAULT_PATHS "C:/Program Files/JACK2") set(JACK_DEFAULT_NAME "jack64;jack") set(JACK_DEFAULT_LIB_SUFFIX "lib") endif() set(CMAKE_FIND_LIBRARY_PREFIXES "lib;") else() set(JACK_DEFAULT_NAME "jack") set(JACK_DEFAULT_LIB_SUFFIX "lib") endif() find_package (PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules (PC_JACK jack>=0.100.0) endif() # Look for the necessary header find_path(Jack_INCLUDE_DIR NAMES jack/jack.h PATH_SUFFIXES include includes HINTS ${PC_JACK_INCLUDE_DIRS} PATHS ${JACK_DEFAULT_PATHS} ) mark_as_advanced(Jack_INCLUDE_DIR) # Look for the necessary library find_library(Jack_LIBRARY NAMES ${PC_JACK_LIBRARIES} ${JACK_DEFAULT_NAME} NAMES_PER_DIR PATH_SUFFIXES ${JACK_DEFAULT_LIB_SUFFIX} HINTS ${PC_JACK_LIBRARY_DIRS} PATHS ${JACK_DEFAULT_PATHS} ) mark_as_advanced(Jack_LIBRARY) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Jack REQUIRED_VARS Jack_LIBRARY Jack_INCLUDE_DIR) # Create the imported target if(Jack_FOUND) set(Jack_INCLUDE_DIRS ${Jack_INCLUDE_DIR}) set(Jack_LIBRARIES ${Jack_LIBRARY}) if(NOT TARGET Jack::Jack) add_library(Jack::Jack UNKNOWN IMPORTED) set_target_properties(Jack::Jack PROPERTIES IMPORTED_LOCATION "${Jack_LIBRARY}") target_include_directories(Jack::Jack INTERFACE "${Jack_INCLUDE_DIR}") endif() else() message(STATUS "Set Jack_ROOT cmake or environment variable to the Jack install root directory to use a specific Jack installation.") endif() qjackctl-1.0.4/PaxHeaders/src0000644000000000000000000000012614771215054013111 xustar0029 mtime=1743067692.33063656 28 atime=1743067692.3182779 29 ctime=1743067692.33063656 qjackctl-1.0.4/src/0000755000175000001440000000000014771215054013153 5ustar00rncbcusersqjackctl-1.0.4/src/PaxHeaders/qjackctlSessionForm.h0000644000000000000000000000013214771215054017320 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSessionForm.h0000644000175000001440000001173514771215054017317 0ustar00rncbcusers// qjackctlSessionForm.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlSessionForm_h #define __qjackctlSessionForm_h #include "ui_qjackctlSessionForm.h" #include "qjackctlSession.h" #include #include // Forward declarations. class qjackctlSetup; class QMenu; class QIcon; class QLineEdit; class QToolButton; //------------------------------------------------------------------------- // qjackctlSessionInfraClientItemEditor class qjackctlSessionInfraClientItemEditor : public QWidget { Q_OBJECT public: // Constructor. qjackctlSessionInfraClientItemEditor( QWidget *pParent, const QModelIndex& index); // Shortcut text accessors. void setText(const QString& sText); QString text() const; // Default (initial) shortcut text accessors. void setDefaultText(const QString& sDefaultText) { m_sDefaultText = sDefaultText; } const QString& defaultText() const { return m_sDefaultText; } signals: void finishSignal(); protected slots: void browseSlot(); void resetSlot(); void finishSlot(); private: // Instance variables. QModelIndex m_index; QLineEdit *m_pItemEdit; QToolButton *m_pBrowseButton; QToolButton *m_pResetButton; QString m_sDefaultText; }; //------------------------------------------------------------------------- // qjackctlSessionInfraClientItemDelegate class qjackctlSessionInfraClientItemDelegate : public QItemDelegate { Q_OBJECT public: // Constructor. qjackctlSessionInfraClientItemDelegate(QObject *pParent = nullptr); protected: QWidget *createEditor(QWidget *pParent, const QStyleOptionViewItem& option, const QModelIndex& index) const; void setEditorData(QWidget *pEditor, const QModelIndex &index) const; void setModelData(QWidget *pEditor, QAbstractItemModel *pModel, const QModelIndex& index) const; protected slots: void commitEditor(); }; //---------------------------------------------------------------------------- // qjackctlSessionForm -- UI wrapper form. class qjackctlSessionForm : public QWidget { Q_OBJECT public: // Constructor. qjackctlSessionForm(QWidget *pParent = nullptr, Qt::WindowFlags wflags = Qt::WindowFlags()); // Destructor. ~qjackctlSessionForm(); // Global setup method. void setup(qjackctlSetup *pSetup); // Maybe ask whether we can close. bool queryClose(); // Recent session directories and save type accessors. const QStringList& sessionDirs() const; void setSessionSaveVersion(bool bSessionSaveVersion); bool isSessionSaveVersion() const; // Recent menu accessor. QMenu *recentMenu() const; // Save menu accessor. QMenu *saveMenu() const; void stabilizeForm(bool bEnabled); public slots: void loadSession(); void saveSessionSave(); void saveSessionSaveAndQuit(); void saveSessionSaveTemplate(); void saveSessionVersion(bool); void updateSession(); protected slots: void recentSession(); void updateRecentMenu(); void clearRecentMenu(); void sessionViewContextMenu(const QPoint& pos); void addInfraClient(); void editInfraClient(); void editInfraClientCommit(); void removeInfraClient(); void selectInfraClient(); void updateInfraClients(); void infraClientContextMenu(const QPoint& pos); protected: void showEvent(QShowEvent *); void hideEvent(QHideEvent *); void closeEvent(QCloseEvent *); void keyPressEvent(QKeyEvent *); typedef qjackctlSession::SaveType SaveType; void saveSessionEx(SaveType stype); void loadSessionDir(const QString& sSessionDir); void saveSessionDir(const QString& sSessionDir, SaveType stype); void updateRecent(const QString& sSessionDir); void updateSessionView(); static QIcon iconStatus(const QIcon& icon, bool bStatus); private: // The Qt-designer UI struct... Ui::qjackctlSessionForm m_ui; // Common (sigleton) session object. qjackctlSession *m_pSession; // Recent session menu. QMenu *m_pRecentMenu; // Save session menu. QMenu *m_pSaveMenu; // Setup options. qjackctlSetup *m_pSetup; // Session directory history. QStringList m_sessionDirs; // session versioning flag. bool m_bSessionSaveVersion; }; #endif // __qjackctlSessionForm_h // end of qjackctlSessionForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlSessionForm.cpp0000644000000000000000000000013214771215054017653 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSessionForm.cpp0000644000175000001440000007040014771215054017644 0ustar00rncbcusers// qjackctlSessionForm.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlSessionForm.h" #include "qjackctlSessionSaveForm.h" #include "qjackctlMainForm.h" #include #include #include #include #include #include #include #include #include #include #include #include // Local prototypes. static void remove_dir_list(const QList& list); static void remove_dir(const QString& sDir); // Remove specific file path. static void remove_dir ( const QString& sDir ) { QDir dir(sDir); remove_dir_list( dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot)); dir.rmdir(sDir); } static void remove_dir_list ( const QList& list ) { QListIterator iter(list); while (iter.hasNext()) { const QFileInfo& info = iter.next(); const QString& sPath = info.absoluteFilePath(); if (info.isDir()) { remove_dir(sPath); } else { QFile::remove(sPath); } } } //------------------------------------------------------------------------- // qjackctlSessionInfraClientItemEditor qjackctlSessionInfraClientItemEditor::qjackctlSessionInfraClientItemEditor ( QWidget *pParent, const QModelIndex& index ) : QWidget(pParent), m_index(index) { m_pItemEdit = new QLineEdit(/*this*/); if (index.column() == 1) { m_pBrowseButton = new QToolButton(/*this*/); m_pBrowseButton->setFixedWidth(18); m_pBrowseButton->setText("..."); } else m_pBrowseButton = nullptr; m_pResetButton = new QToolButton(/*this*/); m_pResetButton->setFixedWidth(18); m_pResetButton->setText("x"); QHBoxLayout *pLayout = new QHBoxLayout(); pLayout->setSpacing(0); pLayout->setContentsMargins(0, 0, 0, 0); pLayout->addWidget(m_pItemEdit); if (m_pBrowseButton) pLayout->addWidget(m_pBrowseButton); pLayout->addWidget(m_pResetButton); QWidget::setLayout(pLayout); QWidget::setFocusPolicy(Qt::StrongFocus); QWidget::setFocusProxy(m_pItemEdit); QObject::connect(m_pItemEdit, SIGNAL(editingFinished()), SLOT(finishSlot())); if (m_pBrowseButton) QObject::connect(m_pBrowseButton, SIGNAL(clicked()), SLOT(browseSlot())); QObject::connect(m_pResetButton, SIGNAL(clicked()), SLOT(resetSlot())); } // Item text accessors. void qjackctlSessionInfraClientItemEditor::setText ( const QString& sText ) { m_pItemEdit->setText(sText); } QString qjackctlSessionInfraClientItemEditor::text (void) const { return m_pItemEdit->text(); } // Item command browser. void qjackctlSessionInfraClientItemEditor::browseSlot (void) { const bool bBlockSignals = m_pItemEdit->blockSignals(true); const QString& sCommand = QFileDialog::getOpenFileName(parentWidget(), tr("Infra-command")); if (!sCommand.isEmpty()) m_pItemEdit->setText(sCommand); m_pItemEdit->blockSignals(bBlockSignals); } // Item text clear/toggler. void qjackctlSessionInfraClientItemEditor::resetSlot (void) { if (m_pItemEdit->text() == m_sDefaultText) m_pItemEdit->clear(); else m_pItemEdit->setText(m_sDefaultText); m_pItemEdit->setFocus(); } // Item text finish notification. void qjackctlSessionInfraClientItemEditor::finishSlot (void) { const bool bBlockSignals = m_pItemEdit->blockSignals(true); emit finishSignal(); m_index = QModelIndex(); m_sDefaultText.clear(); m_pItemEdit->blockSignals(bBlockSignals); } //------------------------------------------------------------------------- // qjackctlSessionInfraClientItemDelegate qjackctlSessionInfraClientItemDelegate::qjackctlSessionInfraClientItemDelegate ( QObject *pParent ) : QItemDelegate(pParent) { } QWidget *qjackctlSessionInfraClientItemDelegate::createEditor ( QWidget *pParent, const QStyleOptionViewItem& /*option*/, const QModelIndex& index ) const { qjackctlSessionInfraClientItemEditor *pItemEditor = new qjackctlSessionInfraClientItemEditor(pParent, index); pItemEditor->setDefaultText( index.model()->data(index, Qt::DisplayRole).toString()); QObject::connect(pItemEditor, SIGNAL(finishSignal()), SLOT(commitEditor())); return pItemEditor; } void qjackctlSessionInfraClientItemDelegate::setEditorData ( QWidget *pEditor, const QModelIndex& index ) const { qjackctlSessionInfraClientItemEditor *pItemEditor = qobject_cast (pEditor); pItemEditor->setText( index.model()->data(index, Qt::DisplayRole).toString()); } void qjackctlSessionInfraClientItemDelegate::setModelData ( QWidget *pEditor, QAbstractItemModel *pModel, const QModelIndex& index ) const { qjackctlSessionInfraClientItemEditor *pItemEditor = qobject_cast (pEditor); pModel->setData(index, pItemEditor->text()); } void qjackctlSessionInfraClientItemDelegate::commitEditor (void) { qjackctlSessionInfraClientItemEditor *pItemEditor = qobject_cast (sender()); const QString& sText = pItemEditor->text(); const QString& sDefaultText = pItemEditor->defaultText(); if (sText != sDefaultText) emit commitData(pItemEditor); emit closeEditor(pItemEditor); } //---------------------------------------------------------------------------- // qjackctlSessionForm -- UI wrapper form. // Constructor. qjackctlSessionForm::qjackctlSessionForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QWidget(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); m_pSetup = nullptr; m_bSessionSaveVersion = false; // Common (sigleton) session object. m_pSession = new qjackctlSession(); // Set recent menu stuff... m_pRecentMenu = new QMenu(tr("&Recent")); m_ui.RecentSessionPushButton->setMenu(m_pRecentMenu); m_pSaveMenu = new QMenu(tr("&Save")); m_pSaveMenu->setIcon(QIcon(":/images/save1.png")); m_pSaveMenu->addAction(QIcon(":/images/save1.png"), tr("&Save..."), this, SLOT(saveSessionSave())); #ifdef CONFIG_JACK_SESSION m_pSaveMenu->addAction( tr("Save and &Quit..."), this, SLOT(saveSessionSaveAndQuit())); m_pSaveMenu->addAction( tr("Save &Template..."), this, SLOT(saveSessionSaveTemplate())); #endif m_ui.SaveSessionPushButton->setMenu(m_pSaveMenu); // Session tree view... QHeaderView *pHeader = m_ui.SessionTreeView->header(); // pHeader->setDefaultAlignment(Qt::AlignLeft); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) // pHeader->setSectionResizeMode(QHeaderView::ResizeToContents); #else // pHeader->setResizeMode(QHeaderView::ResizeToContents); #endif pHeader->resizeSection(0, 200); // Client/Ports pHeader->resizeSection(1, 40); // UUID pHeader->setStretchLastSection(true); m_ui.SessionTreeView->setContextMenuPolicy(Qt::CustomContextMenu); // Infra-client list view... pHeader = m_ui.InfraClientListView->header(); // pHeader->setDefaultAlignment(Qt::AlignLeft); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) // pHeader->setSectionResizeMode(QHeaderView::ResizeToContents); #else // pHeader->setResizeMode(QHeaderView::ResizeToContents); #endif pHeader->resizeSection(0, 120); // Infra-client pHeader->setStretchLastSection(true); m_ui.InfraClientListView->setItemDelegate( new qjackctlSessionInfraClientItemDelegate(m_ui.InfraClientListView)); m_ui.InfraClientListView->setContextMenuPolicy(Qt::CustomContextMenu); m_ui.InfraClientListView->sortItems(0, Qt::AscendingOrder); // UI connections... QObject::connect(m_ui.LoadSessionPushButton, SIGNAL(clicked()), SLOT(loadSession())); QObject::connect(m_ui.UpdateSessionPushButton, SIGNAL(clicked()), SLOT(updateSession())); QObject::connect(m_ui.SessionTreeView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(sessionViewContextMenu(const QPoint&))); QObject::connect(m_ui.InfraClientListView, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), SLOT(selectInfraClient())); QObject::connect(m_ui.AddInfraClientPushButton, SIGNAL(clicked()), SLOT(addInfraClient())); QObject::connect(m_ui.EditInfraClientPushButton, SIGNAL(clicked()), SLOT(editInfraClient())); QObject::connect(m_ui.RemoveInfraClientPushButton, SIGNAL(clicked()), SLOT(removeInfraClient())); QObject::connect(m_ui.InfraClientListView->itemDelegate(), SIGNAL(commitData(QWidget *)), SLOT(editInfraClientCommit())); QObject::connect(m_ui.InfraClientListView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(infraClientContextMenu(const QPoint&))); // Start disabled. stabilizeForm(false); } // Destructor. qjackctlSessionForm::~qjackctlSessionForm (void) { delete m_pSaveMenu; delete m_pRecentMenu; delete m_pSession; } // Set reference to global options, mostly needed for // the initial session save type and directories. void qjackctlSessionForm::setup ( qjackctlSetup *pSetup ) { m_pSetup = pSetup; if (m_pSetup) { // Have recent session directories and versioning option... m_sessionDirs = m_pSetup->sessionDirs; m_bSessionSaveVersion = m_pSetup->bSessionSaveVersion; // Setup infra-clients table view... QList sizes; sizes.append(320); sizes.append(120); m_pSetup->loadSplitterSizes(m_ui.InfraClientSplitter, sizes); // Load infra-clients table-view... m_pSession->loadInfraClients(m_pSetup->settings()); } updateRecentMenu(); updateInfraClients(); } // Maybe ask whether we can close. bool qjackctlSessionForm::queryClose (void) { bool bQueryClose = true; // Maybe just save some splitter sizes... if (m_pSetup && bQueryClose) { // Rebuild infra-clients list... m_pSession->clearInfraClients(); qjackctlSession::InfraClientList& list = m_pSession->infra_clients(); const int iItemCount = m_ui.InfraClientListView->topLevelItemCount(); for (int i = 0; i < iItemCount; ++i) { QTreeWidgetItem *pItem = m_ui.InfraClientListView->topLevelItem(i); if (pItem) { const QString& sKey = pItem->text(0); const QString& sValue = pItem->text(1); if (!sValue.isEmpty()) { qjackctlSession::InfraClientItem *pInfraClientItem = new qjackctlSession::InfraClientItem; pInfraClientItem->client_name = sKey; pInfraClientItem->client_command = sValue; list.insert(sKey, pInfraClientItem); } } } // Save infra-clients table-view... m_pSession->saveInfraClients(m_pSetup->settings()); m_pSetup->saveSplitterSizes(m_ui.InfraClientSplitter); } return bQueryClose; } // Recent session directories accessor. const QStringList& qjackctlSessionForm::sessionDirs (void) const { return m_sessionDirs; } // Session save versioning option. void qjackctlSessionForm::setSessionSaveVersion ( bool bSessionSaveVersion ) { m_bSessionSaveVersion = bSessionSaveVersion; } bool qjackctlSessionForm::isSessionSaveVersion (void) const { return m_bSessionSaveVersion; } // Recent menu accessor. QMenu *qjackctlSessionForm::recentMenu (void) const { return m_pRecentMenu; } // Save menu accessor. QMenu *qjackctlSessionForm::saveMenu (void) const { return m_pSaveMenu; } // Notify our parent that we're emerging. void qjackctlSessionForm::showEvent ( QShowEvent *pShowEvent ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); QWidget::showEvent(pShowEvent); } // Notify our parent that we're closing. void qjackctlSessionForm::hideEvent ( QHideEvent *pHideEvent ) { QWidget::hideEvent(pHideEvent); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); } // Just about to notify main-window that we're closing. void qjackctlSessionForm::closeEvent ( QCloseEvent *pCloseEvent ) { if (m_pSetup) { // Save recent session directories and versioning option... m_pSetup->sessionDirs = m_sessionDirs; m_pSetup->bSessionSaveVersion = m_bSessionSaveVersion; } QWidget::closeEvent(pCloseEvent); } // Open/load session from specific file path. void qjackctlSessionForm::loadSession (void) { QString sSessionDir; #if 0 QFileDialog loadDialog(this, tr("Load Session")); loadDialog.setAcceptMode(QFileDialog::AcceptOpen); loadDialog.setFileMode(QFileDialog::Directory); loadDialog.setViewMode(QFileDialog::List); loadDialog.setOptions(QFileDialog::ShowDirsOnly); loadDialog.setNameFilter(tr("Session directory")); loadDialog.setHistory(m_sessionDirs); if (!m_sessionDirs.isEmpty()) loadDialog.setDirectory(m_sessionDirs.first()); if (!loadDialog.exec()) return; sSessionDir = loadDialog.selectedFiles().first(); #else if (!m_sessionDirs.isEmpty()) sSessionDir = m_sessionDirs.first(); sSessionDir = QFileDialog::getExistingDirectory( this, tr("Load Session"), sSessionDir); #endif loadSessionDir(sSessionDir); } // Load a recent session. void qjackctlSessionForm::recentSession (void) { QAction *pAction = qobject_cast (sender()); if (pAction) { const int i = pAction->data().toInt(); if (i >= 0 && i < m_sessionDirs.count()) loadSessionDir(m_sessionDirs.at(i)); } } // Save current session to specific file path. void qjackctlSessionForm::saveSessionSave (void) { saveSessionEx(SaveType::Save); } void qjackctlSessionForm::saveSessionSaveAndQuit (void) { saveSessionEx(SaveType::SaveAndQuit); } void qjackctlSessionForm::saveSessionSaveTemplate (void) { saveSessionEx(SaveType::SaveTemplate); } void qjackctlSessionForm::saveSessionEx ( SaveType stype ) { QString sTitle = tr("Save Session"); switch (stype) { case SaveType::Save: default: break; case SaveType::SaveAndQuit: sTitle += ' ' + tr("and Quit"); break; case SaveType::SaveTemplate: sTitle += ' ' + tr("Template"); break; } qjackctlSessionSaveForm saveForm(this, sTitle, m_sessionDirs); saveForm.setSessionSaveVersion(isSessionSaveVersion()); if (saveForm.exec()) { setSessionSaveVersion(saveForm.isSessionSaveVersion()); saveSessionDir(saveForm.sessionDir(), stype); } } // Save current session to specific file path. void qjackctlSessionForm::saveSessionVersion ( bool bOn ) { setSessionSaveVersion(bOn); } // Update the recent session list and menu. void qjackctlSessionForm::updateRecent ( const QString& sSessionDir ) { const int i = m_sessionDirs.indexOf(sSessionDir); if (i >= 0) m_sessionDirs.removeAt(i); m_sessionDirs.prepend(sSessionDir); updateRecentMenu(); } // Update/stabilize recent sessions menu. void qjackctlSessionForm::updateRecentMenu (void) { int iRecent = m_sessionDirs.count(); for (; iRecent > 8; --iRecent) m_sessionDirs.pop_back(); m_pRecentMenu->clear(); for (int i = 0; i < iRecent; ++i) { const QString& sSessionDir = m_sessionDirs.at(i); if (QDir(sSessionDir).exists()) { QAction *pAction = m_pRecentMenu->addAction( QFileInfo(sSessionDir).fileName(), this, SLOT(recentSession())); pAction->setData(i); } } if (iRecent > 0) { m_pRecentMenu->addSeparator(); m_pRecentMenu->addAction(tr("&Clear"), this, SLOT(clearRecentMenu())); } m_ui.RecentSessionPushButton->setEnabled(iRecent > 0); } // Clear recent sessions menu. void qjackctlSessionForm::clearRecentMenu (void) { m_sessionDirs.clear(); updateRecentMenu(); } // Open/load session from specific file path. void qjackctlSessionForm::loadSessionDir ( const QString& sSessionDir ) { if (sSessionDir.isEmpty()) return; const QDir sessionDir(sSessionDir); if (!sessionDir.exists("session.xml")) { QMessageBox::critical(this, tr("Warning") + " - " QJACKCTL_TITLE, tr("A session could not be found in this folder:\n\n\"%1\"") .arg(sSessionDir)); return; } qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return; pMainForm->appendMessages( tr("%1: loading session...").arg(sSessionDir)); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); const bool bLoadSession = m_pSession->load(sSessionDir); if (bLoadSession) updateRecent(sessionDir.absolutePath()); updateSessionView(); QApplication::restoreOverrideCursor(); pMainForm->appendMessages( tr("%1: load session %2.").arg(sSessionDir) .arg(bLoadSession ? "OK" : "FAILED")); } // Save current session to specific file path. void qjackctlSessionForm::saveSessionDir ( const QString& sSessionDir, SaveType stype ) { if (sSessionDir.isEmpty()) return; QDir sessionDir(sSessionDir); const QList list = sessionDir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot); if (!list.isEmpty()) { if (sessionDir.exists("session.xml")) { if (QMessageBox::warning(this, tr("Warning") + " - " QJACKCTL_TITLE, tr("A session already exists in this folder:\n\n\"%1\"\n\n" "Are you sure to overwrite the existing session?").arg(sSessionDir), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } else { if (QMessageBox::warning(this, tr("Warning") + " - " QJACKCTL_TITLE, tr("This folder already exists and is not empty:\n\n\"%1\"\n\n" "Are you sure to overwrite the existing folder?").arg(sSessionDir), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; } // remove_dir_list(list); } qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return; pMainForm->appendMessages( tr("%1: saving session...").arg(sSessionDir)); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); if (!list.isEmpty()) { if (isSessionSaveVersion()) { int iSessionDirNo = 0; const QString sSessionDirMask = sSessionDir + ".%1"; QFileInfo fi(sSessionDirMask.arg(++iSessionDirNo)); while (fi.exists()) fi.setFile(sSessionDirMask.arg(++iSessionDirNo)); sessionDir.rename(sSessionDir, fi.absoluteFilePath()); } else remove_dir_list(list); sessionDir.refresh(); } if (!sessionDir.exists()) sessionDir.mkpath(sSessionDir); const bool bSaveSession = m_pSession->save(sSessionDir, stype); if (bSaveSession) updateRecent(sSessionDir); updateSessionView(); QApplication::restoreOverrideCursor(); pMainForm->appendMessages( tr("%1: save session %2.").arg(sSessionDir) .arg(bSaveSession ? "OK" : "FAILED")); } // Set icon error status according to given flag. QIcon qjackctlSessionForm::iconStatus ( const QIcon& icon, bool bStatus ) { QPixmap pm(icon.pixmap(16, 16)); // Merge with the overlay pixmap... if (bStatus) { const QPixmap pmOverlay(":/images/error1.png"); if (!pmOverlay.mask().isNull()) { QBitmap mask = pm.mask(); QPainter(&mask).drawPixmap(0, 0, pmOverlay.mask()); pm.setMask(mask); QPainter(&pm).drawPixmap(0, 0, pmOverlay); } } return QIcon(pm); } // Update/populate session tree view. void qjackctlSessionForm::updateSessionView (void) { m_ui.SessionTreeView->clear(); QList items; const QIcon iconClient(":/images/client1.png"); const QIcon iconPort(":/images/port1.png"); const QIcon iconConnect(":/images/connect1.png"); qjackctlSession::ClientList::ConstIterator iterClient = m_pSession->clients().constBegin(); for ( ; iterClient != m_pSession->clients().constEnd(); ++iterClient) { qjackctlSession::ClientItem *pClientItem = iterClient.value(); QTreeWidgetItem *pTopLevelItem = new QTreeWidgetItem(); pTopLevelItem->setIcon(0, iconStatus(iconClient, pClientItem->connected)); pTopLevelItem->setText(0, pClientItem->client_name); pTopLevelItem->setText(1, pClientItem->client_uuid); pTopLevelItem->setText(2, pClientItem->client_command); QListIterator iterPort(pClientItem->ports); QTreeWidgetItem *pChildItem = nullptr; while (iterPort.hasNext()) { qjackctlSession::PortItem *pPortItem = iterPort.next(); pChildItem = new QTreeWidgetItem(pTopLevelItem, pChildItem); pChildItem->setIcon(0, iconStatus(iconPort, pPortItem->connected)); pChildItem->setText(0, pPortItem->port_name); QListIterator iterConnect(pPortItem->connects); QTreeWidgetItem *pLeafItem = nullptr; while (iterConnect.hasNext()) { qjackctlSession::ConnectItem *pConnectItem = iterConnect.next(); pLeafItem = new QTreeWidgetItem(pChildItem, pLeafItem); pLeafItem->setIcon(0, iconStatus(iconConnect, !pConnectItem->connected)); pLeafItem->setText(0, pConnectItem->client_name + ':' + pConnectItem->port_name); } } items.append(pTopLevelItem); } m_ui.SessionTreeView->insertTopLevelItems(0, items); m_ui.SessionTreeView->expandAll(); } // Update/populate session connections and tree view. void qjackctlSessionForm::updateSession (void) { m_pSession->update(); updateSessionView(); updateInfraClients(); } // Context menu event handler. void qjackctlSessionForm::sessionViewContextMenu ( const QPoint& pos ) { QMenu menu(this); QAction *pAction; bool bEnabled = false; qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) bEnabled = (pMainForm->jackClient() != nullptr); pAction = menu.addAction(QIcon(":/images/open1.png"), tr("&Load..."), this, SLOT(loadSession())); pAction->setEnabled(bEnabled); pAction = menu.addMenu(m_pRecentMenu); pAction->setEnabled(bEnabled && !m_pRecentMenu->isEmpty()); menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/save1.png"), tr("&Save..."), this, SLOT(saveSessionSave())); pAction->setEnabled(bEnabled); #ifdef CONFIG_JACK_SESSION pAction = menu.addAction( tr("Save and &Quit..."), this, SLOT(saveSessionSaveAndQuit())); pAction->setEnabled(bEnabled); pAction = menu.addAction( tr("Save &Template..."), this, SLOT(saveSessionSaveTemplate())); pAction->setEnabled(bEnabled); #endif menu.addSeparator(); pAction = menu.addAction( tr("&Versioning"), this, SLOT(saveSessionVersion(bool))); pAction->setCheckable(true); pAction->setChecked(isSessionSaveVersion()); pAction->setEnabled(bEnabled); menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/refresh1.png"), tr("Re&fresh"), this, SLOT(updateSession())); menu.exec(m_ui.SessionTreeView->mapToGlobal(pos)); } // Add a new infra-client entry. void qjackctlSessionForm::addInfraClient (void) { #ifdef CONFIG_DEBUG_0 qDebug("qjackctlSessionForm::addInfraClient()"); #endif const QString& sNewInfraClient = tr("New Client"); QTreeWidgetItem *pItem = nullptr; const QList& items = m_ui.InfraClientListView->findItems(sNewInfraClient, Qt::MatchExactly); if (items.isEmpty()) { pItem = m_ui.InfraClientListView->currentItem(); pItem = new QTreeWidgetItem(m_ui.InfraClientListView, pItem); pItem->setIcon(0, iconStatus(QIcon(":/images/client1.png"), true)); pItem->setText(0, sNewInfraClient); pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); } else { pItem = items.first(); } m_ui.InfraClientListView->editItem(pItem, 0); } // Edit current infra-client entry. void qjackctlSessionForm::editInfraClient (void) { #ifdef CONFIG_DEBUG_0 qDebug("qjackctlSessionForm::editInfraClient()"); #endif QTreeWidgetItem *pItem = m_ui.InfraClientListView->currentItem(); if (pItem) m_ui.InfraClientListView->editItem(pItem, 1); } void qjackctlSessionForm::editInfraClientCommit (void) { #ifdef CONFIG_DEBUG_0 qDebug("qjackctlSessionForm::editInfraClientCommit()"); #endif QTreeWidgetItem *pItem = m_ui.InfraClientListView->currentItem(); if (pItem) { const QString& sKey = pItem->text(0); if (!sKey.isEmpty()) { const QString& sValue = pItem->text(1); qjackctlSession::InfraClientItem *pInfraClientItem = nullptr; qjackctlSession::InfraClientList& list = m_pSession->infra_clients(); qjackctlSession::InfraClientList::Iterator iter = list.find(sKey); if (iter == list.end()) { pInfraClientItem = new qjackctlSession::InfraClientItem; pInfraClientItem->client_name = sKey; pInfraClientItem->client_command = sValue; list.insert(sKey, pInfraClientItem); } else { pInfraClientItem = iter.value(); pInfraClientItem->client_command = sValue; } pItem->setIcon(0, iconStatus(QIcon(":/images/client1.png"), pInfraClientItem->client_command.isEmpty())); } } } // Remove current infra-client entry. void qjackctlSessionForm::removeInfraClient (void) { #ifdef CONFIG_DEBUG_0 qDebug("qjackctlSessionForm::removeInfraClient()"); #endif QTreeWidgetItem *pItem = m_ui.InfraClientListView->currentItem(); if (pItem) { const QString& sKey = pItem->text(0); qjackctlSession::InfraClientList& list = m_pSession->infra_clients(); qjackctlSession::InfraClientList::Iterator iter = list.find(sKey); if (iter != list.end()) list.erase(iter); delete pItem; updateInfraClients(); } } // Select current infra-client entry. void qjackctlSessionForm::selectInfraClient (void) { #ifdef CONFIG_DEBUG_0 qDebug("qjackctlSessionForm::selectInfraClient()"); #endif QTreeWidgetItem *pItem = m_ui.InfraClientListView->currentItem(); m_ui.AddInfraClientPushButton->setEnabled(true); m_ui.EditInfraClientPushButton->setEnabled(pItem != nullptr); m_ui.RemoveInfraClientPushButton->setEnabled(pItem != nullptr); } // Update/populate infra-clients commands list view. void qjackctlSessionForm::updateInfraClients (void) { #ifdef CONFIG_DEBUG_0 qDebug("qjackctlSessionForm::updateInfraClients()"); #endif const int iOldItem = m_ui.InfraClientListView->indexOfTopLevelItem( m_ui.InfraClientListView->currentItem()); m_ui.InfraClientListView->clear(); const QIcon iconClient(":/images/client1.png"); QTreeWidgetItem *pItem = nullptr; qjackctlSession::InfraClientList& list = m_pSession->infra_clients(); qjackctlSession::InfraClientList::ConstIterator iter = list.constBegin(); const qjackctlSession::InfraClientList::ConstIterator& iter_end = list.constEnd(); for( ; iter != iter_end; ++iter) { qjackctlSession::InfraClientItem *pInfraClientItem = iter.value(); pItem = new QTreeWidgetItem(m_ui.InfraClientListView, pItem); pItem->setIcon(0, iconStatus(iconClient, pInfraClientItem->client_command.isEmpty())); pItem->setText(0, pInfraClientItem->client_name); pItem->setText(1, pInfraClientItem->client_command); pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); } int iItemCount = m_ui.InfraClientListView->topLevelItemCount(); if (iOldItem >= 0 && iOldItem < iItemCount) { m_ui.InfraClientListView->setCurrentItem( m_ui.InfraClientListView->topLevelItem(iOldItem)); } } // Infra-client list context menu. void qjackctlSessionForm::infraClientContextMenu ( const QPoint& pos ) { QMenu menu(this); QAction *pAction; QTreeWidgetItem *pItem = m_ui.InfraClientListView->currentItem(); pAction = menu.addAction(QIcon(":/images/add1.png"), tr("&Add"), this, SLOT(addInfraClient())); // pAction->setEnabled(true); pAction = menu.addAction(QIcon(":/images/edit1.png"), tr("&Edit"), this, SLOT(editInfraClient())); pAction->setEnabled(pItem != nullptr); pAction = menu.addAction(QIcon(":/images/remove1.png"), tr("Re&move"), this, SLOT(removeInfraClient())); pAction->setEnabled(pItem != nullptr); menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/refresh1.png"), tr("Re&fresh"), this, SLOT(updateInfraClients())); // pAction->setEnabled(true); menu.exec(m_ui.InfraClientListView->mapToGlobal(pos)); } // Stabilize form status. void qjackctlSessionForm::stabilizeForm ( bool bEnabled ) { m_ui.LoadSessionPushButton->setEnabled(bEnabled); m_ui.RecentSessionPushButton->setEnabled(bEnabled && !m_pRecentMenu->isEmpty()); m_ui.SaveSessionPushButton->setEnabled(bEnabled); m_ui.UpdateSessionPushButton->setEnabled(bEnabled); if (!bEnabled) { m_pSession->clear(); m_ui.SessionTreeView->clear(); } selectInfraClient(); } // Keyboard event handler. void qjackctlSessionForm::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qjackctlSessionForm::keyPressEvent(%d)", pKeyEvent->key()); #endif const int iKey = pKeyEvent->key(); switch (iKey) { case Qt::Key_Escape: close(); break; default: QWidget::keyPressEvent(pKeyEvent); break; } } // end of qjackctlSessionForm.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlMessagesStatusForm.ui0000644000000000000000000000013214771215054021036 xustar0030 mtime=1743067692.326636579 30 atime=1743067692.326636579 30 ctime=1743067692.326636579 qjackctl-1.0.4/src/qjackctlMessagesStatusForm.ui0000644000175000001440000001441014771215054021026 0ustar00rncbcusers rncbc aka Rui Nuno Capela JACK Audio Connection Kit - Qt GUI Interface. Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlMessagesStatusForm 0 0 480 320 0 0 Messages / Status :/images/messagesstatus1.png 0 :/images/messages1.png &Messages Messages log 320 80 Messages output log false QTextEdit::NoWrap true :/images/status1.png &Status Status information 0 0 240 0 Statistics since last server startup true QAbstractItemView::NoSelection true true false true Description Value Reset XRUN statistic values Re&set :/images/reset1.png Qt::Horizontal QSizePolicy::Expanding 313 16 Refresh XRUN statistic values &Refresh :/images/refresh1.png MessagesTextView StatsListView ResetPushButton RefreshPushButton qjackctl-1.0.4/src/PaxHeaders/appdata0000644000000000000000000000013014771215054014516 xustar0030 mtime=1743067692.318540145 28 atime=1743067692.3182779 30 ctime=1743067692.318540145 qjackctl-1.0.4/src/appdata/0000755000175000001440000000000014771215054014565 5ustar00rncbcusersqjackctl-1.0.4/src/appdata/PaxHeaders/org.rncbc.qjackctl.metainfo.xml0000644000000000000000000000013214771215054022570 xustar0030 mtime=1743067692.318540145 30 atime=1743067692.318540145 30 ctime=1743067692.318540145 qjackctl-1.0.4/src/appdata/org.rncbc.qjackctl.metainfo.xml0000644000175000001440000000547214771215054022570 0ustar00rncbcusers org.rncbc.qjackctl FSFAP GPL-2.0+ QjackCtl JACK Audio Connection Kit Qt GUI Interface Interface graphique Qt pour le kit de connexion audio JACK

JACK Audio Connection Kit - Qt GUI Interface: A simple Qt application to control the JACK server. Written in C++ around the Qt framework for X11, most exclusively using Qt Designer. Provides a simple GUI dialog for setting several JACK server parameters, which are properly saved between sessions, and a way control of the status of the audio server. With time, this primordial interface has become richer by including a enhanced patchbay and connection control features.

Interface graphique Qt pour le kit de connexion audio Jack : une application Qt simple pour contrôler le server Jack. Écrite en c++ autour du kit de développement Qt pour X11, presque exclusivement en utilisant Qt Designer. Fourni une interface graphique simple de dialogue pour plusieurs paramètres du serveur JACK qui sont sauvegardés proprement entre les sessions, et un moyen de contrôle du status du serveur audio. Avec le temps, cette interface primordiale est devenue plus riche en incluant une baie de brassage améliorée et des fonctionnalités de contrôle de connexion.

org.rncbc.qjackctl.desktop qjackctl https://qjackctl.sourceforge.io/image/qjackctl-screenshot1.png The main window showing the application in action La fenêtre principale montrant l'application en action Audio MIDI ALSA JACK Qt https://qjackctl.sourceforge.io rncbc.org rncbc aka. Rui Nuno Capela rncbc@rncbc.org
qjackctl-1.0.4/src/appdata/PaxHeaders/Info.plist0000644000000000000000000000013214771215054016545 xustar0030 mtime=1743067692.318508791 30 atime=1743067692.318508791 30 ctime=1743067692.318508791 qjackctl-1.0.4/src/appdata/Info.plist0000644000175000001440000000145314771215054016540 0ustar00rncbcusers NSPrincipalClass NSApplication CFBundleIconFile QjackCtl.icns CFBundlePackageType APPL CFBundleGetInfoString JACK Audio Connection Kit Qt GUI Interface CFBundleSignature ???? CFBundleExecutable QjackCtl CFBundleIdentifier org.rncbc.QjackCtl NSMicrophoneUsageDescription JACK requires microphone permissions for audio input. NSSupportsAutomaticGraphicsSwitching qjackctl-1.0.4/src/appdata/PaxHeaders/org.rncbc.qjackctl.desktop0000644000000000000000000000013214771215054021640 xustar0030 mtime=1743067692.318540145 30 atime=1743067692.318508791 30 ctime=1743067692.318540145 qjackctl-1.0.4/src/appdata/org.rncbc.qjackctl.desktop0000644000175000001440000000220414771215054021626 0ustar00rncbcusers[Desktop Entry] Name=QjackCtl Version=1.0 GenericName=JACK Control GenericName[de]=JACK-Steuerung GenericName[fr]=Contrôle JACK GenericName[it]=Interfaccia di controllo per JACK GenericName[ru]=Управление JACK GenericName[uk]=Керування JACK Comment=QjackCtl is a JACK Audio Connection Kit Qt GUI Interface Comment[de]=Grafisches Werkzeug zur Steuerung des JACK-Audio-Systems Comment[fr]=QjackCtl est une interface graphique Qt pour le kit de connexion audio JACK Comment[it]=QjackCtl è un'interfaccia di controllo per JACK basata su Qt Comment[ru]=Программа для управления звуковым сервером JACK Comment[sk]=QjackCtl je grafické rozhranie (Qt) na ovládanie zvukového servera JACK Comment[uk]=QjackCtl є програмою для керування звуковим сервером JACK Exec=qjackctl Icon=org.rncbc.qjackctl Categories=Audio;AudioVideo;Midi;X-Alsa;X-Jack;Qt; Keywords=Audio;MIDI;ALSA;JACK;LV2;Qt; Keywords[uk]=Audio;MIDI;ALSA;JACK;LV2;Qt;Звук;міді;алса;джек; Terminal=false Type=Application StartupWMClass=qjackctl X-Window-Icon=qjackctl X-SuSE-translate=true qjackctl-1.0.4/src/PaxHeaders/qjackctlPatchbayForm.cpp0000644000000000000000000000012714771215054017767 xustar0029 mtime=1743067692.32863657 29 atime=1743067692.32863657 29 ctime=1743067692.32863657 qjackctl-1.0.4/src/qjackctlPatchbayForm.cpp0000644000175000001440000004506114771215054017761 0ustar00rncbcusers// qjackctlPatchbayForm.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlPatchbayForm.h" #include "qjackctlPatchbayFile.h" #include "qjackctlMainForm.h" #include #include #include #include #include #include //---------------------------------------------------------------------------- // qjackctlPatchbayForm -- UI wrapper form. // Constructor. qjackctlPatchbayForm::qjackctlPatchbayForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QWidget(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); m_pSetup = nullptr; // Create the patchbay view object. m_pPatchbay = new qjackctlPatchbay(m_ui.PatchbayView); m_iUntitled = 0; m_bActivePatchbay = false; m_iUpdate = 0; // UI connections... QObject::connect(m_ui.NewPatchbayPushButton, SIGNAL(clicked()), SLOT(newPatchbay())); QObject::connect(m_ui.LoadPatchbayPushButton, SIGNAL(clicked()), SLOT(loadPatchbay())); QObject::connect(m_ui.SavePatchbayPushButton, SIGNAL(clicked()), SLOT(savePatchbay())); QObject::connect(m_ui.PatchbayComboBox, SIGNAL(activated(int)), SLOT(selectPatchbay(int))); QObject::connect(m_ui.ActivatePatchbayPushButton, SIGNAL(clicked()), SLOT(toggleActivePatchbay())); QObject::connect(m_ui.OSocketAddPushButton, SIGNAL(clicked()), SLOT(addOSocket())); QObject::connect(m_ui.OSocketEditPushButton, SIGNAL(clicked()), SLOT(editOSocket())); QObject::connect(m_ui.OSocketCopyPushButton, SIGNAL(clicked()), SLOT(copyOSocket())); QObject::connect(m_ui.OSocketRemovePushButton, SIGNAL(clicked()), SLOT(removeOSocket())); QObject::connect(m_ui.OSocketMoveUpPushButton, SIGNAL(clicked()), SLOT(moveUpOSocket())); QObject::connect(m_ui.OSocketMoveDownPushButton, SIGNAL(clicked()), SLOT(moveDownOSocket())); QObject::connect(m_ui.ISocketAddPushButton, SIGNAL(clicked()), SLOT(addISocket())); QObject::connect(m_ui.ISocketEditPushButton, SIGNAL(clicked()), SLOT(editISocket())); QObject::connect(m_ui.ISocketCopyPushButton, SIGNAL(clicked()), SLOT(copyISocket())); QObject::connect(m_ui.ISocketRemovePushButton, SIGNAL(clicked()), SLOT(removeISocket())); QObject::connect(m_ui.ISocketMoveUpPushButton, SIGNAL(clicked()), SLOT(moveUpISocket())); QObject::connect(m_ui.ISocketMoveDownPushButton, SIGNAL(clicked()), SLOT(moveDownISocket())); QObject::connect(m_ui.ConnectPushButton, SIGNAL(clicked()), SLOT(connectSelected())); QObject::connect(m_ui.DisconnectPushButton, SIGNAL(clicked()), SLOT(disconnectSelected())); QObject::connect(m_ui.DisconnectAllPushButton, SIGNAL(clicked()), SLOT(disconnectAll())); QObject::connect(m_ui.ExpandAllPushButton, SIGNAL(clicked()), SLOT(expandAll())); QObject::connect(m_ui.RefreshPushButton, SIGNAL(clicked()), SLOT(refreshForm())); // Connect it to some UI feedback slot. QObject::connect(m_ui.PatchbayView->OListView(), SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(stabilizeForm())); QObject::connect(m_ui.PatchbayView->IListView(), SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(stabilizeForm())); // Dirty patchbay dispatcher (stabilization deferral). QObject::connect(m_ui.PatchbayView, SIGNAL(contentsChanged()), SLOT(contentsChanged())); newPatchbayFile(false); stabilizeForm(); } // Destructor. qjackctlPatchbayForm::~qjackctlPatchbayForm (void) { // May delete the patchbay view object. delete m_pPatchbay; } // Notify our parent that we're emerging. void qjackctlPatchbayForm::showEvent ( QShowEvent *pShowEvent ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); stabilizeForm(); QWidget::showEvent(pShowEvent); } // Notify our parent that we're closing. void qjackctlPatchbayForm::hideEvent ( QHideEvent *pHideEvent ) { QWidget::hideEvent(pHideEvent); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); } // Just about to notify main-window that we're closing. void qjackctlPatchbayForm::closeEvent ( QCloseEvent *pCloseEvent ) { if (m_pSetup) { const QString& sPatchbayPath = patchbayPath(); if (!sPatchbayPath.isEmpty()) m_pSetup->sPatchbayPath = sPatchbayPath; } QWidget::closeEvent(pCloseEvent); } // Set reference to global options, mostly needed for the // initial sizes of the main splitter views... void qjackctlPatchbayForm::setup ( qjackctlSetup *pSetup ) { m_pSetup = pSetup; // Load main splitter sizes... if (m_pSetup) { QList sizes; sizes.append(180); sizes.append(60); sizes.append(180); m_pSetup->loadSplitterSizes(m_ui.PatchbayView, sizes); } } // Patchbay view accessor. qjackctlPatchbayView *qjackctlPatchbayForm::patchbayView (void) const { return m_ui.PatchbayView; } // Window close event handlers. bool qjackctlPatchbayForm::queryClose (void) { bool bQueryClose = true; if (m_ui.PatchbayView->dirty()) { switch (QMessageBox::warning(this, tr("Warning") + " - " QJACKCTL_TITLE, tr("The patchbay definition has been changed:\n\n" "\"%1\"\n\nDo you want to save the changes?") .arg(m_sPatchbayName), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) { case QMessageBox::Save: savePatchbay(); // Fall thru.... case QMessageBox::Discard: break; default: // Cancel. bQueryClose = false; } } // Save main splitter sizes... if (m_pSetup && bQueryClose) m_pSetup->saveSplitterSizes(m_ui.PatchbayView); return bQueryClose; } // Contents change deferrer slot... void qjackctlPatchbayForm::contentsChanged (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->refreshPatchbay(); } // Refresh complete form. void qjackctlPatchbayForm::refreshForm (void) { m_pPatchbay->refresh(); stabilizeForm(); } // A helper stabilization slot. void qjackctlPatchbayForm::stabilizeForm ( void ) { m_ui.SavePatchbayPushButton->setEnabled(m_ui.PatchbayView->dirty()); m_ui.ActivatePatchbayPushButton->setEnabled( QFileInfo(m_sPatchbayPath).exists()); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); m_bActivePatchbay = (pMainForm && pMainForm->isActivePatchbay(m_sPatchbayPath)); m_ui.ActivatePatchbayPushButton->setChecked(m_bActivePatchbay); if (m_ui.PatchbayView->dirty()) { m_ui.PatchbayComboBox->setItemText( m_ui.PatchbayComboBox->currentIndex(), tr("%1 [modified]").arg(m_sPatchbayName)); } // Take care that IT might be destroyed already... if (m_ui.PatchbayView->binding() == nullptr) return; bool bExpandAll = false; qjackctlSocketList *pSocketList; qjackctlSocketItem *pSocketItem; int iItemCount, iItem; pSocketList = m_pPatchbay->OSocketList(); pSocketItem = pSocketList->selectedSocketItem(); iItemCount = (pSocketList->listView())->topLevelItemCount(); bExpandAll = bExpandAll || (iItemCount > 0); if (pSocketItem) { iItem = (pSocketList->listView())->indexOfTopLevelItem(pSocketItem); m_ui.OSocketEditPushButton->setEnabled(true); m_ui.OSocketCopyPushButton->setEnabled(true); m_ui.OSocketRemovePushButton->setEnabled(true); m_ui.OSocketMoveUpPushButton->setEnabled(iItem > 0); m_ui.OSocketMoveDownPushButton->setEnabled(iItem < iItemCount - 1); } else { m_ui.OSocketEditPushButton->setEnabled(false); m_ui.OSocketCopyPushButton->setEnabled(false); m_ui.OSocketRemovePushButton->setEnabled(false); m_ui.OSocketMoveUpPushButton->setEnabled(false); m_ui.OSocketMoveDownPushButton->setEnabled(false); } pSocketList = m_pPatchbay->ISocketList(); pSocketItem = pSocketList->selectedSocketItem(); iItemCount = (pSocketList->listView())->topLevelItemCount(); bExpandAll = bExpandAll || (iItemCount > 0); if (pSocketItem) { iItem = (pSocketList->listView())->indexOfTopLevelItem(pSocketItem); m_ui.ISocketEditPushButton->setEnabled(true); m_ui.ISocketCopyPushButton->setEnabled(true); m_ui.ISocketRemovePushButton->setEnabled(true); m_ui.ISocketMoveUpPushButton->setEnabled(iItem > 0); m_ui.ISocketMoveDownPushButton->setEnabled(iItem < iItemCount - 1); } else { m_ui.ISocketEditPushButton->setEnabled(false); m_ui.ISocketCopyPushButton->setEnabled(false); m_ui.ISocketRemovePushButton->setEnabled(false); m_ui.ISocketMoveUpPushButton->setEnabled(false); m_ui.ISocketMoveDownPushButton->setEnabled(false); } m_ui.ConnectPushButton->setEnabled( m_pPatchbay->canConnectSelected()); m_ui.DisconnectPushButton->setEnabled( m_pPatchbay->canDisconnectSelected()); m_ui.DisconnectAllPushButton->setEnabled( m_pPatchbay->canDisconnectAll()); m_ui.ExpandAllPushButton->setEnabled(bExpandAll); } // Patchbay path accessor. const QString& qjackctlPatchbayForm::patchbayPath (void) const { return m_sPatchbayPath; } // Reset patchbay definition from scratch. void qjackctlPatchbayForm::newPatchbayFile ( bool bSnapshot ) { m_pPatchbay->clear(); m_sPatchbayPath.clear(); m_sPatchbayName = tr("Untitled%1").arg(m_iUntitled++); if (bSnapshot) m_pPatchbay->connectionsSnapshot(); // updateRecentPatchbays(); } // Load patchbay definitions from specific file path. bool qjackctlPatchbayForm::loadPatchbayFile ( const QString& sFileName ) { // Check if we're going to discard safely the current one... if (!queryClose()) return false; // We'll have a temporary rack... qjackctlPatchbayRack rack; // Step 1: load from file... if (!qjackctlPatchbayFile::load(&rack, sFileName)) { QMessageBox::critical(this, tr("Error") + " - " QJACKCTL_TITLE, tr("Could not load patchbay definition file: \n\n\"%1\"") .arg(sFileName), QMessageBox::Cancel); // Reset/disable further trials. m_sPatchbayPath.clear(); return false; } // Step 2: load from rack... m_pPatchbay->loadRack(&rack); // Step 3: stabilize form... m_sPatchbayPath = sFileName; m_sPatchbayName = QFileInfo(sFileName).completeBaseName(); // updateRecentPatchbays(); return true; } // Save current patchbay definition to specific file path. bool qjackctlPatchbayForm::savePatchbayFile ( const QString& sFileName ) { // We'll have a temporary rack... qjackctlPatchbayRack rack; // Step 1: save to rack... m_pPatchbay->saveRack(&rack); // Step 2: save to file... if (!qjackctlPatchbayFile::save(&rack, sFileName)) { QMessageBox::critical(this, tr("Error") + " - " QJACKCTL_TITLE, tr("Could not save patchbay definition file: \n\n\"%1\"") .arg(sFileName), QMessageBox::Cancel); return false; } // Step 3: stabilize form... m_sPatchbayPath = sFileName; m_sPatchbayName = QFileInfo(sFileName).completeBaseName(); // updateRecentPatchbays(); // Step 4: notify main form if applicable ... qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); m_bActivePatchbay = (pMainForm && pMainForm->isActivePatchbay(m_sPatchbayPath)); if (m_bActivePatchbay) pMainForm->updateActivePatchbay(); return true; } // Dirty-(re)load patchbay definitions from know rack. void qjackctlPatchbayForm::loadPatchbayRack ( qjackctlPatchbayRack *pRack ) { // Step 1: load from rack... m_pPatchbay->loadRack(pRack); // Override dirty flag. m_ui.PatchbayView->setDirty(true); // Done. stabilizeForm(); } // Create a new patchbay definition from scratch. void qjackctlPatchbayForm::newPatchbay (void) { // Assume a snapshot from scratch... bool bSnapshot = false; // Ask user what he/she wants to do... qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm && (pMainForm->jackClient() || pMainForm->alsaSeq())) { switch (QMessageBox::information(this, tr("New Patchbay definition") + " - " QJACKCTL_TITLE, tr("Create patchbay definition as a snapshot\n" "of all actual client connections?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel)) { case QMessageBox::Yes: bSnapshot = true; break; case QMessageBox::No: bSnapshot = false; break; default: // Cancel. return; } } // Check if we can discard safely the current one... if (!queryClose()) return; // Reset patchbay editor. newPatchbayFile(bSnapshot); updateRecentPatchbays(); stabilizeForm(); } // Load patchbay definitions from file. void qjackctlPatchbayForm::loadPatchbay (void) { QString sFileName = QFileDialog::getOpenFileName( this, tr("Load Patchbay Definition"), // Parent & Caption. m_sPatchbayPath, // Start here. tr("Patchbay Definition files") + " (*.xml)" // Filter (XML files) ); if (sFileName.isEmpty()) return; // Load it right away. if (loadPatchbayFile(sFileName)) updateRecentPatchbays(); stabilizeForm(); } // Save current patchbay definition to file. void qjackctlPatchbayForm::savePatchbay (void) { QString sFileName = QFileDialog::getSaveFileName( this, tr("Save Patchbay Definition"), // Parent & Caption. m_sPatchbayPath, // Start here. tr("Patchbay Definition files") + " (*.xml)" // Filter (XML files) ); if (sFileName.isEmpty()) return; // Enforce .xml extension... if (QFileInfo(sFileName).suffix().isEmpty()) sFileName += ".xml"; // Save it right away. if (savePatchbayFile(sFileName)) updateRecentPatchbays(); stabilizeForm(); } // A new patchbay has been selected void qjackctlPatchbayForm::selectPatchbay ( int iPatchbay ) { // Remember and avoid reloading the previous (first) selected one. if (iPatchbay > 0) { // Take care whether the first is untitled, and // thus not present in the recenet ptachbays list if (m_sPatchbayPath.isEmpty()) iPatchbay--; if (iPatchbay >= 0 && iPatchbay < m_recentPatchbays.count()) { // If we cannot load the new one, backout... loadPatchbayFile(m_recentPatchbays[iPatchbay]); updateRecentPatchbays(); } } stabilizeForm(); } // Set current active patchbay definition file. void qjackctlPatchbayForm::toggleActivePatchbay (void) { // Check if we're going to discard safely the current one... if (!queryClose()) return; // Activate it... qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) { pMainForm->setActivePatchbay( m_bActivePatchbay ? QString() : m_sPatchbayPath); } // Need to force/refresh the patchbay list... updateRecentPatchbays(); stabilizeForm(); } // Set/initialize the MRU patchbay list. void qjackctlPatchbayForm::setRecentPatchbays ( const QStringList& patchbays ) { m_recentPatchbays = patchbays; } // Update patchbay MRU variables and widgets. void qjackctlPatchbayForm::updateRecentPatchbays (void) { // Try not to be reeentrant. if (m_iUpdate > 0) return; m_iUpdate++; // Update the visible combobox... const QIcon icon(":/images/patchbay1.png"); m_ui.PatchbayComboBox->clear(); if (m_sPatchbayPath.isEmpty()) { // Display a probable untitled patchbay... m_ui.PatchbayComboBox->addItem(icon, m_sPatchbayName); } else { // Remove from list if already there (avoid duplicates)... int iIndex = m_recentPatchbays.indexOf(m_sPatchbayPath); if (iIndex >= 0) m_recentPatchbays.removeAt(iIndex); // Put it to front... m_recentPatchbays.push_front(m_sPatchbayPath); } // Time to keep the list under limits. while (m_recentPatchbays.count() > 8) m_recentPatchbays.pop_back(); // Update the main setup list... qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->setRecentPatchbays(m_recentPatchbays); QStringListIterator iter(m_recentPatchbays); while (iter.hasNext()) { const QString& sPatchbayPath = iter.next(); QString sText = QFileInfo(sPatchbayPath).completeBaseName(); if (pMainForm && pMainForm->isActivePatchbay(sPatchbayPath)) sText += " [" + tr("active") + "]"; m_ui.PatchbayComboBox->addItem(icon, sText); } // Sure this one must be currently selected. m_ui.PatchbayComboBox->setCurrentIndex(0); // stabilizeForm(); m_iUpdate--; } // Output socket list push button handlers gallore... void qjackctlPatchbayForm::addOSocket (void) { (m_pPatchbay->OSocketList())->addSocketItem(); } void qjackctlPatchbayForm::removeOSocket (void) { (m_pPatchbay->OSocketList())->removeSocketItem(); } void qjackctlPatchbayForm::editOSocket (void) { (m_pPatchbay->OSocketList())->editSocketItem(); } void qjackctlPatchbayForm::copyOSocket (void) { (m_pPatchbay->OSocketList())->copySocketItem(); } void qjackctlPatchbayForm::moveUpOSocket (void) { (m_pPatchbay->OSocketList())->moveUpSocketItem(); } void qjackctlPatchbayForm::moveDownOSocket (void) { (m_pPatchbay->OSocketList())->moveDownSocketItem(); } // Input socket list push button handlers gallore... void qjackctlPatchbayForm::addISocket (void) { (m_pPatchbay->ISocketList())->addSocketItem(); } void qjackctlPatchbayForm::removeISocket (void) { (m_pPatchbay->ISocketList())->removeSocketItem(); } void qjackctlPatchbayForm::editISocket (void) { (m_pPatchbay->ISocketList())->editSocketItem(); } void qjackctlPatchbayForm::copyISocket (void) { (m_pPatchbay->ISocketList())->copySocketItem(); } void qjackctlPatchbayForm::moveUpISocket (void) { (m_pPatchbay->ISocketList())->moveUpSocketItem(); } void qjackctlPatchbayForm::moveDownISocket (void) { (m_pPatchbay->ISocketList())->moveDownSocketItem(); } // Connect current selected ports. void qjackctlPatchbayForm::connectSelected (void) { m_pPatchbay->connectSelected(); } // Disconnect current selected ports. void qjackctlPatchbayForm::disconnectSelected (void) { m_pPatchbay->disconnectSelected(); } // Disconnect all connected ports. void qjackctlPatchbayForm::disconnectAll (void) { m_pPatchbay->disconnectAll(); } // Expand all socket items. void qjackctlPatchbayForm::expandAll (void) { m_pPatchbay->expandAll(); } // Keyboard event handler. void qjackctlPatchbayForm::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qjackctlPatchbayForm::keyPressEvent(%d)", pKeyEvent->key()); #endif int iKey = pKeyEvent->key(); switch (iKey) { case Qt::Key_Escape: close(); break; default: QWidget::keyPressEvent(pKeyEvent); break; } } // end of qjackctlPatchbayForm.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlConnect.cpp0000644000000000000000000000013214771215054016775 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlConnect.cpp0000644000175000001440000015233714771215054017000 0ustar00rncbcusers// qjackctlConnect.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAbout.h" #include "qjackctlConnect.h" #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) #include #include #endif //---------------------------------------------------------------------- // class qjackctlPortItem -- Port list item. // // Constructor. qjackctlPortItem::qjackctlPortItem ( qjackctlClientItem *pClient ) : QTreeWidgetItem(pClient, QJACKCTL_PORTITEM) { m_pClient = pClient; // m_sPortName = sPortName; m_iPortMark = 0; m_bHilite = false; m_pClient->ports().append(this); } // Default destructor. qjackctlPortItem::~qjackctlPortItem (void) { const int iPort = m_pClient->ports().indexOf(this); if (iPort >= 0) m_pClient->ports().removeAt(iPort); QListIterator iter(m_connects); while (iter.hasNext()) (iter.next())->removeConnect(this); m_connects.clear(); } // Instance accessors. void qjackctlPortItem::setPortName ( const QString& sPortName ) { m_sPortName = sPortName; updatePortName(); } const QString& qjackctlPortItem::clientName (void) const { return m_pClient->clientName(); } const QString& qjackctlPortItem::portName (void) const { return m_sPortName; } // Port name alias accessors. void qjackctlPortItem::setPortNameAlias ( const QString& sPortNameAlias ) { // Check aliasing... qjackctlClientListView *pClientListView = (m_pClient->clientList())->listView(); qjackctlAliasList *pAliasList = pClientListView->aliasList(); if (pAliasList) { const QString& sClientName = m_pClient->clientName(); pAliasList->setPortAlias(sClientName, m_sPortName, sPortNameAlias); pClientListView->emitAliasesChanged(); } } QString qjackctlPortItem::portNameAlias ( bool *pbRenameEnabled ) const { QString sPortNameAlias = m_sPortName; bool bRenameEnabled = false; // Check aliasing... qjackctlClientListView *pClientListView = (m_pClient->clientList())->listView(); qjackctlAliasList *pAliasList = pClientListView->aliasList(); if (pAliasList) { const QString& sClientName = m_pClient->clientName(); sPortNameAlias = pAliasList->portAlias(sClientName, m_sPortName); bRenameEnabled = pClientListView->isRenameEnabled(); } if (pbRenameEnabled) *pbRenameEnabled = bRenameEnabled; return sPortNameAlias; } // Proto-pretty/alias display name method. void qjackctlPortItem::updatePortName ( bool /*bRename*/ ) { bool bRenameEnabled = false; const QString& sPortNameEx = portNameAlias(&bRenameEnabled); setPortText(sPortNameEx, bRenameEnabled); } // Tooltip text builder. QString qjackctlPortItem::tooltip (void) const { return portName(); } // Port display name accessors. void qjackctlPortItem::setPortText ( const QString& sPortText, bool bRenameEnabled ) { QTreeWidgetItem::setText(0, sPortText); const Qt::ItemFlags flags = QTreeWidgetItem::flags(); if (bRenameEnabled) QTreeWidgetItem::setFlags(flags | Qt::ItemIsEditable); else QTreeWidgetItem::setFlags(flags & ~Qt::ItemIsEditable); } QString qjackctlPortItem::portText (void) const { return QTreeWidgetItem::text(0); } // Complete client:port name helper. QString qjackctlPortItem::clientPortName (void) const { return m_pClient->clientName() + ':' + m_sPortName; } // Connect client item accessor. qjackctlClientItem *qjackctlPortItem::client (void) const { return m_pClient; } // Client:port set housekeeping marker. void qjackctlPortItem::markPort ( int iMark ) { setHilite(false); m_iPortMark = iMark; if (iMark > 0) m_connects.clear(); } void qjackctlPortItem::markClientPort ( int iMark ) { markPort(iMark); m_pClient->markClient(iMark); } int qjackctlPortItem::portMark (void) const { return m_iPortMark; } // Connected port list primitives. void qjackctlPortItem::addConnect ( qjackctlPortItem *pPort ) { m_connects.append(pPort); } void qjackctlPortItem::removeConnect ( qjackctlPortItem *pPort ) { pPort->setHilite(false); const int iPort = m_connects.indexOf(pPort); if (iPort >= 0) m_connects.removeAt(iPort); } // Connected port finder. qjackctlPortItem *qjackctlPortItem::findConnect ( const QString& sClientPortName ) { QListIterator iter(m_connects); while (iter.hasNext()) { qjackctlPortItem *pPort = iter.next(); if (sClientPortName == pPort->clientPortName()) return pPort; } return nullptr; } qjackctlPortItem *qjackctlPortItem::findConnectPtr ( qjackctlPortItem *pPortPtr ) { QListIterator iter(m_connects); while (iter.hasNext()) { qjackctlPortItem *pPort = iter.next(); if (pPortPtr == pPort) return pPort; } return nullptr; } // Connection cache list accessor. const QList& qjackctlPortItem::connects (void) const { return m_connects; } // Connectiopn highlight methods. bool qjackctlPortItem::isHilite (void) const { return m_bHilite; } void qjackctlPortItem::setHilite ( bool bHilite ) { // Update the port highlightning if changed... if ((m_bHilite && !bHilite) || (!m_bHilite && bHilite)) { m_bHilite = bHilite; // Propagate this to the parent... m_pClient->setHilite(bHilite); } // Set the new color. QTreeWidget *pTreeWidget = QTreeWidgetItem::treeWidget(); if (pTreeWidget == nullptr) return; const QPalette& pal = pTreeWidget->palette(); QTreeWidgetItem::setForeground(0, m_bHilite ? (pal.base().color().value() < 0x7f ? Qt::cyan : Qt::blue) : pal.text().color()); } // Proxy sort override method. // - Natural decimal sorting comparator. bool qjackctlPortItem::operator< ( const QTreeWidgetItem& other ) const { return qjackctlClientList::lessThan(*this, other); } //---------------------------------------------------------------------- // class qjackctlClientItem -- Jack client list item. // // Constructor. qjackctlClientItem::qjackctlClientItem ( qjackctlClientList *pClientList ) : QTreeWidgetItem(pClientList->listView(), QJACKCTL_CLIENTITEM) { m_pClientList = pClientList; // m_sClientName = sClientName; m_iClientMark = 0; m_iHilite = 0; m_pClientList->clients().append(this); } // Default destructor. qjackctlClientItem::~qjackctlClientItem (void) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) qDeleteAll(m_ports); #endif m_ports.clear(); const int iClient = m_pClientList->clients().indexOf(this); if (iClient >= 0) m_pClientList->clients().removeAt(iClient); } // Port finder. qjackctlPortItem *qjackctlClientItem::findPort (const QString& sPortName) { QListIterator iter(m_ports); while (iter.hasNext()) { qjackctlPortItem *pPort = iter.next(); if (sPortName == pPort->portName()) return pPort; } return nullptr; } // Client list accessor. qjackctlClientList *qjackctlClientItem::clientList (void) const { return m_pClientList; } // Port list accessor. QList& qjackctlClientItem::ports (void) { return m_ports; } // Instance accessors. void qjackctlClientItem::setClientName ( const QString& sClientName ) { m_sClientName = sClientName; updateClientName(); } const QString& qjackctlClientItem::clientName (void) const { return m_sClientName; } // Client name alias accessors. void qjackctlClientItem::setClientNameAlias ( const QString& sClientNameAlias ) { qjackctlClientListView *pClientListView = m_pClientList->listView(); qjackctlAliasList *pAliasList = pClientListView->aliasList(); if (pAliasList) { pAliasList->setClientAlias(m_sClientName, sClientNameAlias); pClientListView->emitAliasesChanged(); } } QString qjackctlClientItem::clientNameAlias ( bool *pbRenameEnabled ) const { QString sClientNameAlias = m_sClientName; bool bRenameEnabled = false; // Check aliasing... qjackctlClientListView *pClientListView = m_pClientList->listView(); qjackctlAliasList *pAliasList = pClientListView->aliasList(); if (pAliasList) { sClientNameAlias = pAliasList->clientAlias(m_sClientName); bRenameEnabled = pClientListView->isRenameEnabled(); } if (pbRenameEnabled) *pbRenameEnabled = bRenameEnabled; return sClientNameAlias; } // Proto-pretty/alias display name method. void qjackctlClientItem::updateClientName ( bool /*bRename*/ ) { bool bRenameEnabled = false; const QString& sClientNameEx = clientNameAlias(&bRenameEnabled); setClientText(sClientNameEx, bRenameEnabled); } // Client display name accessors. void qjackctlClientItem::setClientText ( const QString& sClientText, bool bRenameEnabled ) { QTreeWidgetItem::setText(0, sClientText); const Qt::ItemFlags flags = QTreeWidgetItem::flags(); if (bRenameEnabled) QTreeWidgetItem::setFlags(flags | Qt::ItemIsEditable); else QTreeWidgetItem::setFlags(flags & ~Qt::ItemIsEditable); } QString qjackctlClientItem::clientText (void) const { return QTreeWidgetItem::text(0); } // Readable flag client accessor. bool qjackctlClientItem::isReadable (void) const { return m_pClientList->isReadable(); } // Client:port set housekeeping marker. void qjackctlClientItem::markClient ( int iMark ) { setHilite(false); m_iClientMark = iMark; } void qjackctlClientItem::markClientPorts ( int iMark ) { markClient(iMark); QListIterator iter(m_ports); while (iter.hasNext()) (iter.next())->markPort(iMark); } int qjackctlClientItem::cleanClientPorts ( int iMark ) { int iDirtyCount = 0; QMutableListIterator iter(m_ports); while (iter.hasNext()) { qjackctlPortItem *pPort = iter.next(); if (pPort->portMark() == iMark) { iter.remove(); delete pPort; ++iDirtyCount; } } return iDirtyCount; } int qjackctlClientItem::clientMark (void) const { return m_iClientMark; } // Connectiopn highlight methods. bool qjackctlClientItem::isHilite (void) const { return (m_iHilite > 0); } void qjackctlClientItem::setHilite ( bool bHilite ) { if (bHilite) m_iHilite++; else if (m_iHilite > 0) m_iHilite--; // Set the new color. QTreeWidget *pTreeWidget = QTreeWidgetItem::treeWidget(); if (pTreeWidget == nullptr) return; const QPalette& pal = pTreeWidget->palette(); QTreeWidgetItem::setForeground(0, m_iHilite > 0 ? (pal.base().color().value() < 0x7f ? Qt::darkCyan : Qt::darkBlue) : pal.text().color()); } // Socket item openness status. void qjackctlClientItem::setOpen ( bool bOpen ) { QTreeWidgetItem::setExpanded(bOpen); } bool qjackctlClientItem::isOpen (void) const { return QTreeWidgetItem::isExpanded(); } // Proxy sort override method. // - Natural decimal sorting comparator. bool qjackctlClientItem::operator< ( const QTreeWidgetItem& other ) const { return qjackctlClientList::lessThan(*this, other); } //---------------------------------------------------------------------- // qjackctlClientList -- Client list. // // Constructor. qjackctlClientList::qjackctlClientList ( qjackctlClientListView *pListView, bool bReadable ) { m_pListView = pListView; m_bReadable = bReadable; m_pHiliteItem = 0; } // Default destructor. qjackctlClientList::~qjackctlClientList (void) { clear(); } // Do proper contents cleanup. void qjackctlClientList::clear (void) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) qDeleteAll(m_clients); #endif m_clients.clear(); if (m_pListView) m_pListView->clear(); } // Client finder. qjackctlClientItem *qjackctlClientList::findClient ( const QString& sClientName ) { QListIterator iter(m_clients); while (iter.hasNext()) { qjackctlClientItem *pClient = iter.next(); if (sClientName == pClient->clientName()) return pClient; } return nullptr; } // Client:port finder. qjackctlPortItem *qjackctlClientList::findClientPort ( const QString& sClientPort ) { qjackctlPortItem *pPort = 0; const int iColon = sClientPort.indexOf(':'); if (iColon >= 0) { qjackctlClientItem *pClient = findClient(sClientPort.left(iColon)); if (pClient) { pPort = pClient->findPort( sClientPort.right(sClientPort.length() - iColon - 1)); } } return pPort; } // Client list accessor. QList& qjackctlClientList::clients (void) { return m_clients; } // List view accessor. qjackctlClientListView *qjackctlClientList::listView (void) const { return m_pListView; } // Readable flag client accessor. bool qjackctlClientList::isReadable (void) const { return m_bReadable; } // Client:port set housekeeping marker. void qjackctlClientList::markClientPorts ( int iMark ) { m_pHiliteItem = 0; QListIterator iter(m_clients); while (iter.hasNext()) (iter.next())->markClientPorts(iMark); } int qjackctlClientList::cleanClientPorts ( int iMark ) { int iDirtyCount = 0; QMutableListIterator iter(m_clients); while (iter.hasNext()) { qjackctlClientItem *pClient = iter.next(); if (pClient->clientMark() == iMark) { iter.remove(); delete pClient; ++iDirtyCount; } else { iDirtyCount += pClient->cleanClientPorts(iMark); } } return iDirtyCount; } // Client:port hilite update stabilization. void qjackctlClientList::hiliteClientPorts (void) { qjackctlClientItem *pClient; qjackctlPortItem *pPort; QTreeWidgetItem *pItem = m_pListView->currentItem(); // Dehilite the previous selected items. if (m_pHiliteItem && pItem != m_pHiliteItem) { if (m_pHiliteItem->type() == QJACKCTL_CLIENTITEM) { pClient = static_cast (m_pHiliteItem); QListIterator iter(pClient->ports()); while (iter.hasNext()) { pPort = iter.next(); QListIterator it(pPort->connects()); while (it.hasNext()) (it.next())->setHilite(false); } } else { pPort = static_cast (m_pHiliteItem); QListIterator it(pPort->connects()); while (it.hasNext()) (it.next())->setHilite(false); } } // Hilite the now current selected items. if (pItem) { if (pItem->type() == QJACKCTL_CLIENTITEM) { pClient = static_cast (pItem); QListIterator iter(pClient->ports()); while (iter.hasNext()) { pPort = iter.next(); QListIterator it(pPort->connects()); while (it.hasNext()) (it.next())->setHilite(true); } } else { pPort = static_cast (pItem); QListIterator it(pPort->connects()); while (it.hasNext()) (it.next())->setHilite(true); } } // Do remember this one, ever. m_pHiliteItem = pItem; } // Natural decimal sorting comparator. bool qjackctlClientList::lessThan ( const QTreeWidgetItem& item1, const QTreeWidgetItem& item2 ) { const QString& s1 = item1.text(0); const QString& s2 = item2.text(0); const int n1 = s1.length(); const int n2 = s2.length(); int i1, i2; for (i1 = i2 = 0; i1 < n1 && i2 < n2; ++i1, ++i2) { // skip (white)spaces... while (s1.at(i1).isSpace()) ++i1; while (s2.at(i2).isSpace()) ++i2; // Normalize (to uppercase) the next characters... QChar c1 = s1.at(i1).toUpper(); QChar c2 = s2.at(i2).toUpper(); if (c1.isDigit() && c2.isDigit()) { // Find the whole length numbers... int j1 = i1++; while (i1 < n1 && s1.at(i1).isDigit()) ++i1; int j2 = i2++; while (i2 < n2 && s2.at(i2).isDigit()) ++i2; // Compare as natural decimal-numbers... j1 = s1.mid(j1, i1 - j1).toInt(); j2 = s2.mid(j2, i2 - j2).toInt(); if (j1 != j2) return (j1 < j2); // Never go out of bounds... if (i1 >= n1 || i2 >= n2) break; // Go on with this next char... c1 = s1.at(i1).toUpper(); c2 = s2.at(i2).toUpper(); } // Compare this char... if (c1 != c2) return (c1 < c2); } // Probable exact match. return false; } // Do proper contents refresh/update. void qjackctlClientList::refresh (void) { QHeaderView *pHeader = m_pListView->header(); m_pListView->sortItems( pHeader->sortIndicatorSection(), pHeader->sortIndicatorOrder()); } //---------------------------------------------------------------------------- // qjackctlClientListView -- Client list view, supporting drag-n-drop. // Constructor. qjackctlClientListView::qjackctlClientListView ( qjackctlConnectView *pConnectView, bool bReadable ) : QTreeWidget(pConnectView) { m_pConnectView = pConnectView; m_pAutoOpenTimer = 0; m_iAutoOpenTimeout = 0; m_pDragItem = nullptr; m_pDragItem = nullptr; m_pAliasList = nullptr; m_bRenameEnabled = false; QHeaderView *pHeader = QTreeWidget::header(); pHeader->setDefaultAlignment(Qt::AlignLeft); // pHeader->setDefaultSectionSize(120); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionsMovable(false); pHeader->setSectionsClickable(true); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setMovable(false); pHeader->setClickable(true); #endif pHeader->setSortIndicatorShown(true); pHeader->setStretchLastSection(true); QTreeWidget::setRootIsDecorated(true); QTreeWidget::setUniformRowHeights(true); // QTreeWidget::setDragEnabled(true); QTreeWidget::setAcceptDrops(true); QTreeWidget::setDropIndicatorShown(true); QTreeWidget::setAutoScroll(true); QTreeWidget::setSelectionMode(QAbstractItemView::ExtendedSelection); QTreeWidget::setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); QTreeWidget::setSortingEnabled(true); QTreeWidget::setMinimumWidth(120); QTreeWidget::setColumnCount(1); QString sText; if (bReadable) sText = tr("Readable Clients / Output Ports"); else sText = tr("Writable Clients / Input Ports"); QTreeWidget::headerItem()->setText(0, sText); QTreeWidget::sortItems(0, Qt::AscendingOrder); QTreeWidget::setToolTip(sText); // Trap for help/tool-tips events. QTreeWidget::viewport()->installEventFilter(this); QObject::connect(QTreeWidget::itemDelegate(), SIGNAL(commitData(QWidget*)), SLOT(renamedSlot())); setAutoOpenTimeout(800); } // Default destructor. qjackctlClientListView::~qjackctlClientListView (void) { setAutoOpenTimeout(0); } // Binding indirect accessor. qjackctlConnect *qjackctlClientListView::binding() const { return m_pConnectView->binding(); } // Auto-open timeout method. void qjackctlClientListView::setAutoOpenTimeout ( int iAutoOpenTimeout ) { m_iAutoOpenTimeout = iAutoOpenTimeout; if (m_pAutoOpenTimer) delete m_pAutoOpenTimer; m_pAutoOpenTimer = nullptr; if (m_iAutoOpenTimeout > 0) { m_pAutoOpenTimer = new QTimer(this); QObject::connect(m_pAutoOpenTimer, SIGNAL(timeout()), SLOT(timeoutSlot())); } } // Auto-open timeout accessor. int qjackctlClientListView::autoOpenTimeout (void) const { return m_iAutoOpenTimeout; } // Aliasing support methods. void qjackctlClientListView::setAliasList ( qjackctlAliasList *pAliasList, bool bRenameEnabled ) { m_pAliasList = pAliasList; m_bRenameEnabled = bRenameEnabled; // For each client item, if any. const int iItemCount = QTreeWidget::topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = QTreeWidget::topLevelItem(iItem); if (pItem->type() != QJACKCTL_CLIENTITEM) continue; qjackctlClientItem *pClientItem = static_cast (pItem); if (pClientItem == nullptr) continue; pClientItem->updateClientName(); // For each port item... const int iChildCount = pClientItem->childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChildItem = pClientItem->child(iChild); if (pChildItem->type() != QJACKCTL_PORTITEM) continue; qjackctlPortItem *pPortItem = static_cast (pChildItem); if (pPortItem == nullptr) continue; pPortItem->updatePortName(); } } } qjackctlAliasList *qjackctlClientListView::aliasList (void) const { return m_pAliasList; } bool qjackctlClientListView::isRenameEnabled (void) const { return m_bRenameEnabled; } // In-place aliasing slot. void qjackctlClientListView::startRenameSlot (void) { QTreeWidgetItem *pItem = QTreeWidget::currentItem(); if (pItem) QTreeWidget::editItem(pItem, 0); } // In-place aliasing slot. void qjackctlClientListView::renamedSlot (void) { if (m_pAliasList == nullptr) return; QTreeWidgetItem *pItem = QTreeWidget::currentItem(); if (pItem == nullptr) return; const QString& sText = pItem->text(0); if (pItem->type() == QJACKCTL_CLIENTITEM) { qjackctlClientItem *pClientItem = static_cast (pItem); pClientItem->setClientNameAlias(sText); pClientItem->updateClientName(true); } else { qjackctlPortItem *pPortItem = static_cast (pItem); pPortItem->setPortNameAlias(sText); pPortItem->updatePortName(true); } // m_pConnectView->setDirty(true); } // Auto-open timer slot. void qjackctlClientListView::timeoutSlot (void) { if (m_pAutoOpenTimer) { m_pAutoOpenTimer->stop(); if (m_pDropItem && m_pDropItem->type() == QJACKCTL_CLIENTITEM) { qjackctlClientItem *pClientItem = static_cast (m_pDropItem); if (pClientItem && !pClientItem->isOpen()) pClientItem->setOpen(true); } } } // Trap for help/tool-tip events. bool qjackctlClientListView::eventFilter ( QObject *pObject, QEvent *pEvent ) { QWidget *pViewport = QTreeWidget::viewport(); if (static_cast (pObject) == pViewport && pEvent->type() == QEvent::ToolTip) { QHelpEvent *pHelpEvent = static_cast (pEvent); if (pHelpEvent) { QTreeWidgetItem *pItem = QTreeWidget::itemAt(pHelpEvent->pos()); if (pItem && pItem->type() == QJACKCTL_CLIENTITEM) { qjackctlClientItem *pClientItem = static_cast (pItem); if (pClientItem) { QToolTip::showText(pHelpEvent->globalPos(), pClientItem->clientName(), pViewport); return true; } } else if (pItem && pItem->type() == QJACKCTL_PORTITEM) { qjackctlPortItem *pPortItem = static_cast (pItem); if (pPortItem) { QToolTip::showText(pHelpEvent->globalPos(), pPortItem->tooltip(), pViewport); return true; } } } } // Not handled here. return QTreeWidget::eventFilter(pObject, pEvent); } // Drag-n-drop stuff. QTreeWidgetItem *qjackctlClientListView::dragDropItem ( const QPoint& pos ) { QTreeWidgetItem *pItem = QTreeWidget::itemAt(pos); if (pItem) { if (m_pDropItem != pItem) { QTreeWidget::setCurrentItem(pItem); m_pDropItem = pItem; if (m_pAutoOpenTimer) m_pAutoOpenTimer->start(m_iAutoOpenTimeout); qjackctlConnect *pConnect = m_pConnectView->binding(); if ((pItem->flags() & Qt::ItemIsDropEnabled) == 0 || pConnect == nullptr || !pConnect->canConnectSelected()) pItem = nullptr; } } else { m_pDropItem = nullptr; if (m_pAutoOpenTimer) m_pAutoOpenTimer->stop(); } return pItem; } void qjackctlClientListView::dragEnterEvent ( QDragEnterEvent *pDragEnterEvent ) { if (pDragEnterEvent->source() != this && pDragEnterEvent->mimeData()->hasText() && #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) dragDropItem(pDragEnterEvent->position().toPoint())) { #else dragDropItem(pDragEnterEvent->pos())) { #endif pDragEnterEvent->accept(); } else { pDragEnterEvent->ignore(); } } void qjackctlClientListView::dragMoveEvent ( QDragMoveEvent *pDragMoveEvent ) { if (pDragMoveEvent->source() != this && pDragMoveEvent->mimeData()->hasText() && #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) dragDropItem(pDragMoveEvent->position().toPoint())) { #else dragDropItem(pDragMoveEvent->pos())) { #endif pDragMoveEvent->accept(); } else { pDragMoveEvent->ignore(); } } void qjackctlClientListView::dragLeaveEvent ( QDragLeaveEvent * ) { m_pDropItem = 0; if (m_pAutoOpenTimer) m_pAutoOpenTimer->stop(); } void qjackctlClientListView::dropEvent( QDropEvent *pDropEvent ) { if (pDropEvent->source() != this && pDropEvent->mimeData()->hasText() && #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) dragDropItem(pDropEvent->position().toPoint())) { #else dragDropItem(pDropEvent->pos())) { #endif const QString sText = pDropEvent->mimeData()->text(); qjackctlConnect *pConnect = m_pConnectView->binding(); if (!sText.isEmpty() && pConnect) pConnect->connectSelected(); } dragLeaveEvent(0); } // Handle mouse events for drag-and-drop stuff. void qjackctlClientListView::mousePressEvent ( QMouseEvent *pMouseEvent ) { QTreeWidget::mousePressEvent(pMouseEvent); if (pMouseEvent->button() == Qt::LeftButton) { m_posDrag = pMouseEvent->pos(); m_pDragItem = QTreeWidget::itemAt(m_posDrag); } } void qjackctlClientListView::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { QTreeWidget::mouseMoveEvent(pMouseEvent); if ((pMouseEvent->buttons() & Qt::LeftButton) && m_pDragItem && ((pMouseEvent->pos() - m_posDrag).manhattanLength() >= QApplication::startDragDistance())) { // We'll start dragging something alright... QMimeData *pMimeData = new QMimeData(); pMimeData->setText(m_pDragItem->text(0)); QDrag *pDrag = new QDrag(this); pDrag->setMimeData(pMimeData); pDrag->setPixmap(m_pDragItem->icon(0).pixmap(16)); pDrag->setHotSpot(QPoint(-4, -12)); pDrag->exec(Qt::LinkAction); // We've dragged and maybe dropped it by now... m_pDragItem = nullptr; } } // Context menu request event handler. void qjackctlClientListView::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { qjackctlConnect *pConnect = m_pConnectView->binding(); if (pConnect == 0) return; QMenu menu(this); QAction *pAction; #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) pAction = menu.addAction(QIcon(":/images/connect1.png"), tr("&Connect"), tr("Alt+C", "Connect"), pConnect, SLOT(connectSelected())); pAction->setEnabled(pConnect->canConnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnect1.png"), tr("&Disconnect"), tr("Alt+D", "Disconnect"), pConnect, SLOT(disconnectSelected())); pAction->setEnabled(pConnect->canDisconnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnectall1.png"), tr("Disconnect &All"), tr("Alt+A", "Disconnect All"), pConnect, SLOT(disconnectAll())); pAction->setEnabled(pConnect->canDisconnectAll()); if (m_bRenameEnabled) { menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/edit1.png"), tr("Re&name"), tr("Alt+N", "Rename"), this, SLOT(startRenameSlot())); QTreeWidgetItem *pItem = QTreeWidget::currentItem(); pAction->setEnabled(pItem && (pItem->flags() & Qt::ItemIsEditable)); } menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/refresh1.png"), tr("&Refresh"), tr("Alt+R", "Refresh"), pConnect, SLOT(refresh())); #else pAction = menu.addAction(QIcon(":/images/connect1.png"), tr("&Connect"), pConnect, SLOT(connectSelected()), tr("Alt+C", "Connect")); pAction->setEnabled(pConnect->canConnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnect1.png"), tr("&Disconnect"), pConnect, SLOT(disconnectSelected()), tr("Alt+D", "Disconnect")); pAction->setEnabled(pConnect->canDisconnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnectall1.png"), tr("Disconnect &All"), pConnect, SLOT(disconnectAll()), tr("Alt+A", "Disconnect All")); pAction->setEnabled(pConnect->canDisconnectAll()); if (m_bRenameEnabled) { menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/edit1.png"), tr("Re&name"), this, SLOT(startRenameSlot()), tr("Alt+N", "Rename")); QTreeWidgetItem *pItem = QTreeWidget::currentItem(); pAction->setEnabled(pItem && (pItem->flags() & Qt::ItemIsEditable)); } menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/refresh1.png"), tr("&Refresh"), pConnect, SLOT(refresh()), tr("Alt+R", "Refresh")); #endif menu.exec(pContextMenuEvent->globalPos()); } // Dirty aliases notification. void qjackctlClientListView::emitAliasesChanged (void) { m_pConnectView->emitAliasesChanged(); } //---------------------------------------------------------------------- // qjackctlConnectorView -- Jack port connector widget. // // Constructor. qjackctlConnectorView::qjackctlConnectorView ( qjackctlConnectView *pConnectView ) : QWidget(pConnectView) { m_pConnectView = pConnectView; QWidget::setMinimumWidth(20); // QWidget::setMaximumWidth(120); QWidget::setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); } // Default destructor. qjackctlConnectorView::~qjackctlConnectorView (void) { } // Legal client/port item position helper. int qjackctlConnectorView::itemY ( QTreeWidgetItem *pItem ) const { QRect rect; QTreeWidget *pList = pItem->treeWidget(); QTreeWidgetItem *pParent = pItem->parent(); qjackctlClientItem *pClientItem = nullptr; if (pParent && pParent->type() == QJACKCTL_CLIENTITEM) pClientItem = static_cast (pParent); if (pClientItem && !pClientItem->isOpen()) { rect = pList->visualItemRect(pClientItem); } else { rect = pList->visualItemRect(pItem); } return rect.top() + rect.height() / 2; } // Draw visible port connection relation lines void qjackctlConnectorView::drawConnectionLine ( QPainter *pPainter, int x1, int y1, int x2, int y2, int h1, int h2, const QPen& pen ) { // Set apropriate pen... pPainter->setPen(pen); // Account for list view headers. y1 += h1; y2 += h2; // Invisible output ports don't get a connecting dot. if (y1 > h1) pPainter->drawLine(x1, y1, x1 + 4, y1); // Setup control points QPolygon spline(4); const int cp = int(float(x2 - x1 - 8) * 0.4f); spline.putPoints(0, 4, x1 + 4, y1, x1 + 4 + cp, y1, x2 - 4 - cp, y2, x2 - 4, y2); // The connection line, it self. QPainterPath path; path.moveTo(spline.at(0)); path.cubicTo(spline.at(1), spline.at(2), spline.at(3)); pPainter->strokePath(path, pen); // Invisible input ports don't get a connecting dot. if (y2 > h2) pPainter->drawLine(x2 - 4, y2, x2, y2); } // Draw visible port connection relation arrows. void qjackctlConnectorView::paintEvent ( QPaintEvent * ) { if (m_pConnectView == nullptr) return; if (m_pConnectView->OListView() == nullptr || m_pConnectView->IListView() == nullptr) return; qjackctlClientListView *pOListView = m_pConnectView->OListView(); qjackctlClientListView *pIListView = m_pConnectView->IListView(); const int yc = QWidget::pos().y(); const int yo = pOListView->pos().y(); const int yi = pIListView->pos().y(); QPainter painter(this); int x1, y1, h1; int x2, y2, h2; int rgb[3] = { 0x33, 0x66, 0x99 }; // Draw all lines anti-aliased... painter.setRenderHint(QPainter::Antialiasing); // Inline adaptive to darker background themes... if (QWidget::palette().window().color().value() < 0x7f) for (int i = 0; i < 3; ++i) rgb[i] += 0x33; // Almost constants. x1 = 0; x2 = QWidget::width(); h1 = (pOListView->header())->sizeHint().height(); h2 = (pIListView->header())->sizeHint().height(); // For each output client item... const int iItemCount = pOListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = pOListView->topLevelItem(iItem); if (pItem->type() != QJACKCTL_CLIENTITEM) continue; qjackctlClientItem *pOClient = static_cast (pItem); if (pOClient == nullptr) continue; // Set new connector color. const QString& sOClientName = pOClient->clientName(); int k = m_colorMap.value(sOClientName, -1); if (k < 0) { k = m_colorMap.size() + 1; m_colorMap.insert(sOClientName, k); } QPen pen(QColor(rgb[k % 3], rgb[(k / 3) % 3], rgb[(k / 9) % 3])); // For each port item const int iChildCount = pOClient->childCount(); for (int iChild = 0; iChild < iChildCount; ++iChild) { QTreeWidgetItem *pChild = pOClient->child(iChild); if (pChild->type() != QJACKCTL_PORTITEM) continue; qjackctlPortItem *pOPort = static_cast (pChild); if (pOPort) { // Set proposed line width... const int w1 = (pOPort->isHilite() ? 2 : 1); // Get starting connector arrow coordinates. y1 = itemY(pOPort) + (yo - yc); // Get port connections... QListIterator iter(pOPort->connects()); while (iter.hasNext()) { qjackctlPortItem *pIPort = iter.next(); // Obviously, should be a connection // from pOPort to pIPort items: y2 = itemY(pIPort) + (yi - yc); pen.setWidth(pIPort->isHilite() ? 2 : w1); drawConnectionLine(&painter, x1, y1, x2, y2, h1, h2, pen); } } } } } // Context menu request event handler. void qjackctlConnectorView::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { qjackctlConnect *pConnect = m_pConnectView->binding(); if (pConnect == 0) return; QMenu menu(this); QAction *pAction; #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) pAction = menu.addAction(QIcon(":/images/connect1.png"), tr("&Connect"), tr("Alt+C", "Connect"), pConnect, SLOT(connectSelected())); pAction->setEnabled(pConnect->canConnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnect1.png"), tr("&Disconnect"), tr("Alt+D", "Disconnect"), pConnect, SLOT(disconnectSelected())); pAction->setEnabled(pConnect->canDisconnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnectall1.png"), tr("Disconnect &All"), tr("Alt+A", "Disconnect All"), pConnect, SLOT(disconnectAll())); pAction->setEnabled(pConnect->canDisconnectAll()); menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/refresh1.png"), tr("&Refresh"), tr("Alt+R", "Refresh"), pConnect, SLOT(refresh())); #else pAction = menu.addAction(QIcon(":/images/connect1.png"), tr("&Connect"), pConnect, SLOT(connectSelected()), tr("Alt+C", "Connect")); pAction->setEnabled(pConnect->canConnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnect1.png"), tr("&Disconnect"), pConnect, SLOT(disconnectSelected()), tr("Alt+D", "Disconnect")); pAction->setEnabled(pConnect->canDisconnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnectall1.png"), tr("Disconnect &All"), pConnect, SLOT(disconnectAll()), tr("Alt+A", "Disconnect All")); pAction->setEnabled(pConnect->canDisconnectAll()); menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/refresh1.png"), tr("&Refresh"), pConnect, SLOT(refresh()), tr("Alt+R", "Refresh")); #endif menu.exec(pContextMenuEvent->globalPos()); } // Widget event slots... void qjackctlConnectorView::contentsChanged (void) { QWidget::update(); } //---------------------------------------------------------------------------- // qjackctlConnectView -- Integrated connections view widget. // Constructor. qjackctlConnectView::qjackctlConnectView ( QWidget *pParent ) : QSplitter(Qt::Horizontal, pParent) { m_pOListView = new qjackctlClientListView(this, true); m_pConnectorView = new qjackctlConnectorView(this); m_pIListView = new qjackctlClientListView(this, false); m_pConnect = nullptr; m_iIconSize = 0; QSplitter::setHandleWidth(2); QObject::connect(m_pOListView, SIGNAL(itemExpanded(QTreeWidgetItem *)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pOListView, SIGNAL(itemCollapsed(QTreeWidgetItem *)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pOListView->verticalScrollBar(), SIGNAL(valueChanged(int)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pOListView->header(), SIGNAL(sectionClicked(int)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pIListView, SIGNAL(itemExpanded(QTreeWidgetItem *)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pIListView, SIGNAL(itemCollapsed(QTreeWidgetItem *)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pIListView->verticalScrollBar(), SIGNAL(valueChanged(int)), m_pConnectorView, SLOT(contentsChanged())); QObject::connect(m_pIListView->header(), SIGNAL(sectionClicked(int)), m_pConnectorView, SLOT(contentsChanged())); m_bDirty = false; } // Default destructor. qjackctlConnectView::~qjackctlConnectView (void) { } // Connect binding methods. void qjackctlConnectView::setBinding ( qjackctlConnect *pConnect ) { m_pConnect = pConnect; } qjackctlConnect *qjackctlConnectView::binding (void) const { return m_pConnect; } // Connect client list accessors. qjackctlClientList *qjackctlConnectView::OClientList (void) const { if (m_pConnect) return m_pConnect->OClientList(); else return nullptr; } qjackctlClientList *qjackctlConnectView::IClientList (void) const { if (m_pConnect) return m_pConnect->OClientList(); else return nullptr; } // Common icon size methods. void qjackctlConnectView::setIconSize ( int iIconSize ) { // Update only if changed. if (iIconSize == m_iIconSize) return; // Go for it... m_iIconSize = iIconSize; // Update item sizes properly... const int px = (16 << m_iIconSize); const QSize iconSize(px, px); m_pOListView->setIconSize(iconSize); m_pIListView->setIconSize(iconSize); // Call binding descendant implementation, // and do a complete content reset... if (m_pConnect) m_pConnect->updateContents(true); } int qjackctlConnectView::iconSize (void) const { return m_iIconSize; } // Dirty aliases notification. void qjackctlConnectView::emitAliasesChanged (void) { emit aliasesChanged(); } //---------------------------------------------------------------------- // qjackctlConnect -- Output-to-Input client/ports connection object. // // Constructor. qjackctlConnect::qjackctlConnect ( qjackctlConnectView *pConnectView ) { m_pConnectView = pConnectView; m_pOClientList = nullptr; m_pIClientList = nullptr; m_iMutex = 0; m_pConnectView->setBinding(this); } // Default destructor. qjackctlConnect::~qjackctlConnect (void) { // Force end of works here. m_iMutex++; m_pConnectView->setBinding(nullptr); if (m_pOClientList) delete m_pOClientList; if (m_pIClientList) delete m_pIClientList; m_pOClientList = nullptr; m_pIClientList = nullptr; m_pConnectView->connectorView()->update(); } // These must be accessed by the descendant constructor. qjackctlConnectView *qjackctlConnect::connectView (void) const { return m_pConnectView; } void qjackctlConnect::setOClientList ( qjackctlClientList *pOClientList ) { m_pOClientList = pOClientList; } void qjackctlConnect::setIClientList ( qjackctlClientList *pIClientList ) { m_pIClientList = pIClientList; } // Connection primitive. bool qjackctlConnect::connectPortsEx ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort ) { if (pOPort->findConnectPtr(pIPort) != nullptr) return false; emit connecting(pOPort, pIPort); if (!connectPorts(pOPort, pIPort)) return false; pOPort->addConnect(pIPort); pIPort->addConnect(pOPort); return true; } // Disconnection primitive. bool qjackctlConnect::disconnectPortsEx ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort ) { if (pOPort->findConnectPtr(pIPort) == nullptr) return false; emit disconnecting(pOPort, pIPort); if (!disconnectPorts(pOPort, pIPort)) return false; pOPort->removeConnect(pIPort); pIPort->removeConnect(pOPort); return true; } // Test if selected ports are connectable. bool qjackctlConnect::canConnectSelected (void) { bool bResult = false; if (startMutex()) { bResult = canConnectSelectedEx(); endMutex(); } return bResult; } bool qjackctlConnect::canConnectSelectedEx (void) { // Take this opportunity to highlight any current selections. m_pOClientList->hiliteClientPorts(); m_pIClientList->hiliteClientPorts(); m_pConnectView->connectorView()->update(); // Now with our predicate work... const QList oitems = (m_pOClientList->listView())->selectedItems(); const QList iitems = (m_pIClientList->listView())->selectedItems(); if (oitems.isEmpty() || iitems.isEmpty()) return false; QListIterator oiter(oitems); QListIterator iiter(iitems); const int iNumItems = qMax(oitems.count(), iitems.count()); for (int i = 0; i < iNumItems; ++i) { if (!oiter.hasNext()) oiter.toFront(); if (!iiter.hasNext()) iiter.toFront(); QTreeWidgetItem *pOItem = oiter.next(); QTreeWidgetItem *pIItem = iiter.next(); if (pOItem->type() == QJACKCTL_CLIENTITEM) { qjackctlClientItem *pOClient = static_cast (pOItem); if (pIItem->type() == QJACKCTL_CLIENTITEM) { // Each-to-each connections... qjackctlClientItem *pIClient = static_cast (pIItem); QListIterator oport(pOClient->ports()); QListIterator iport(pIClient->ports()); while (oport.hasNext() && iport.hasNext()) { qjackctlPortItem *pOPort = oport.next(); qjackctlPortItem *pIPort = iport.next(); if (pOPort->findConnectPtr(pIPort) == nullptr) return true; } } else { // Many(all)-to-one/many connection... QListIterator oport(pOClient->ports()); while (oport.hasNext() && pIItem && pIItem->type() == QJACKCTL_PORTITEM) { qjackctlPortItem *pOPort = oport.next(); qjackctlPortItem *pIPort = static_cast (pIItem); if (pOPort->findConnectPtr(pIPort) == nullptr) return true; pIItem = (m_pIClientList->listView())->itemBelow(pIItem); } } } else { qjackctlPortItem *pOPort = static_cast (pOItem); if (pIItem->type() == QJACKCTL_CLIENTITEM) { // One-to-many(all) connection... qjackctlClientItem *pIClient = static_cast (pIItem); QListIterator iport(pIClient->ports()); while (iport.hasNext()) { qjackctlPortItem *pIPort = iport.next(); if (pOPort->findConnectPtr(pIPort) == nullptr) return true; } } else { // One-to-one connection... qjackctlPortItem *pIPort = static_cast (pIItem); return (pOPort->findConnectPtr(pIPort) == nullptr); } } } return false; } // Connect current selected ports. bool qjackctlConnect::connectSelected (void) { bool bResult = false; if (startMutex()) { bResult = connectSelectedEx(); endMutex(); } m_pConnectView->connectorView()->update(); if (bResult) emit connectChanged(); return bResult; } bool qjackctlConnect::connectSelectedEx (void) { const QList oitems = (m_pOClientList->listView())->selectedItems(); const QList iitems = (m_pIClientList->listView())->selectedItems(); if (oitems.isEmpty() || iitems.isEmpty()) return false; QListIterator oiter(oitems); QListIterator iiter(iitems); const int iNumItems = qMax(oitems.count(), iitems.count()); for (int i = 0; i < iNumItems; ++i) { if (!oiter.hasNext()) oiter.toFront(); if (!iiter.hasNext()) iiter.toFront(); QTreeWidgetItem *pOItem = oiter.next(); QTreeWidgetItem *pIItem = iiter.next(); if (pOItem->type() == QJACKCTL_CLIENTITEM) { qjackctlClientItem *pOClient = static_cast (pOItem); if (pIItem->type() == QJACKCTL_CLIENTITEM) { // Each-to-each connections... qjackctlClientItem *pIClient = static_cast (pIItem); QListIterator oport(pOClient->ports()); QListIterator iport(pIClient->ports()); while (oport.hasNext() && iport.hasNext()) { qjackctlPortItem *pOPort = oport.next(); qjackctlPortItem *pIPort = iport.next(); connectPortsEx(pOPort, pIPort); } } else { // Many(all)-to-one/many connection... QListIterator oport(pOClient->ports()); while (oport.hasNext() && pIItem && pIItem->type() == QJACKCTL_PORTITEM) { qjackctlPortItem *pOPort = oport.next(); qjackctlPortItem *pIPort = static_cast (pIItem); connectPortsEx(pOPort, pIPort); pIItem = (m_pIClientList->listView())->itemBelow(pIItem); } } } else { qjackctlPortItem *pOPort = static_cast (pOItem); if (pIItem->type() == QJACKCTL_CLIENTITEM) { // One-to-many(all) connection... qjackctlClientItem *pIClient = static_cast (pIItem); QListIterator iport(pIClient->ports()); while (iport.hasNext()) { qjackctlPortItem *pIPort = iport.next(); connectPortsEx(pOPort, pIPort); } } else { // One-to-one connection... qjackctlPortItem *pIPort = static_cast (pIItem); connectPortsEx(pOPort, pIPort); } } } return true; } // Test if selected ports are disconnectable. bool qjackctlConnect::canDisconnectSelected (void) { bool bResult = false; if (startMutex()) { bResult = canDisconnectSelectedEx(); endMutex(); } return bResult; } bool qjackctlConnect::canDisconnectSelectedEx (void) { const QList oitems = (m_pOClientList->listView())->selectedItems(); const QList iitems = (m_pIClientList->listView())->selectedItems(); if (oitems.isEmpty() || iitems.isEmpty()) return false; QListIterator oiter(oitems); QListIterator iiter(iitems); const int iNumItems = qMax(oitems.count(), iitems.count()); for (int i = 0; i < iNumItems; ++i) { if (!oiter.hasNext()) oiter.toFront(); if (!iiter.hasNext()) iiter.toFront(); QTreeWidgetItem *pOItem = oiter.next(); QTreeWidgetItem *pIItem = iiter.next(); if (pOItem->type() == QJACKCTL_CLIENTITEM) { qjackctlClientItem *pOClient = static_cast (pOItem); if (pIItem->type() == QJACKCTL_CLIENTITEM) { // Each-to-each connections... qjackctlClientItem *pIClient = static_cast (pIItem); QListIterator oport(pOClient->ports()); QListIterator iport(pIClient->ports()); while (oport.hasNext() && iport.hasNext()) { qjackctlPortItem *pOPort = oport.next(); qjackctlPortItem *pIPort = iport.next(); if (pOPort->findConnectPtr(pIPort) != nullptr) return true; } } else { // Many(all)-to-one/many connection... QListIterator oport(pOClient->ports()); while (oport.hasNext() && pIItem && pIItem->type() == QJACKCTL_PORTITEM) { qjackctlPortItem *pOPort = oport.next(); qjackctlPortItem *pIPort = static_cast (pIItem); if (pOPort->findConnectPtr(pIPort) != nullptr) return true; pIItem = (m_pIClientList->listView())->itemBelow(pIItem); } } } else { qjackctlPortItem *pOPort = static_cast (pOItem); if (pIItem->type() == QJACKCTL_CLIENTITEM) { // One-to-many(all) connection... qjackctlClientItem *pIClient = static_cast (pIItem); QListIterator iport(pIClient->ports()); while (iport.hasNext()) { qjackctlPortItem *pIPort = iport.next(); if (pOPort->findConnectPtr(pIPort) != nullptr) return true; } } else { // One-to-one connection... qjackctlPortItem *pIPort = static_cast (pIItem); return (pOPort->findConnectPtr(pIPort) != nullptr); } } } return false; } // Disconnect current selected ports. bool qjackctlConnect::disconnectSelected (void) { bool bResult = false; if (startMutex()) { bResult = disconnectSelectedEx(); endMutex(); } m_pConnectView->connectorView()->update(); if (bResult) emit connectChanged(); return bResult; } bool qjackctlConnect::disconnectSelectedEx (void) { const QList oitems = (m_pOClientList->listView())->selectedItems(); const QList iitems = (m_pIClientList->listView())->selectedItems(); if (oitems.isEmpty() || iitems.isEmpty()) return false; QListIterator oiter(oitems); QListIterator iiter(iitems); const int iNumItems = qMax(oitems.count(), iitems.count()); for (int i = 0; i < iNumItems; ++i) { if (!oiter.hasNext()) oiter.toFront(); if (!iiter.hasNext()) iiter.toFront(); QTreeWidgetItem *pOItem = oiter.next(); QTreeWidgetItem *pIItem = iiter.next(); if (pOItem->type() == QJACKCTL_CLIENTITEM) { qjackctlClientItem *pOClient = static_cast (pOItem); if (pIItem->type() == QJACKCTL_CLIENTITEM) { // Each-to-each connections... qjackctlClientItem *pIClient = static_cast (pIItem); QListIterator oport(pOClient->ports()); QListIterator iport(pIClient->ports()); while (oport.hasNext() && iport.hasNext()) { qjackctlPortItem *pOPort = oport.next(); qjackctlPortItem *pIPort = iport.next(); disconnectPortsEx(pOPort, pIPort); } } else { // Many(all)-to-one/many connection... QListIterator oport(pOClient->ports()); while (oport.hasNext() && pIItem && pIItem->type() == QJACKCTL_PORTITEM) { qjackctlPortItem *pOPort = oport.next(); qjackctlPortItem *pIPort = static_cast (pIItem); disconnectPortsEx(pOPort, pIPort); pIItem = (m_pIClientList->listView())->itemBelow(pIItem); } } } else { qjackctlPortItem *pOPort = static_cast (pOItem); if (pIItem->type() == QJACKCTL_CLIENTITEM) { // One-to-many(all) connection... qjackctlClientItem *pIClient = static_cast (pIItem); QListIterator iport(pIClient->ports()); while (iport.hasNext()) { qjackctlPortItem *pIPort = iport.next(); disconnectPortsEx(pOPort, pIPort); } } else { // One-to-one connection... qjackctlPortItem *pIPort = static_cast (pIItem); disconnectPortsEx(pOPort, pIPort); } } } return true; } // Test if any port is disconnectable. bool qjackctlConnect::canDisconnectAll (void) { bool bResult = false; if (startMutex()) { bResult = canDisconnectAllEx(); endMutex(); } return bResult; } bool qjackctlConnect::canDisconnectAllEx (void) { QListIterator iter(m_pOClientList->clients()); while (iter.hasNext()) { qjackctlClientItem *pOClient = iter.next(); QListIterator oport(pOClient->ports()); while (oport.hasNext()) { qjackctlPortItem *pOPort = oport.next(); if (pOPort->connects().count() > 0) return true; } } return false; } // Disconnect all ports. bool qjackctlConnect::disconnectAll (void) { if (QMessageBox::warning(m_pConnectView, tr("Warning") + " - " QJACKCTL_TITLE, tr("This will suspend sound processing\n" "from all client applications.\n\nAre you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { return false; } bool bResult = false; if (startMutex()) { bResult = disconnectAllEx(); endMutex(); } m_pConnectView->connectorView()->update(); if (bResult) emit connectChanged(); return bResult; } bool qjackctlConnect::disconnectAllEx (void) { QListIterator iter(m_pOClientList->clients()); while (iter.hasNext()) { qjackctlClientItem *pOClient = iter.next(); QListIterator oport(pOClient->ports()); while (oport.hasNext()) { qjackctlPortItem *pOPort = oport.next(); QListIterator iport(pOPort->connects()); while (iport.hasNext()) { qjackctlPortItem *pIPort = iport.next(); disconnectPortsEx(pOPort, pIPort); } } } return true; } // Expand all client ports. void qjackctlConnect::expandAll (void) { (m_pOClientList->listView())->expandAll(); (m_pIClientList->listView())->expandAll(); (m_pConnectView->connectorView())->update(); } // Complete/incremental contents rebuilder; check dirty status if incremental. void qjackctlConnect::updateContents ( bool bClear ) { int iDirtyCount = 0; if (startMutex()) { // Do we do a complete rebuild? if (bClear) { m_pOClientList->clear(); m_pIClientList->clear(); updateIconPixmaps(); } // Add (newer) client:ports and respective connections... if (m_pOClientList->updateClientPorts() > 0) { m_pOClientList->refresh(); ++iDirtyCount; } if (m_pIClientList->updateClientPorts() > 0) { m_pIClientList->refresh(); ++iDirtyCount; } updateConnections(); endMutex(); } (m_pConnectView->connectorView())->update(); if (!bClear && iDirtyCount > 0) emit connectChanged(); } // Incremental contents rebuilder; check dirty status. void qjackctlConnect::refresh (void) { updateContents(false); } // Dunno. But this may avoid some conflicts. bool qjackctlConnect::startMutex (void) { const bool bMutex = (m_iMutex == 0); if (bMutex) m_iMutex++; return bMutex; } void qjackctlConnect::endMutex (void) { if (m_iMutex > 0) m_iMutex--; } // Connect client list accessors. qjackctlClientList *qjackctlConnect::OClientList (void) const { return m_pOClientList; } qjackctlClientList *qjackctlConnect::IClientList (void) const { return m_pIClientList; } // Common pixmap factory-method. QPixmap *qjackctlConnect::createIconPixmap ( const QString& sIconName ) { QString sName = sIconName; const int iSize = m_pConnectView->iconSize() * 32; if (iSize > 0) sName += QString("_%1x%2").arg(iSize).arg(iSize); return new QPixmap(":/images/" + sName + ".png"); } // end of qjackctlConnect.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlSessionSaveForm.h0000644000000000000000000000013214771215054020137 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSessionSaveForm.h0000644000175000001440000000416214771215054020132 0ustar00rncbcusers// qjackctlSessionSaveForm.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlSessionSaveForm_h #define __qjackctlSessionSaveForm_h #include "ui_qjackctlSessionSaveForm.h" // forward decls. class qjackctlSetup; //---------------------------------------------------------------------------- // qjackctlSessionSaveForm -- UI wrapper form. class qjackctlSessionSaveForm : public QDialog { Q_OBJECT public: // Constructor. qjackctlSessionSaveForm(QWidget *pParent, const QString& sTitle, const QStringList& sessionDirs); // Destructor. ~qjackctlSessionSaveForm(); // Retrieve the accepted session directory, if the case arises. const QString& sessionDir() const; // Session directory versioning option. void setSessionSaveVersion(bool bSessionSaveVersion); bool isSessionSaveVersion() const; protected slots: void accept(); void reject(); void changeSessionName(const QString& sSessionName); void changeSessionDir(const QString& sSessionDir); void browseSessionDir(); protected: void stabilizeForm(); private: // The Qt-designer UI struct... Ui::qjackctlSessionSaveForm m_ui; // Instance variables... QString m_sSessionDir; }; #endif // __qjackctlSessionSaveForm_h // end of qjackctlSessionSaveForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlAlsaConnect.h0000644000000000000000000000013214771215054017243 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlAlsaConnect.h0000644000175000001440000000725514771215054017244 0ustar00rncbcusers// qjackctlAlsaConnect.h // /**************************************************************************** Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlAlsaConnect_h #define __qjackctlAlsaConnect_h #include "qjackctlAbout.h" #include "qjackctlConnect.h" #ifdef CONFIG_ALSA_SEQ #include #else typedef void snd_seq_t; #endif // Forward declarations. class qjackctlAlsaPort; class qjackctlAlsaClient; class qjackctlAlsaClientList; class qjackctlAlsaConnect; // Pixmap-set array indexes. #define QJACKCTL_ALSA_CLIENTO 0 // Output client item pixmap. #define QJACKCTL_ALSA_CLIENTI 1 // Input client item pixmap. #define QJACKCTL_ALSA_PORTO 2 // Output port pixmap. #define QJACKCTL_ALSA_PORTI 3 // Input port pixmap. #define QJACKCTL_ALSA_PIXMAPS 4 // Number of pixmaps in local array. // Jack port list item. class qjackctlAlsaPort : public qjackctlPortItem { public: // Constructor. qjackctlAlsaPort(qjackctlAlsaClient *pClient); // Default destructor. ~qjackctlAlsaPort(); // Jack handles accessors. int alsaClient() const; int alsaPort() const; }; // Jack client list item. class qjackctlAlsaClient : public qjackctlClientItem { public: // Constructor. qjackctlAlsaClient(qjackctlAlsaClientList *pClientList); // Default destructor. ~qjackctlAlsaClient(); // Jack client accessors. int alsaClient() const; // Port finder by id. qjackctlAlsaPort *findPort(int iAlsaPort); }; // Jack client list. class qjackctlAlsaClientList : public qjackctlClientList { public: // Constructor. qjackctlAlsaClientList(qjackctlClientListView *pListView, bool bReadable); // Default destructor. ~qjackctlAlsaClientList(); // Client finder by id. qjackctlAlsaClient *findClient(int iAlsaClient); // Client port finder by id. qjackctlAlsaPort *findClientPort(int iAlsaClient, int iAlsaPort); // Client:port refreshner (return newest item count). int updateClientPorts(); }; //---------------------------------------------------------------------------- // qjackctlAlsaConnect -- Connections model integrated object. class qjackctlAlsaConnect : public qjackctlConnect { public: // Constructor. qjackctlAlsaConnect(qjackctlConnectView *pConnectView); // Default destructor. ~qjackctlAlsaConnect(); // Common pixmap accessor. const QPixmap& pixmap(int iPixmap) const; protected: // Virtual Connect/Disconnection primitives. bool connectPorts (qjackctlPortItem *pOPort, qjackctlPortItem *pIPort); bool disconnectPorts (qjackctlPortItem *pOPort, qjackctlPortItem *pIPort); // Update port connection references. void updateConnections(); // Update icon size implementation. void updateIconPixmaps(); private: // Local pixmap-set janitor methods. void createIconPixmaps(); void deleteIconPixmaps(); // Local pixmap-set array. QPixmap *m_apPixmaps[QJACKCTL_ALSA_PIXMAPS]; }; #endif // __qjackctlAlsaConnect_h // end of qjackctlAlsaConnect.h qjackctl-1.0.4/src/PaxHeaders/qjackctlGraphForm.cpp0000644000000000000000000000013214771215054017271 xustar0030 mtime=1743067692.325636584 30 atime=1743067692.325636584 30 ctime=1743067692.325636584 qjackctl-1.0.4/src/qjackctlGraphForm.cpp0000644000175000001440000010701214771215054017262 0ustar00rncbcusers// qjackctlGraphForm.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlGraphForm.h" #include "qjackctlJackGraph.h" #include "qjackctlAlsaGraph.h" #include "qjackctlMainForm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // qjackctlGraphZoomSlider -- Custom slider widget. #include class qjackctlGraphZoomSlider : public QSlider { public: qjackctlGraphZoomSlider() : QSlider(Qt::Horizontal) { QSlider::setMinimum(10); QSlider::setMaximum(190); QSlider::setTickInterval(90); QSlider::setTickPosition(QSlider::TicksBothSides); } protected: void mousePressEvent(QMouseEvent *ev) { QSlider::mousePressEvent(ev); if (ev->button() == Qt::MiddleButton) QSlider::setValue(100); } }; //---------------------------------------------------------------------------- // qjackctlGraphForm -- UI wrapper form. // Constructor. qjackctlGraphForm::qjackctlGraphForm ( QWidget *parent, Qt::WindowFlags wflags ) : QMainWindow(parent, wflags), m_config(nullptr), m_jack(nullptr), m_alsa(nullptr) { // Setup UI struct... m_ui.setupUi(this); m_jack_changed = 0; m_alsa_changed = 0; m_ins = m_mids = m_outs = 0; m_repel_overlapping_nodes = 0; m_thumb = nullptr; m_thumb_update = 0; QUndoStack *commands = m_ui.graphCanvas->commands(); QAction *undo_action = commands->createUndoAction(this, tr("&Undo")); undo_action->setIcon(QIcon(":/images/graphUndo.png")); undo_action->setStatusTip(tr("Undo last edit action")); undo_action->setShortcuts(QKeySequence::Undo); QAction *redo_action = commands->createRedoAction(this, tr("&Redo")); redo_action->setIcon(QIcon(":/images/graphRedo.png")); redo_action->setStatusTip(tr("Redo last edit action")); redo_action->setShortcuts(QKeySequence::Redo); QAction *before_action = m_ui.editSelectAllAction; m_ui.editMenu->insertAction(before_action, undo_action); m_ui.editMenu->insertAction(before_action, redo_action); m_ui.editMenu->insertSeparator(before_action); before_action = m_ui.viewCenterAction; m_ui.ToolBar->insertAction(before_action, undo_action); m_ui.ToolBar->insertAction(before_action, redo_action); m_ui.ToolBar->insertSeparator(before_action); // Special zoom composite widget... QWidget *zoom_widget = new QWidget(); zoom_widget->setMaximumWidth(240); zoom_widget->setToolTip(tr("Zoom")); QHBoxLayout *zoom_layout = new QHBoxLayout(); zoom_layout->setContentsMargins(0, 0, 0, 0); zoom_layout->setSpacing(2); QToolButton *zoom_out = new QToolButton(); zoom_out->setDefaultAction(m_ui.viewZoomOutAction); zoom_out->setFixedSize(22, 22); zoom_layout->addWidget(zoom_out); m_zoom_slider = new qjackctlGraphZoomSlider(); m_zoom_slider->setFixedHeight(22); zoom_layout->addWidget(m_zoom_slider); QToolButton *zoom_in = new QToolButton(); zoom_in->setDefaultAction(m_ui.viewZoomInAction); zoom_in->setFixedSize(22, 22); zoom_layout->addWidget(zoom_in); m_zoom_spinbox = new QSpinBox(); m_zoom_spinbox->setFixedHeight(22); m_zoom_spinbox->setAlignment(Qt::AlignCenter); m_zoom_spinbox->setMinimum(10); m_zoom_spinbox->setMaximum(200); m_zoom_spinbox->setSuffix(" %"); zoom_layout->addWidget(m_zoom_spinbox); zoom_widget->setLayout(zoom_layout); m_ui.StatusBar->addPermanentWidget(zoom_widget); QObject::connect(m_zoom_spinbox, SIGNAL(valueChanged(int)), SLOT(zoomValueChanged(int))); QObject::connect(m_zoom_slider, SIGNAL(valueChanged(int)), SLOT(zoomValueChanged(int))); QObject::connect(m_ui.graphCanvas, SIGNAL(added(qjackctlGraphNode *)), SLOT(added(qjackctlGraphNode *))); QObject::connect(m_ui.graphCanvas, SIGNAL(updated(qjackctlGraphNode *)), SLOT(updated(qjackctlGraphNode *))); QObject::connect(m_ui.graphCanvas, SIGNAL(removed(qjackctlGraphNode *)), SLOT(removed(qjackctlGraphNode *))); QObject::connect(m_ui.graphCanvas, SIGNAL(connected(qjackctlGraphPort *, qjackctlGraphPort *)), SLOT(connected(qjackctlGraphPort *, qjackctlGraphPort *))); QObject::connect(m_ui.graphCanvas, SIGNAL(disconnected(qjackctlGraphPort *, qjackctlGraphPort *)), SLOT(disconnected(qjackctlGraphPort *, qjackctlGraphPort *))); QObject::connect(m_ui.graphCanvas, SIGNAL(connected(qjackctlGraphConnect *)), SLOT(connected(qjackctlGraphConnect *))); QObject::connect(m_ui.graphCanvas, SIGNAL(renamed(qjackctlGraphItem *, const QString&)), SLOT(renamed(qjackctlGraphItem *, const QString&))); QObject::connect(m_ui.graphCanvas, SIGNAL(changed()), SLOT(changed())); // Some actions surely need those // shortcuts firmly attached... addAction(m_ui.viewMenubarAction); addAction(m_ui.editSearchItemAction); // HACK: Make old Ins/Del standard shortcuts // for connect/disconnect available again... QList shortcuts; shortcuts.append(m_ui.graphConnectAction->shortcut()); shortcuts.append(QKeySequence("Ins")); m_ui.graphConnectAction->setShortcuts(shortcuts); shortcuts.clear(); shortcuts.append(m_ui.graphDisconnectAction->shortcut()); shortcuts.append(QKeySequence("Del")); m_ui.graphDisconnectAction->setShortcuts(shortcuts); QObject::connect(m_ui.graphConnectAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(connectItems())); QObject::connect(m_ui.graphDisconnectAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(disconnectItems())); QObject::connect(m_ui.graphCloseAction, SIGNAL(triggered(bool)), SLOT(close())); QObject::connect(m_ui.editSelectAllAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(selectAll())); QObject::connect(m_ui.editSelectNoneAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(selectNone())); QObject::connect(m_ui.editSelectInvertAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(selectInvert())); QObject::connect(m_ui.editRenameItemAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(renameItem())); QObject::connect(m_ui.editSearchItemAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(searchItem())); QObject::connect(m_ui.viewMenubarAction, SIGNAL(triggered(bool)), SLOT(viewMenubar(bool))); QObject::connect(m_ui.viewStatusbarAction, SIGNAL(triggered(bool)), SLOT(viewStatusbar(bool))); QObject::connect(m_ui.viewToolbarAction, SIGNAL(triggered(bool)), SLOT(viewToolbar(bool))); m_thumb_mode = new QActionGroup(this); m_thumb_mode->setExclusive(true); m_thumb_mode->addAction(m_ui.viewThumbviewTopLeftAction); m_thumb_mode->addAction(m_ui.viewThumbviewTopRightAction); m_thumb_mode->addAction(m_ui.viewThumbviewBottomLeftAction); m_thumb_mode->addAction(m_ui.viewThumbviewBottomRightAction); m_thumb_mode->addAction(m_ui.viewThumbviewNoneAction); m_ui.viewThumbviewTopLeftAction->setData(qjackctlGraphThumb::TopLeft); m_ui.viewThumbviewTopRightAction->setData(qjackctlGraphThumb::TopRight); m_ui.viewThumbviewBottomLeftAction->setData(qjackctlGraphThumb::BottomLeft); m_ui.viewThumbviewBottomRightAction->setData(qjackctlGraphThumb::BottomRight); m_ui.viewThumbviewNoneAction->setData(qjackctlGraphThumb::None); QObject::connect(m_ui.viewThumbviewTopLeftAction, SIGNAL(triggered(bool)), SLOT(viewThumbviewAction())); QObject::connect(m_ui.viewThumbviewTopRightAction, SIGNAL(triggered(bool)), SLOT(viewThumbviewAction())); QObject::connect(m_ui.viewThumbviewBottomLeftAction, SIGNAL(triggered(bool)), SLOT(viewThumbviewAction())); QObject::connect(m_ui.viewThumbviewBottomRightAction, SIGNAL(triggered(bool)), SLOT(viewThumbviewAction())); QObject::connect(m_ui.viewThumbviewNoneAction, SIGNAL(triggered(bool)), SLOT(viewThumbviewAction())); QObject::connect(m_ui.viewTextBesideIconsAction, SIGNAL(triggered(bool)), SLOT(viewTextBesideIcons(bool))); QObject::connect(m_ui.viewCenterAction, SIGNAL(triggered(bool)), SLOT(viewCenter())); QObject::connect(m_ui.viewRefreshAction, SIGNAL(triggered(bool)), SLOT(viewRefresh())); QObject::connect(m_ui.viewZoomInAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(zoomIn())); QObject::connect(m_ui.viewZoomOutAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(zoomOut())); QObject::connect(m_ui.viewZoomFitAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(zoomFit())); QObject::connect(m_ui.viewZoomResetAction, SIGNAL(triggered(bool)), m_ui.graphCanvas, SLOT(zoomReset())); QObject::connect(m_ui.viewZoomRangeAction, SIGNAL(triggered(bool)), SLOT(viewZoomRange(bool))); QObject::connect(m_ui.viewRepelOverlappingNodesAction, SIGNAL(triggered(bool)), SLOT(viewRepelOverlappingNodes(bool))); QObject::connect(m_ui.viewConnectThroughNodesAction, SIGNAL(triggered(bool)), SLOT(viewConnectThroughNodes(bool))); m_ui.viewColorsJackAudioAction->setData(qjackctlJackGraph::audioPortType()); m_ui.viewColorsJackMidiAction->setData(qjackctlJackGraph::midiPortType()); int iAddSeparator = 0; #ifdef CONFIG_JACK_CV m_ui.viewColorsJackCvAction->setData(qjackctlJackGraph::cvPortType()); m_ui.viewColorsMenu->insertAction( m_ui.viewColorsResetAction, m_ui.viewColorsJackCvAction); ++iAddSeparator; #endif #ifdef CONFIG_JACK_OSC m_ui.viewColorsJackOscAction->setData(qjackctlJackGraph::oscPortType()); m_ui.viewColorsMenu->insertAction( m_ui.viewColorsResetAction, m_ui.viewColorsJackOscAction); ++iAddSeparator; #endif if (iAddSeparator > 0) m_ui.viewColorsMenu->insertSeparator(m_ui.viewColorsResetAction); #ifdef CONFIG_ALSA_SEQ m_ui.viewColorsAlsaMidiAction->setData(qjackctlAlsaGraph::midiPortType()); m_ui.viewColorsMenu->insertAction( m_ui.viewColorsResetAction, m_ui.viewColorsAlsaMidiAction); m_ui.viewColorsMenu->insertSeparator(m_ui.viewColorsResetAction); #endif QObject::connect(m_ui.viewColorsJackAudioAction, SIGNAL(triggered(bool)), SLOT(viewColorsAction())); QObject::connect(m_ui.viewColorsJackMidiAction, SIGNAL(triggered(bool)), SLOT(viewColorsAction())); #ifdef CONFIG_JACK_CV QObject::connect(m_ui.viewColorsJackCvAction, SIGNAL(triggered(bool)), SLOT(viewColorsAction())); #endif #ifdef CONFIG_JACK_OSC QObject::connect(m_ui.viewColorsJackOscAction, SIGNAL(triggered(bool)), SLOT(viewColorsAction())); #endif #ifdef CONFIG_ALSA_SEQ QObject::connect(m_ui.viewColorsAlsaMidiAction, SIGNAL(triggered(bool)), SLOT(viewColorsAction())); #endif QObject::connect(m_ui.viewColorsResetAction, SIGNAL(triggered(bool)), SLOT(viewColorsReset())); m_sort_type = new QActionGroup(this); m_sort_type->setExclusive(true); m_sort_type->addAction(m_ui.viewSortPortNameAction); m_sort_type->addAction(m_ui.viewSortPortTitleAction); m_sort_type->addAction(m_ui.viewSortPortIndexAction); m_ui.viewSortPortNameAction->setData(qjackctlGraphPort::PortName); m_ui.viewSortPortTitleAction->setData(qjackctlGraphPort::PortTitle); m_ui.viewSortPortIndexAction->setData(qjackctlGraphPort::PortIndex); QObject::connect(m_ui.viewSortPortNameAction, SIGNAL(triggered(bool)), SLOT(viewSortTypeAction())); QObject::connect(m_ui.viewSortPortTitleAction, SIGNAL(triggered(bool)), SLOT(viewSortTypeAction())); QObject::connect(m_ui.viewSortPortIndexAction, SIGNAL(triggered(bool)), SLOT(viewSortTypeAction())); m_sort_order = new QActionGroup(this); m_sort_order->setExclusive(true); m_sort_order->addAction(m_ui.viewSortAscendingAction); m_sort_order->addAction(m_ui.viewSortDescendingAction); m_ui.viewSortAscendingAction->setData(qjackctlGraphPort::Ascending); m_ui.viewSortDescendingAction->setData(qjackctlGraphPort::Descending); QObject::connect(m_ui.viewSortAscendingAction, SIGNAL(triggered(bool)), SLOT(viewSortOrderAction())); QObject::connect(m_ui.viewSortDescendingAction, SIGNAL(triggered(bool)), SLOT(viewSortOrderAction())); QObject::connect(m_ui.helpAboutAction, SIGNAL(triggered(bool)), SLOT(helpAbout())); QObject::connect(m_ui.helpAboutQtAction, SIGNAL(triggered(bool)), SLOT(helpAboutQt())); QObject::connect(m_ui.ToolBar, SIGNAL(orientationChanged(Qt::Orientation)), SLOT(orientationChanged(Qt::Orientation))); m_ui.graphCanvas->setSearchPlaceholderText( m_ui.editSearchItemAction->statusTip() + QString(3, '.')); } // Destructor. qjackctlGraphForm::~qjackctlGraphForm (void) { if (m_thumb) delete m_thumb; delete m_thumb_mode; delete m_sort_order; delete m_sort_type; if (m_jack) delete m_jack; #ifdef CONFIG_ALSA_SEQ if (m_alsa) delete m_alsa; #endif if (m_config) delete m_config; } // Set reference to global options, mostly needed for // the initial state of the main dockable views and // those client/port aliasing feature. void qjackctlGraphForm::setup ( qjackctlSetup *pSetup ) { m_config = new qjackctlGraphConfig(&pSetup->settings()); m_ui.graphCanvas->setSettings(m_config->settings()); m_ui.graphCanvas->setAliases(&(pSetup->aliases)); m_config->restoreState(this); // Raise the operational sects... m_jack = new qjackctlJackGraph(m_ui.graphCanvas); #ifdef CONFIG_ALSA_SEQ if (pSetup->bAlsaSeqEnabled) m_alsa = new qjackctlAlsaGraph(m_ui.graphCanvas); #endif m_ui.viewMenubarAction->setChecked(m_config->isMenubar()); m_ui.viewToolbarAction->setChecked(m_config->isToolbar()); m_ui.viewStatusbarAction->setChecked(m_config->isStatusbar()); m_ui.viewTextBesideIconsAction->setChecked(m_config->isTextBesideIcons()); m_ui.viewZoomRangeAction->setChecked(m_config->isZoomRange()); m_ui.viewRepelOverlappingNodesAction->setChecked(m_config->isRepelOverlappingNodes()); m_ui.viewConnectThroughNodesAction->setChecked(m_config->isConnectThroughNodes()); const qjackctlGraphPort::SortType sort_type = qjackctlGraphPort::SortType(m_config->sortType()); qjackctlGraphPort::setSortType(sort_type); switch (sort_type) { case qjackctlGraphPort::PortIndex: m_ui.viewSortPortIndexAction->setChecked(true); break; case qjackctlGraphPort::PortTitle: m_ui.viewSortPortTitleAction->setChecked(true); break; case qjackctlGraphPort::PortName: default: m_ui.viewSortPortNameAction->setChecked(true); break; } const qjackctlGraphPort::SortOrder sort_order = qjackctlGraphPort::SortOrder(m_config->sortOrder()); qjackctlGraphPort::setSortOrder(sort_order); switch (sort_order) { case qjackctlGraphPort::Descending: m_ui.viewSortDescendingAction->setChecked(true); break; case qjackctlGraphPort::Ascending: default: m_ui.viewSortAscendingAction->setChecked(true); break; } viewMenubar(m_config->isMenubar()); viewToolbar(m_config->isToolbar()); viewStatusbar(m_config->isStatusbar()); viewThumbview(m_config->thumbview()); viewTextBesideIcons(m_config->isTextBesideIcons()); viewZoomRange(m_config->isZoomRange()); viewRepelOverlappingNodes(m_config->isRepelOverlappingNodes()); viewConnectThroughNodes(m_config->isConnectThroughNodes()); m_ui.graphCanvas->restoreState(); updateViewColors(); stabilize(); // Make it ready :-) m_ui.StatusBar->showMessage(tr("Ready"), 3000); // Trigger refresh cycle... jack_changed(); alsa_changed(); } // Update the canvas palette. void qjackctlGraphForm::updatePalette (void) { m_ui.graphCanvas->updatePalette(); if (m_thumb) m_thumb->updatePalette(); viewRefresh(); } // Main menu slots. void qjackctlGraphForm::viewMenubar ( bool on ) { m_ui.MenuBar->setVisible(on); ++m_thumb_update; } void qjackctlGraphForm::viewToolbar ( bool on ) { m_ui.ToolBar->setVisible(on); ++m_thumb_update; } void qjackctlGraphForm::viewStatusbar ( bool on ) { m_ui.StatusBar->setVisible(on); ++m_thumb_update; } void qjackctlGraphForm::viewThumbviewAction (void) { QAction *action = qobject_cast (sender()); if (action) viewThumbview(action->data().toInt()); } void qjackctlGraphForm::viewThumbview ( int thumbview ) { const qjackctlGraphThumb::Position position = qjackctlGraphThumb::Position(thumbview); if (position == qjackctlGraphThumb::None) { if (m_thumb) { m_thumb->hide(); delete m_thumb; m_thumb = nullptr; m_thumb_update = 0; } } else { if (m_thumb) { m_thumb->setPosition(position); } else { m_thumb = new qjackctlGraphThumb(m_ui.graphCanvas, position); QObject::connect(m_thumb, SIGNAL(contextMenuRequested(const QPoint&)), SLOT(thumbviewContextMenu(const QPoint&)), Qt::QueuedConnection); QObject::connect(m_thumb, SIGNAL(positionRequested(int)), SLOT(viewThumbview(int)), Qt::QueuedConnection); ++m_thumb_update; } } switch (position) { case qjackctlGraphThumb::TopLeft: m_ui.viewThumbviewTopLeftAction->setChecked(true); break; case qjackctlGraphThumb::TopRight: m_ui.viewThumbviewTopRightAction->setChecked(true); break; case qjackctlGraphThumb::BottomLeft: m_ui.viewThumbviewBottomLeftAction->setChecked(true); break; case qjackctlGraphThumb::BottomRight: m_ui.viewThumbviewBottomRightAction->setChecked(true); break; case qjackctlGraphThumb::None: default: m_ui.viewThumbviewNoneAction->setChecked(true); break; } } void qjackctlGraphForm::viewTextBesideIcons ( bool on ) { if (on) { m_ui.ToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); } else { m_ui.ToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); } ++m_thumb_update; } void qjackctlGraphForm::viewCenter (void) { const QRectF& scene_rect = m_ui.graphCanvas->scene()->itemsBoundingRect(); m_ui.graphCanvas->centerOn(scene_rect.center()); stabilize(); } void qjackctlGraphForm::viewRefresh (void) { if (m_jack) m_jack->clearItems(); #ifdef CONFIG_ALSA_SEQ if (m_alsa) m_alsa->clearItems(); #endif jack_changed(); alsa_changed(); if (m_ui.graphCanvas->isRepelOverlappingNodes()) ++m_repel_overlapping_nodes; // fake nodes added! ++m_thumb_update; refresh(); } void qjackctlGraphForm::viewZoomRange ( bool on ) { m_ui.graphCanvas->setZoomRange(on); } void qjackctlGraphForm::viewColorsAction (void) { QAction *action = qobject_cast (sender()); if (action == nullptr) return; const uint port_type = action->data().toUInt(); if (0 >= port_type) return; const QColor& color = QColorDialog::getColor( m_ui.graphCanvas->portTypeColor(port_type), this, tr("Colors - %1").arg(action->text().remove('&'))); if (color.isValid()) { m_ui.graphCanvas->setPortTypeColor(port_type, color); m_ui.graphCanvas->updatePortTypeColors(port_type); updateViewColorsAction(action); } ++m_thumb_update; } void qjackctlGraphForm::viewColorsReset (void) { m_ui.graphCanvas->clearPortTypeColors(); if (m_jack) m_jack->resetPortTypeColors(); #ifdef CONFIG_ALSA_SEQ if (m_alsa) m_alsa->resetPortTypeColors(); #endif m_ui.graphCanvas->updatePortTypeColors(); updateViewColors(); } void qjackctlGraphForm::viewSortTypeAction (void) { QAction *action = qobject_cast (sender()); if (action == nullptr) return; const qjackctlGraphPort::SortType sort_type = qjackctlGraphPort::SortType(action->data().toInt()); qjackctlGraphPort::setSortType(sort_type); m_ui.graphCanvas->updateNodes(); } void qjackctlGraphForm::viewSortOrderAction (void) { QAction *action = qobject_cast (sender()); if (action == nullptr) return; const qjackctlGraphPort::SortOrder sort_order = qjackctlGraphPort::SortOrder(action->data().toInt()); qjackctlGraphPort::setSortOrder(sort_order); m_ui.graphCanvas->updateNodes(); } void qjackctlGraphForm::viewRepelOverlappingNodes ( bool on ) { m_ui.graphCanvas->setRepelOverlappingNodes(on); if (on) ++m_repel_overlapping_nodes; } void qjackctlGraphForm::viewConnectThroughNodes ( bool on ) { qjackctlGraphConnect::setConnectThroughNodes(on); m_ui.graphCanvas->updateConnects(); } void qjackctlGraphForm::helpAbout (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->showAboutForm(); } void qjackctlGraphForm::helpAboutQt (void) { QMessageBox::aboutQt(this); } void qjackctlGraphForm::thumbviewContextMenu ( const QPoint& pos ) { stabilize(); QMenu menu(this); menu.addMenu(m_ui.viewThumbviewMenu); menu.addSeparator(); menu.addAction(m_ui.viewCenterAction); menu.addMenu(m_ui.viewZoomMenu); menu.exec(pos); stabilize(); } void qjackctlGraphForm::zoomValueChanged ( int zoom_value ) { m_ui.graphCanvas->setZoom(0.01 * qreal(zoom_value)); } // Node life-cycle slots. void qjackctlGraphForm::added ( qjackctlGraphNode *node ) { const qjackctlGraphCanvas *canvas = m_ui.graphCanvas; const QRectF& rect = canvas->mapToScene(canvas->viewport()->rect()).boundingRect(); const QPointF& pos = rect.center(); const qreal w = 0.33 * qMax(rect.width(), 800.0); const qreal h = 0.33 * qMax(rect.height(), 600.0); qreal x = pos.x(); qreal y = pos.y(); switch (node->nodeMode()) { case qjackctlGraphItem::Input: ++m_ins &= 0x0f; x += w; y += 0.33 * h * (m_ins & 1 ? +m_ins : -m_ins); break; case qjackctlGraphItem::Output: ++m_outs &= 0x0f; x -= w; y += 0.33 * h * (m_outs & 1 ? +m_outs : -m_outs); break; default: { int dx = 0; int dy = 0; for (int i = 0; i < m_mids; ++i) { if ((qAbs(dx) > qAbs(dy)) || (dx == dy && dx < 0)) dy += (dx < 0 ? +1 : -1); else dx += (dy < 0 ? -1 : +1); } x += 0.33 * w * qreal(dx); y += 0.33 * h * qreal(dy); ++m_mids &= 0x1f; break; }} x -= qreal(::rand() & 0x1f); y -= qreal(::rand() & 0x1f); node->setPos(canvas->snapPos(QPointF(x, y))); updated(node); } void qjackctlGraphForm::updated ( qjackctlGraphNode */*node*/ ) { if (m_ui.graphCanvas->isRepelOverlappingNodes()) ++m_repel_overlapping_nodes; } void qjackctlGraphForm::removed ( qjackctlGraphNode */*node*/ ) { #if 0// FIXME: DANGEROUS! Node might have been deleted by now... if (node) { switch (node->nodeMode()) { case qjackctlGraphItem::Input: --m_ins; break; case qjackctlGraphItem::Output: --m_outs; break; default: --m_mids; break; } } #endif } // Port (dis)connection slots. void qjackctlGraphForm::connected ( qjackctlGraphPort *port1, qjackctlGraphPort *port2 ) { if (qjackctlJackGraph::isPortType(port1->portType())) { if (m_jack) m_jack->connectPorts(port1, port2, true); jack_changed(); } #ifdef CONFIG_ALSA_SEQ else if (qjackctlAlsaGraph::isPortType(port1->portType())) { if (m_alsa) m_alsa->connectPorts(port1, port2, true); alsa_changed(); } #endif stabilize(); } void qjackctlGraphForm::disconnected ( qjackctlGraphPort *port1, qjackctlGraphPort *port2 ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->queryDisconnect(port1, port2); if (qjackctlJackGraph::isPortType(port1->portType())) { if (m_jack) m_jack->connectPorts(port1, port2, false); jack_changed(); } #ifdef CONFIG_ALSA_SEQ else if (qjackctlAlsaGraph::isPortType(port1->portType())) { if (m_alsa) m_alsa->connectPorts(port1, port2, false); alsa_changed(); } #endif stabilize(); } void qjackctlGraphForm::connected ( qjackctlGraphConnect *connect ) { qjackctlGraphPort *port1 = connect->port1(); if (port1 == nullptr) return; if (qjackctlJackGraph::isPortType(port1->portType())) { if (m_jack) m_jack->addItem(connect, false); } #ifdef CONFIG_ALSA_SEQ else if (qjackctlAlsaGraph::isPortType(port1->portType())) { if (m_alsa) m_alsa->addItem(connect, false); } #endif } // Item renaming slot. void qjackctlGraphForm::renamed ( qjackctlGraphItem *item, const QString& name ) { qjackctlGraphSect *sect = item_sect(item); if (sect) sect->renameItem(item, name); } // Graph view change slot. void qjackctlGraphForm::changed (void) { ++m_thumb_update; stabilize(); } // Graph section slots. void qjackctlGraphForm::jack_shutdown (void) { m_ui.graphCanvas->clearSelection(); m_jack_changed = 0; if (m_jack) m_jack->clearItems(); stabilize(); } void qjackctlGraphForm::jack_changed (void) { ++m_jack_changed; } void qjackctlGraphForm::alsa_changed (void) { ++m_alsa_changed; } // Graph refreshner. void qjackctlGraphForm::refresh (void) { if (m_ui.graphCanvas->isBusy()) return; int nchanged = 0; if (m_jack_changed > 0) { m_jack_changed = 0; if (m_jack) m_jack->updateItems(); ++nchanged; } #ifdef CONFIG_ALSA_SEQ else if (m_alsa_changed > 0) { m_alsa_changed = 0; if (m_alsa) m_alsa->updateItems(); ++nchanged; } #endif if (nchanged > 0) stabilize(); else if (m_repel_overlapping_nodes > 0) { m_repel_overlapping_nodes = 0; m_ui.graphCanvas->repelOverlappingNodesAll(); stabilize(); ++nchanged; } if (m_thumb_update > 0 || nchanged > 0) { m_thumb_update = 0; if (m_thumb) m_thumb->updateView(); } } // Graph selection change slot. void qjackctlGraphForm::stabilize (void) { const qjackctlGraphCanvas *canvas = m_ui.graphCanvas; m_ui.graphConnectAction->setEnabled(canvas->canConnect()); m_ui.graphDisconnectAction->setEnabled(canvas->canDisconnect()); m_ui.editSelectNoneAction->setEnabled( !canvas->scene()->selectedItems().isEmpty()); m_ui.editRenameItemAction->setEnabled( canvas->canRenameItem()); m_ui.editSearchItemAction->setEnabled( canvas->canSearchItem()); #if 0 const QRectF& outter_rect = canvas->scene()->sceneRect().adjusted(-2.0, -2.0, +2.0, +2.0); const QRectF& inner_rect = canvas->mapToScene(canvas->viewport()->rect()).boundingRect(); const bool is_contained = outter_rect.contains(inner_rect) || canvas->horizontalScrollBar()->isVisible() || canvas->verticalScrollBar()->isVisible(); #else const bool is_contained = true; #endif const qreal zoom = canvas->zoom(); m_ui.viewCenterAction->setEnabled(is_contained); m_ui.viewZoomInAction->setEnabled(zoom < 1.9); m_ui.viewZoomOutAction->setEnabled(zoom > 0.1); m_ui.viewZoomFitAction->setEnabled(is_contained); m_ui.viewZoomResetAction->setEnabled(zoom != 1.0); const int zoom_value = int(100.0f * zoom); const bool is_spinbox_blocked = m_zoom_spinbox->blockSignals(true); const bool is_slider_blocked = m_zoom_slider->blockSignals(true); m_zoom_spinbox->setValue(zoom_value); m_zoom_slider->setValue(zoom_value); m_zoom_spinbox->blockSignals(is_spinbox_blocked); m_zoom_slider->blockSignals(is_slider_blocked); } // Tool-bar orientation change slot. void qjackctlGraphForm::orientationChanged ( Qt::Orientation orientation ) { if (m_config && m_config->isTextBesideIcons() && orientation == Qt::Horizontal) { m_ui.ToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); } else { m_ui.ToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); } } // Context-menu event handler. void qjackctlGraphForm::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { m_ui.graphCanvas->clear(); stabilize(); QMenu menu(this); menu.addAction(m_ui.graphConnectAction); menu.addAction(m_ui.graphDisconnectAction); menu.addSeparator(); menu.addActions(m_ui.editMenu->actions()); menu.addSeparator(); menu.addMenu(m_ui.viewZoomMenu); menu.exec(pContextMenuEvent->globalPos()); stabilize(); } // Widget resize event handler. void qjackctlGraphForm::resizeEvent ( QResizeEvent *pResizeEvent ) { QMainWindow::resizeEvent(pResizeEvent); if (m_thumb) { m_thumb_update = 0; m_thumb->updateView(); } stabilize(); } // Notify our parent that we're emerging. void qjackctlGraphForm::showEvent ( QShowEvent *pShowEvent ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); ++m_thumb_update; QWidget::showEvent(pShowEvent); } // Notify our parent that we're closing. void qjackctlGraphForm::hideEvent ( QHideEvent *pHideEvent ) { QWidget::hideEvent(pHideEvent); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); } // Widget close event handler. void qjackctlGraphForm::closeEvent ( QCloseEvent *pCloseEvent ) { m_ui.graphCanvas->saveState(); if (m_config && QMainWindow::isVisible()) { m_config->setThumbview(m_thumb ? m_thumb->position() : qjackctlGraphThumb::None); m_config->setConnectThroughNodes(m_ui.viewConnectThroughNodesAction->isChecked()); m_config->setRepelOverlappingNodes(m_ui.viewRepelOverlappingNodesAction->isChecked()); m_config->setSortOrder(int(qjackctlGraphPort::sortOrder())); m_config->setSortType(int(qjackctlGraphPort::sortType())); m_config->setTextBesideIcons(m_ui.viewTextBesideIconsAction->isChecked()); m_config->setZoomRange(m_ui.viewZoomRangeAction->isChecked()); m_config->setStatusbar(m_ui.StatusBar->isVisible()); m_config->setToolbar(m_ui.ToolBar->isVisible()); m_config->setMenubar(m_ui.MenuBar->isVisible()); m_config->saveState(this); } QMainWindow::closeEvent(pCloseEvent); } // Special port-type color methods. void qjackctlGraphForm::updateViewColorsAction ( QAction *action ) { const uint port_type = action->data().toUInt(); if (0 >= port_type) return; const QColor& color = m_ui.graphCanvas->portTypeColor(port_type); if (!color.isValid()) return; QPixmap pm(22, 22); QPainter(&pm).fillRect(0, 0, pm.width(), pm.height(), color); action->setIcon(QIcon(pm)); } void qjackctlGraphForm::updateViewColors (void) { updateViewColorsAction(m_ui.viewColorsJackAudioAction); updateViewColorsAction(m_ui.viewColorsJackMidiAction); #ifdef CONFIG_ALSA_SEQ updateViewColorsAction(m_ui.viewColorsAlsaMidiAction); #endif #ifdef CONFIG_JACK_CV updateViewColorsAction(m_ui.viewColorsJackCvAction); #endif #ifdef CONFIG_JACK_OSC updateViewColorsAction(m_ui.viewColorsJackOscAction); #endif } // Item sect predicate. qjackctlGraphSect *qjackctlGraphForm::item_sect ( qjackctlGraphItem *item ) const { if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node && qjackctlJackGraph::isNodeType(node->nodeType())) return m_jack; #ifdef CONFIG_ALSA_SEQ else if (node && qjackctlAlsaGraph::isNodeType(node->nodeType())) return m_alsa; #endif } else if (item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port = static_cast (item); if (port && qjackctlJackGraph::isPortType(port->portType())) return m_jack; #ifdef CONFIG_ALSA_SEQ else if (port && qjackctlAlsaGraph::isPortType(port->portType())) return m_alsa; #endif } return nullptr; // No deal! } //---------------------------------------------------------------------------- // qjackctlGraphConfig -- Canvas state memento. // Local constants. static const char *LayoutGroup = "/GraphLayout"; static const char *ViewGroup = "/GraphView"; static const char *ViewMenubarKey = "/Menubar"; static const char *ViewToolbarKey = "/Toolbar"; static const char *ViewStatusbarKey = "/Statusbar"; static const char *ViewThumbviewKey = "/Thumbview"; static const char *ViewTextBesideIconsKey = "/TextBesideIcons"; static const char *ViewZoomRangeKey = "/ZoomRange"; static const char *ViewSortTypeKey = "/SortType"; static const char *ViewSortOrderKey = "/SortOrder"; static const char *ViewRepelOverlappingNodesKey = "/RepelOverlappingNodes"; static const char *ViewConnectThroughNodesKey = "/ConnectThroughNodes"; // Constructors. qjackctlGraphConfig::qjackctlGraphConfig ( QSettings *settings ) : m_settings(settings), m_menubar(false), m_toolbar(false), m_statusbar(false), m_thumbview(0), m_texticons(false), m_zoomrange(false), m_sorttype(0), m_sortorder(0), m_repelnodes(false), m_cthrunodes(false) { } QSettings *qjackctlGraphConfig::settings (void) const { return m_settings; } void qjackctlGraphConfig::setMenubar ( bool menubar ) { m_menubar = menubar; } bool qjackctlGraphConfig::isMenubar (void) const { return m_menubar; } void qjackctlGraphConfig::setToolbar ( bool toolbar ) { m_toolbar = toolbar; } bool qjackctlGraphConfig::isToolbar (void) const { return m_toolbar; } void qjackctlGraphConfig::setStatusbar ( bool statusbar ) { m_statusbar = statusbar; } bool qjackctlGraphConfig::isStatusbar (void) const { return m_statusbar; } void qjackctlGraphConfig::setThumbview ( int thumbview ) { m_thumbview = thumbview; } int qjackctlGraphConfig::thumbview (void) const { return m_thumbview; } void qjackctlGraphConfig::setTextBesideIcons ( bool texticons ) { m_texticons = texticons; } bool qjackctlGraphConfig::isTextBesideIcons (void) const { return m_texticons; } void qjackctlGraphConfig::setZoomRange ( bool zoomrange ) { m_zoomrange = zoomrange; } bool qjackctlGraphConfig::isZoomRange (void) const { return m_zoomrange; } void qjackctlGraphConfig::setSortType ( int sorttype ) { m_sorttype = sorttype; } int qjackctlGraphConfig::sortType (void) const { return m_sorttype; } void qjackctlGraphConfig::setSortOrder ( int sortorder ) { m_sortorder = sortorder; } int qjackctlGraphConfig::sortOrder (void) const { return m_sortorder; } void qjackctlGraphConfig::setRepelOverlappingNodes ( bool repelnodes ) { m_repelnodes = repelnodes; } bool qjackctlGraphConfig::isRepelOverlappingNodes (void) const { return m_repelnodes; } void qjackctlGraphConfig::setConnectThroughNodes ( bool cthrunodes ) { m_cthrunodes = cthrunodes; } bool qjackctlGraphConfig::isConnectThroughNodes (void) const { return m_cthrunodes; } // Graph main-widget state methods. bool qjackctlGraphConfig::restoreState ( QMainWindow *widget ) { if (m_settings == nullptr || widget == nullptr) return false; m_settings->beginGroup(ViewGroup); m_menubar = m_settings->value(ViewMenubarKey, true).toBool(); m_toolbar = m_settings->value(ViewToolbarKey, true).toBool(); m_statusbar = m_settings->value(ViewStatusbarKey, true).toBool(); m_thumbview = m_settings->value(ViewThumbviewKey, 0).toInt(); m_texticons = m_settings->value(ViewTextBesideIconsKey, true).toBool(); m_zoomrange = m_settings->value(ViewZoomRangeKey, false).toBool(); m_sorttype = m_settings->value(ViewSortTypeKey, 0).toInt(); m_sortorder = m_settings->value(ViewSortOrderKey, 0).toInt(); m_repelnodes = m_settings->value(ViewRepelOverlappingNodesKey, false).toBool(); m_cthrunodes = m_settings->value(ViewConnectThroughNodesKey, false).toBool(); m_settings->endGroup(); m_settings->beginGroup(LayoutGroup); const QByteArray& layout_state = m_settings->value('/' + widget->objectName()).toByteArray(); m_settings->endGroup(); if (!layout_state.isEmpty()) widget->restoreState(layout_state); return true; } bool qjackctlGraphConfig::saveState ( QMainWindow *widget ) const { if (m_settings == nullptr || widget == nullptr) return false; m_settings->beginGroup(ViewGroup); m_settings->setValue(ViewMenubarKey, m_menubar); m_settings->setValue(ViewToolbarKey, m_toolbar); m_settings->setValue(ViewStatusbarKey, m_statusbar); m_settings->setValue(ViewThumbviewKey, m_thumbview); m_settings->setValue(ViewTextBesideIconsKey, m_texticons); m_settings->setValue(ViewZoomRangeKey, m_zoomrange); m_settings->setValue(ViewSortTypeKey, m_sorttype); m_settings->setValue(ViewSortOrderKey, m_sortorder); m_settings->setValue(ViewRepelOverlappingNodesKey, m_repelnodes); m_settings->setValue(ViewConnectThroughNodesKey, m_cthrunodes); m_settings->endGroup(); m_settings->beginGroup(LayoutGroup); const QByteArray& layout_state = widget->saveState(); m_settings->setValue('/' + widget->objectName(), layout_state); m_settings->endGroup(); return true; } // end of qjackctlGraphForm.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlSystemTray.cpp0000644000000000000000000000012714771215054017534 xustar0029 mtime=1743067692.33063656 29 atime=1743067692.33063656 29 ctime=1743067692.33063656 qjackctl-1.0.4/src/qjackctlSystemTray.cpp0000644000175000001440000000731514771215054017526 0ustar00rncbcusers// qjackctlSystemTray.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAbout.h" #include "qjackctlSystemTray.h" #include #include #if QT_VERSION < QT_VERSION_CHECK(4, 5, 0) namespace Qt { const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000); } #endif //---------------------------------------------------------------------------- // qjackctlSystemTray -- Custom system tray widget. // Constructor. qjackctlSystemTray::qjackctlSystemTray ( QWidget *pParent ) : QSystemTrayIcon(pParent) { // Set things inherited... if (pParent) { #if QT_VERSION < QT_VERSION_CHECK(6, 1, 0) m_icon = QIcon(":/images/qjackctl.png"); #else m_icon = pParent->windowIcon().pixmap(32, 32); #endif setBackground(Qt::transparent); // also updates pixmap. QSystemTrayIcon::setIcon(m_icon); QSystemTrayIcon::setToolTip(pParent->windowTitle()); } QObject::connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), SLOT(activated(QSystemTrayIcon::ActivationReason))); QSystemTrayIcon::show(); } // Redirect to hide. void qjackctlSystemTray::close (void) { QSystemTrayIcon::hide(); } // Handle systeam tray activity. void qjackctlSystemTray::activated ( QSystemTrayIcon::ActivationReason reason ) { switch (reason) { case QSystemTrayIcon::Trigger: emit clicked(); break; case QSystemTrayIcon::MiddleClick: emit middleClicked(); break; case QSystemTrayIcon::DoubleClick: emit doubleClicked(); break; case QSystemTrayIcon::Unknown: default: break; } } // Default destructor. qjackctlSystemTray::~qjackctlSystemTray (void) { } // System tray icon/pixmaps update method. void qjackctlSystemTray::updatePixmap (void) { // Renitialize icon as fit... m_pixmap = m_icon.pixmap(32, 32); // Merge with the overlay pixmap... if (!m_pixmapOverlay.mask().isNull()) { const int y = m_pixmap.height() - m_pixmapOverlay.height(); QBitmap mask = m_pixmap.mask(); QPainter(&mask).drawPixmap(0, y, m_pixmapOverlay.mask()); m_pixmap.setMask(mask); QPainter(&m_pixmap).drawPixmap(0, y, m_pixmapOverlay); } if (m_background != Qt::transparent) { QPixmap pixmap(m_pixmap); m_pixmap.fill(m_background); QPainter(&m_pixmap).drawPixmap(0, 0, pixmap); } // Setup system tray icon directly... QSystemTrayIcon::setIcon(QIcon(m_pixmap)); } // Background mask methods. void qjackctlSystemTray::setBackground ( const QColor& background ) { // Set background color, now. m_background = background; updatePixmap(); } const QColor& qjackctlSystemTray::background (void) const { return m_background; } // Set system tray icon overlay. void qjackctlSystemTray::setPixmapOverlay ( const QPixmap& pmOverlay ) { m_pixmapOverlay = pmOverlay; updatePixmap(); } const QPixmap& qjackctlSystemTray::pixmapOverlay (void) const { return m_pixmapOverlay; } // end of qjackctlSystemTray.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlAlsaGraph.h0000644000000000000000000000013214771215054016713 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlAlsaGraph.h0000644000175000001440000000462314771215054016710 0ustar00rncbcusers// qjackctlAlsaGraph.h // /**************************************************************************** Copyright (C) 2003-2023, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlAlsaGraph_h #define __qjackctlAlsaGraph_h #include "qjackctlAbout.h" #include "qjackctlGraph.h" #ifdef CONFIG_ALSA_SEQ #include #include //---------------------------------------------------------------------------- // qjackctlAlsaGraph -- ALSA graph driver class qjackctlAlsaGraph : public qjackctlGraphSect { public: // Constructor. qjackctlAlsaGraph(qjackctlGraphCanvas *canvas); // ALSA port (dis)connection. void connectPorts( qjackctlGraphPort *port1, qjackctlGraphPort *port2, bool is_connect); // ALSA graph updaters. void updateItems(); void clearItems(); // Special port-type colors defaults (virtual). void resetPortTypeColors(); // ALSA node type inquirer. static bool isNodeType(uint node_type); // ALSA node type. static uint nodeType(); // ALSA port type inquirer. static bool isPortType(uint port_type); // ALSA port type. static uint midiPortType(); protected: // ALSA client:port finder and creator if not existing. bool findClientPort(snd_seq_client_info_t *client_info, snd_seq_port_info_t *port_info, qjackctlGraphItem::Mode port_mode, qjackctlGraphNode **node, qjackctlGraphPort **port, bool add_new); // Client/port item aliases accessor. QList item_aliases(qjackctlGraphItem *item) const; private: // Notifier sanity mutex. QMutex m_mutex; }; #endif // CONFIG_ALSA_SEQ #endif // __qjackctlAlsaGraph_h // end of qjackctlAlsaGraph.h qjackctl-1.0.4/src/PaxHeaders/qjackctlMainForm.cpp0000644000000000000000000000013214771215054017114 xustar0030 mtime=1743067692.326636579 30 atime=1743067692.325636584 30 ctime=1743067692.326636579 qjackctl-1.0.4/src/qjackctlMainForm.cpp0000644000175000001440000041673314771215054017122 0ustar00rncbcusers// qjackctlMainForm.cpp // /**************************************************************************** Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlMainForm.h" #include "qjackctlStatus.h" #include "qjackctlPatchbay.h" #include "qjackctlPatchbayFile.h" #include "qjackctlMessagesStatusForm.h" #include "qjackctlSessionForm.h" #include "qjackctlConnectionsForm.h" #include "qjackctlPatchbayForm.h" #include "qjackctlGraphForm.h" #include "qjackctlSetupForm.h" #include "qjackctlAboutForm.h" #include "qjackctlJackGraph.h" #ifdef CONFIG_ALSA_SEQ #include "qjackctlAlsaGraph.h" #endif #ifdef CONFIG_SYSTEM_TRAY #include "qjackctlSystemTray.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION < QT_VERSION_CHECK(4, 5, 0) namespace Qt { const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000); } #endif // Deprecated QTextStreamFunctions/Qt namespaces workaround. #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) #define endl Qt::endl #endif #ifdef CONFIG_DBUS #include #include #include #endif #ifdef CONFIG_JACK_STATISTICS #include #endif #ifdef CONFIG_JACK_METADATA #include #endif // Timer constant stuff. #define QJACKCTL_TIMER_MSECS 200 // Status refresh cycle (~2 secs) #define QJACKCTL_STATUS_CYCLE 10 // Server display enumerated states. #define QJACKCTL_INACTIVE 0 #define QJACKCTL_ACTIVATING 1 #define QJACKCTL_ACTIVE 2 #define QJACKCTL_STARTING 3 #define QJACKCTL_STARTED 4 #define QJACKCTL_STOPPING 5 #define QJACKCTL_STOPPED 6 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) #include #undef HAVE_POLL_H #undef HAVE_SIGNAL_H #else #include #include // Notification pipes descriptors #define QJACKCTL_FDNIL -1 #define QJACKCTL_FDREAD 0 #define QJACKCTL_FDWRITE 1 static int g_fdStdout[2] = { QJACKCTL_FDNIL, QJACKCTL_FDNIL }; #endif #ifdef HAVE_POLL_H #include #endif // Custom event types. #define QJACKCTL_PORT_EVENT QEvent::Type(QEvent::User + 1) #define QJACKCTL_XRUN_EVENT QEvent::Type(QEvent::User + 2) #define QJACKCTL_BUFF_EVENT QEvent::Type(QEvent::User + 3) #define QJACKCTL_FREE_EVENT QEvent::Type(QEvent::User + 4) #define QJACKCTL_SHUT_EVENT QEvent::Type(QEvent::User + 5) #define QJACKCTL_EXIT_EVENT QEvent::Type(QEvent::User + 6) #ifdef CONFIG_DBUS #define QJACKCTL_LINE_EVENT QEvent::Type(QEvent::User + 7) #endif #ifdef CONFIG_JACK_METADATA #define QJACKCTL_PROP_EVENT QEvent::Type(QEvent::User + 8) #endif // Time dashes format helper.^ static const char *c_szTimeDashes = "--:--:--.---"; //------------------------------------------------------------------------- // UNIX Signal handling support stuff. #ifdef HAVE_SIGNAL_H #include #include #include // File descriptor for SIGTERM notifier. static int g_fdSigterm[2] = { QJACKCTL_FDNIL, QJACKCTL_FDNIL }; // Unix SIGTERM signal handler. static void qjackctl_sigterm_handler ( int /* signo */ ) { char c = 1; (void) (::write(g_fdSigterm[0], &c, sizeof(c)) > 0); } #endif // HAVE_SIGNAL_H //---------------------------------------------------------------------------- // qjackctl -- Static callback posters. // To have clue about current buffer size (in frames). static jack_nframes_t g_buffsize = 0; // Current freewheel running state. static int g_freewheel = 0; // Current server error state. static QProcess::ProcessError g_error = QProcess::UnknownError; // Jack client registration callback funtion, called // whenever a jack client is registered or unregistered. static void qjackctl_client_registration_callback ( const char *, int, void * ) { QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_PORT_EVENT)); } // Jack port registration callback funtion, called // whenever a jack port is registered or unregistered. static void qjackctl_port_registration_callback ( jack_port_id_t, int, void * ) { QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_PORT_EVENT)); } // Jack port (dis)connection callback funtion, called // whenever a jack port is connected or disconnected. static void qjackctl_port_connect_callback ( jack_port_id_t, jack_port_id_t, int, void * ) { QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_PORT_EVENT)); } // Jack graph order callback function, called // whenever the processing graph is reordered. static int qjackctl_graph_order_callback ( void * ) { QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_PORT_EVENT)); return 0; } #ifdef CONFIG_JACK_PORT_RENAME // Jack port rename callback funtion, called // whenever a jack port is renamed. static void qjackctl_port_rename_callback ( jack_port_id_t, const char *, const char *, void * ) { QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_PORT_EVENT)); } #endif // Jack XRUN callback function, called // whenever there is a xrun. static int qjackctl_xrun_callback ( void * ) { QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_XRUN_EVENT)); return 0; } // Jack buffer size function, called // whenever the server changes buffer size. static int qjackctl_buffer_size_callback ( jack_nframes_t nframes, void * ) { // Update our global static variable. g_buffsize = nframes; QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_BUFF_EVENT)); return 0; } // Jack freewheel callback function, called // whenever the server enters/exits freewheel mode. static void qjackctl_freewheel_callback ( int starting, void * ) { // Update our global static variable. g_freewheel = starting; QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_FREE_EVENT)); } // Jack shutdown function, called // whenever the server terminates this client. static void qjackctl_on_shutdown ( void * ) { QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_SHUT_EVENT)); } // Jack process exit function, called // whenever the server terminates abnormally. static void qjackctl_on_error ( QProcess::ProcessError error ) { g_error = error; QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_EXIT_EVENT)); } #ifdef CONFIG_DBUS //---------------------------------------------------------------------- // class qjackctlDBusLogWatcher -- Simple D-BUS log watcher thread. // class qjackctlDBusLogWatcher : public QThread { public: // Constructor. qjackctlDBusLogWatcher(const QString& sFilename) : QThread(), m_sFilename(sFilename), m_bRunState(false) {} // Destructor. ~qjackctlDBusLogWatcher() { if (isRunning()) do { m_bRunState = false; } while (!wait(1000)); } // Custom log event. class LineEvent : public QEvent { public: // Constructor. LineEvent(QEvent::Type eType, const QString& sLine) : QEvent(eType), m_sLine(sLine) { m_sLine.remove(QRegularExpression("\\x1B\\[[0-9|;]+m")); } // Accessor. const QString& line() const { return m_sLine; } private: // Custom event data. QString m_sLine; }; protected: // The main thread executive. void run() { QFile file(m_sFilename); m_bRunState = true; while (m_bRunState) { if (file.isOpen()) { char achBuffer[1024]; while (file.readLine(achBuffer, sizeof(achBuffer)) > 0) { QApplication::postEvent( qjackctlMainForm::getInstance(), new LineEvent(QJACKCTL_LINE_EVENT, achBuffer)); } if (file.size() == file.pos() && file.error() == QFile::NoError) { msleep(1000); } else { file.close(); } } else if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { file.seek(file.size()); } else msleep(1000); } } private: // The log filename to watch. QString m_sFilename; // Whether the thread is logically running. volatile bool m_bRunState; }; #endif // CONFIG_DBUS #ifdef CONFIG_JACK_METADATA // Jack property change function, called // whenever metadata is changed static void qjackctl_property_change_callback ( jack_uuid_t, const char *key, jack_property_change_t, void * ) { // PRETTY_NAME is the only metadata we are currently interested in... if (qjackctlJackClientList::isJackClientPortMetadata() && key && (strcmp(key, JACK_METADATA_PRETTY_NAME) == 0)) { QApplication::postEvent( qjackctlMainForm::getInstance(), new QEvent(QJACKCTL_PROP_EVENT)); } } #endif //---------------------------------------------------------------------------- // qjackctlMainForm -- UI wrapper form. // Kind of singleton reference. qjackctlMainForm *qjackctlMainForm::g_pMainForm = nullptr; // Constructor. qjackctlMainForm::qjackctlMainForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QWidget(pParent, wflags), m_menu(this) { // Setup UI struct... m_ui.setupUi(this); #if QT_VERSION < QT_VERSION_CHECK(6, 1, 0) QWidget::setWindowIcon(QIcon(":/images/qjackctl.png")); #endif // Pseudo-singleton reference setup. g_pMainForm = this; m_pSetup = nullptr; m_iServerState = QJACKCTL_INACTIVE; m_pJack = nullptr; m_pJackClient = nullptr; m_bJackDetach = false; m_bJackShutdown = false; m_bJackRestart = false; m_pAlsaSeq = nullptr; #ifdef CONFIG_DBUS m_pDBusControl = nullptr; m_pDBusConfig = nullptr; m_pDBusLogWatcher = nullptr; m_bDBusStarted = false; m_bDBusDetach = false; #endif #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) m_bJackKilled = false; #endif m_iStartDelay = 0; m_iTimerDelay = 0; m_iTimerRefresh = 0; m_iJackRefresh = 0; m_iAlsaRefresh = 0; m_iJackDirty = 0; m_iAlsaDirty = 0; m_iStatusRefresh = 0; m_iStatusBlink = 0; m_iPatchbayRefresh = 0; m_iJackRefreshClear = 0; m_iAlsaRefreshClear = 0; m_pStdoutNotifier = nullptr; m_pAlsaNotifier = nullptr; // All forms are to be created later on setup. m_pMessagesStatusForm = nullptr; m_pSessionForm = nullptr; m_pConnectionsForm = nullptr; m_pPatchbayForm = nullptr; m_pGraphForm = nullptr; m_pSetupForm = nullptr; // Patchbay rack can be readily created. m_pPatchbayRack = new qjackctlPatchbayRack(); #ifdef CONFIG_SYSTEM_TRAY // The eventual system tray widget. m_pSystemTray = nullptr; m_bQuitClose = false; #endif // We're not quitting so early :) m_bQuitForce = false; // Transport skip accelerate factor. m_fSkipAccel = 1.0; // Avoid extra transport toggles (play/stop) m_iTransportPlay = 0; // Whether to update context menu on next status refresh. m_iMenuRefresh = 0; // Whether we've Qt::Tool flag (from bKeepOnTop), // this is actually the main last application window... QWidget::setAttribute(Qt::WA_QuitOnClose); #ifdef HAVE_SIGNAL_H // Set to ignore any fatal "Broken pipe" signals. ::signal(SIGPIPE, SIG_IGN); // Initialize file descriptors for SIGTERM socket notifier. ::socketpair(AF_UNIX, SOCK_STREAM, 0, g_fdSigterm); m_pSigtermNotifier = new QSocketNotifier(g_fdSigterm[1], QSocketNotifier::Read, this); QObject::connect(m_pSigtermNotifier, SIGNAL(activated(int)), SLOT(sigtermNotifySlot(int))); // Install SIGTERM signal handler. struct sigaction sigterm; sigterm.sa_handler = qjackctl_sigterm_handler; sigemptyset(&sigterm.sa_mask); sigterm.sa_flags = 0; sigterm.sa_flags |= SA_RESTART; ::sigaction(SIGTERM, &sigterm, nullptr); ::sigaction(SIGQUIT, &sigterm, nullptr); // Ignore SIGHUP/SIGINT signals. ::signal(SIGHUP, SIG_IGN); ::signal(SIGINT, SIG_IGN); // Also ignore SIGUSR1 (LADISH Level 1). ::signal(SIGUSR1, SIG_IGN); #else // HAVE_SIGNAL_H m_pSigtermNotifier = nullptr; #endif // !HAVE_SIGNAL_H #if 0 // FIXME: Iterate for every child text label... m_ui.StatusDisplayFrame->setAutoFillBackground(true); QList labels = m_ui.StatusDisplayFrame->findChildren (); QListIterator iter(labels); while (iter.hasNext()) iter.next()->setAutoFillBackground(false); #endif // UI connections... QObject::connect(m_ui.StartToolButton, SIGNAL(clicked()), SLOT(startJack())); QObject::connect(m_ui.StopToolButton, SIGNAL(clicked()), SLOT(stopJack())); QObject::connect(m_ui.MessagesStatusToolButton, SIGNAL(clicked()), SLOT(toggleMessagesStatusForm())); QObject::connect(m_ui.SessionToolButton, SIGNAL(clicked()), SLOT(toggleSessionForm())); QObject::connect(m_ui.GraphToolButton, SIGNAL(clicked()), SLOT(toggleGraphForm())); QObject::connect(m_ui.ConnectionsToolButton, SIGNAL(clicked()), SLOT(toggleConnectionsForm())); QObject::connect(m_ui.PatchbayToolButton, SIGNAL(clicked()), SLOT(togglePatchbayForm())); QObject::connect(m_ui.QuitToolButton, SIGNAL(clicked()), SLOT(quitMainForm())); QObject::connect(m_ui.SetupToolButton, SIGNAL(clicked()), SLOT(showSetupForm())); QObject::connect(m_ui.AboutToolButton, SIGNAL(clicked()), SLOT(showAboutForm())); QObject::connect(m_ui.RewindToolButton, SIGNAL(clicked()), SLOT(transportRewind())); QObject::connect(m_ui.BackwardToolButton, SIGNAL(clicked()), SLOT(transportBackward())); QObject::connect(m_ui.PlayToolButton, SIGNAL(toggled(bool)), SLOT(transportPlay(bool))); QObject::connect(m_ui.PauseToolButton, SIGNAL(clicked()), SLOT(transportStop())); QObject::connect(m_ui.ForwardToolButton, SIGNAL(clicked()), SLOT(transportForward())); #ifdef __APPLE__ // Setup macOS menu bar QMenuBar* const menuBar = new QMenuBar(nullptr); menuBar->setNativeMenuBar(true); QMenu* const menu = menuBar->addMenu("QjackCtl"); QAction* const actQuit = menu->addAction(tr("&Quit")); actQuit->setMenuRole(QAction::QuitRole); QObject::connect(actQuit, SIGNAL(triggered()), SLOT(quitMainForm())); QAction* const actPreferences = menu->addAction(tr("Set&up...")); actPreferences->setMenuRole(QAction::PreferencesRole); QObject::connect(actPreferences, SIGNAL(triggered()), SLOT(showSetupForm())); QAction* const actAbout = menu->addAction(tr("Ab&out...")); actAbout->setMenuRole(QAction::AboutRole); QObject::connect(actAbout, SIGNAL(triggered()), SLOT(showAboutForm())); #endif } // Destructor. qjackctlMainForm::~qjackctlMainForm (void) { #ifdef HAVE_SIGNAL_H if (m_pSigtermNotifier) delete m_pSigtermNotifier; #endif // Stop server, if not already... #ifdef CONFIG_DBUS if (m_pSetup->bStopJack || !m_pSetup->bJackDBusEnabled) stopJackServer(); if (m_pDBusLogWatcher) delete m_pDBusLogWatcher; if (m_pDBusConfig) delete m_pDBusConfig; if (m_pDBusControl) delete m_pDBusControl; m_pDBusControl = nullptr; m_pDBusConfig = nullptr; m_pDBusLogWatcher = nullptr; m_bDBusStarted = false; m_bDBusDetach = false; #else stopJackServer(); #endif // Terminate local ALSA sequencer interface. if (m_pAlsaNotifier) delete m_pAlsaNotifier; #ifdef CONFIG_ALSA_SEQ if (m_pAlsaSeq) snd_seq_close(m_pAlsaSeq); #endif m_pAlsaNotifier = nullptr; m_pAlsaSeq = nullptr; // Finally drop any popup widgets around... if (m_pMessagesStatusForm) delete m_pMessagesStatusForm; if (m_pSessionForm) delete m_pSessionForm; if (m_pConnectionsForm) delete m_pConnectionsForm; if (m_pPatchbayForm) delete m_pPatchbayForm; if (m_pGraphForm) delete m_pGraphForm; if (m_pSetupForm) delete m_pSetupForm; #ifdef CONFIG_SYSTEM_TRAY // Quit off system tray widget. if (m_pSystemTray) delete m_pSystemTray; #endif // Patchbay rack is also dead. if (m_pPatchbayRack) delete m_pPatchbayRack; // Pseudo-singleton reference shut-down. g_pMainForm = nullptr; } // Kind of singleton reference. qjackctlMainForm *qjackctlMainForm::getInstance (void) { return g_pMainForm; } // Make and set a proper setup step. bool qjackctlMainForm::setup ( qjackctlSetup *pSetup ) { // Finally, fix settings descriptor // and stabilize the form. m_pSetup = pSetup; // To avoid any background flickering, // we'll hide the main display. m_ui.StatusDisplayFrame->hide(); updateButtons(); // What style do we create these forms? QWidget *pParent = nullptr; Qt::WindowFlags wflags = Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint; if (m_pSetup->bKeepOnTop) { pParent = this; wflags |= Qt::Tool; } // All forms are to be created right now. m_pMessagesStatusForm = new qjackctlMessagesStatusForm (pParent, wflags); m_pSessionForm = new qjackctlSessionForm (pParent, wflags); m_pConnectionsForm = new qjackctlConnectionsForm (pParent, wflags); m_pPatchbayForm = new qjackctlPatchbayForm (pParent, wflags); // Graph form should be a full-blown top-level window... m_pGraphForm = new qjackctlGraphForm(pParent, wflags); // Setup form is kind of special (modeless dialog). m_pSetupForm = new qjackctlSetupForm(this); // Setup appropriately... m_pMessagesStatusForm->setTabPage(m_pSetup->iMessagesStatusTabPage); m_pMessagesStatusForm->setLogging( m_pSetup->bMessagesLog, m_pSetup->sMessagesLogPath); m_pSessionForm->setup(m_pSetup); m_pConnectionsForm->setTabPage(m_pSetup->iConnectionsTabPage); m_pConnectionsForm->setup(m_pSetup); m_pPatchbayForm->setup(m_pSetup); m_pGraphForm->setup(m_pSetup); m_pSetupForm->setup(m_pSetup); // Maybe time to load default preset aliases? m_pSetup->loadAliases(); // Check out some initial nullities(tm)... if (m_pSetup->sMessagesFont.isEmpty() && m_pMessagesStatusForm) m_pSetup->sMessagesFont = m_pMessagesStatusForm->messagesFont().toString(); if (m_pSetup->sDisplayFont1.isEmpty()) m_pSetup->sDisplayFont1 = m_ui.TimeDisplayTextLabel->font().toString(); if (m_pSetup->sDisplayFont2.isEmpty()) m_pSetup->sDisplayFont2 = m_ui.ServerStateTextLabel->font().toString(); if (m_pSetup->sConnectionsFont.isEmpty() && m_pConnectionsForm) m_pSetup->sConnectionsFont = m_pConnectionsForm->connectionsFont().toString(); // Set the patchbay cable connection notification signal/slot. QObject::connect(m_pPatchbayRack, SIGNAL(cableConnected(const QString&, const QString&, unsigned int)), SLOT(cableConnectSlot(const QString&, const QString&, unsigned int))); // Try to restore old window positioning and appearence. m_pSetup->loadWidgetGeometry(this, true); // And for the whole widget gallore... m_pSetup->loadWidgetGeometry(m_pMessagesStatusForm); m_pSetup->loadWidgetGeometry(m_pSessionForm); m_pSetup->loadWidgetGeometry(m_pConnectionsForm); m_pSetup->loadWidgetGeometry(m_pPatchbayForm); m_pSetup->loadWidgetGeometry(m_pGraphForm); // m_pSetup->loadWidgetGeometry(m_pSetupForm); // Make it final show... m_ui.StatusDisplayFrame->show(); // Set other defaults... updateDisplayEffect(); updateTimeDisplayFonts(); updateTimeDisplayToolTips(); updateMessagesFont(); updateMessagesLimit(); updateConnectionsFont(); updateConnectionsIconSize(); updateJackClientPortAlias(); updateJackClientPortMetadata(); // updateActivePatchbay(); #ifdef CONFIG_SYSTEM_TRAY updateSystemTray(); #endif // Initial XRUN statistics reset. resetXrunStats(); // Check if we can redirect our own stdout/stderr... #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32) if (m_pSetup->bStdoutCapture && ::pipe(g_fdStdout) == 0) { ::dup2(g_fdStdout[QJACKCTL_FDWRITE], STDOUT_FILENO); ::dup2(g_fdStdout[QJACKCTL_FDWRITE], STDERR_FILENO); stdoutBlock(g_fdStdout[QJACKCTL_FDWRITE], false); m_pStdoutNotifier = new QSocketNotifier( g_fdStdout[QJACKCTL_FDREAD], QSocketNotifier::Read, this); QObject::connect(m_pStdoutNotifier, SIGNAL(activated(int)), SLOT(stdoutNotifySlot(int))); } #endif #ifdef CONFIG_ALSA_SEQ if (m_pSetup->bAlsaSeqEnabled) { // Start our ALSA sequencer interface. if (snd_seq_open(&m_pAlsaSeq, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) m_pAlsaSeq = nullptr; if (m_pAlsaSeq) { snd_seq_port_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; struct pollfd pfd[1]; const int iPort = snd_seq_create_simple_port( m_pAlsaSeq, "qjackctl", SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT, SND_SEQ_PORT_TYPE_APPLICATION ); if (iPort >= 0) { snd_seq_port_subscribe_alloca(&pAlsaSubs); seq_addr.client = SND_SEQ_CLIENT_SYSTEM; seq_addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE; snd_seq_port_subscribe_set_sender(pAlsaSubs, &seq_addr); seq_addr.client = snd_seq_client_id(m_pAlsaSeq); seq_addr.port = iPort; snd_seq_port_subscribe_set_dest(pAlsaSubs, &seq_addr); snd_seq_subscribe_port(m_pAlsaSeq, pAlsaSubs); snd_seq_poll_descriptors(m_pAlsaSeq, pfd, 1, POLLIN); m_pAlsaNotifier = new QSocketNotifier(pfd[0].fd, QSocketNotifier::Read); QObject::connect(m_pAlsaNotifier, SIGNAL(activated(int)), SLOT(alsaNotifySlot(int))); } } // Could we start without it? if (m_pAlsaSeq) { // Rather obvious setup. if (m_pConnectionsForm) m_pConnectionsForm->stabilizeAlsa(true); if (m_pGraphForm) m_pGraphForm->alsa_changed(); } else { appendMessagesError( tr("Could not open ALSA sequencer as a client.\n\n" "ALSA MIDI patchbay will be not available.")); } } #endif #ifdef CONFIG_DBUS // Register D-Bus service... if (m_pSetup->bDBusEnabled) { const QString s; // Just an empty string. const QString sDBusName("org.rncbc.qjackctl"); QDBusConnection dbus = QDBusConnection::systemBus(); dbus.connect(s, s, sDBusName, "start", this, SLOT(startJack())); dbus.connect(s, s, sDBusName, "stop", this, SLOT(stopJack())); dbus.connect(s, s, sDBusName, "reset", this, SLOT(resetXrunStats())); dbus.connect(s, s, sDBusName, "main", this, SLOT(toggleMainForm())); dbus.connect(s, s, sDBusName, "messages", this, SLOT(toggleMessagesForm())); dbus.connect(s, s, sDBusName, "status", this, SLOT(toggleStatusForm())); dbus.connect(s, s, sDBusName, "session", this, SLOT(toggleSessionForm())); dbus.connect(s, s, sDBusName, "connections", this, SLOT(toggleConnectionsForm())); dbus.connect(s, s, sDBusName, "patchbay", this, SLOT(togglePatchbayForm())); dbus.connect(s, s, sDBusName, "graph", this, SLOT(toggleGraphForm())); dbus.connect(s, s, sDBusName, "rewind", this, SLOT(transportRewind())); dbus.connect(s, s, sDBusName, "backward", this, SLOT(transportBackward())); dbus.connect(s, s, sDBusName, "play", this, SLOT(transportStart())); dbus.connect(s, s, sDBusName, "pause", this, SLOT(transportStop())); dbus.connect(s, s, sDBusName, "forward", this, SLOT(transportForward())); dbus.connect(s, s, sDBusName, "setup", this, SLOT(showSetupForm())); dbus.connect(s, s, sDBusName, "about", this, SLOT(showAboutForm())); dbus.connect(s, s, sDBusName, "quit", this, SLOT(quitMainForm())); dbus.connect(s, s, sDBusName, "preset", this, SLOT(activatePreset(const QString&))); dbus.connect(s, s, sDBusName, "active-patchbay", this, SLOT(activatePatchbay(const QString&))); // Session related slots... if (m_pSessionForm) { dbus.connect(s, s, sDBusName, "load", m_pSessionForm, SLOT(loadSession())); dbus.connect(s, s, sDBusName, "save", m_pSessionForm, SLOT(saveSessionSave())); #ifdef CONFIG_JACK_SESSION dbus.connect(s, s, sDBusName, "savequit", m_pSessionForm, SLOT(saveSessionSaveAndQuit())); dbus.connect(s, s, sDBusName, "savetemplate", m_pSessionForm, SLOT(saveSessionSaveTemplate())); #endif } } // Register JACK D-Bus service... updateJackDBus(); #endif // Load patchbay form recent paths... if (m_pPatchbayForm) { m_pPatchbayForm->setRecentPatchbays(m_pSetup->patchbays); if (!m_pSetup->sPatchbayPath.isEmpty() && QFileInfo(m_pSetup->sPatchbayPath).exists()) m_pPatchbayForm->loadPatchbayFile(m_pSetup->sPatchbayPath); m_pPatchbayForm->updateRecentPatchbays(); m_pPatchbayForm->stabilizeForm(); } // Try to find if we can start in detached mode (client-only) // just in case there's a JACK server already running. startJackClient(true); // Final startup stabilization... stabilizeForm(); jackStabilize(); // Look for immediate server startup?... if (m_pSetup->bStartJack || !m_pSetup->cmdLine.isEmpty()) m_pSetup->bStartJackCmd = true; if (m_pSetup->bStartJackCmd) startJack(); // Register the first timer slot. QTimer::singleShot(QJACKCTL_TIMER_MSECS, this, SLOT(timerSlot())); // We're ready to go... return true; } // Setup accessor. qjackctlSetup *qjackctlMainForm::setup (void) const { return m_pSetup; } // Window close event handlers. bool qjackctlMainForm::queryClose (void) { bool bQueryClose = true; if (m_pSetup == nullptr) return bQueryClose; #ifdef CONFIG_SYSTEM_TRAY // If we're not quitting explicitly and there's an // active system tray icon, then just hide ourselves. if (!m_bQuitClose && !m_bQuitForce && isVisible() && m_pSetup->bSystemTray && m_pSystemTray) { m_pSetup->saveWidgetGeometry(this, true); if (m_pSetup->bSystemTrayQueryClose) { const QString& sTitle = tr("Information"); const QString& sText = tr("The program will keep running in the system tray.\n\n" "To terminate the program, please choose \"Quit\"\n" "in the context menu of the system tray icon."); #if 0//QJACKCTL_SYSTEM_TRAY_QUERY_CLOSE if (QSystemTrayIcon::supportsMessages()) { m_pSystemTray->showMessage( sTitle + " - " QJACKCTL_TITLE, sText, QSystemTrayIcon::Information); } else QMessageBox::information(this, sTitle, sText); #else QMessageBox mbox(this); mbox.setIcon(QMessageBox::Information); mbox.setWindowTitle(sTitle); mbox.setText(sText); mbox.setStandardButtons(QMessageBox::Ok|QMessageBox::Cancel); QCheckBox cbox(tr("Don't show this message again")); cbox.setChecked(false); cbox.blockSignals(true); mbox.addButton(&cbox, QMessageBox::ActionRole); bQueryClose = (mbox.exec() == QMessageBox::Ok); if (cbox.isChecked()) m_pSetup->bSystemTrayQueryClose = false; #endif } if (bQueryClose) hide(); updateContextMenu(); bQueryClose = false; } #endif // Check if we really want to quit... if (bQueryClose && !m_bQuitForce && m_pSetup->bQueryClose) { show(); raise(); activateWindow(); updateContextMenu(); const QString& sTitle = tr("Warning"); QString sText; // Check if JACK daemon is currently running... if (((m_pJack && m_pJack->state() == QProcess::Running) #ifdef CONFIG_DBUS || (m_pDBusControl && m_bDBusStarted) #endif ) && m_pSetup->bQueryShutdown) { sText = tr("JACK is currently running.\n\n" "Do you want to terminate the JACK audio server?"); } else { sText = tr("%1 is about to terminate.\n\n" "Are you sure?").arg(QJACKCTL_TITLE); } #if 0//QJACKCTL_QUERY_CLOSE bQueryClose = (QMessageBox::warning(this, sTitle, sText, QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok); #else QMessageBox mbox(this); mbox.setIcon(QMessageBox::Warning); mbox.setWindowTitle(sTitle); mbox.setText(sText); mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); QCheckBox cbox(tr("Don't ask this again")); cbox.setChecked(false); cbox.blockSignals(true); mbox.addButton(&cbox, QMessageBox::ActionRole); bQueryClose = (mbox.exec() == QMessageBox::Ok); if (bQueryClose && cbox.isChecked()) m_pSetup->bQueryClose = false; #endif } // Try to save current aliases default settings. if (bQueryClose && !m_bQuitForce) bQueryClose = queryClosePreset(); // Try to save current setup settings. if (bQueryClose && !m_bQuitForce && m_pSetupForm) bQueryClose = m_pSetupForm->queryClose(); // Try to save current patchbay default settings. if (bQueryClose && !m_bQuitForce && m_pPatchbayForm) bQueryClose = m_pPatchbayForm->queryClose(); // Try to save current session directories list... if (bQueryClose && !m_bQuitForce && m_pSessionForm) bQueryClose = m_pSessionForm->queryClose(); // Some windows default fonts are here on demand too. if (bQueryClose && m_pMessagesStatusForm) { m_pSetup->sMessagesFont = m_pMessagesStatusForm->messagesFont().toString(); m_pSetup->iMessagesStatusTabPage = m_pMessagesStatusForm->tabPage(); } // Whether we're really quitting. #ifdef CONFIG_SYSTEM_TRAY m_bQuitClose = bQueryClose; #endif m_bQuitForce = bQueryClose; // Try to save current positioning. if (bQueryClose) { m_pSetup->saveWidgetGeometry(m_pMessagesStatusForm); m_pSetup->saveWidgetGeometry(m_pSessionForm); m_pSetup->saveWidgetGeometry(m_pConnectionsForm); m_pSetup->saveWidgetGeometry(m_pPatchbayForm); m_pSetup->saveWidgetGeometry(m_pGraphForm); // m_pSetup->saveWidgetGeometry(m_pSetupForm); m_pSetup->saveWidgetGeometry(this, true); // Close popup widgets. if (m_pMessagesStatusForm) m_pMessagesStatusForm->close(); if (m_pSessionForm) m_pSessionForm->close(); if (m_pConnectionsForm) m_pConnectionsForm->close(); if (m_pPatchbayForm) m_pPatchbayForm->close(); if (m_pGraphForm) m_pGraphForm->close(); if (m_pSetupForm) m_pSetupForm->close(); #if 0//CONFIG_SYSTEM_TRAY // And the system tray icon too. if (m_pSystemTray) m_pSystemTray->close(); #endif // Stop any service out there... if (m_pSetup->bStopJack) stopJackServer(); // Finally, save settings. m_pSetup->saveSetup(); } return bQueryClose; } // Query whether current preset can be closed. bool qjackctlMainForm::queryClosePreset (void) { bool bQueryClose = true; if (m_pSetup->aliases.dirty) { switch (QMessageBox::warning(this, tr("Warning") + " - " QJACKCTL_TITLE, tr("The preset aliases have been changed:\n\n" "\"%1\"\n\nDo you want to save the changes?") .arg(m_pSetup->aliases.key), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) { case QMessageBox::Save: m_pSetup->saveAliases(); // Fall thru.... case QMessageBox::Discard: break; default: // Cancel. bQueryClose = false; break; } } return bQueryClose; } // Query whether to restart the JACK service. bool qjackctlMainForm::queryRestart (void) { bool bQueryRestart = (m_pJackClient && m_iServerState != QJACKCTL_ACTIVE); if (bQueryRestart) bQueryRestart = queryClosePreset(); // If client service is currently running, // prompt the effective warning... if (bQueryRestart && m_pSetup->bQueryRestart) { const QString& sTitle = tr("Warning"); const QString& sText = tr("Server settings will be only effective after\n" "restarting the JACK audio server."); // Should ask the user whether to // restart the JACK audio server... if (m_pSetup->bQueryShutdown) { const QString& sQueryText = sText + "\n\n" + tr("Do you want to restart the JACK audio server?"); #if 0//QJACKCTL_QUERY_RESTART bQueryRestart = (QMessageBox::warning(this, sTitle, sQueryText, QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok); #else QMessageBox mbox(this); mbox.setIcon(QMessageBox::Warning); mbox.setWindowTitle(sTitle); mbox.setText(sQueryText); mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); QCheckBox cbox(tr("Don't ask this again")); cbox.setChecked(false); cbox.blockSignals(true); mbox.addButton(&cbox, QMessageBox::ActionRole); bQueryRestart = (mbox.exec() == QMessageBox::Ok); if (cbox.isChecked()) { m_pSetup->bQueryRestart = bQueryRestart; m_pSetup->bQueryShutdown = false; } #endif } else { // Show the old warning message... #ifdef CONFIG_SYSTEM_TRAY if (m_pSetup->bSystemTray && m_pSystemTray && QSystemTrayIcon::supportsMessages()) { m_pSystemTray->showMessage( sTitle + " - " QJACKCTL_TITLE, sText, QSystemTrayIcon::Warning); } else #endif QMessageBox::warning(this, sTitle, sText); } } return bQueryRestart; } // Query whether to stop the JACK service. bool qjackctlMainForm::queryShutdown (void) { bool bQueryShutdown = (m_pJackClient && queryClosePreset()); // Check if we're allowed to stop (shutdown)... if (bQueryShutdown && m_pSetup->bQueryShutdown && m_pConnectionsForm && (m_pConnectionsForm->isAudioConnected() || m_pConnectionsForm->isMidiConnected())) { const QString& sTitle = tr("Warning"); const QString& sText = tr("Some client audio applications\n" "are still active and connected.\n\n" "Do you want to stop the JACK audio server?"); #if 0//QJACKCTL_QUERY_SHUTDOWN bQueryShutdown = (QMessageBox::warning(this, sTitle, sText, QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok); #else QMessageBox mbox(this); mbox.setIcon(QMessageBox::Warning); mbox.setWindowTitle(sTitle); mbox.setText(sText); QCheckBox cbox(tr("Don't ask this again")); cbox.setChecked(false); cbox.blockSignals(true); mbox.addButton(&cbox, QMessageBox::ActionRole); mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); bQueryShutdown = (mbox.exec() == QMessageBox::Ok); if (bQueryShutdown && cbox.isChecked()) m_pSetup->bQueryShutdown = false; #endif } return bQueryShutdown; } void qjackctlMainForm::showEvent ( QShowEvent *pShowEvent ) { QWidget::showEvent(pShowEvent); updateContextMenu(); } void qjackctlMainForm::hideEvent ( QHideEvent *pHideEvent ) { QWidget::hideEvent(pHideEvent); updateContextMenu(); } void qjackctlMainForm::closeEvent ( QCloseEvent *pCloseEvent ) { // Let's be sure about that... if (queryClose()) { pCloseEvent->accept(); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QApplication::exit(0); #else QApplication::quit(); #endif } else { pCloseEvent->ignore(); } } void qjackctlMainForm::resizeEvent ( QResizeEvent *pResizeEvent ) { updateDisplayEffect(); QWidget::resizeEvent(pResizeEvent); } void qjackctlMainForm::customEvent ( QEvent *pEvent ) { switch (int(pEvent->type())) { case QJACKCTL_PORT_EVENT: portNotifyEvent(); break; case QJACKCTL_XRUN_EVENT: xrunNotifyEvent(); break; case QJACKCTL_BUFF_EVENT: buffNotifyEvent(); break; case QJACKCTL_FREE_EVENT: freeNotifyEvent(); break; case QJACKCTL_SHUT_EVENT: shutNotifyEvent(); break; case QJACKCTL_EXIT_EVENT: exitNotifyEvent(); break; #ifdef CONFIG_DBUS case QJACKCTL_LINE_EVENT: appendStdoutBuffer( static_cast (pEvent)->line()); break; #endif #ifdef CONFIG_JACK_METADATA case QJACKCTL_PROP_EVENT: propNotifyEvent(); break; #endif default: QWidget::customEvent(pEvent); break; } } // Common exit status text formatter... QString qjackctlMainForm::formatExitStatus ( int iExitStatus ) const { QString sTemp = " "; if (iExitStatus == 0) sTemp += tr("successfully"); else sTemp += tr("with exit status=%1").arg(iExitStatus); return sTemp + "."; } // Common shell script executive, with placeholder substitution... void qjackctlMainForm::shellExecute ( const QString& sShellCommand, const QString& sStartMessage, const QString& sStopMessage ) { QString sTemp = sShellCommand; sTemp.replace("%P", m_pSetup->sDefPreset); sTemp.replace("%N", m_pSetup->sServerName); sTemp.replace("%s", m_preset.sServerPrefix); sTemp.replace("%d", m_preset.sDriver); sTemp.replace("%i", m_preset.sInterface); sTemp.replace("%r", QString::number(m_preset.iSampleRate)); sTemp.replace("%p", QString::number(m_preset.iFrames)); sTemp.replace("%n", QString::number(m_preset.iPeriods)); appendMessages(sStartMessage); appendMessagesColor(sTemp.trimmed(), Qt::darkMagenta); stabilize(QJACKCTL_TIMER_MSECS); // Execute and set exit status message... sTemp = sStopMessage + formatExitStatus( ::system(sTemp.toUtf8().constData())); // Wait a litle bit before continue... stabilize(QJACKCTL_TIMER_MSECS); // Final log message... appendMessages(sTemp); } // Start jack audio server... void qjackctlMainForm::startJack (void) { // If can't be already a client, are we? if (m_pJackClient) return; // Is the server process instance still here? if (m_pJack) { if (QMessageBox::warning(this, tr("Warning") + " - " QJACKCTL_TITLE, tr("Could not start JACK.\n\n" "Maybe JACK audio server is already started."), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { m_pJack->terminate(); #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) m_bJackKilled = true; #endif m_pJack->kill(); } return; } // Stabilize emerging server state... QPalette pal; pal.setColor(QPalette::WindowText, Qt::yellow); m_ui.ServerStateTextLabel->setPalette(pal); m_ui.StartToolButton->setEnabled(false); updateServerState(QJACKCTL_ACTIVATING); // Reset our timer counters... m_iStartDelay = 0; m_iTimerDelay = 0; m_iJackRefresh = 0; // Now we're sure it ain't detached. m_bJackShutdown = false; m_bJackDetach = false; #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) m_bJackKilled = false; #endif // Check whether we had any previous preset but default... if ((m_pSetup->sDefPreset.isEmpty() || qjackctlSetup::defName() == qjackctlSetup::defName()) && !m_pSetup->sOldPreset.isEmpty()) { m_pSetup->sDefPreset = m_pSetup->sOldPreset; m_pSetup->sOldPreset.clear(); if (m_pSetupForm) m_pSetupForm->updateCurrentPreset(); } // Load primary/default server preset... if (!m_pSetup->loadPreset(m_preset, m_pSetup->sDefPreset)) { appendMessagesError(tr("Could not load preset \"%1\".\n\nRetrying with default.").arg(m_pSetup->sDefPreset)); m_pSetup->sDefPreset = qjackctlSetup::defName(); if (!m_pSetup->loadPreset(m_preset, m_pSetup->sDefPreset)) { appendMessagesError(tr("Could not load default preset.\n\nSorry.")); jackCleanup(); return; } } // Override server name now... if (m_pSetup->sServerName.isEmpty()) m_pSetup->sServerName = m_preset.sServerName; // Take care for the environment as well... if (m_pSetup->sServerName.isEmpty()) { const char *pszServerName = ::getenv("JACK_DEFAULT_SERVER"); if (pszServerName && strcmp("default", pszServerName)) m_pSetup->sServerName = QString::fromUtf8(pszServerName); } // No JACK Classic command line to start with, yet... m_sJackCmdLine.clear(); // If we ain't to be the server master, maybe we'll start // detached as client only (jackd server already running?) if (startJackClient(true)) { m_ui.StopToolButton->setEnabled(true); return; } // Say that we're starting... updateServerState(QJACKCTL_STARTING); // Do we have any startup script?... if (m_pSetup->bStartupScript && !m_pSetup->sStartupScriptShell.isEmpty()) { shellExecute(m_pSetup->sStartupScriptShell, tr("Startup script..."), tr("Startup script terminated")); } #ifdef CONFIG_DBUS // Jack D-BUS server backend startup method... if (m_pDBusControl) { // Jack D-BUS server backend configuration... setDBusParameters(m_preset); QDBusMessage dbusm = m_pDBusControl->call("StartServer"); if (dbusm.type() == QDBusMessage::ReplyMessage) { m_bDBusDetach = true; appendMessages( tr("D-BUS: JACK server is starting...")); } else { appendMessagesError( tr("D-BUS: JACK server could not be started.\n\nSorry")); } // Delay our control client... startJackClientDelay(); // JACK D-BUS startup is done. return; } #endif // !CONFIG_DBUS // Split the server path into arguments... QStringList args = m_preset.sServerPrefix.split(' '); // Look for the executable in the search path; // this enforces the server command to be an // executable absolute path whenever possible. QString sCommand = args[0]; QFileInfo fi(sCommand); if (fi.isRelative()) { #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) const char chPathSep = ';'; if (fi.suffix().isEmpty()) sCommand += ".exe"; #else const char chPathSep = ':'; #endif const QString sPath = QString::fromUtf8(::getenv("PATH")); QStringList paths = sPath.split(chPathSep); #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) paths.append(QString("%1\\JACK2").arg(::getenv("PROGRAMFILES"))); paths.append(QString("%1\\JACK2").arg(::getenv("PROGRAMFILES(x86)"))); #elif defined(__APPLE__) paths.append("/usr/local/bin/"); #endif QStringListIterator iter(paths); while (iter.hasNext()) { const QString& sDirectory = iter.next(); fi.setFile(QDir(sDirectory), sCommand); if (fi.exists() && fi.isExecutable()) { sCommand = fi.filePath(); break; } } } // Now that we got a command, remove it from args list... args.removeAt(0); // Build process arguments... const bool bDummy = (m_preset.sDriver == "dummy"); const bool bSun = (m_preset.sDriver == "sun"); const bool bOss = (m_preset.sDriver == "oss"); const bool bAlsa = (m_preset.sDriver == "alsa"); const bool bPortaudio = (m_preset.sDriver == "portaudio"); const bool bCoreaudio = (m_preset.sDriver == "coreaudio"); const bool bFirewire = (m_preset.sDriver == "firewire"); const bool bNet = (m_preset.sDriver == "net" || m_preset.sDriver == "netone"); if (!m_pSetup->sServerName.isEmpty()) args.append("-n" + m_pSetup->sServerName); if (m_preset.bVerbose) args.append("-v"); if (m_preset.bRealtime) { // args.append("-R"); if (m_preset.iPriority > 5 && !bCoreaudio) args.append("-P" + QString::number(m_preset.iPriority)); } else args.append("-r"); if (m_preset.iPortMax > 0 && m_preset.iPortMax != 256) args.append("-p" + QString::number(m_preset.iPortMax)); if (m_preset.iTimeout > 0 && m_preset.iTimeout != 500) args.append("-t" + QString::number(m_preset.iTimeout)); if (m_preset.bNoMemLock) args.append("-m"); else if (m_preset.bUnlockMem) args.append("-u"); if (m_preset.bSync) args.append("-S"); if (m_preset.ucClockSource > 0 && m_preset.ucClockSource != ' ') args.append("-c" + QString(char(m_preset.ucClockSource))); if (m_preset.ucSelfConnectMode > 0 && m_preset.ucSelfConnectMode != ' ') args.append("-a" + QString(char(m_preset.ucSelfConnectMode))); args.append("-d" + m_preset.sDriver); if ((bAlsa || bPortaudio) && (m_preset.iAudio != QJACKCTL_DUPLEX || m_preset.sInDevice.isEmpty() || m_preset.sOutDevice.isEmpty())) { QString sInterface = m_preset.sInterface; if (bAlsa && sInterface.isEmpty()) sInterface = "hw:0"; if (!sInterface.isEmpty()) args.append("-d" + formatQuoted(sInterface)); } if (bPortaudio && m_preset.iChan > 0) args.append("-c" + QString::number(m_preset.iChan)); if ((bCoreaudio || bFirewire) && !m_preset.sInterface.isEmpty()) args.append("-d" + formatQuoted(m_preset.sInterface)); if (m_preset.iSampleRate > 0 && !bNet) args.append("-r" + QString::number(m_preset.iSampleRate)); if (m_preset.iFrames > 0 && !bNet) args.append("-p" + QString::number(m_preset.iFrames)); if (bAlsa || bSun || bOss || bFirewire) { if (m_preset.iPeriods > 1) args.append("-n" + QString::number(m_preset.iPeriods)); } if (bAlsa) { if (m_preset.bSoftMode) args.append("-s"); if (m_preset.bMonitor) args.append("-m"); if (m_preset.bShorts) args.append("-S"); if (m_preset.bHWMeter) args.append("-M"); #ifdef CONFIG_JACK_MIDI if (!m_preset.sMidiDriver.isEmpty()) args.append("-X" + formatQuoted(m_preset.sMidiDriver)); #endif } if (bAlsa || bCoreaudio || bPortaudio) { switch (m_preset.iAudio) { case QJACKCTL_DUPLEX: if (!m_preset.sInDevice.isEmpty() || !m_preset.sOutDevice.isEmpty()) args.append("-D"); if (!m_preset.sInDevice.isEmpty()) args.append("-C" + formatQuoted(m_preset.sInDevice)); if (!m_preset.sOutDevice.isEmpty()) args.append("-P" + formatQuoted(m_preset.sOutDevice)); break; case QJACKCTL_CAPTURE: args.append("-C" + formatQuoted(m_preset.sInDevice)); break; case QJACKCTL_PLAYBACK: args.append("-P" + formatQuoted(m_preset.sOutDevice)); break; } if (m_preset.iInChannels > 0 && m_preset.iAudio != QJACKCTL_PLAYBACK) args.append("-i" + QString::number(m_preset.iInChannels)); if (m_preset.iOutChannels > 0 && m_preset.iAudio != QJACKCTL_CAPTURE) args.append("-o" + QString::number(m_preset.iOutChannels)); switch (m_preset.iDither) { case 0: // args.append("-z-"); break; case 1: args.append("-zr"); break; case 2: args.append("-zs"); break; case 3: args.append("-zt"); break; } } else if (bOss || bSun) { if (m_preset.bIgnoreHW) args.append("-b"); if (m_preset.iWordLength > 0 && m_preset.iWordLength != 16) args.append("-w" + QString::number(m_preset.iWordLength)); if (!m_preset.sInDevice.isEmpty() && m_preset.iAudio != QJACKCTL_PLAYBACK) args.append("-C" + formatQuoted(m_preset.sInDevice)); if (!m_preset.sOutDevice.isEmpty() && m_preset.iAudio != QJACKCTL_CAPTURE) args.append("-P" + formatQuoted(m_preset.sOutDevice)); if (m_preset.iAudio == QJACKCTL_PLAYBACK) args.append("-i0"); else if (m_preset.iInChannels > 0) args.append("-i" + QString::number(m_preset.iInChannels)); if (m_preset.iAudio == QJACKCTL_CAPTURE) args.append("-o0"); else if (m_preset.iOutChannels > 0) args.append("-o" + QString::number(m_preset.iOutChannels)); } else if (bCoreaudio || bFirewire || bNet) { if (m_preset.iInChannels > 0 && m_preset.iAudio != QJACKCTL_PLAYBACK) args.append("-i" + QString::number(m_preset.iInChannels)); if (m_preset.iOutChannels > 0 && m_preset.iAudio != QJACKCTL_CAPTURE) args.append("-o" + QString::number(m_preset.iOutChannels)); } if (bDummy && m_preset.iWait > 0 && m_preset.iWait != 21333) args.append("-w" + QString::number(m_preset.iWait)); if (bAlsa || bSun || bOss || bCoreaudio || bPortaudio || bFirewire) { if (m_preset.iInLatency > 0) args.append("-I" + QString::number(m_preset.iInLatency)); if (m_preset.iOutLatency > 0) args.append("-O" + QString::number(m_preset.iOutLatency)); } // Split the server path into arguments... if (!m_preset.sServerSuffix.isEmpty()) args.append(m_preset.sServerSuffix.split(' ')); // This is emulated jackd command line, for future reference purposes... m_sJackCmdLine = sCommand + ' ' + args.join(" ").trimmed(); // JACK Classic server backend startup process... m_pJack = new QProcess(this); // Setup stdout/stderr capture... if (m_pSetup->bStdoutCapture) { #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) // QProcess::ForwardedChannels doesn't seem to work in windows. m_pJack->setProcessChannelMode(QProcess::MergedChannels); #else m_pJack->setProcessChannelMode(QProcess::ForwardedChannels); #endif QObject::connect(m_pJack, SIGNAL(readyReadStandardOutput()), SLOT(readStdout())); QObject::connect(m_pJack, SIGNAL(readyReadStandardError()), SLOT(readStdout())); } // The unforgiveable signal communication... QObject::connect(m_pJack, SIGNAL(started()), SLOT(jackStarted())); QObject::connect(m_pJack, #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) SIGNAL(error(QProcess::ProcessError)), #else SIGNAL(errorOccurred(QProcess::ProcessError)), #endif SLOT(jackError(QProcess::ProcessError))); QObject::connect(m_pJack, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(jackFinished())); appendMessages(tr("JACK is starting...")); appendMessagesColor(m_sJackCmdLine, Qt::darkMagenta); #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) const QString& sCurrentDir = QFileInfo(sCommand).dir().absolutePath(); m_pJack->setWorkingDirectory(sCurrentDir); // QDir::setCurrent(sCurrentDir); #endif // Unquote arguments as necessary... const QChar q = '"'; QStringList cmd_args; QStringListIterator iter(args); while (iter.hasNext()) { const QString& arg = iter.next(); if (arg.contains(q)) { cmd_args.append(arg.section(q, 0, 0)); cmd_args.append(arg.section(q, 1, 1)); } else { cmd_args.append(arg); } } // Go JACK, go... m_pJack->start(sCommand, cmd_args); } // Stop jack audio server... void qjackctlMainForm::stopJack (void) { // Stop the server conditionally... if (queryShutdown()) stopJackServer(); } // Restart jack audio service. void qjackctlMainForm::restartJack (void) { // Stop the server conditionally... if (queryRestart()) { stopJackServer(); m_bJackRestart = true; } updateTitleStatus(); updateContextMenu(); } // Stop jack audio server... void qjackctlMainForm::stopJackServer (void) { // Clear timer counters... m_iStartDelay = 0; m_iTimerDelay = 0; m_iJackRefresh = 0; // Stop client code. stopJackClient(); // And try to stop server. if ((m_pJack && m_pJack->state() == QProcess::Running) #ifdef CONFIG_DBUS || (m_pDBusControl && m_bDBusStarted) #endif ) { updateServerState(QJACKCTL_STOPPING); // Do we have any pre-shutdown script?... if (m_pSetup->bShutdownScript && !m_pSetup->sShutdownScriptShell.isEmpty()) { shellExecute(m_pSetup->sShutdownScriptShell, tr("Shutdown script..."), tr("Shutdown script terminated")); } // Now it's the time to real try stopping the server daemon... if (!m_bJackShutdown) { // Jack classic server backend... if (m_pJack) { appendMessages(tr("JACK is stopping...")); #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) // Try harder... m_bJackKilled = true; m_pJack->kill(); #else // Try softly... m_pJack->terminate(); #endif } #ifdef CONFIG_DBUS // Jack D-BUS server backend... if (m_pDBusControl) { QDBusMessage dbusm = m_pDBusControl->call("StopServer"); if (dbusm.type() == QDBusMessage::ReplyMessage) { appendMessages( tr("D-BUS: JACK server is stopping...")); } else { appendMessagesError( tr("D-BUS: JACK server could not be stopped.\n\nSorry")); } } #endif // Give it some time to terminate gracefully and stabilize... stabilize(QJACKCTL_TIMER_MSECS); // Keep on, if not exiting for good. if (!m_bQuitForce) return; } } // Do final processing anyway. jackCleanup(); } void qjackctlMainForm::toggleJack (void) { if (m_pJackClient) stopJack(); else startJack(); } // Stdout handler... void qjackctlMainForm::readStdout (void) { appendStdoutBuffer(m_pJack->readAllStandardOutput()); } // Stdout buffer handler -- now splitted by complete new-lines... void qjackctlMainForm::appendStdoutBuffer ( const QString& s ) { m_sStdoutBuffer.append(s); processStdoutBuffer(); } void qjackctlMainForm::processStdoutBuffer (void) { const int iLength = m_sStdoutBuffer.lastIndexOf('\n'); if (iLength > 0) { QStringListIterator iter(m_sStdoutBuffer.left(iLength).split('\n')); while (iter.hasNext()) { QString sTemp = iter.next(); if (!sTemp.isEmpty()) #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) appendMessagesText(detectXrun(sTemp).trimmed()); #else appendMessagesText(detectXrun(sTemp)); #endif } m_sStdoutBuffer.remove(0, iLength + 1); } } // Stdout flusher -- show up any unfinished line... void qjackctlMainForm::flushStdoutBuffer (void) { processStdoutBuffer(); if (!m_sStdoutBuffer.isEmpty()) { #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) appendMessagesText(detectXrun(m_sStdoutBuffer).trimmed()); #else appendMessagesText(detectXrun(m_sStdoutBuffer)); #endif m_sStdoutBuffer.clear(); } } // Jack audio server startup. void qjackctlMainForm::jackStarted (void) { // Sure we're over any previous shutdown... m_bJackShutdown = false; // We're still starting... updateServerState(QJACKCTL_STARTING); // Show startup results... if (m_pJack) { appendMessages(tr("JACK was started with PID=%1.") #if QT_VERSION < QT_VERSION_CHECK(5, 3, 0) .arg(quint64(m_pJack->pid()))); #else .arg(quint64(m_pJack->processId()))); #endif } #ifdef CONFIG_DBUS // Special for D-BUS control.... if (m_pDBusControl) { m_bDBusStarted = true; appendMessages(tr("D-BUS: JACK server was started (%1 aka jackdbus).") .arg(m_pDBusControl->service())); } #endif // Delay our control client... startJackClientDelay(); } // Jack audio server got an error. void qjackctlMainForm::jackError ( QProcess::ProcessError error ) { qjackctl_on_error(error); } // Jack audio server finish. void qjackctlMainForm::jackFinished (void) { // Force client code cleanup. if (!m_bJackShutdown) jackCleanup(); } // Jack audio server cleanup. void qjackctlMainForm::jackCleanup (void) { // Force client code cleanup. bool bPostShutdown = m_bJackDetach; if (!bPostShutdown) stopJackClient(); // Flush anything that maybe pending... flushStdoutBuffer(); // Classic server control... if (m_pJack) { if (m_pJack->state() != QProcess::NotRunning) { appendMessages(tr("JACK is being forced...")); #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) m_bJackKilled = true; #endif // Force final server shutdown... m_pJack->kill(); // Give it some time to terminate gracefully and stabilize... stabilize(QJACKCTL_TIMER_MSECS); } // Force final server shutdown... appendMessages(tr("JACK was stopped")); // Destroy it. delete m_pJack; m_pJack = nullptr; // Flag we need a post-shutdown script... bPostShutdown = true; } #ifdef CONFIG_DBUS // Special for D-BUS control... if (m_pDBusControl && m_bDBusStarted) { m_bDBusStarted = false; m_bDBusDetach = false; appendMessages(tr("D-BUS: JACK server was stopped (%1 aka jackdbus).") .arg(m_pDBusControl->service())); // Flag we need a post-shutdown script... bPostShutdown = true; } #endif // Cannot be detached anymore. m_bJackDetach = false; // Do we have any post-shutdown script?... // (this will be always called, despite we've started the server or not) if (bPostShutdown && m_pSetup->bPostShutdownScript && !m_pSetup->sPostShutdownScriptShell.isEmpty()) { shellExecute(m_pSetup->sPostShutdownScriptShell, tr("Post-shutdown script..."), tr("Post-shutdown script terminated")); } // Reset server name. m_pSetup->sServerName.clear(); // Stabilize final server state... jackStabilize(); } // Stabilize server state... void qjackctlMainForm::jackStabilize (void) { QPalette pal; pal.setColor(QPalette::WindowText, m_pJackClient == nullptr ? Qt::darkYellow : Qt::yellow); m_ui.ServerStateTextLabel->setPalette(pal); m_ui.StartToolButton->setEnabled(m_pJackClient == nullptr); m_ui.StopToolButton->setEnabled(m_pJackClient != nullptr); m_ui.RewindToolButton->setEnabled(false); m_ui.BackwardToolButton->setEnabled(false); m_ui.PlayToolButton->setEnabled(false); m_ui.PauseToolButton->setEnabled(false); m_ui.ForwardToolButton->setEnabled(false); transportPlayStatus(false); #ifdef CONFIG_DBUS if (m_pDBusConfig && m_bDBusStarted) updateServerState(m_pJackClient ? QJACKCTL_STARTED : QJACKCTL_STOPPED); else #endif if (m_bJackDetach) updateServerState(m_pJackClient ? QJACKCTL_ACTIVE : QJACKCTL_INACTIVE); else updateServerState(QJACKCTL_STOPPED); } // XRUN detection routine. QString& qjackctlMainForm::detectXrun ( QString& s ) { if (m_iXrunSkips > 1) return s; QRegularExpression rx(m_pSetup->sXrunRegex); QRegularExpressionMatch match(rx.match(s)); if (match.hasMatch()) { const int iPos = match.capturedStart(0); s.insert(iPos + match.capturedLength(0), ""); s.insert(iPos, ""); #ifndef CONFIG_JACK_XRUN_DELAY m_fXrunLast = 0.0f; updateXrunStats(match.captured(1).toFloat()); refreshXrunStats(); #endif } return s; } // Update the XRUN last delay and immediate statistical values (in msecs). void qjackctlMainForm::updateXrunStats ( float fXrunLast ) { if (m_iXrunStats > 0) { m_fXrunLast = fXrunLast; m_fXrunTotal += m_fXrunLast; if (m_fXrunLast < m_fXrunMin || m_iXrunCount == 0) m_fXrunMin = m_fXrunLast; if (m_fXrunLast > m_fXrunMax || m_iXrunCount == 0) m_fXrunMax = m_fXrunLast; ++m_iXrunCount; // refreshXrunStats(); } ++m_iXrunStats; } // SIGTERM signal handler... void qjackctlMainForm::sigtermNotifySlot ( int /* fd */ ) { #ifdef HAVE_SIGNAL_H char c; if (::read(g_fdSigterm[1], &c, sizeof(c)) > 0) quitMainForm(); #endif } #if defined(Q_CC_GNU) || defined(Q_CC_MINGW) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif // Set stdout/stderr blocking mode. bool qjackctlMainForm::stdoutBlock ( int fd, bool bBlock ) const { #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32) const int iFlags = ::fcntl(fd, F_GETFL, 0); const bool bNonBlock = bool(iFlags & O_NONBLOCK); if (bBlock && bNonBlock) bBlock = (::fcntl(fd, F_SETFL, iFlags & ~O_NONBLOCK) == 0); else if (!bBlock && !bNonBlock) bBlock = (::fcntl(fd, F_SETFL, iFlags | O_NONBLOCK) != 0); #endif return bBlock; } // Own stdout/stderr socket notifier slot. void qjackctlMainForm::stdoutNotifySlot ( int fd ) { #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32) // Set non-blocking reads, if not already... const bool bBlock = stdoutBlock(fd, false); // Read as much as is available... QString sTemp; char achBuffer[1024]; const int cchBuffer = sizeof(achBuffer) - 1; int cchRead = ::read(fd, achBuffer, cchBuffer); while (cchRead > 0) { achBuffer[cchRead] = (char) 0; sTemp.append(achBuffer); cchRead = (bBlock ? 0 : ::read(fd, achBuffer, cchBuffer)); } // Needs to be non-empty... if (!sTemp.isEmpty()) appendStdoutBuffer(sTemp); #endif } #if defined(Q_CC_GNU) || defined(Q_CC_MINGW) #pragma GCC diagnostic pop #endif // Messages output methods. void qjackctlMainForm::appendMessages ( const QString& s ) { if (m_pMessagesStatusForm) m_pMessagesStatusForm->appendMessages(s); } void qjackctlMainForm::appendMessagesColor ( const QString& s, const QColor& rgb ) { if (m_pMessagesStatusForm) m_pMessagesStatusForm->appendMessagesColor(s, rgb); } void qjackctlMainForm::appendMessagesText ( const QString& s ) { if (m_pMessagesStatusForm) m_pMessagesStatusForm->appendMessagesText(s); } void qjackctlMainForm::appendMessagesError ( const QString& s ) { if (m_pMessagesStatusForm) { m_pMessagesStatusForm->setTabPage( int(qjackctlMessagesStatusForm::MessagesTab)); m_pMessagesStatusForm->show(); } appendMessagesColor(s.simplified(), Qt::red); const QString& sTitle = tr("Error"); #ifdef CONFIG_SYSTEM_TRAY if (m_pSetup->bSystemTray && m_pSystemTray && QSystemTrayIcon::supportsMessages()) m_pSystemTray->showMessage( sTitle + " - " QJACKCTL_TITLE, s, QSystemTrayIcon::Critical); else #endif QMessageBox::critical(this, sTitle, s, QMessageBox::Cancel); } // Force update of the messages font. void qjackctlMainForm::updateMessagesFont (void) { if (m_pSetup == nullptr) return; if (m_pMessagesStatusForm && !m_pSetup->sMessagesFont.isEmpty()) { QFont font; if (font.fromString(m_pSetup->sMessagesFont)) m_pMessagesStatusForm->setMessagesFont(font); } } // Update messages window line limit. void qjackctlMainForm::updateMessagesLimit (void) { if (m_pSetup == nullptr) return; if (m_pMessagesStatusForm) { if (m_pSetup->bMessagesLimit) m_pMessagesStatusForm->setMessagesLimit(m_pSetup->iMessagesLimitLines); else m_pMessagesStatusForm->setMessagesLimit(-1); } } // Update messages logging state. void qjackctlMainForm::updateMessagesLogging (void) { if (m_pSetup == nullptr) return; if (m_pMessagesStatusForm) { m_pMessagesStatusForm->setLogging( m_pSetup->bMessagesLog, m_pSetup->sMessagesLogPath); } } // Force update of the connections font. void qjackctlMainForm::updateConnectionsFont (void) { if (m_pSetup == nullptr) return; if (m_pConnectionsForm && !m_pSetup->sConnectionsFont.isEmpty()) { QFont font; if (font.fromString(m_pSetup->sConnectionsFont)) m_pConnectionsForm->setConnectionsFont(font); } } // Update of the connections view icon size. void qjackctlMainForm::updateConnectionsIconSize (void) { if (m_pSetup == nullptr) return; if (m_pConnectionsForm) m_pConnectionsForm->setConnectionsIconSize(m_pSetup->iConnectionsIconSize); } // Update of JACK client/port alias display mode. void qjackctlMainForm::updateJackClientPortAlias (void) { if (m_pSetup == nullptr) return; qjackctlJackClientList::setJackClientPortAlias(m_pSetup->iJackClientPortAlias); refreshJackConnections(); } // Update of JACK client/port pretty-name (metadata) display mode. void qjackctlMainForm::updateJackClientPortMetadata (void) { if (m_pSetup == nullptr) return; qjackctlJackClientList::setJackClientPortMetadata(m_pSetup->bJackClientPortMetadata); refreshJackConnections(); } // Update main display background effect. void qjackctlMainForm::updateDisplayEffect (void) { if (m_pSetup == nullptr) return; // Set the main background... QPalette pal; if (m_pSetup->bDisplayEffect) { const QImage img(":/images/displaybg1.png"); pal.setBrush(QPalette::Window, QBrush(img.scaled(m_ui.StatusDisplayFrame->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation))); } else { pal.setColor(QPalette::Window, Qt::black); } m_ui.StatusDisplayFrame->setPalette(pal); } // Force update of big time display related fonts. void qjackctlMainForm::updateTimeDisplayFonts (void) { QFont font; if (!m_pSetup->sDisplayFont1.isEmpty() && font.fromString(m_pSetup->sDisplayFont1)) m_ui.TimeDisplayTextLabel->setFont(font); if (!m_pSetup->sDisplayFont2.isEmpty() && font.fromString(m_pSetup->sDisplayFont2)) { m_ui.ServerStateTextLabel->setFont(font); m_ui.ServerModeTextLabel->setFont(font); m_ui.DspLoadTextLabel->setFont(font); m_ui.SampleRateTextLabel->setFont(font); m_ui.XrunCountTextLabel->setFont(font); m_ui.TransportStateTextLabel->setFont(font); m_ui.TransportBpmTextLabel->setFont(font); font.setBold(true); m_ui.TransportTimeTextLabel->setFont(font); } } // Force update of big time display related tooltips. void qjackctlMainForm::updateTimeDisplayToolTips (void) { QString sTimeDisplay = tr("Transport BBT (bar.beat.ticks)"); QString sTransportTime = tr("Transport time code"); switch (m_pSetup->iTimeDisplay) { case DISPLAY_TRANSPORT_TIME: { QString sTemp = sTimeDisplay; sTimeDisplay = sTransportTime; sTransportTime = sTemp; break; } case DISPLAY_RESET_TIME: sTimeDisplay = tr("Elapsed time since last reset"); break; case DISPLAY_XRUN_TIME: sTimeDisplay = tr("Elapsed time since last XRUN"); break; } m_ui.TimeDisplayTextLabel->setToolTip(sTimeDisplay); m_ui.TransportTimeTextLabel->setToolTip(sTransportTime); } // Update the connections client/port aliases. void qjackctlMainForm::updateAliases (void) { if (m_pConnectionsForm) m_pConnectionsForm->updateAliases(); } // Update the main form buttons display. void qjackctlMainForm::updateButtons (void) { updateTitleStatus(); if (m_pSetup->bLeftButtons) { m_ui.StartToolButton->show(); m_ui.StopToolButton->show(); m_ui.MessagesStatusToolButton->show(); m_ui.SessionToolButton->show(); m_ui.ConnectionsToolButton->setVisible(!m_pSetup->bGraphButton); m_ui.GraphToolButton->setVisible(m_pSetup->bGraphButton); m_ui.PatchbayToolButton->show(); } else { m_ui.StartToolButton->hide(); m_ui.StopToolButton->hide(); m_ui.MessagesStatusToolButton->hide(); m_ui.SessionToolButton->hide(); m_ui.GraphToolButton->hide(); m_ui.ConnectionsToolButton->hide(); m_ui.PatchbayToolButton->hide(); } if (m_pSetup->bRightButtons) { m_ui.QuitToolButton->show(); m_ui.SetupToolButton->show(); } else { m_ui.QuitToolButton->hide(); m_ui.SetupToolButton->hide(); } if (m_pSetup->bRightButtons && (m_pSetup->bLeftButtons || m_pSetup->bTransportButtons)) { m_ui.AboutToolButton->show(); } else { m_ui.AboutToolButton->hide(); } if (m_pSetup->bLeftButtons || m_pSetup->bTransportButtons) { m_ui.RewindToolButton->show(); m_ui.BackwardToolButton->show(); m_ui.PlayToolButton->show(); m_ui.PauseToolButton->show(); m_ui.ForwardToolButton->show(); } else { m_ui.RewindToolButton->hide(); m_ui.BackwardToolButton->hide(); m_ui.PlayToolButton->hide(); m_ui.PauseToolButton->hide(); m_ui.ForwardToolButton->hide(); } Qt::ToolButtonStyle toolButtonStyle = (m_pSetup->bTextLabels ? Qt::ToolButtonTextBesideIcon : Qt::ToolButtonIconOnly); m_ui.StartToolButton->setToolButtonStyle(toolButtonStyle); m_ui.StopToolButton->setToolButtonStyle(toolButtonStyle); m_ui.MessagesStatusToolButton->setToolButtonStyle(toolButtonStyle); m_ui.SessionToolButton->setToolButtonStyle(toolButtonStyle); m_ui.ConnectionsToolButton->setToolButtonStyle(toolButtonStyle); m_ui.GraphToolButton->setToolButtonStyle(toolButtonStyle); m_ui.PatchbayToolButton->setToolButtonStyle(toolButtonStyle); m_ui.QuitToolButton->setToolButtonStyle(toolButtonStyle); m_ui.SetupToolButton->setToolButtonStyle(toolButtonStyle); m_ui.AboutToolButton->setToolButtonStyle(toolButtonStyle); #if 0// Main-window fixed size (pre-adjustment...) const bool bVisible = isVisible(); if (bVisible) hide(); setMinimumSize(0, 0); setMaximumSize(640, 480); #endif adjustSize(); #if 0// Main-window fixed size (post-adjustmment...) setFixedSize(size()); if (bVisible) show(); #endif } // Update the Graph canvas palette. void qjackctlMainForm::updatePalette (void) { if (m_pGraphForm) m_pGraphForm->updatePalette(); } #ifdef CONFIG_DBUS void qjackctlMainForm::updateJackDBus (void) { // Unregister JACK D-Bus service controller... if (m_pDBusLogWatcher) { delete m_pDBusLogWatcher; m_pDBusLogWatcher = nullptr; } if (m_pDBusConfig) { delete m_pDBusConfig; m_pDBusConfig = nullptr; } if (m_pDBusControl) { delete m_pDBusControl; m_pDBusControl = nullptr; } // Register JACK D-Bus service... if (m_pSetup->bJackDBusEnabled) { // Detect whether jackdbus is avaliable... QDBusConnection dbusc = QDBusConnection::sessionBus(); m_pDBusControl = new QDBusInterface( "org.jackaudio.service", // Service "/org/jackaudio/Controller", // Path "org.jackaudio.JackControl", // Interface dbusc); // Connection QDBusMessage dbusm = m_pDBusControl->call("IsStarted"); if (dbusm.type() == QDBusMessage::ReplyMessage) { // Yes, jackdbus is available and/or already started // -- use jackdbus control interface... appendMessages(tr("D-BUS: Service is available (%1 aka jackdbus).") .arg(m_pDBusControl->service())); // Parse reply (should be boolean) m_bDBusStarted = dbusm.arguments().first().toBool(); // Register server start/stop notification slots... dbusc.connect( m_pDBusControl->service(), m_pDBusControl->path(), m_pDBusControl->interface(), "ServerStarted", this, SLOT(jackStarted())); dbusc.connect( m_pDBusControl->service(), m_pDBusControl->path(), m_pDBusControl->interface(), "ServerStopped", this, SLOT(jackFinished())); // -- use jackdbus configure interface... m_pDBusConfig = new QDBusInterface( m_pDBusControl->service(), // Service m_pDBusControl->path(), // Path "org.jackaudio.Configure", // Interface m_pDBusControl->connection()); // Connection // Start our log watcher thread... m_pDBusLogWatcher = new qjackctlDBusLogWatcher( QDir::homePath() + "/.log/jack/jackdbus.log"); m_pDBusLogWatcher->start(); // Ready now. } else { // No, jackdbus is not available, not started // or not even installed -- use classic jackd, BAU... appendMessages(tr("D-BUS: Service not available (%1 aka jackdbus).") .arg(m_pDBusControl->service())); // Destroy tentative jackdbus interface. delete m_pDBusControl; m_pDBusControl = nullptr; } } } #endif // Force update of active patchbay definition profile, if applicable. bool qjackctlMainForm::isActivePatchbay ( const QString& sPatchbayPath ) const { bool bActive = false; if (m_pSetup && m_pSetup->bActivePatchbay && !m_pSetup->sActivePatchbayPath.isEmpty()) bActive = (m_pSetup->sActivePatchbayPath == sPatchbayPath); return bActive; } // Force update of active patchbay definition profile, if applicable. void qjackctlMainForm::updateActivePatchbay (void) { if (m_pSetup == nullptr) return; // Time to load the active patchbay rack profiler? if (m_pSetup->bActivePatchbay && !m_pSetup->sActivePatchbayPath.isEmpty()) { // Check whether to reset/disconnect-all on patchbay activation... if (m_pSetup->bActivePatchbayReset) { if (m_pJackClient) { m_pPatchbayRack->disconnectAllJackPorts(m_pJackClient); m_iJackRefresh = 0; } if (m_pAlsaSeq) { m_pPatchbayRack->disconnectAllAlsaPorts(m_pAlsaSeq); m_iAlsaRefresh = 0; } appendMessages(tr("Patchbay reset.")); } // Load/activate patchbay-rack... const QFileInfo fi(m_pSetup->sActivePatchbayPath); if (fi.isRelative()) m_pSetup->sActivePatchbayPath = fi.absoluteFilePath(); if (!qjackctlPatchbayFile::load(m_pPatchbayRack, m_pSetup->sActivePatchbayPath)) { appendMessagesError( tr("Could not load active patchbay definition.\n\n\"%1\"\n\nDisabled.") .arg(m_pSetup->sActivePatchbayPath)); m_pSetup->bActivePatchbay = false; } else { appendMessages(tr("Patchbay activated.")); // If we're up and running, make it dirty :) if (m_pJackClient) ++m_iJackDirty; if (m_pAlsaSeq) ++m_iAlsaDirty; } } // We're sure there's no active patchbay... else appendMessages(tr("Patchbay deactivated.")); // Should refresh anyway. ++m_iPatchbayRefresh; } // Toggle active patchbay setting. void qjackctlMainForm::setActivePatchbay ( const QString& sPatchbayPath ) { if (m_pSetup == nullptr) return; if (sPatchbayPath.isEmpty()) { m_pSetup->bActivePatchbay = false; } else { m_pSetup->bActivePatchbay = true; m_pSetup->sActivePatchbayPath = sPatchbayPath; } updateActivePatchbay(); } // Reset the MRU patchbay list. void qjackctlMainForm::setRecentPatchbays ( const QStringList& patchbays ) { m_pSetup->patchbays = patchbays; } // Stabilize current form toggle buttons that may be astray. void qjackctlMainForm::stabilizeForm (void) { m_ui.MessagesStatusToolButton->setChecked( m_pMessagesStatusForm && m_pMessagesStatusForm->isVisible()); m_ui.SessionToolButton->setChecked( m_pSessionForm && m_pSessionForm->isVisible()); m_ui.GraphToolButton->setChecked( m_pGraphForm && m_pGraphForm->isVisible()); m_ui.ConnectionsToolButton->setChecked( m_pConnectionsForm && m_pConnectionsForm->isVisible()); m_ui.PatchbayToolButton->setChecked( m_pPatchbayForm && m_pPatchbayForm->isVisible()); m_ui.SetupToolButton->setChecked( m_pSetupForm && m_pSetupForm->isVisible()); } void qjackctlMainForm::stabilizeFormEx (void) { updateContextMenu(); stabilizeForm(); } // Stabilize current business over the application event loop. void qjackctlMainForm::stabilize ( int msecs ) { QElapsedTimer timer; timer.start(); while (timer.elapsed() < msecs) QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } // Reset XRUN cache items. void qjackctlMainForm::resetXrunStats (void) { m_timeResetLast = QTime::currentTime(); m_timerResetLast.start(); m_iXrunStats = 0; m_iXrunCount = 0; m_fXrunTotal = 0.0f; m_fXrunMin = 0.0f; m_fXrunMax = 0.0f; m_fXrunLast = 0.0f; m_timeXrunLast.setHMS(0, 0, 0); m_timerXrunLast.start(); m_iXrunCallbacks = 0; m_iXrunSkips = 0; #ifdef CONFIG_JACK_MAX_DELAY if (m_pJackClient) jack_reset_max_delayed_usecs(m_pJackClient); #endif refreshXrunStats(); appendMessages(tr("Statistics reset.")); // Make sure all status(es) will be updated ASAP. m_iStatusRefresh += QJACKCTL_STATUS_CYCLE; } // Update the XRUN count/callbacks item. void qjackctlMainForm::updateXrunCount (void) { // We'll change XRUN status colors here! QColor color = (m_pJackClient ? Qt::green : Qt::darkGreen); if ((m_iXrunCount + m_iXrunCallbacks) > 0) { if (m_iXrunCallbacks > 0) color = (m_pJackClient ? Qt::red : Qt::darkRed); else color = (m_pJackClient ? Qt::yellow : Qt::darkYellow); #ifdef CONFIG_SYSTEM_TRAY // Change the system tray icon background color! if (m_pSystemTray) m_pSystemTray->setBackground(color); } // Reset the system tray icon background! else if (m_pSystemTray) m_pSystemTray->setBackground(Qt::transparent); #else } #endif QPalette pal; pal.setColor(QPalette::WindowText, color); m_ui.XrunCountTextLabel->setPalette(pal); QString sText = QString::number(m_iXrunCount); sText += " ("; sText += QString::number(m_iXrunCallbacks); sText += ")"; updateStatusItem(STATUS_XRUN_COUNT, sText); } // Convert whole elapsed seconds to hh:mm:ss time format. QString qjackctlMainForm::formatTime ( float secs ) const { unsigned int hh, mm, ss; hh = mm = ss = 0; if (secs >= 3600.0f) { hh = (unsigned int) (secs / 3600.0f); secs -= (float) hh * 3600.0f; } if (secs >= 60.0f) { mm = (unsigned int) (secs / 60.0f); secs -= (float) mm * 60.0f; } if (secs >= 0.0) { ss = (unsigned int) secs; secs -= (float) ss; } // Raw milliseconds #if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) QString sTemp; sTemp.sprintf("%02u:%02u:%02u.%03u", hh, mm, ss, (unsigned int) (secs * 1000.0f)); return sTemp; #else return QString::asprintf("%02u:%02u:%02u.%03u", hh, mm, ss, (unsigned int) (secs * 1000.0f)); #endif } // Update the XRUN last/elapsed time item. QString qjackctlMainForm::formatElapsedTime ( int iStatusItem, const QTime& time, const QElapsedTimer& timer ) const { QString sTemp = c_szTimeDashes; QString sText; // Compute and format elapsed time. if (time.isNull() || time.msec() < 1) { sText = sTemp; } else { sText = time.toString(); if (m_pJackClient) { const float secs = float(timer.elapsed()) / 1000.0f; if (secs > 0) { sTemp = formatTime(secs); sText += " (" + sTemp + ")"; } } } // Display elapsed time as big time? if ((iStatusItem == STATUS_RESET_TIME && m_pSetup->iTimeDisplay == DISPLAY_RESET_TIME) || (iStatusItem == STATUS_XRUN_TIME && m_pSetup->iTimeDisplay == DISPLAY_XRUN_TIME)) { m_ui.TimeDisplayTextLabel->setText(sTemp); } return sText; } // Update the XRUN last/elapsed time item. void qjackctlMainForm::updateElapsedTimes (void) { // Display time remaining on start delay... if (m_iTimerDelay < m_iStartDelay) { m_ui.TimeDisplayTextLabel->setText(formatTime( float(m_iStartDelay - m_iTimerDelay) / 1000.0f)); } else { updateStatusItem(STATUS_RESET_TIME, formatElapsedTime(STATUS_RESET_TIME, m_timeResetLast, m_timerResetLast)); updateStatusItem(STATUS_XRUN_TIME, formatElapsedTime(STATUS_XRUN_TIME, m_timeXrunLast, m_timerXrunLast)); } } // Update the XRUN list view items. void qjackctlMainForm::refreshXrunStats (void) { updateXrunCount(); if (m_fXrunTotal < 0.001f) { const QString n = "--"; updateStatusItem(STATUS_XRUN_TOTAL, n); updateStatusItem(STATUS_XRUN_MIN, n); updateStatusItem(STATUS_XRUN_MAX, n); updateStatusItem(STATUS_XRUN_AVG, n); updateStatusItem(STATUS_XRUN_LAST, n); } else { float fXrunAverage = 0.0f; if (m_iXrunCount > 0) fXrunAverage = (m_fXrunTotal / m_iXrunCount); const QString s = " " + tr("msec"); updateStatusItem(STATUS_XRUN_TOTAL, QString::number(m_fXrunTotal) + s); updateStatusItem(STATUS_XRUN_MIN, QString::number(m_fXrunMin) + s); updateStatusItem(STATUS_XRUN_MAX, QString::number(m_fXrunMax) + s); updateStatusItem(STATUS_XRUN_AVG, QString::number(fXrunAverage) + s); updateStatusItem(STATUS_XRUN_LAST, QString::number(m_fXrunLast) + s); } updateElapsedTimes(); } // Jack port/graph change event notifier. void qjackctlMainForm::portNotifyEvent (void) { // Log some message here, if new. if (m_iJackRefresh == 0) appendMessagesColor(tr("JACK connection graph change."), "#cc9966"); // Do what has to be done. refreshJackConnections(); // We'll be dirty too... ++m_iJackDirty; } // Jack XRUN event notifier. void qjackctlMainForm::xrunNotifyEvent (void) { // Just increment callback counter. ++m_iXrunCallbacks; // Skip this one? Maybe we're under some kind of storm... ++m_iXrunSkips; // Report rate must be under one second... if (m_timerXrunLast.restart() < 1000) return; // Mark this one... m_timeXrunLast = QTime::currentTime(); #ifdef CONFIG_JACK_XRUN_DELAY // We have an official XRUN delay value (convert usecs to msecs)... updateXrunStats(0.001f * jack_get_xrun_delayed_usecs(m_pJackClient)); #endif // Just log this single event... appendMessagesColor(tr("XRUN callback (%1).") .arg(m_iXrunCallbacks), "#cc66cc"); } // Jack buffer size event notifier. void qjackctlMainForm::buffNotifyEvent (void) { // Don't need to nothing, it was handled on qjackctl_buffer_size_callback; // just log this event as routine. appendMessagesColor(tr("Buffer size change (%1).") .arg((int) g_buffsize), "#996633"); } // Jack shutdown event notifier. void qjackctlMainForm::shutNotifyEvent (void) { // Log this event. appendMessagesColor(tr("Shutdown notification."), "#cc6666"); // SHUTDOWN: JACK client handle might not be valid anymore... m_bJackShutdown = true; // m_pJackClient = nullptr; // Do what has to be done. stopJackServer(); } // Jack freewheel event notifier. void qjackctlMainForm::freeNotifyEvent (void) { // Log this event. appendMessagesColor(g_freewheel ? tr("Freewheel started...") : tr("Freewheel exited."), "#996633"); } // Process exit event notifier. void qjackctlMainForm::exitNotifyEvent (void) { // Poor-mans read, copy, update (RCU) QProcess::ProcessError error = g_error; g_error = QProcess::UnknownError; switch (error) { case QProcess::FailedToStart: appendMessagesError(tr("Could not start JACK.\n\nSorry.")); jackFinished(); break; case QProcess::Crashed: #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) if (!m_bJackKilled) #endif appendMessagesColor(tr("JACK has crashed."), "#cc3366"); break; case QProcess::Timedout: appendMessagesColor(tr("JACK timed out."), "#cc3366"); break; case QProcess::WriteError: appendMessagesColor(tr("JACK write error."), "#cc3366"); break; case QProcess::ReadError: appendMessagesColor(tr("JACK read error."), "#cc3366"); break; case QProcess::UnknownError: default: appendMessagesColor(tr("Unknown JACK error (%d).") .arg(int(error)), "#990099"); break; } } #ifdef CONFIG_JACK_METADATA // Jack property (metadata) event notifier. void qjackctlMainForm::propNotifyEvent (void) { // Log some message here, if new. if (m_iJackRefresh == 0) appendMessagesColor(tr("JACK property change."), "#993366"); // Do what has to be done. refreshJackConnections(true); // We'll be dirty too... ++m_iJackDirty; } #endif // ALSA announce slot. void qjackctlMainForm::alsaNotifySlot ( int /*fd*/ ) { #ifdef CONFIG_ALSA_SEQ do { snd_seq_event_t *pAlsaEvent; snd_seq_event_input(m_pAlsaSeq, &pAlsaEvent); snd_seq_free_event(pAlsaEvent); } while (snd_seq_event_input_pending(m_pAlsaSeq, 0) > 0); #endif // Log some message here, if new. if (m_iAlsaRefresh == 0) appendMessagesColor(tr("ALSA connection graph change."), "#66cc99"); // Do what has to be done. refreshAlsaConnections(); // We'll be dirty too... ++m_iAlsaDirty; } // Timer callback funtion. void qjackctlMainForm::timerSlot (void) { // Is it about to restart? if (m_bJackRestart && m_pJack == nullptr) { m_bJackRestart = false; startJack(); } // Is it the first shot on server start after a few delay? if (m_iTimerDelay < m_iStartDelay) { m_iTimerDelay += QJACKCTL_TIMER_MSECS; if (m_iTimerDelay >= m_iStartDelay) { // If we cannot start it now, // maybe we ought to cease & desist... if (!startJackClient(false)) stopJackServer(); } } // Is the connection patchbay dirty enough? if (m_pConnectionsForm && !g_freewheel) { const QString sEllipsis = "..."; // Are we about to enforce an audio connections persistence profile? if (m_iJackDirty > 0) { m_iJackDirty = 0; if (m_pSessionForm) m_pSessionForm->updateSession(); if (m_pSetup->bActivePatchbay) { appendMessagesColor( tr("JACK active patchbay scan") + sEllipsis, "#6699cc"); m_pPatchbayRack->connectJackScan(m_pJackClient); } refreshJackConnections(); } // Or is it from the MIDI field? if (m_iAlsaDirty > 0) { m_iAlsaDirty = 0; if (m_pSetup->bActivePatchbay) { appendMessagesColor( tr("ALSA active patchbay scan") + sEllipsis, "#99cc66"); m_pPatchbayRack->connectAlsaScan(m_pAlsaSeq); } refreshAlsaConnections(); } // Are we about to refresh it, really? if (m_iJackRefresh > 0 && m_pJackClient != nullptr) { const bool bClear = (m_iJackRefreshClear > 0); m_iJackRefreshClear = 0; m_iJackRefresh = 0; m_pConnectionsForm->refreshAudio(true, bClear); m_pConnectionsForm->refreshMidi(true, bClear); } if (m_iAlsaRefresh > 0 && m_pAlsaSeq != nullptr) { const bool bClear = (m_iAlsaRefreshClear > 0); m_iAlsaRefreshClear = 0; m_iAlsaRefresh = 0; m_pConnectionsForm->refreshAlsa(true, bClear); } } // Is the patchbay dirty enough? if (m_pPatchbayForm && m_iPatchbayRefresh > 0) { m_iPatchbayRefresh = 0; m_pPatchbayForm->refreshForm(); } // Is the graph dirty enough? if (m_pGraphForm) m_pGraphForm->refresh(); // Update some statistical fields, directly. refreshStatus(); // Register the next timer slot. QTimer::singleShot(QJACKCTL_TIMER_MSECS, this, SLOT(timerSlot())); } // JACK connection notification slot. void qjackctlMainForm::jackConnectChanged (void) { // Just shake the audio connections status quo. if (++m_iJackDirty == 1) appendMessagesColor(tr("JACK connection change."), "#9999cc"); } // ALSA connection notification slot. void qjackctlMainForm::alsaConnectChanged (void) { // Just shake the MIDI connections status quo. if (++m_iAlsaDirty == 1) appendMessagesColor(tr("ALSA connection change."), "#cccc99"); } // Cable connection notification slot. void qjackctlMainForm::cableConnectSlot ( const QString& sOutputPort, const QString& sInputPort, unsigned int ulCableFlags ) { QString sText = QFileInfo(m_pSetup->sActivePatchbayPath).baseName() + ": "; QString sColor; sText += sOutputPort; sText += " -> "; sText += sInputPort; sText += " "; switch (ulCableFlags) { case QJACKCTL_CABLE_CHECKED: sText += tr("checked"); sColor = "#99cccc"; break; case QJACKCTL_CABLE_CONNECTED: sText += tr("connected"); sColor = "#669999"; break; case QJACKCTL_CABLE_DISCONNECTED: sText += tr("disconnected"); sColor = "#cc9999"; break; case QJACKCTL_CABLE_FAILED: default: sText += tr("failed"); sColor = "#cc6699"; break; } appendMessagesColor(sText + '.', sColor); } // Patchbay (dis)connection slot. void qjackctlMainForm::queryDisconnect ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort, int iSocketType ) { queryDisconnect( pOPort->clientName(), pOPort->portName(), pIPort->clientName(), pIPort->portName(), iSocketType); } void qjackctlMainForm::queryDisconnect ( qjackctlGraphPort *port1, qjackctlGraphPort *port2 ) { qjackctlGraphNode *node1 = port1->portNode(); qjackctlGraphNode *node2 = port2->portNode(); if (node1 == nullptr || node2 == nullptr) return; int iSocketType = QJACKCTL_SOCKETTYPE_DEFAULT; if (qjackctlJackGraph::audioPortType() == port1->portType()) iSocketType = QJACKCTL_SOCKETTYPE_JACK_AUDIO; else if (qjackctlJackGraph::midiPortType() == port1->portType()) iSocketType = QJACKCTL_SOCKETTYPE_JACK_MIDI; #ifdef CONFIG_ALSA_SEQ else if (qjackctlAlsaGraph::midiPortType() == port1->portType()) iSocketType = QJACKCTL_SOCKETTYPE_ALSA_MIDI; #endif queryDisconnect( node1->nodeName(), port1->portName(), node2->nodeName(), port2->portName(), iSocketType); } void qjackctlMainForm::queryDisconnect ( const QString& sOClientName, const QString& sOPortName, const QString& sIClientName, const QString& sIPortName, int iSocketType ) { if (m_pSetup->bActivePatchbay && m_pSetup->bQueryDisconnect) { qjackctlPatchbayCable *pCable = m_pPatchbayRack->findCable( sOClientName, sOPortName, sIClientName, sIPortName, iSocketType); if (pCable) { bool bQueryDisconnect = true; const QString& sTitle = tr("Warning") + " - " QJACKCTL_TITLE; const QString& sText = tr("A patchbay definition is currently active,\n" "which is probable to redo this connection:\n\n" "%1 -> %2\n\n" "Do you want to remove the patchbay connection?") .arg(pCable->outputSocket()->name()) .arg(pCable->inputSocket()->name()); #if 0//QJACKCTL_QUERY_DISCONNECT bQueryDisconnect = (QMessageBox::warning(this, sTitle, Text, QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok); #else QMessageBox mbox(this); mbox.setIcon(QMessageBox::Warning); mbox.setWindowTitle(sTitle); mbox.setText(sText); mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); QCheckBox cbox(tr("Don't ask this again")); cbox.setChecked(false); cbox.blockSignals(true); mbox.addButton(&cbox, QMessageBox::ActionRole); bQueryDisconnect = (mbox.exec() == QMessageBox::Ok); if (bQueryDisconnect && cbox.isChecked()) m_pSetup->bQueryDisconnect = false; #endif if (bQueryDisconnect) m_pPatchbayRack->removeCable(pCable); } // Refresh patchbay form anyway... if (m_pPatchbayForm && isActivePatchbay(m_pPatchbayForm->patchbayPath())) m_pPatchbayForm->loadPatchbayRack(m_pPatchbayRack); } } // Delay jack control client start... void qjackctlMainForm::startJackClientDelay (void) { // Sloppy boy fix: may the serve be stopped, just in case // the client will nerver make it... m_ui.StopToolButton->setEnabled(true); // Make sure all status(es) will be updated ASAP... m_iStatusRefresh += QJACKCTL_STATUS_CYCLE; m_iStatusBlink = 0; // Reset (yet again) the timer counters... m_iStartDelay = 1 + (m_preset.iStartDelay * 1000); m_iTimerDelay = 0; m_iJackRefresh = 0; } // Start our jack audio control client... bool qjackctlMainForm::startJackClient ( bool bDetach ) { // If can't be already started, are we? if (m_pJackClient) return true; // Have it a setup? if (m_pSetup == nullptr) return false; // Make sure all status(es) will be updated ASAP. m_iStatusRefresh += QJACKCTL_STATUS_CYCLE; m_iStatusBlink = 0; // Are we about to start detached? if (bDetach) { // To fool timed client initialization delay. m_iTimerDelay += (m_iStartDelay + 1); // Refresh status (with dashes?) refreshStatus(); } // Create the jack client handle, using a distinct identifier (PID?) const char *pszClientName = "qjackctl"; jack_status_t status = JackFailure; if (m_pSetup->sServerName.isEmpty()) { m_pJackClient = jack_client_open(pszClientName, JackNoStartServer, &status); } else { m_pJackClient = jack_client_open(pszClientName, jack_options_t(JackNoStartServer | JackServerName), &status, m_pSetup->sServerName.toUtf8().constData()); } if (m_pJackClient == nullptr) { if (!bDetach) { QStringList errs; if (status & JackFailure) errs << tr("Overall operation failed."); if (status & JackInvalidOption) errs << tr("Invalid or unsupported option."); if (status & JackNameNotUnique) errs << tr("Client name not unique."); if (status & JackServerStarted) errs << tr("Server is started."); if (status & JackServerFailed) errs << tr("Unable to connect to server."); if (status & JackServerError) errs << tr("Server communication error."); if (status & JackNoSuchClient) errs << tr("Client does not exist."); if (status & JackLoadFailure) errs << tr("Unable to load internal client."); if (status & JackInitFailure) errs << tr("Unable to initialize client."); if (status & JackShmFailure) errs << tr("Unable to access shared memory."); if (status & JackVersionError) errs << tr("Client protocol version mismatch."); appendMessagesError( tr("Could not connect to JACK server as client.\n" "- %1\nPlease check the messages window for more info.") .arg(errs.join("\n- "))); // To stop timed client initialization delay... m_iTimerDelay += (m_iStartDelay + 1); // Refresh status (with dashes?) refreshStatus(); } return false; } // Set notification callbacks. jack_set_graph_order_callback(m_pJackClient, qjackctl_graph_order_callback, this); jack_set_client_registration_callback(m_pJackClient, qjackctl_client_registration_callback, this); jack_set_port_registration_callback(m_pJackClient, qjackctl_port_registration_callback, this); jack_set_port_connect_callback(m_pJackClient, qjackctl_port_connect_callback, this); #ifdef CONFIG_JACK_PORT_RENAME jack_set_port_rename_callback(m_pJackClient, qjackctl_port_rename_callback, this); #endif jack_set_xrun_callback(m_pJackClient, qjackctl_xrun_callback, this); jack_set_buffer_size_callback(m_pJackClient, qjackctl_buffer_size_callback, this); jack_set_freewheel_callback(m_pJackClient, qjackctl_freewheel_callback, this); jack_on_shutdown(m_pJackClient, qjackctl_on_shutdown, this); #ifdef CONFIG_JACK_METADATA jack_set_property_change_callback(m_pJackClient, qjackctl_property_change_callback, this); #endif // First knowledge about buffer size. g_buffsize = jack_get_buffer_size(m_pJackClient); // Sure we're not freewheeling at this point... g_freewheel = 0; // Reconstruct our connections and session... if (m_pConnectionsForm) { m_pConnectionsForm->stabilizeAudio(true); m_pConnectionsForm->stabilizeMidi(true); } if (m_pSessionForm) m_pSessionForm->stabilizeForm(true); if (bDetach #ifdef CONFIG_DBUS // Current D-BUS configuration makes it the default preset always... || (m_pDBusConfig && !m_bDBusDetach) #endif ) { const QString& sPreset = qjackctlSetup::defName(); if (m_pSetup->loadPreset(m_preset, sPreset)) { #ifdef CONFIG_DBUS if (m_pDBusConfig && !m_bDBusDetach) getDBusParameters(m_preset); #endif // Save current preset if not the default already... if (!m_pSetup->sDefPreset.isEmpty() && m_pSetup->sDefPreset != qjackctlSetup::defName()) m_pSetup->sOldPreset = m_pSetup->sDefPreset; // Have current preset changed anyhow? m_pSetup->sDefPreset = sPreset; if (m_pSetupForm) m_pSetupForm->updateCurrentPreset(); } } // Save server configuration file. if (m_pSetup->bServerConfig && !m_sJackCmdLine.isEmpty()) { const QString sFilename = QString::fromUtf8(::getenv("HOME")) + '/' + m_pSetup->sServerConfigName; QFile file(sFilename); if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { QTextStream(&file) << m_sJackCmdLine << endl; file.close(); appendMessagesColor( tr("Server configuration saved to \"%1\".") .arg(sFilename), "#999933"); } } // Time to (re)load current preset aliases? m_pSetup->loadAliases(); // We'll flag that we've been detached! if (bDetach) m_bJackDetach = true; else // Do not forget to reset XRUN stats variables... resetXrunStats(); // Activate us as a client... jack_activate(m_pJackClient); // All displays are highlighted from now on. QPalette pal; pal.setColor(QPalette::WindowText, Qt::yellow); m_ui.ServerStateTextLabel->setPalette(pal); m_ui.DspLoadTextLabel->setPalette(pal); m_ui.ServerModeTextLabel->setPalette(pal); pal.setColor(QPalette::WindowText, Qt::darkYellow); m_ui.SampleRateTextLabel->setPalette(pal); pal.setColor(QPalette::WindowText, Qt::green); m_ui.TimeDisplayTextLabel->setPalette(pal); m_ui.TransportStateTextLabel->setPalette(pal); m_ui.TransportBpmTextLabel->setPalette(pal); m_ui.TransportTimeTextLabel->setPalette(pal); // Whether we've started detached, just change active status. updateServerState(m_bJackDetach #ifdef CONFIG_DBUS && !(m_pDBusConfig && m_bDBusStarted) #endif ? QJACKCTL_ACTIVE : QJACKCTL_STARTED); m_ui.StopToolButton->setEnabled(true); // Log success here. appendMessages(tr("Client activated.")); // Formal patchbay activation, if any, is in order... updateActivePatchbay(); // Do we have any post-startup scripting?... // (only if we're not a detached client) if (!bDetach && !m_bJackDetach) { if (m_pSetup->bPostStartupScript && !m_pSetup->sPostStartupScriptShell.isEmpty()) { shellExecute(m_pSetup->sPostStartupScriptShell, tr("Post-startup script..."), tr("Post-startup script terminated")); } } // Have we an initial command-line to start away? if (!m_pSetup->cmdLine.isEmpty()) { // Run it dettached... shellExecute(m_pSetup->cmdLine.join(' '), tr("Command line argument..."), tr("Command line argument started")); // And reset it forever more... m_pSetup->cmdLine.clear(); } // Remember to schedule an initial connection refreshment. refreshConnections(); // OK, we're at it! return true; } // Stop jack audio client... void qjackctlMainForm::stopJackClient (void) { // Deactivate and close us as a client... if (m_pJackClient) { jack_deactivate(m_pJackClient); jack_client_close(m_pJackClient); m_pJackClient = nullptr; // Log deactivation here. appendMessages(tr("Client deactivated.")); } // Reset command-line configuration info. m_sJackCmdLine.clear(); // Clear out the connections and session... if (m_pConnectionsForm) { m_pConnectionsForm->stabilizeAudio(false); m_pConnectionsForm->stabilizeMidi(false); } if (m_pSessionForm) m_pSessionForm->stabilizeForm(false); if (m_pGraphForm) m_pGraphForm->jack_shutdown(); // Displays are dimmed again. QPalette pal; pal.setColor(QPalette::WindowText, Qt::darkYellow); m_ui.ServerModeTextLabel->setPalette(pal); m_ui.DspLoadTextLabel->setPalette(pal); m_ui.SampleRateTextLabel->setPalette(pal); pal.setColor(QPalette::WindowText, Qt::darkGreen); m_ui.TimeDisplayTextLabel->setPalette(pal); m_ui.TransportStateTextLabel->setPalette(pal); m_ui.TransportBpmTextLabel->setPalette(pal); m_ui.TransportTimeTextLabel->setPalette(pal); // Refresh jack client statistics explicitly. refreshXrunStats(); } // JACK client accessor. jack_client_t *qjackctlMainForm::jackClient (void) const { return (m_bJackShutdown ? nullptr : m_pJackClient); } // ALSA sequencer client accessor. snd_seq_t *qjackctlMainForm::alsaSeq (void) const { return m_pAlsaSeq; } // Rebuild all patchbay items. void qjackctlMainForm::refreshConnections (void) { refreshJackConnections(); refreshAlsaConnections(); } void qjackctlMainForm::refreshJackConnections ( bool bClear ) { // Hack this as for a while... if (m_pGraphForm) m_pGraphForm->jack_changed(); #if 0 if (m_pConnectionsForm && m_iJackRefresh == 0) { m_pConnectionsForm->stabilizeAudio(false); m_pConnectionsForm->stabilizeMidi(false); } #endif // Just increment our intentions; it will be deferred // to be executed just on timer slot processing... ++m_iJackRefresh; if (bClear) ++m_iJackRefreshClear; } void qjackctlMainForm::refreshAlsaConnections ( bool bClear ) { // Hack this as for a while... if (m_pGraphForm) m_pGraphForm->alsa_changed(); #if 0 if (m_pConnectionsForm && m_iAlsaRefresh == 0) m_pConnectionsForm->stabilizeAlsa(false); #endif // Just increment our intentions; it will be deferred // to be executed just on timer slot processing... ++m_iAlsaRefresh; if (bClear) ++m_iAlsaRefreshClear; } void qjackctlMainForm::refreshPatchbay (void) { // Just increment our intentions; it will be deferred // to be executed just on timer slot processing... ++m_iPatchbayRefresh; } // Main form visibility requester slot. void qjackctlMainForm::toggleMainForm (void) { if (m_pSetup == nullptr) return; m_pSetup->saveWidgetGeometry(this, true); if (isVisible() && !isMinimized()) { #ifdef CONFIG_SYSTEM_TRAY // Hide away from sight, totally... if (m_pSetup->bSystemTray && m_pSystemTray) hide(); else #endif // Minimize (iconify) normally. showMinimized(); } else { // Show normally. showNormal(); raise(); activateWindow(); } // updateContextMenu(); } // Message log/status form requester slot. void qjackctlMainForm::toggleMessagesStatusForm (void) { if (m_pMessagesStatusForm) { m_pSetup->saveWidgetGeometry(m_pMessagesStatusForm); if (m_pMessagesStatusForm->isVisible()) { m_pMessagesStatusForm->hide(); } else { m_pMessagesStatusForm->show(); m_pMessagesStatusForm->raise(); m_pMessagesStatusForm->activateWindow(); } } updateContextMenu(); } void qjackctlMainForm::toggleMessagesForm (void) { if (m_pMessagesStatusForm) { const int iTabPage = m_pMessagesStatusForm->tabPage(); m_pMessagesStatusForm->setTabPage( int(qjackctlMessagesStatusForm::MessagesTab)); if (m_pMessagesStatusForm->isVisible() && iTabPage != m_pMessagesStatusForm->tabPage()) return; } toggleMessagesStatusForm(); } void qjackctlMainForm::toggleStatusForm (void) { if (m_pMessagesStatusForm) { const int iTabPage = m_pMessagesStatusForm->tabPage(); m_pMessagesStatusForm->setTabPage( int(qjackctlMessagesStatusForm::StatusTab)); if (m_pMessagesStatusForm->isVisible() && iTabPage != m_pMessagesStatusForm->tabPage()) return; } toggleMessagesStatusForm(); } // Session form requester slot. void qjackctlMainForm::toggleSessionForm (void) { if (m_pSessionForm) { m_pSetup->saveWidgetGeometry(m_pSessionForm); m_pSessionForm->stabilizeForm(m_pJackClient != nullptr); if (m_pSessionForm->isVisible()) { m_pSessionForm->hide(); } else { m_pSessionForm->show(); m_pSessionForm->raise(); m_pSessionForm->activateWindow(); } } updateContextMenu(); } // Connections form requester slot. void qjackctlMainForm::toggleConnectionsForm (void) { if (m_pConnectionsForm) { m_pSetup->saveWidgetGeometry(m_pConnectionsForm); m_pConnectionsForm->stabilizeAudio(m_pJackClient != nullptr); m_pConnectionsForm->stabilizeMidi(m_pJackClient != nullptr); m_pConnectionsForm->stabilizeAlsa(m_pAlsaSeq != nullptr); if (m_pConnectionsForm->isVisible()) { m_pConnectionsForm->hide(); } else { m_pConnectionsForm->show(); m_pConnectionsForm->raise(); m_pConnectionsForm->activateWindow(); } } updateContextMenu(); } // Patchbay form requester slot. void qjackctlMainForm::togglePatchbayForm (void) { if (m_pPatchbayForm) { m_pSetup->saveWidgetGeometry(m_pPatchbayForm); if (m_pPatchbayForm->isVisible()) { m_pPatchbayForm->hide(); } else { m_pPatchbayForm->show(); m_pPatchbayForm->raise(); m_pPatchbayForm->activateWindow(); } } updateContextMenu(); } // Graph form requester slot. void qjackctlMainForm::toggleGraphForm (void) { if (m_pGraphForm) { m_pSetup->saveWidgetGeometry(m_pGraphForm); if (m_pGraphForm->isVisible()) { m_pGraphForm->hide(); } else { m_pGraphForm->show(); m_pGraphForm->raise(); m_pGraphForm->activateWindow(); } } updateContextMenu(); } // Setup dialog requester slot. void qjackctlMainForm::showSetupForm (void) { if (m_pSetupForm) { // m_pSetup->saveWidgetGeometry(m_pSetupForm); if (m_pSetupForm->isVisible()) { m_pSetupForm->hide(); } else { m_pSetupForm->show(); m_pSetupForm->raise(); m_pSetupForm->activateWindow(); } } updateContextMenu(); } // About dialog requester slot. void qjackctlMainForm::showAboutForm (void) { qjackctlAboutForm(this).exec(); } // Transport rewind. void qjackctlMainForm::transportRewind (void) { #ifdef CONFIG_JACK_TRANSPORT if (m_pJackClient) { jack_transport_locate(m_pJackClient, 0); // Log this here. appendMessages(tr("Transport rewind.")); // Make sure all status(es) will be updated ASAP... m_iStatusRefresh += QJACKCTL_STATUS_CYCLE; ++m_iMenuRefresh; } #endif } // Transport backward. void qjackctlMainForm::transportBackward (void) { #ifdef CONFIG_JACK_TRANSPORT if (m_pJackClient) { jack_position_t tpos; jack_transport_query(m_pJackClient, &tpos); float rate = float(tpos.frame_rate); float tloc = ((float(tpos.frame) / rate) - m_fSkipAccel) * rate; if (tloc < 0.0f) tloc = 0.0f; jack_transport_locate(m_pJackClient, (jack_nframes_t) tloc); // Log this here (if on initial toggle). if (m_fSkipAccel < 1.1f) appendMessages(tr("Transport backward.")); // Take care of backward acceleration... if (m_ui.BackwardToolButton->isDown() && m_fSkipAccel < 60.0) m_fSkipAccel *= 1.1f; // Make sure all status(es) will be updated ASAP... m_iStatusRefresh += QJACKCTL_STATUS_CYCLE; ++m_iMenuRefresh; } #endif } // Transport toggle (start/stop) void qjackctlMainForm::transportPlay ( bool bOn ) { if (m_iTransportPlay > 0) return; if (bOn) transportStart(); else transportStop(); } // Transport start (play) void qjackctlMainForm::transportStart (void) { #ifdef CONFIG_JACK_TRANSPORT if (m_pJackClient) { jack_transport_start(m_pJackClient); updateStatusItem(STATUS_TRANSPORT_STATE, tr("Starting")); // Log this here. appendMessages(tr("Transport start.")); // Make sure all status(es) will be updated ASAP... m_iStatusRefresh += QJACKCTL_STATUS_CYCLE; ++m_iMenuRefresh; } #endif } // Transport stop (pause). void qjackctlMainForm::transportStop (void) { #ifdef CONFIG_JACK_TRANSPORT if (m_pJackClient) { jack_transport_stop(m_pJackClient); updateStatusItem(STATUS_TRANSPORT_STATE, tr("Stopping")); // Log this here. appendMessages(tr("Transport stop.")); // Make sure all status(es) will be updated ASAP... m_iStatusRefresh += QJACKCTL_STATUS_CYCLE; ++m_iMenuRefresh; } #endif } // Transport forward. void qjackctlMainForm::transportForward (void) { #ifdef CONFIG_JACK_TRANSPORT if (m_pJackClient) { jack_position_t tpos; jack_transport_query(m_pJackClient, &tpos); float rate = float(tpos.frame_rate); float tloc = ((float(tpos.frame) / rate) + m_fSkipAccel) * rate; if (tloc < 0.0f) tloc = 0.0f; jack_transport_locate(m_pJackClient, (jack_nframes_t) tloc); // Log this here. if (m_fSkipAccel < 1.1f) appendMessages(tr("Transport forward.")); // Take care of forward acceleration... if (m_ui.ForwardToolButton->isDown() && m_fSkipAccel < 60.0f) m_fSkipAccel *= 1.1f; // Make sure all status(es) will be updated ASAP... m_iStatusRefresh += QJACKCTL_STATUS_CYCLE; ++m_iMenuRefresh; } #endif } // Almost-complete running status refresher. void qjackctlMainForm::refreshStatus (void) { const QString n = "--"; const QString b = "-.-.---"; const QString sStopped = tr("Stopped"); ++m_iStatusRefresh; if (m_pJackClient) { const QString s = " "; #ifdef CONFIG_JACK_TRANSPORT QString sText = n; jack_position_t tpos; jack_transport_state_t tstate = jack_transport_query(m_pJackClient, &tpos); const bool bPlaying = (tstate == JackTransportRolling || tstate == JackTransportLooping); // Transport timecode position. // if (bPlaying) updateStatusItem(STATUS_TRANSPORT_TIME, formatTime(float(tpos.frame) / float(tpos.frame_rate))); // else // updateStatusItem(STATUS_TRANSPORT_TIME, c_szTimeDashes); // Transport barcode position (bar:beat.tick) if (tpos.valid & JackPositionBBT) { #if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) updateStatusItem(STATUS_TRANSPORT_BBT, QString().sprintf("%u.%u.%03u", tpos.bar, tpos.beat, tpos.tick)); #else updateStatusItem(STATUS_TRANSPORT_BBT, QString::asprintf("%u.%u.%03u", tpos.bar, tpos.beat, tpos.tick)); #endif updateStatusItem(STATUS_TRANSPORT_BPM, QString::number(tpos.beats_per_minute)); } else { updateStatusItem(STATUS_TRANSPORT_BBT, b); updateStatusItem(STATUS_TRANSPORT_BPM, n); } #endif // !CONFIG_JACK_TRANSPORT // Less frequent status items update... if (m_iStatusRefresh >= QJACKCTL_STATUS_CYCLE) { m_iStatusRefresh = 0; const float fDspLoad = jack_cpu_load(m_pJackClient); const char f = (fDspLoad > 0.1f ? 'f' : 'g'); // format const int p = (fDspLoad > 1.0f ? 1 : 2 ); // precision #ifdef CONFIG_SYSTEM_TRAY if (m_pSystemTray) { if (m_iXrunCount > 0) { m_pSystemTray->setToolTip(tr("%1 (%2%)") .arg(windowTitle()) .arg(fDspLoad, 0, f, p)); } else { m_pSystemTray->setToolTip(tr("%1 (%2%, %3 xruns)") .arg(windowTitle()) .arg(fDspLoad, 0, f, p) .arg(m_iXrunCount)); } } #endif // !CONFIG_SYSTEM_TRAY updateStatusItem(STATUS_DSP_LOAD, tr("%1 %").arg(fDspLoad, 0, f, p)); updateStatusItem(STATUS_SAMPLE_RATE, tr("%1 Hz").arg(jack_get_sample_rate(m_pJackClient))); updateStatusItem(STATUS_BUFFER_SIZE, tr("%1 frames").arg(g_buffsize)); // Blink server mode indicator?... if (m_pSetup && m_pSetup->bDisplayBlink) { QPalette pal; pal.setColor(QPalette::WindowText, (++m_iStatusBlink % 2) ? Qt::darkYellow: Qt::yellow); m_ui.ServerModeTextLabel->setPalette(pal); } #ifdef CONFIG_JACK_REALTIME const bool bRealtime = jack_is_realtime(m_pJackClient); updateStatusItem(STATUS_REALTIME, (bRealtime ? tr("Yes") : tr("No"))); #else updateStatusItem(STATUS_REALTIME, n); #endif // !CONFIG_JACK_REALTIME if (g_freewheel) m_ui.ServerModeTextLabel->setText(tr("FW")); else #ifdef CONFIG_JACK_REALTIME m_ui.ServerModeTextLabel->setText(bRealtime ? tr("RT") : n); #else m_ui.ServerModeTextLabel->setText(n); #endif // !CONFIG_JACK_REALTIME #ifdef CONFIG_JACK_TRANSPORT switch (tstate) { case JackTransportStarting: sText = tr("Starting"); break; case JackTransportRolling: sText = tr("Rolling"); break; case JackTransportLooping: sText = tr("Looping"); break; case JackTransportStopped: default: sText = sStopped; break; } updateStatusItem(STATUS_TRANSPORT_STATE, sText); m_ui.RewindToolButton->setEnabled(tpos.frame > 0); m_ui.BackwardToolButton->setEnabled(tpos.frame > 0); m_ui.PlayToolButton->setEnabled(true); m_ui.PauseToolButton->setEnabled(bPlaying); m_ui.ForwardToolButton->setEnabled(true); transportPlayStatus(bPlaying); if (!m_ui.BackwardToolButton->isDown() && !m_ui.ForwardToolButton->isDown()) m_fSkipAccel = 1.0; #else updateStatusItem(STATUS_TRANSPORT_STATE, n); m_ui.RewindToolButton->setEnabled(false); m_ui.BackwardToolButton->setEnabled(false); m_ui.PlayToolButton->setEnabled(false); m_ui.PauseToolButton->setEnabled(false); m_ui.ForwardToolButton->setEnabled(false); transportPlayStatus(false); updateStatusItem(STATUS_TRANSPORT_TIME, c_szTimeDashes); updateStatusItem(STATUS_TRANSPORT_BBT, b); updateStatusItem(STATUS_TRANSPORT_BPM, n); #endif // !CONFIG_JACK_TRANSPORT #ifdef CONFIG_JACK_MAX_DELAY updateStatusItem(STATUS_MAX_DELAY, tr("%1 msec") .arg(0.001f * jack_get_max_delayed_usecs(m_pJackClient))); #endif // !CONFIG_JACK_MAX_DELAY // Check if we're have some XRUNs to report... if (m_iXrunSkips > 0) { // Maybe we've skipped some... if (m_iXrunSkips > 1) { appendMessagesColor(tr("XRUN callback (%1 skipped).") .arg(m_iXrunSkips - 1), "#cc99cc"); } // Reset skip count. m_iXrunSkips = 0; // Highlight the (new) status... refreshXrunStats(); } } #ifdef CONFIG_SYSTEM_TRAY // XRUN: blink the system-tray icon backgroung... if (m_pSystemTray && m_iXrunCallbacks > 0 && m_pSetup && m_pSetup->bDisplayBlink) { const int iElapsed = m_timerXrunLast.elapsed(); if (iElapsed > 0x7ff) { // T=2048ms. QColor color(m_pSystemTray->background()); color.setAlpha(0x0ff - ((iElapsed >> 3) & 0x0ff)); m_pSystemTray->setBackground(color); } } #endif // !CONFIG_SYSTEM_TRAY } // No need to update often if we're just idle... else if (m_iStatusRefresh >= QJACKCTL_STATUS_CYCLE) { m_iStatusRefresh = 0; updateStatusItem(STATUS_DSP_LOAD, n); updateStatusItem(STATUS_SAMPLE_RATE, n); updateStatusItem(STATUS_BUFFER_SIZE, n); updateStatusItem(STATUS_REALTIME, n); m_ui.ServerModeTextLabel->setText(n); updateStatusItem(STATUS_TRANSPORT_STATE, n); updateStatusItem(STATUS_TRANSPORT_TIME, c_szTimeDashes); updateStatusItem(STATUS_TRANSPORT_BBT, b); updateStatusItem(STATUS_TRANSPORT_BPM, n); m_ui.RewindToolButton->setEnabled(false); m_ui.BackwardToolButton->setEnabled(false); m_ui.PlayToolButton->setEnabled(false); m_ui.PauseToolButton->setEnabled(false); m_ui.ForwardToolButton->setEnabled(false); transportPlayStatus(false); } // Elapsed times should be rigorous... updateElapsedTimes(); if (m_iMenuRefresh > 0) { m_iMenuRefresh = 0; updateContextMenu(); } } // Status item updater. void qjackctlMainForm::updateStatusItem( int iStatusItem, const QString& sText ) { switch (iStatusItem) { case STATUS_SERVER_STATE: m_ui.ServerStateTextLabel->setText(sText); break; case STATUS_DSP_LOAD: m_ui.DspLoadTextLabel->setText(sText); break; case STATUS_SAMPLE_RATE: m_ui.SampleRateTextLabel->setText(sText); break; case STATUS_XRUN_COUNT: m_ui.XrunCountTextLabel->setText(sText); break; case STATUS_TRANSPORT_STATE: m_ui.TransportStateTextLabel->setText(sText); break; case STATUS_TRANSPORT_TIME: if (m_pSetup->iTimeDisplay == DISPLAY_TRANSPORT_TIME) m_ui.TimeDisplayTextLabel->setText(sText); else m_ui.TransportTimeTextLabel->setText(sText); break; case STATUS_TRANSPORT_BBT: if (m_pSetup->iTimeDisplay == DISPLAY_TRANSPORT_BBT) m_ui.TimeDisplayTextLabel->setText(sText); else if (m_pSetup->iTimeDisplay == DISPLAY_TRANSPORT_TIME) m_ui.TransportTimeTextLabel->setText(sText); break; case STATUS_TRANSPORT_BPM: m_ui.TransportBpmTextLabel->setText(sText); break; } if (m_pMessagesStatusForm) m_pMessagesStatusForm->updateStatusItem(iStatusItem, sText); } // Main window caption title and system tray icon and tooltip update. void qjackctlMainForm::updateTitleStatus (void) { QString sTitle = m_pSetup->sDefPreset; QString sState; const QString sDots(3, '.'); switch (m_iServerState) { case QJACKCTL_STARTING: sState = tr("Starting"); sState += sDots; break; case QJACKCTL_STARTED: sState = tr("Started"); break; case QJACKCTL_STOPPING: sState = tr("Stopping"); sState += sDots; break; case QJACKCTL_STOPPED: sState = tr("Stopped"); break; case QJACKCTL_ACTIVE: sState = tr("Active"); break; case QJACKCTL_ACTIVATING: sState = tr("Activating"); sState += sDots; break; case QJACKCTL_INACTIVE: default: sState = tr("Inactive"); break; } sTitle += ' '; sTitle += sState; setWindowTitle(sTitle); updateStatusItem(STATUS_SERVER_STATE, sState); #ifdef CONFIG_SYSTEM_TRAY if (m_pSystemTray) { switch (m_iServerState) { case QJACKCTL_STARTING: m_pSystemTray->setPixmapOverlay(QPixmap(":/images/xstarting1.png")); break; case QJACKCTL_STARTED: m_pSystemTray->setPixmapOverlay(QPixmap(":/images/xstarted1.png")); break; case QJACKCTL_STOPPING: m_pSystemTray->setPixmapOverlay(QPixmap(":/images/xstopping1.png")); break; case QJACKCTL_STOPPED: m_pSystemTray->setPixmapOverlay(QPixmap(":/images/xstopped1.png")); break; case QJACKCTL_ACTIVE: m_pSystemTray->setPixmapOverlay(QPixmap(":/images/xactive1.png")); break; case QJACKCTL_ACTIVATING: m_pSystemTray->setPixmapOverlay(QPixmap(":/images/xactivating1.png")); break; case QJACKCTL_INACTIVE: default: m_pSystemTray->setPixmapOverlay(QPixmap(":/images/xinactive1.png")); break; } m_pSystemTray->setToolTip(sTitle); } #endif QString sServerName = m_pSetup->sServerName; if (sServerName.isEmpty()) sServerName = QString::fromUtf8(::getenv("JACK_DEFAULT_SERVER")); if (sServerName.isEmpty()) sServerName = qjackctlSetup::defName(); updateStatusItem(STATUS_SERVER_NAME, sServerName); } // Main server state status update helper. void qjackctlMainForm::updateServerState ( int iServerState ) { // Just set the new server state. m_iServerState = iServerState; // Now's time to update main window // caption title and status immediately. updateTitleStatus(); // Update context-menu for sure... updateContextMenu(); } #ifdef CONFIG_SYSTEM_TRAY // System tray master switcher. void qjackctlMainForm::updateSystemTray (void) { if (!QSystemTrayIcon::isSystemTrayAvailable()) return; if (!m_pSetup->bSystemTray && m_pSystemTray) { // Strange enough, this would close the application too. // m_pSystemTray->close(); delete m_pSystemTray; m_pSystemTray = nullptr; } if (m_pSetup->bSystemTray && m_pSystemTray == nullptr) { m_pSystemTray = new qjackctlSystemTray(this); m_pSystemTray->setContextMenu(&m_menu); QObject::connect(m_pSystemTray, SIGNAL(clicked()), SLOT(toggleMainForm())); QObject::connect(m_pSystemTray, SIGNAL(middleClicked()), SLOT(resetXrunStats())); QObject::connect(m_pSystemTray, SIGNAL(doubleClicked()), SLOT(toggleJack())); m_pSystemTray->show(); } else { // Make sure the main widget is visible. show(); raise(); activateWindow(); } updateContextMenu(); } #endif // Common context menu request slots. void qjackctlMainForm::updateContextMenu (void) { m_menu.clear(); QAction *pAction; QString sHideMinimize = tr("Mi&nimize"); QString sShowRestore = tr("Rest&ore"); #ifdef CONFIG_SYSTEM_TRAY if (m_pSetup->bSystemTray && m_pSystemTray) { sHideMinimize = tr("&Hide"); sShowRestore = tr("S&how"); } #endif pAction = m_menu.addAction(isVisible() && !isMinimized() ? sHideMinimize : sShowRestore, this, SLOT(toggleMainForm())); m_menu.addSeparator(); if (m_pJackClient == nullptr) { pAction = m_menu.addAction(QIcon(":/images/start1.png"), tr("&Start"), this, SLOT(startJack())); } else { pAction = m_menu.addAction(QIcon(":/images/stop1.png"), tr("&Stop"), this, SLOT(stopJack())); } pAction = m_menu.addAction(QIcon(":/images/reset1.png"), tr("&Reset"), this, SLOT(resetXrunStats())); // pAction->setEnabled(m_pJackClient != nullptr); m_menu.addSeparator(); // Construct the actual presets menu, // overriding the last one, if any... QMenu *pPresetsMenu = m_menu.addMenu(tr("&Presets")); // Assume QStringList iteration follows item index order (0,1,2...) int iPreset = 0; QStringListIterator iter(m_pSetup->presets); while (iter.hasNext()) { const QString& sPreset = iter.next(); pAction = pPresetsMenu->addAction(sPreset); pAction->setCheckable(true); pAction->setChecked(sPreset == m_pSetup->sDefPreset); pAction->setData(iPreset); ++iPreset; } // Default preset always present, and has invalid index parameter (-1)... if (iPreset > 0) pPresetsMenu->addSeparator(); pAction = pPresetsMenu->addAction(qjackctlSetup::defName()); pAction->setCheckable(true); pAction->setChecked( m_pSetup->sDefPreset.isEmpty() || m_pSetup->sDefPreset == qjackctlSetup::defName()); pAction->setData(-1); QObject::connect(pPresetsMenu, SIGNAL(triggered(QAction*)), SLOT(activatePresetsMenu(QAction*))); m_menu.addSeparator(); if (m_pSessionForm) { const bool bEnabled = (m_pJackClient != nullptr); const QString sTitle = tr("S&ession"); const QIcon iconSession(":/images/session1.png"); QMenu *pSessionMenu = m_menu.addMenu(sTitle); pSessionMenu->setIcon(iconSession); pAction = pSessionMenu->addAction(m_pSessionForm->isVisible() ? tr("&Hide") : tr("S&how"), this, SLOT(toggleSessionForm())); pSessionMenu->addSeparator(); pAction = pSessionMenu->addAction(QIcon(":/images/open1.png"), tr("&Load..."), m_pSessionForm, SLOT(loadSession())); pAction->setEnabled(bEnabled); QMenu *pRecentMenu = m_pSessionForm->recentMenu(); pAction = pSessionMenu->addMenu(pRecentMenu); pAction->setEnabled(m_pJackClient != nullptr && !pRecentMenu->isEmpty()); pSessionMenu->addSeparator(); pAction = pSessionMenu->addAction(QIcon(":/images/save1.png"), tr("&Save..."), m_pSessionForm, SLOT(saveSessionSave())); pAction->setEnabled(bEnabled); #ifdef CONFIG_JACK_SESSION pAction = pSessionMenu->addAction( tr("Save and &Quit..."), m_pSessionForm, SLOT(saveSessionSaveAndQuit())); pAction->setEnabled(bEnabled); pAction = pSessionMenu->addAction( tr("Save &Template..."), m_pSessionForm, SLOT(saveSessionSaveTemplate())); pAction->setEnabled(bEnabled); #endif pSessionMenu->addSeparator(); pAction = pSessionMenu->addAction( tr("&Versioning"), m_pSessionForm, SLOT(saveSessionVersion(bool))); pAction->setCheckable(true); pAction->setChecked(m_pSessionForm->isSessionSaveVersion()); pAction->setEnabled(bEnabled); pSessionMenu->addSeparator(); pAction = pSessionMenu->addAction(QIcon(":/images/refresh1.png"), tr("Re&fresh"), m_pSessionForm, SLOT(updateSession())); pAction->setEnabled(bEnabled); } pAction = m_menu.addAction(QIcon(":/images/messages1.png"), tr("&Messages"), this, SLOT(toggleMessagesForm())); pAction->setCheckable(true); pAction->setChecked(m_pMessagesStatusForm && m_pMessagesStatusForm->isVisible() && m_pMessagesStatusForm->tabPage() == qjackctlMessagesStatusForm::MessagesTab); pAction = m_menu.addAction(QIcon(":/images/status1.png"), tr("St&atus"), this, SLOT(toggleStatusForm())); pAction->setCheckable(true); pAction->setChecked(m_pMessagesStatusForm && m_pMessagesStatusForm->isVisible() && m_pMessagesStatusForm->tabPage() == qjackctlMessagesStatusForm::StatusTab); pAction = m_menu.addAction(QIcon(":/images/graph1.png"), tr("&Graph"), this, SLOT(toggleGraphForm())); pAction->setCheckable(true); pAction->setChecked(m_pGraphForm && m_pGraphForm->isVisible()); pAction = m_menu.addAction(QIcon(":/images/connections1.png"), tr("&Connections"), this, SLOT(toggleConnectionsForm())); pAction->setCheckable(true); pAction->setChecked(m_pConnectionsForm && m_pConnectionsForm->isVisible()); pAction = m_menu.addAction(QIcon(":/images/patchbay1.png"), tr("Patch&bay"), this, SLOT(togglePatchbayForm())); pAction->setCheckable(true); pAction->setChecked(m_pPatchbayForm && m_pPatchbayForm->isVisible()); m_menu.addSeparator(); QMenu *pTransportMenu = m_menu.addMenu(tr("&Transport")); pAction = pTransportMenu->addAction(QIcon(":/images/rewind1.png"), tr("&Rewind"), this, SLOT(transportRewind())); pAction->setEnabled(m_ui.RewindToolButton->isEnabled()); // pAction = pTransportMenu->addAction(QIcon(":/images/backward1.png"), // tr("&Backward"), this, SLOT(transportBackward())); // pAction->setEnabled(m_ui.BackwardToolButton->isEnabled()); pAction = pTransportMenu->addAction(QIcon(":/images/play1.png"), tr("&Play"), this, SLOT(transportStart())); pAction->setEnabled(!m_ui.PlayToolButton->isChecked()); pAction = pTransportMenu->addAction(QIcon(":/images/pause1.png"), tr("Pa&use"), this, SLOT(transportStop())); pAction->setEnabled(m_ui.PauseToolButton->isEnabled()); // pAction = pTransportMenu->addAction(QIcon(":/images/forward1.png"), // tr("&Forward"), this, SLOT(transportForward())); // pAction->setEnabled(m_ui.ForwardToolButton->isEnabled()); m_menu.addSeparator(); pAction = m_menu.addAction(QIcon(":/images/setup1.png"), tr("Set&up..."), this, SLOT(showSetupForm())); pAction->setCheckable(true); pAction->setChecked(m_pSetupForm && m_pSetupForm->isVisible()); if (!m_pSetup->bRightButtons || !m_pSetup->bTransportButtons) { pAction = m_menu.addAction(QIcon(":/images/about1.png"), tr("Ab&out..."), this, SLOT(showAboutForm())); } m_menu.addSeparator(); pAction = m_menu.addAction(QIcon(":/images/quit1.png"), tr("&Quit"), this, SLOT(quitMainForm())); } // Setup otions change warning. void qjackctlMainForm::showDirtySetupWarning (void) { const QString& sTitle = tr("Information"); const QString& sText = tr("Some settings will be only effective\n" "the next time you start this program."); #ifdef CONFIG_SYSTEM_TRAY if (m_pSetup->bSystemTray && m_pSystemTray && QSystemTrayIcon::supportsMessages()) { m_pSystemTray->showMessage( sTitle + " - " QJACKCTL_TITLE, sText, QSystemTrayIcon::Information); } else #endif QMessageBox::information(this, sTitle, sText); } // Select the current default preset (by name from context menu). void qjackctlMainForm::activatePresetsMenu ( QAction *pAction ) { activatePreset(pAction->data().toInt()); } // Select the current default preset (by name). void qjackctlMainForm::activatePreset ( const QString& sPreset ) { activatePreset(m_pSetup->presets.indexOf(sPreset)); } // Select the current default preset (by index). void qjackctlMainForm::activatePreset ( int iPreset ) { if (iPreset >= 0 && iPreset < m_pSetup->presets.count()) m_pSetup->sDefPreset = m_pSetup->presets.at(iPreset); else m_pSetup->sDefPreset = qjackctlSetup::defName(); // Have current preset changed anyhow? if (m_pSetupForm) m_pSetupForm->updateCurrentPreset(); restartJack(); } // Select the current active patchbay profile (by path). void qjackctlMainForm::activatePatchbay ( const QString& sPatchbayPath ) { if (QFileInfo(sPatchbayPath).exists() && !isActivePatchbay(sPatchbayPath)) { setActivePatchbay(sPatchbayPath); if (m_pPatchbayForm) { m_pPatchbayForm->loadPatchbayFile(sPatchbayPath); m_pPatchbayForm->updateRecentPatchbays(); m_pPatchbayForm->stabilizeForm(); } } } // Close main form slot. void qjackctlMainForm::quitMainForm (void) { #ifdef CONFIG_SYSTEM_TRAY // Flag that we're quitting explicitly. m_bQuitClose = true; #endif // And then, do the closing dance. close(); } // Context menu event handler. void qjackctlMainForm::contextMenuEvent ( QContextMenuEvent *pEvent ) { m_menu.exec(pEvent->globalPos()); } void qjackctlMainForm::mousePressEvent(QMouseEvent *pMouseEvent) { if (pMouseEvent->button() == Qt::MiddleButton && m_ui.StatusDisplayFrame->geometry().contains(pMouseEvent->pos())) { resetXrunStats(); } } #ifdef CONFIG_DBUS // D-BUS: Set/reset parameter values from current selected preset options. void qjackctlMainForm::setDBusParameters ( const qjackctlPreset& preset ) { if (m_pDBusConfig == nullptr) return; // Set configuration parameters... const bool bDummy = (preset.sDriver == "dummy"); const bool bSun = (preset.sDriver == "sun"); const bool bOss = (preset.sDriver == "oss"); const bool bAlsa = (preset.sDriver == "alsa"); const bool bPortaudio = (preset.sDriver == "portaudio"); const bool bCoreaudio = (preset.sDriver == "coreaudio"); const bool bFirewire = (preset.sDriver == "firewire"); const bool bNet = (preset.sDriver == "net" || m_preset.sDriver == "netone"); // setDBusEngineParameter("name", // m_pSetup->sServerName, // !m_pSetup->sServerName.isEmpty()); setDBusEngineParameter("sync", preset.bSync); setDBusEngineParameter("verbose", preset.bVerbose); setDBusEngineParameter("realtime", preset.bRealtime); setDBusEngineParameter("realtime-priority", preset.iPriority, preset.bRealtime && preset.iPriority > 5); setDBusEngineParameter("port-max", uint(preset.iPortMax), preset.iPortMax > 0 && preset.iPortMax != 256); setDBusEngineParameter("client-timeout", preset.iTimeout, preset.iTimeout > 0 && preset.iTimeout != 500); setDBusEngineParameter("clock-source", uint(preset.ucClockSource), preset.ucClockSource > 0 && preset.ucClockSource != ' '); setDBusEngineParameter("self-connect-mode", QVariant::fromValue (preset.ucSelfConnectMode), preset.ucSelfConnectMode > 0 && preset.ucSelfConnectMode != ' '); // setDBusEngineParameter("no-mem-lock", // preset.bNoMemLock, // !preset.bNoMemLock); // setDBusEngineParameter("libs-unlock", // preset.bUnlockMem, // !preset.bNoMemLock); setDBusEngineParameter("driver", preset.sDriver); if ((bAlsa || bPortaudio) && (preset.iAudio != QJACKCTL_DUPLEX || preset.sInDevice.isEmpty() || preset.sOutDevice.isEmpty())) { QString sInterface = preset.sInterface; if (bAlsa && sInterface.isEmpty()) sInterface = "hw:0"; setDBusDriverParameter("device", sInterface, !sInterface.isEmpty()); } if (bPortaudio) { setDBusDriverParameter("channel", uint(preset.iChan), preset.iChan > 0); } if (bCoreaudio || bFirewire) { setDBusDriverParameter("device", preset.sInterface, !preset.sInterface.isEmpty()); } if (!bNet) { setDBusDriverParameter("rate", uint(preset.iSampleRate), preset.iSampleRate > 0); setDBusDriverParameter("period", uint(preset.iFrames), preset.iFrames > 0); } if (bAlsa || bSun || bOss || bFirewire) { setDBusDriverParameter("nperiods", uint(preset.iPeriods), preset.iPeriods > 1); } if (bAlsa) { setDBusDriverParameter("softmode", preset.bSoftMode, !preset.bSoftMode); setDBusDriverParameter("monitor", preset.bMonitor, !preset.bMonitor); setDBusDriverParameter("shorts", preset.bShorts, !preset.bShorts); setDBusDriverParameter("hwmeter", preset.bHWMeter, !preset.bShorts); #ifdef CONFIG_JACK_MIDI setDBusDriverParameter("midi-driver", preset.sMidiDriver, !preset.sMidiDriver.isEmpty()); #endif } if (bAlsa || bPortaudio) { QString sInterface = preset.sInterface; if (bAlsa && sInterface.isEmpty()) sInterface = "hw:0"; QString sInDevice = preset.sInDevice; if (sInDevice.isEmpty()) sInDevice = sInterface; QString sOutDevice = preset.sOutDevice; if (sOutDevice.isEmpty()) sOutDevice = sInterface; switch (preset.iAudio) { case QJACKCTL_DUPLEX: setDBusDriverParameter("duplex", true); setDBusDriverParameter("capture", sInDevice); setDBusDriverParameter("playback", sOutDevice); break; case QJACKCTL_CAPTURE: resetDBusDriverParameter("duplex"); setDBusDriverParameter("capture", sInDevice); resetDBusDriverParameter("playback"); break; case QJACKCTL_PLAYBACK: resetDBusDriverParameter("duplex"); setDBusDriverParameter("playback", sOutDevice); resetDBusDriverParameter("capture"); break; } setDBusDriverParameter("inchannels", uint(preset.iInChannels), preset.iInChannels > 0 && preset.iAudio != QJACKCTL_PLAYBACK); setDBusDriverParameter("outchannels", uint(preset.iOutChannels), preset.iOutChannels > 0 && preset.iAudio != QJACKCTL_CAPTURE); uchar dither = 0; switch (preset.iDither) { case 0: dither = 'n'; break; case 1: dither = 'r'; break; case 2: dither = 's'; break; case 3: dither = 't'; break; } setDBusDriverParameter("dither", QVariant::fromValue(dither), dither > 0); } else if (bOss || bSun) { QString sInDevice = preset.sInDevice; if (sInDevice.isEmpty() && preset.iAudio == QJACKCTL_CAPTURE) sInDevice = preset.sInterface; setDBusDriverParameter("capture", sInDevice, !sInDevice.isEmpty() && preset.iAudio != QJACKCTL_PLAYBACK); QString sOutDevice = preset.sOutDevice; if (sOutDevice.isEmpty() && preset.iAudio == QJACKCTL_PLAYBACK) sOutDevice = preset.sInterface; setDBusDriverParameter("playback", sOutDevice, !sOutDevice.isEmpty() && preset.iAudio != QJACKCTL_CAPTURE); setDBusDriverParameter("inchannels", uint(preset.iInChannels), preset.iInChannels > 0 && preset.iAudio != QJACKCTL_PLAYBACK); setDBusDriverParameter("outchannels", uint(preset.iOutChannels), preset.iOutChannels > 0 && preset.iAudio != QJACKCTL_CAPTURE); } else if (bCoreaudio || bFirewire || bNet) { setDBusDriverParameter("inchannels", uint(preset.iInChannels), preset.iInChannels > 0 && preset.iAudio != QJACKCTL_PLAYBACK); setDBusDriverParameter("outchannels", uint(preset.iOutChannels), preset.iOutChannels > 0 && preset.iAudio != QJACKCTL_CAPTURE); } if (bDummy) { setDBusDriverParameter("wait", uint(preset.iWait), preset.iWait > 0 && preset.iWait != 21333); } else if (!bNet) { setDBusDriverParameter("input-latency", uint(preset.iInLatency), preset.iInLatency > 0); setDBusDriverParameter("output-latency", uint(preset.iOutLatency), preset.iOutLatency > 0); } } // D-BUS: Set parameter values (with reset option). bool qjackctlMainForm::setDBusEngineParameter ( const QString& param, const QVariant& value, bool bSet ) { return setDBusParameter(QStringList() << "engine" << param, value, bSet); } bool qjackctlMainForm::setDBusDriverParameter ( const QString& param, const QVariant& value, bool bSet ) { return setDBusParameter(QStringList() << "driver" << param, value, bSet); } bool qjackctlMainForm::setDBusParameter ( const QStringList& path, const QVariant& value, bool bSet ) { if (m_pDBusConfig == nullptr) return false; if (!bSet) return resetDBusParameter(path); // Reset option. QDBusMessage dbusm = m_pDBusConfig->call( "SetParameterValue", path, QVariant::fromValue(QDBusVariant(value))); if (dbusm.type() == QDBusMessage::ErrorMessage) { if (m_bDBusDetach) { appendMessagesError( tr("D-BUS: SetParameterValue('%1', '%2'):\n\n" "%3.\n(%4)").arg(path.join(":")).arg(value.toString()) .arg(dbusm.errorMessage()) .arg(dbusm.errorName())); } return false; } return true; } // D-BUS: Reset parameter (to default) values. bool qjackctlMainForm::resetDBusEngineParameter ( const QString& param ) { return resetDBusParameter(QStringList() << "engine" << param); } bool qjackctlMainForm::resetDBusDriverParameter ( const QString& param ) { return resetDBusParameter(QStringList() << "driver" << param); } bool qjackctlMainForm::resetDBusParameter ( const QStringList& path ) { if (m_pDBusConfig == nullptr) return false; QDBusMessage dbusm = m_pDBusConfig->call("ResetParameterValue", path); if (dbusm.type() == QDBusMessage::ErrorMessage) { if (m_bDBusDetach) { appendMessagesError( tr("D-BUS: ResetParameterValue('%1'):\n\n" "%2.\n(%3)").arg(path.join(":")) .arg(dbusm.errorMessage()) .arg(dbusm.errorName())); } return false; } return true; } // D-BUS: Get preset options from current parameter values. bool qjackctlMainForm::getDBusParameters ( qjackctlPreset& preset ) { if (m_pSetup == nullptr) return false; if (m_pDBusConfig == nullptr) return false; // Get configuration parameters... QVariant var; // m_pSetup->sServerName.clear(); // var = getDBusEngineParameter("name"); // if (var.isValid()) // m_pSetup->sServerName = var.toString(); preset.bSync = false; var = getDBusEngineParameter("sync"); if (var.isValid()) preset.bSync = var.toBool(); preset.bVerbose = false; var = getDBusEngineParameter("verbose"); if (var.isValid()) preset.bVerbose = var.toBool(); preset.bRealtime = true; var = getDBusEngineParameter("realtime"); if (var.isValid()) preset.bRealtime = var.toBool(); preset.iPriority = 0; var = getDBusEngineParameter("realtime-priority"); if (var.isValid()) preset.iPriority = var.toInt(); preset.iPortMax = 0; var = getDBusEngineParameter("port-max"); if (var.isValid()) preset.iPortMax = var.toInt(); preset.iTimeout = 0; var = getDBusEngineParameter("client-timeout"); if (var.isValid()) preset.iTimeout = var.toInt(); preset.bNoMemLock = false; // var = getDBusEngineParameter("no-mem-lock"); // if (var.isValid()) // preset.bNoMemLock = var.ToBool(); preset.bUnlockMem = false; // var = getDBusEngineParameter("libs-unlock", // preset.bUnlockMem = var.toBool(); preset.ucSelfConnectMode = 0; var = getDBusEngineParameter("self-connect-mode"); if (var.isValid()) preset.ucClockSource = var.value (); preset.ucSelfConnectMode = 0; var = getDBusEngineParameter("self-connect-mode"); if (var.isValid()) preset.ucSelfConnectMode = var.value (); preset.sDriver.clear(); var = getDBusEngineParameter("driver"); if (var.isValid()) preset.sDriver = var.toString(); const bool bDummy = (preset.sDriver == "dummy"); const bool bSun = (preset.sDriver == "sun"); const bool bOss = (preset.sDriver == "oss"); const bool bAlsa = (preset.sDriver == "alsa"); const bool bPortaudio = (preset.sDriver == "portaudio"); const bool bCoreaudio = (preset.sDriver == "coreaudio"); const bool bFirewire = (preset.sDriver == "firewire"); const bool bNet = (preset.sDriver == "net" || preset.sDriver == "netone"); preset.sInterface.clear(); if (bAlsa || bPortaudio || bCoreaudio || bFirewire) { var = getDBusDriverParameter("device"); if (var.isValid()) preset.sInterface = var.toString(); } preset.iChan = 0; if (bPortaudio) { var = getDBusDriverParameter("channel"); if (var.isValid()) preset.iChan = var.toInt(); } preset.iSampleRate = 0; preset.iFrames = 0; if (!bNet) { var = getDBusDriverParameter("rate"); if (var.isValid()) preset.iSampleRate = var.toInt(); var = getDBusDriverParameter("period"); if (var.isValid()) preset.iFrames = var.toInt(); } preset.iPeriods = 0; if (bAlsa || bSun || bOss || bFirewire) { var = getDBusDriverParameter("nperiods"); if (var.isValid()) preset.iPeriods = var.toInt(); } preset.bSoftMode = false; preset.bMonitor = false; preset.bShorts = false; preset.bHWMeter = false; preset.sMidiDriver.clear(); if (bAlsa) { var = getDBusDriverParameter("softmode"); if (var.isValid()) preset.bSoftMode = var.toBool(); var = getDBusDriverParameter("monitor"); if (var.isValid()) preset.bMonitor = var.toBool(); var = getDBusDriverParameter("shorts"); if (var.isValid()) preset.bShorts = var.toBool(); var = getDBusDriverParameter("hwmeter"); if (var.isValid()) preset.bHWMeter = var.toBool(); #ifdef CONFIG_JACK_MIDI var = getDBusDriverParameter("midi-driver"); if (var.isValid()) preset.sMidiDriver = var.toString(); #endif } preset.iAudio = QJACKCTL_DUPLEX; preset.sInDevice.clear(); preset.sOutDevice.clear(); if (bAlsa || bPortaudio || bOss || bSun) { bool bDuplex = false; var = getDBusDriverParameter("duplex"); if (var.isValid()) bDuplex = var.toBool(); if (!bDuplex) { var = getDBusDriverParameter("capture"); if (var.isValid()) preset.sInDevice = var.toString(); var = getDBusDriverParameter("playback"); if (var.isValid()) preset.sOutDevice = var.toString(); if (!preset.sInDevice.isEmpty()) preset.iAudio = QJACKCTL_CAPTURE; if (!preset.sOutDevice.isEmpty()) preset.iAudio = QJACKCTL_PLAYBACK; } } preset.iInChannels = 0; preset.iOutChannels = 0; if (bAlsa || bPortaudio || bOss || bSun || bCoreaudio || bFirewire || bNet) { if (preset.iAudio != QJACKCTL_PLAYBACK) { var = getDBusDriverParameter("inchannels"); if (var.isValid()) preset.iInChannels = var.toInt(); } if (preset.iAudio != QJACKCTL_CAPTURE) { var = getDBusDriverParameter("outchannels"); if (var.isValid()) preset.iOutChannels = var.toInt(); } } preset.iDither = 0; if (bAlsa || bPortaudio) { unsigned char dither = 'n'; var = getDBusDriverParameter("dither"); if (var.isValid()) dither = var.toChar().cell(); switch (dither) { case 'n': preset.iDither = 0; break; case 'r': preset.iDither = 1; break; case 's': preset.iDither = 2; break; case 't': preset.iDither = 3; break; } } preset.iWait = 0; preset.iInLatency = 0; preset.iOutLatency = 0; if (bDummy) { var = getDBusDriverParameter("wait"); if (var.isValid()) preset.iWait = var.toInt(); } else if (!bNet) { var = getDBusDriverParameter("input-latency"); if (var.isValid()) preset.iInLatency = var.toInt(); var = getDBusDriverParameter("output-latency"); if (var.isValid()) preset.iOutLatency = var.toInt(); } return true; } // D-BUS: Get parameter values. QVariant qjackctlMainForm::getDBusEngineParameter ( const QString& param ) { return getDBusParameter(QStringList() << "engine" << param); } QVariant qjackctlMainForm::getDBusDriverParameter ( const QString& param ) { return getDBusParameter(QStringList() << "driver" << param); } QVariant qjackctlMainForm::getDBusParameter ( const QStringList& path ) { if (m_pDBusConfig == nullptr) return QVariant(); QDBusMessage dbusm = m_pDBusConfig->call("GetParameterValue", path); if (dbusm.type() == QDBusMessage::ErrorMessage) { if (m_bDBusDetach) { appendMessagesError( tr("D-BUS: GetParameterValue('%1'):\n\n" "%2.\n(%3)").arg(path.join(":")) .arg(dbusm.errorMessage()) .arg(dbusm.errorName())); } return QVariant(); } const QDBusVariant& dbusv = qvariant_cast (dbusm.arguments().at(2)); return dbusv.variant(); } QStringList qjackctlMainForm::getDBusParameterValues ( const QStringList& path ) { if (m_pDBusConfig == nullptr) return QStringList(); QDBusMessage dbusm = m_pDBusConfig->call("GetParameterConstraint", path); if (dbusm.type() == QDBusMessage::ErrorMessage) { if (m_bDBusDetach) { appendMessagesError( tr("D-BUS: GetParameterConstraint('%1'):\n\n" "%2.\n(%3)").arg(path.join(":")) .arg(dbusm.errorMessage()) .arg(dbusm.errorName())); } return QStringList(); } const QDBusArgument& dbusa = qvariant_cast (dbusm.arguments().at(3)); // return qdbus_cast (dbusa); QStringList list; dbusa.beginArray(); while (!dbusa.atEnd()) { QVariant var; dbusa >> var; const QDBusVariant& dbusv = qvariant_cast (var); list.append(dbusv.variant().toString()); } dbusa.endArray(); return list; } // D-BUS: List all supported engine/drivers. QStringList qjackctlMainForm::getDBusEngineDrivers (void) { return getDBusParameterValues(QStringList() << "engine" << "driver"); } #endif // CONFIG_DBUS // Whether detached as client only. bool qjackctlMainForm::isJackDetach (void) const { return m_bJackDetach; } // Quotes string with embedded whitespace. QString qjackctlMainForm::formatQuoted ( const QString& s ) const { const QChar b = ' '; const QChar q = '"'; return (s.contains(b) && !s.contains(q) ? q + s + q : s); } // Guarded transport play/pause toggle. void qjackctlMainForm::transportPlayStatus ( bool bOn ) { ++m_iTransportPlay; m_ui.PlayToolButton->setChecked(bOn); --m_iTransportPlay; } void qjackctlMainForm::commitData ( QSessionManager& sm ) { sm.release(); #ifdef CONFIG_SYSTEM_TRAY m_bQuitClose = true; #endif m_bQuitForce = true; } // Some settings that are special someway... bool qjackctlMainForm::resetBuffSize ( jack_nframes_t nframes ) { if (m_pJackClient == nullptr) return false; if (g_buffsize == nframes) return true; if (jack_set_buffer_size(m_pJackClient, nframes) != 0) return false; // May reset some stats... resetXrunStats(); return true; } // end of qjackctlMainForm.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlPatchbayRack.h0000644000000000000000000000012714771215054017411 xustar0029 mtime=1743067692.32863657 29 atime=1743067692.32863657 29 ctime=1743067692.32863657 qjackctl-1.0.4/src/qjackctlPatchbayRack.h0000644000175000001440000002367314771215054017410 0ustar00rncbcusers// qjackctlPatchbayRack.h // /**************************************************************************** Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlPatchbayRack_h #define __qjackctlPatchbayRack_h #include "qjackctlAbout.h" #include #include #include #ifdef CONFIG_ALSA_SEQ #include #else typedef void snd_seq_t; #endif // Patchbay socket types. #define QJACKCTL_SOCKETTYPE_DEFAULT -1 #define QJACKCTL_SOCKETTYPE_JACK_AUDIO 0 #define QJACKCTL_SOCKETTYPE_JACK_MIDI 1 #define QJACKCTL_SOCKETTYPE_ALSA_MIDI 2 // Patchbay slot normalization modes. #define QJACKCTL_SLOTMODE_OPEN 0 #define QJACKCTL_SLOTMODE_HALF 1 #define QJACKCTL_SLOTMODE_FULL 2 // Patchbay change signal flags. #define QJACKCTL_CABLE_FAILED 0 #define QJACKCTL_CABLE_CHECKED 1 #define QJACKCTL_CABLE_CONNECTED 2 #define QJACKCTL_CABLE_DISCONNECTED 3 // Struct name says it all. struct qjackctlAlsaMidiPort { QString sClientName; QString sPortName; int iAlsaClient; int iAlsaPort; }; // Patchbay socket definition. class qjackctlPatchbaySocket { public: // Constructor. qjackctlPatchbaySocket(const QString& sSocketName, const QString& sClientName, int iSocketType); // Default destructor. ~qjackctlPatchbaySocket(); // Socket property accessors. const QString& name() const; const QString& clientName() const; int type() const; bool isExclusive() const; const QString& forward() const; // Socket property methods. void setName(const QString& sSocketName); void setClientName(const QString& sClientName); void setType(int iSocketType); void setExclusive(bool bExclusive); void setForward(const QString& sSocketForward); // Plug list primitive methods. void addPlug(const QString& sPlugName); void removePlug(const QString& sPlugName); // Plug list accessor. QStringList& pluglist(); // Simple socket type methods. static int typeFromText(const QString& sSocketType); static QString textFromType(int iSocketType); private: // Properties. QString m_sSocketName; QString m_sClientName; int m_iSocketType; bool m_bExclusive; QString m_sSocketForward; // Patchbay socket plug list. QStringList m_pluglist; }; // Patchbay socket slot definition. class qjackctlPatchbaySlot { public: // Constructor. qjackctlPatchbaySlot(const QString& sSlotName, int iSlotMode = QJACKCTL_SLOTMODE_OPEN); // Default destructor. ~qjackctlPatchbaySlot(); // Slot property accessors. const QString& name() const; int mode() const; // Slot property methods. void setName(const QString& sSlotName); void setMode(int iSlotMode); // Socket methods. void setOutputSocket(qjackctlPatchbaySocket *pSocket); void setInputSocket(qjackctlPatchbaySocket *pSocket); // Socket accessors. qjackctlPatchbaySocket *outputSocket() const; qjackctlPatchbaySocket *inputSocket() const; private: // Slot properties. QString m_sSlotName; int m_iSlotMode; // Socket references. qjackctlPatchbaySocket *m_pOutputSocket; qjackctlPatchbaySocket *m_pInputSocket; }; // Patchbay cable connection definition. class qjackctlPatchbayCable { public: // Constructor. qjackctlPatchbayCable(qjackctlPatchbaySocket *pOutputSocket, qjackctlPatchbaySocket *pInputSocket); // Default destructor. ~qjackctlPatchbayCable(); // Socket methods. void setOutputSocket(qjackctlPatchbaySocket *pSocket); void setInputSocket(qjackctlPatchbaySocket *pSocket); // Socket accessors. qjackctlPatchbaySocket *outputSocket() const; qjackctlPatchbaySocket *inputSocket() const; private: // Socket references. qjackctlPatchbaySocket *m_pOutputSocket; qjackctlPatchbaySocket *m_pInputSocket; }; // Patchbay rack profile definition. class qjackctlPatchbayRack : public QObject { Q_OBJECT public: // Constructor. qjackctlPatchbayRack(); // Default destructor. ~qjackctlPatchbayRack(); // Common socket list primitive methods. void addSocket(QList& socketlist, qjackctlPatchbaySocket *pSocket); void removeSocket(QList& socketlist, qjackctlPatchbaySocket *pSocket); // Slot list primitive methods. void addSlot(qjackctlPatchbaySlot *pSlot); void removeSlot(qjackctlPatchbaySlot *pSlot); // Cable list primitive methods. void addCable(qjackctlPatchbayCable *pCable); void removeCable(qjackctlPatchbayCable *pCable); // Common socket finder. qjackctlPatchbaySocket *findSocket( QList& socketlist, const QString& sSocketName, int iSocketType = QJACKCTL_SOCKETTYPE_DEFAULT); // Slot finders. qjackctlPatchbaySlot *findSlot(const QString& sSlotName); // Cable finder. qjackctlPatchbayCable *findCable( const QString& sOutputSocket, const QString& sInputSocket); qjackctlPatchbayCable *findCable(qjackctlPatchbayCable *pCablePtr); // Cable finder (logical matching by client/port names). qjackctlPatchbayCable *findCable ( const QString& sOClientName, const QString& sOPortName, const QString& sIClientName, const QString& sIPortName, int iSocketType); // Patchbay cleaner. void clear(); // Patchbay rack socket list accessors. QList& osocketlist(); QList& isocketlist(); // Patchbay rack slots list accessor. QList& slotlist(); // Patchbay cable connections list accessor. QList& cablelist(); // Overloaded cable connection persistence scan cycle methods. void connectJackScan(jack_client_t *pJackClient); void connectAlsaScan(snd_seq_t *pAlsaSeq); // Patchbay snapshot methods. void connectJackSnapshot(jack_client_t *pJackClient); void connectAlsaSnapshot(snd_seq_t *pAlsaSeq); // Patchbay reset/disconnect-all methods. void disconnectAllJackPorts(jack_client_t *pJackClient); void disconnectAllAlsaPorts(snd_seq_t *pAlsaSeq); signals: // Cable connection change signal. void cableConnected(const QString& sOutputPort, const QString& sInputPort, unsigned int uiCableFlags); private: // Audio connection scan related private methods. const char *findJackPort(const char **ppszJackPorts, const QString& sClientName, const QString& sPortName, int n = 0); void connectJackPorts( const char *pszOutputPort, const char *pszInputPort); void disconnectJackPorts( const char *pszOutputPort, const char *pszInputPort); void checkJackPorts( const char *pszOutputPort, const char *pszInputPort); void connectJackSocketPorts( qjackctlPatchbaySocket *pOutputSocket, const char *pszOutputPort, qjackctlPatchbaySocket *pInputSocket, const char *pszInputPort); void connectJackCable( qjackctlPatchbaySocket *pOutputSocket, qjackctlPatchbaySocket *pInputSocket); // MIDI connection scan related private methods. void loadAlsaPorts(QList& midiports, bool bReadable); qjackctlAlsaMidiPort *findAlsaPort(QList& midiports, const QString& sClientName, const QString& sPortName, int n); QString getAlsaPortName(qjackctlAlsaMidiPort *pAlsaPort); void setAlsaPort(qjackctlAlsaMidiPort *pAlsaPort, int iAlsaClient, int iAlsaPort); void connectAlsaPorts( qjackctlAlsaMidiPort *pOutputPort, qjackctlAlsaMidiPort *pInputPort); void disconnectAlsaPorts( qjackctlAlsaMidiPort *pOutputPort, qjackctlAlsaMidiPort *pInputPort); void checkAlsaPorts( qjackctlAlsaMidiPort *pOutputPort, qjackctlAlsaMidiPort *pInputPort); void connectAlsaSocketPorts( qjackctlPatchbaySocket *pOutputSocket, qjackctlAlsaMidiPort *pOutputPort, qjackctlPatchbaySocket *pInputSocket, qjackctlAlsaMidiPort *pInputPort); void connectAlsaCable( qjackctlPatchbaySocket *pOutputSocket, qjackctlPatchbaySocket *pInputSocket); void loadAlsaConnections(QList& midiports, qjackctlAlsaMidiPort *pAlsaPort, bool bReadable); // Audio socket/ports forwarding executive methods. void connectJackForwardPorts( const char *pszPort, const char *pszPortForward); void connectJackForward( qjackctlPatchbaySocket *pSocket, qjackctlPatchbaySocket *pSocketForward); // MIDI socket/ports forwarding executive methods. void connectAlsaForwardPorts( qjackctlAlsaMidiPort *pPort, qjackctlAlsaMidiPort *pPortForward); void connectAlsaForward( qjackctlPatchbaySocket *pSocket, qjackctlPatchbaySocket *pSocketForward); // Common socket forwarding scan method. void connectForwardScan(int iSocketType); // JACK snapshot executive. void connectJackSnapshotEx(int iSocketType); // JACK reset/disconnect-all executive. void disconnectAllJackPortsEx(int iSocketType); // Patchbay sockets lists. QList m_osocketlist; QList m_isocketlist; // Patchbay rack slots list. QList m_slotlist; // Patchbay cable connections list. QList m_cablelist; // Audio connection persistence cache variables. jack_client_t *m_pJackClient; const char **m_ppszOAudioPorts; const char **m_ppszIAudioPorts; const char **m_ppszOMidiPorts; const char **m_ppszIMidiPorts; // MIDI connection persistence cache variables. snd_seq_t *m_pAlsaSeq; QList m_omidiports; QList m_imidiports; }; #endif // __qjackctlPatchbayRack_h // qjackctlPatchbayRack.h qjackctl-1.0.4/src/PaxHeaders/qjackctlSession.h0000644000000000000000000000013214771215054016474 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSession.h0000644000175000001440000000632514771215054016472 0ustar00rncbcusers// qjackctlSession.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlSession_h #define __qjackctlSession_h #include #include #include // Forward decls. class QSettings; //---------------------------------------------------------------------------- // qjackctlSession -- JACK session container. class qjackctlSession { public: // Constructor. qjackctlSession(); // Destructor. ~qjackctlSession(); // Container structs. struct ConnectItem { ConnectItem() : connected(false) {} QString client_name; QString port_name; bool connected; }; typedef QList ConnectList; struct PortItem { PortItem() : connected(0) {} ~PortItem() { qDeleteAll(connects); } QString port_name; int port_type; int connected; ConnectList connects; }; typedef QList PortList; struct ClientItem { ClientItem() : connected(0) {} ~ClientItem() { qDeleteAll(ports); } QString client_name; QString client_uuid; QString client_command; int connected; PortList ports; }; typedef QHash ClientList; // Client list accessor (read-only) const ClientList& clients() const; // House-keeper. void clear(); // Critical methods. enum SaveType { Save = 0, SaveAndQuit, SaveTemplate }; bool save(const QString& sSessionDir, SaveType stype = SaveType::Save); bool load(const QString& sSessionDir); // Update (re)connections utility method. bool update(); // Infra-client table. struct InfraClientItem { QString client_name; QString client_command; }; typedef QHash InfraClientList; // Infra-client list accessor (read-write) InfraClientList& infra_clients(); // Load/save all infra-clients from/to configuration file. void loadInfraClients(QSettings& settings); void saveInfraClients(QSettings& settings); // Clear infra-client table. void clearInfraClients(); // Check whether a given JACK client name exists... bool isJackClient(const QString& sClientName) const; protected: // File methods. bool loadFile(const QString& sFilename); bool saveFile(const QString& sFilename); private: // Instance variables. ClientList m_clients; // Infra-clients table. InfraClientList m_infra_clients; }; #endif // __qjackctlSession_h // end of qjackctlSession.h qjackctl-1.0.4/src/PaxHeaders/qjackctlConnectionsForm.ui0000644000000000000000000000013214771215054020345 xustar0030 mtime=1743067692.324636588 30 atime=1743067692.323773797 30 ctime=1743067692.324636588 qjackctl-1.0.4/src/qjackctlConnectionsForm.ui0000644000175000001440000004032514771215054020341 0ustar00rncbcusers rncbc aka Rui Nuno Capela JACK Audio Connection Kit - Qt GUI Interface. Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlConnectionsForm 0 0 480 320 1 1 0 0 Connections :/images/connections1.png 4 4 0 Audio 4 4 7 7 0 0 Qt::TabFocus 4 4 Connect currently selected ports &Connect :/images/connect1.png Disconnect currently selected ports &Disconnect :/images/disconnect1.png Disconnect all currently connected ports Disconnect &All :/images/disconnectall1.png Qt::Horizontal QSizePolicy::Expanding 8 8 Expand all client ports E&xpand All :/images/expandall1.png Qt::Horizontal QSizePolicy::Expanding 8 8 Refresh current connections view &Refresh :/images/refresh1.png MIDI 4 4 7 7 0 0 Qt::TabFocus 4 4 Connect currently selected ports &Connect :/images/connect1.png Disconnect currently selected ports &Disconnect :/images/disconnect1.png Disconnect all currently connected ports Disconnect &All :/images/disconnectall1.png Qt::Horizontal QSizePolicy::Expanding 8 8 Expand all client ports E&xpand All :/images/expandall1.png Qt::Horizontal QSizePolicy::Expanding 8 8 Refresh current connections view &Refresh :/images/refresh1.png ALSA 4 4 7 7 0 0 Qt::TabFocus 4 4 Connect currently selected ports &Connect :/images/connect1.png Disconnect currently selected ports &Disconnect :/images/disconnect1.png Disconnect all currently connected ports Disconnect &All :/images/disconnectall1.png Qt::Horizontal QSizePolicy::Expanding 8 8 Expand all client ports E&xpand All :/images/expandall1.png Qt::Horizontal QSizePolicy::Expanding 8 8 Refresh current connections view &Refresh :/images/refresh1.png qjackctlConnectView QWidget
qjackctlConnect.h
ConnectionsTabWidget AudioConnectView AudioConnectPushButton AudioDisconnectPushButton AudioDisconnectAllPushButton AudioExpandAllPushButton AudioRefreshPushButton MidiConnectView MidiConnectPushButton MidiDisconnectPushButton MidiDisconnectAllPushButton MidiExpandAllPushButton MidiRefreshPushButton AlsaConnectView AlsaConnectPushButton AlsaDisconnectPushButton AlsaDisconnectAllPushButton AlsaExpandAllPushButton AlsaRefreshPushButton
qjackctl-1.0.4/src/PaxHeaders/qjackctl.h0000644000000000000000000000013214771215054015130 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctl.h0000644000175000001440000000574214771215054015130 0ustar00rncbcusers// qjackctl.h // /**************************************************************************** Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctl_h #define __qjackctl_h #include "qjackctlAbout.h" #include #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #if defined(Q_WS_X11) #define CONFIG_X11 #endif #endif // Forward decls. class QWidget; class QTranslator; #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #ifdef CONFIG_XUNIQUE #ifdef CONFIG_X11 #include typedef unsigned long Window; typedef unsigned long Atom; #endif // CONFIG_X11 #endif // CONFIG_XUNIQUE #else #ifdef CONFIG_XUNIQUE class QSharedMemory; class QLocalServer; #endif // CONFIG_XUNIQUE #endif //------------------------------------------------------------------------- // Singleton application instance stuff (Qt/X11 only atm.) // class qjackctlApplication : public QApplication { Q_OBJECT public: // Constructor. qjackctlApplication(int& argc, char **argv); // Destructor. ~qjackctlApplication(); // Main application widget accessors. void setMainWidget(QWidget *pWidget); QWidget *mainWidget() const { return m_pWidget; } // Check if another instance is running, // and raise its proper main widget... bool setup(const QString& sServerName); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #ifdef CONFIG_XUNIQUE #ifdef CONFIG_X11 void x11PropertyNotify(Window w); bool x11EventFilter(XEvent *pEv) #endif // CONFIG_X11 #endif // CONFIG_XUNIQUE #else #ifdef CONFIG_XUNIQUE protected slots: // Local server slots. void newConnectionSlot(); void readyReadSlot(); protected: // Local server/shmem setup/cleanup. bool setupServer(); void clearServer(); #endif // CONFIG_XUNIQUE #endif private: // Translation support. QTranslator *m_pQtTranslator; QTranslator *m_pMyTranslator; // Instance variables. QWidget *m_pWidget; #ifdef CONFIG_XUNIQUE QString m_sServerName; #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #ifdef CONFIG_X11 Display *m_pDisplay; Atom m_aUnique; Window m_wOwner; #endif // CONFIG_X11 #else QString m_sUnique; QSharedMemory *m_pMemory; QLocalServer *m_pServer; #endif #endif // CONFIG_XUNIQUE }; #endif // __qjackctl_h // end of qjackctl.h qjackctl-1.0.4/src/PaxHeaders/qjackctlSocketForm.cpp0000644000000000000000000000012714771215054017464 xustar0029 mtime=1743067692.33063656 29 atime=1743067692.33063656 29 ctime=1743067692.33063656 qjackctl-1.0.4/src/qjackctlSocketForm.cpp0000644000175000001440000006507714771215054017467 0ustar00rncbcusers// qjackctlSocketForm.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAbout.h" #include "qjackctlSocketForm.h" #include "qjackctlMainForm.h" #include "qjackctlPatchbay.h" #include "qjackctlAliases.h" #include #include #include #include #include #include // QRegularExpression exact match pattern wrapper. #if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) #define EXACT_PATTERN(s) ('^' + s + '$') #else #define EXACT_PATTERN(s) QRegularExpression::anchoredPattern(s) #endif //---------------------------------------------------------------------------- // qjackctlSocketForm -- UI wrapper form. // Constructor. qjackctlSocketForm::qjackctlSocketForm ( QWidget *pParent ) : QDialog(pParent) { // Setup UI struct... m_ui.setupUi(this); m_pSocketList = nullptr; m_bSocketNew = false; m_iSocketNameChanged = 0; m_ppPixmaps = nullptr; m_iDirtyCount = 0; // Setup time-display radio-button group. m_pSocketTypeButtonGroup = new QButtonGroup(this); m_pSocketTypeButtonGroup->addButton(m_ui.AudioRadioButton, 0); m_pSocketTypeButtonGroup->addButton(m_ui.MidiRadioButton, 1); m_pSocketTypeButtonGroup->addButton(m_ui.AlsaRadioButton, 2); m_pSocketTypeButtonGroup->setExclusive(true); // Plug list is not sortable. //m_ui.PlugListView->setSorting(-1); // Plug list view... QHeaderView *pHeader = m_ui.PlugListView->header(); // pHeader->setDefaultAlignment(Qt::AlignLeft); // pHeader->setDefaultSectionSize(300); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setMovable(false); #endif pHeader->setStretchLastSection(true); #ifndef CONFIG_JACK_MIDI m_ui.MidiRadioButton->setEnabled(false); #endif #ifndef CONFIG_ALSA_SEQ m_ui.AlsaRadioButton->setEnabled(false); #endif // UI connections... QObject::connect(m_ui.PlugAddPushButton, SIGNAL(clicked()), SLOT(addPlug())); QObject::connect(m_ui.PlugRemovePushButton, SIGNAL(clicked()), SLOT(removePlug())); QObject::connect(m_ui.PlugEditPushButton, SIGNAL(clicked()), SLOT(editPlug())); QObject::connect(m_ui.PlugUpPushButton, SIGNAL(clicked()), SLOT(moveUpPlug())); QObject::connect(m_ui.PlugDownPushButton, SIGNAL(clicked()), SLOT(moveDownPlug())); QObject::connect(m_ui.PlugListView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(selectedPlug())); QObject::connect(m_ui.SocketNameLineEdit, SIGNAL(textChanged(const QString&)), SLOT(socketNameChanged())); QObject::connect(m_ui.AudioRadioButton, SIGNAL(toggled(bool)), SLOT(socketTypeChanged())); QObject::connect(m_ui.MidiRadioButton, SIGNAL(toggled(bool)), SLOT(socketTypeChanged())); QObject::connect(m_ui.AlsaRadioButton, SIGNAL(toggled(bool)), SLOT(socketTypeChanged())); QObject::connect(m_ui.ExclusiveCheckBox, SIGNAL(toggled(bool)), SLOT(socketTypeChanged())); QObject::connect(m_ui.ClientNameComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(clientNameChanged())); QObject::connect(m_ui.PlugNameComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changed())); QObject::connect(m_ui.PlugListView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(customContextMenu(const QPoint&))); QObject::connect(m_ui.PlugListView->itemDelegate(), SIGNAL(commitData(QWidget*)), SLOT(changed())); QObject::connect(m_ui.SocketForwardComboBox, SIGNAL(activated(int)), SLOT(changed())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); } // Destructor. qjackctlSocketForm::~qjackctlSocketForm (void) { delete m_pSocketTypeButtonGroup; } // Socket caption utility method. void qjackctlSocketForm::setSocketCaption ( const QString& sSocketCaption ) { m_ui.SocketTabWidget->setTabText(0, sSocketCaption); (m_ui.PlugListView->headerItem())->setText(0, sSocketCaption + ' ' + tr("Plugs / Ports")); } // Socket list enablement. void qjackctlSocketForm::setSocketList ( qjackctlSocketList *pSocketList ) { m_pSocketList = pSocketList; } // Socket new flag. void qjackctlSocketForm::setSocketNew ( bool bSocketNew ) { m_bSocketNew = bSocketNew; } // Pixmap utility methods. void qjackctlSocketForm::setPixmaps ( QPixmap **ppPixmaps ) { m_ppPixmaps = ppPixmaps; } // Socket type and exclusiveness editing enablement. void qjackctlSocketForm::setConnectCount ( int iConnectCount ) { // m_ui.SocketTypeGroupBox->setEnabled(iConnectCount < 1); if (iConnectCount) { switch (m_pSocketTypeButtonGroup->checkedId()) { case 0: // QJACKCTL_SOCKETTYPE_JACK_AUDIO m_ui.MidiRadioButton->setEnabled(false); m_ui.AlsaRadioButton->setEnabled(false); break; case 1: // QJACKCTL_SOCKETTYPE_JACK_MIDI m_ui.AudioRadioButton->setEnabled(false); m_ui.AlsaRadioButton->setEnabled(false); break; case 2: // QJACKCTL_SOCKETTYPE_ALSA_MIDI m_ui.AudioRadioButton->setEnabled(false); m_ui.MidiRadioButton->setEnabled(false); break; } } m_ui.ExclusiveCheckBox->setEnabled(iConnectCount < 2); #ifndef CONFIG_JACK_MIDI m_ui.MidiRadioButton->setEnabled(false); #endif #ifndef CONFIG_ALSA_SEQ m_ui.AlsaRadioButton->setEnabled(false); #endif } // Load dialog controls from socket properties. void qjackctlSocketForm::load ( qjackctlPatchbaySocket *pSocket ) { m_ui.SocketNameLineEdit->setText(pSocket->name()); QRadioButton *pRadioButton = static_cast ( m_pSocketTypeButtonGroup->button(pSocket->type())); if (pRadioButton) pRadioButton->setChecked(true); m_ui.ClientNameComboBox->setEditText(pSocket->clientName()); m_ui.ExclusiveCheckBox->setChecked(pSocket->isExclusive()); m_ui.PlugListView->clear(); QTreeWidgetItem *pPlugItem = nullptr; QStringListIterator iter(pSocket->pluglist()); while (iter.hasNext()) { const QString& sPlugName = iter.next(); pPlugItem = new QTreeWidgetItem(m_ui.PlugListView, pPlugItem); if (pPlugItem) { pPlugItem->setText(0, sPlugName); pPlugItem->setFlags(pPlugItem->flags() | Qt::ItemIsEditable); } } socketTypeChanged(); int iItemIndex = 0; if (!pSocket->forward().isEmpty()) { const int iItem = m_ui.SocketForwardComboBox->findText(pSocket->forward()); if (iItem >= 0) iItemIndex = iItem; } m_ui.SocketForwardComboBox->setCurrentIndex(iItemIndex); if (m_bSocketNew) m_iSocketNameChanged = 0; m_iDirtyCount = 0; stabilizeForm(); } // Save dialog controls into socket properties. void qjackctlSocketForm::save ( qjackctlPatchbaySocket *pSocket ) { pSocket->setName(m_ui.SocketNameLineEdit->text()); pSocket->setType(m_pSocketTypeButtonGroup->checkedId()); pSocket->setClientName(m_ui.ClientNameComboBox->currentText()); pSocket->setExclusive(m_ui.ExclusiveCheckBox->isChecked()); pSocket->pluglist().clear(); const int iPlugCount = m_ui.PlugListView->topLevelItemCount(); for (int iPlug = 0; iPlug < iPlugCount; ++iPlug) { QTreeWidgetItem *pItem = m_ui.PlugListView->topLevelItem(iPlug); pSocket->addPlug(pItem->text(0)); } if (m_ui.SocketForwardComboBox->currentIndex() > 0) pSocket->setForward(m_ui.SocketForwardComboBox->currentText()); else pSocket->setForward(QString()); m_iDirtyCount = 0; } // Stabilize current state form. void qjackctlSocketForm::stabilizeForm (void) { m_ui.DialogButtonBox->button( QDialogButtonBox::Ok)->setEnabled(validateForm()); QTreeWidgetItem *pItem = m_ui.PlugListView->currentItem(); if (pItem) { const int iItem = m_ui.PlugListView->indexOfTopLevelItem(pItem); const int iItemCount = m_ui.PlugListView->topLevelItemCount(); m_ui.PlugEditPushButton->setEnabled(true); m_ui.PlugRemovePushButton->setEnabled(true); m_ui.PlugUpPushButton->setEnabled(iItem > 0); m_ui.PlugDownPushButton->setEnabled(iItem < iItemCount - 1); } else { m_ui.PlugEditPushButton->setEnabled(false); m_ui.PlugRemovePushButton->setEnabled(false); m_ui.PlugUpPushButton->setEnabled(false); m_ui.PlugDownPushButton->setEnabled(false); } bool bEnabled = !m_ui.PlugNameComboBox->currentText().isEmpty(); if (bEnabled) { bEnabled = (m_ui.PlugListView->findItems( m_ui.PlugNameComboBox->currentText(), Qt::MatchExactly).isEmpty()); } m_ui.PlugAddPushButton->setEnabled(bEnabled); } // Validate form fields. bool qjackctlSocketForm::validateForm (void) { bool bValid = (m_iDirtyCount > 0); bValid = bValid && !m_ui.SocketNameLineEdit->text().isEmpty(); bValid = bValid && !m_ui.ClientNameComboBox->currentText().isEmpty(); bValid = bValid && (m_ui.PlugListView->topLevelItemCount() > 0); return bValid; } // Validate form fields and accept it valid. void qjackctlSocketForm::accept (void) { if (m_pSocketList == nullptr) return; if (!validateForm()) return; // Check if a socket with the same name already exists... if (m_bSocketNew) { QListIterator iter(m_pSocketList->sockets()); while (iter.hasNext()) { const QString& sSocketName = iter.next()->socketName(); if (m_ui.SocketNameLineEdit->text() == sSocketName) { QMessageBox::critical(this, tr("Error") + " - " QJACKCTL_TITLE, tr("A socket named \"%1\" already exists.") .arg(sSocketName), QMessageBox::Cancel); // Reject. return; } } } QDialog::accept(); } void qjackctlSocketForm::reject (void) { bool bReject = true; // Check if there's any pending changes... if (m_iDirtyCount > 0) { switch (QMessageBox::warning(this, tr("Warning") + " - " QJACKCTL_TITLE, tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), QMessageBox::Apply | QMessageBox::Discard | QMessageBox::Cancel)) { case QMessageBox::Apply: accept(); return; case QMessageBox::Discard: break; default: // Cancel. bReject = false; } } if (bReject) QDialog::reject(); } // Dirty up the current form. void qjackctlSocketForm::changed (void) { ++m_iDirtyCount; stabilizeForm(); } // Add new Plug to socket list. void qjackctlSocketForm::addPlug (void) { if (m_ppPixmaps == nullptr) return; QString sPlugName = m_ui.PlugNameComboBox->currentText(); if (!sPlugName.isEmpty()) { QTreeWidgetItem *pItem = m_ui.PlugListView->currentItem(); if (pItem) pItem->setSelected(false); pItem = new QTreeWidgetItem(m_ui.PlugListView, pItem); if (pItem) { pItem->setText(0, sPlugName); pItem->setFlags(pItem->flags() | Qt::ItemIsEditable); QPixmap *pXpmPlug = nullptr; switch (m_pSocketTypeButtonGroup->checkedId()) { case 0: // QJACKCTL_SOCKETTYPE_JACK_AUDIO pXpmPlug = m_ppPixmaps[QJACKCTL_XPM_AUDIO_PLUG]; break; case 1: // QJACKCTL_SOCKETTYPE_JACK_MIDI case 2: // QJACKCTL_SOCKETTYPE_ALSA_MIDI pXpmPlug = m_ppPixmaps[QJACKCTL_XPM_MIDI_PLUG]; break; } if (pXpmPlug) pItem->setIcon(0, QIcon(*pXpmPlug)); pItem->setSelected(true); m_ui.PlugListView->setCurrentItem(pItem); } m_ui.PlugNameComboBox->setEditText(QString()); } clientNameChanged(); } // Rename current selected Plug. void qjackctlSocketForm::editPlug (void) { QTreeWidgetItem *pItem = m_ui.PlugListView->currentItem(); if (pItem) m_ui.PlugListView->editItem(pItem, 0); clientNameChanged(); } // Remove current selected Plug. void qjackctlSocketForm::removePlug (void) { QTreeWidgetItem *pItem = m_ui.PlugListView->currentItem(); if (pItem) delete pItem; clientNameChanged(); } // Move current selected Plug one position up. void qjackctlSocketForm::moveUpPlug (void) { QTreeWidgetItem *pItem = m_ui.PlugListView->currentItem(); if (pItem) { int iItem = m_ui.PlugListView->indexOfTopLevelItem(pItem); if (iItem > 0) { pItem->setSelected(false); pItem = m_ui.PlugListView->takeTopLevelItem(iItem); m_ui.PlugListView->insertTopLevelItem(iItem - 1, pItem); pItem->setSelected(true); m_ui.PlugListView->setCurrentItem(pItem); } } changed(); } // Move current selected Plug one position down void qjackctlSocketForm::moveDownPlug (void) { QTreeWidgetItem *pItem = m_ui.PlugListView->currentItem(); if (pItem) { int iItem = m_ui.PlugListView->indexOfTopLevelItem(pItem); int iItemCount = m_ui.PlugListView->topLevelItemCount(); if (iItem < iItemCount - 1) { pItem->setSelected(false); pItem = m_ui.PlugListView->takeTopLevelItem(iItem); m_ui.PlugListView->insertTopLevelItem(iItem + 1, pItem); pItem->setSelected(true); m_ui.PlugListView->setCurrentItem(pItem); } } changed(); } // Update selected plug one position down void qjackctlSocketForm::selectedPlug (void) { QTreeWidgetItem *pItem = m_ui.PlugListView->currentItem(); if (pItem) m_ui.PlugNameComboBox->setEditText(pItem->text(0)); stabilizeForm(); } // Add new Plug from context menu. void qjackctlSocketForm::activateAddPlugMenu ( QAction *pAction ) { const int iIndex = pAction->data().toInt(); if (iIndex >= 0 && iIndex < m_ui.PlugNameComboBox->count()) { m_ui.PlugNameComboBox->setCurrentIndex(iIndex); addPlug(); } } // Plug list context menu handler. void qjackctlSocketForm::customContextMenu ( const QPoint& pos ) { int iItem = 0; int iItemCount = 0; QTreeWidgetItem *pItem = m_ui.PlugListView->itemAt(pos); if (pItem == nullptr) pItem = m_ui.PlugListView->currentItem(); if (pItem) { iItem = m_ui.PlugListView->indexOfTopLevelItem(pItem); iItemCount = m_ui.PlugListView->topLevelItemCount(); } QMenu menu(this); QAction *pAction; // Build the add plug sub-menu... QMenu *pAddPlugMenu = menu.addMenu( QIcon(":/images/add1.png"), tr("Add Plug")); int iIndex = 0; for (iIndex = 0; iIndex < m_ui.PlugNameComboBox->count(); iIndex++) { pAction = pAddPlugMenu->addAction( m_ui.PlugNameComboBox->itemText(iIndex)); pAction->setData(iIndex); } QObject::connect(pAddPlugMenu, SIGNAL(triggered(QAction*)), SLOT(activateAddPlugMenu(QAction*))); pAddPlugMenu->setEnabled(iIndex > 0); // Build the plug context menu... const bool bEnabled = (pItem != nullptr); pAction = menu.addAction(QIcon(":/images/edit1.png"), tr("Edit"), this, SLOT(editPlug())); pAction->setEnabled(bEnabled); pAction = menu.addAction(QIcon(":/images/remove1.png"), tr("Remove"), this, SLOT(removePlug())); pAction->setEnabled(bEnabled); menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/up1.png"), tr("Move Up"), this, SLOT(moveUpPlug())); pAction->setEnabled(bEnabled && iItem > 0); pAction = menu.addAction(QIcon(":/images/down1.png"), tr("Move Down"), this, SLOT(moveDownPlug())); pAction->setEnabled(bEnabled && iItem < iItemCount - 1); menu.exec((m_ui.PlugListView->viewport())->mapToGlobal(pos)); } void qjackctlSocketForm::updateJackClients ( int iSocketType ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return; const char *pszJackPortType = JACK_DEFAULT_AUDIO_TYPE; int iPixmap = QJACKCTL_XPM_AUDIO_CLIENT; #ifdef CONFIG_JACK_MIDI if (iSocketType == QJACKCTL_SOCKETTYPE_JACK_MIDI) { pszJackPortType = JACK_DEFAULT_MIDI_TYPE; iPixmap = QJACKCTL_XPM_MIDI_CLIENT; } #endif const bool bReadable = m_pSocketList->isReadable(); const QIcon icon(*m_ppPixmaps[iPixmap]); // Grab all client ports. const char **ppszClientPorts = jack_get_ports( pJackClient, nullptr, pszJackPortType, (bReadable ? JackPortIsOutput : JackPortIsInput)); if (ppszClientPorts) { int iClientPort = 0; while (ppszClientPorts[iClientPort]) { QString sClientPort = QString::fromUtf8(ppszClientPorts[iClientPort]); int iColon = sClientPort.indexOf(':'); if (iColon >= 0) { QString sClientName = qjackctlAliasItem::escapeRegExpDigits( sClientPort.left(iColon)); bool bExists = false; for (int i = 0; i < m_ui.ClientNameComboBox->count() && !bExists; i++) bExists = (sClientName == m_ui.ClientNameComboBox->itemText(i)); if (!bExists) { m_ui.ClientNameComboBox->addItem(icon, sClientName); } } iClientPort++; } jack_free(ppszClientPorts); } } // ALSA client names refreshner. void qjackctlSocketForm::updateAlsaClients ( int iSocketType ) { if (iSocketType != QJACKCTL_SOCKETTYPE_ALSA_MIDI) return; #ifdef CONFIG_ALSA_SEQ qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; snd_seq_t *pAlsaSeq = pMainForm->alsaSeq(); if (pAlsaSeq == nullptr) return; const bool bReadable = m_pSocketList->isReadable(); const QIcon icon(*m_ppPixmaps[QJACKCTL_XPM_MIDI_CLIENT]); // Readd all subscribers... snd_seq_client_info_t *pClientInfo; snd_seq_port_info_t *pPortInfo; unsigned int uiAlsaFlags; if (bReadable) uiAlsaFlags = SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; else uiAlsaFlags = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; snd_seq_client_info_alloca(&pClientInfo); snd_seq_port_info_alloca(&pPortInfo); snd_seq_client_info_set_client(pClientInfo, -1); while (snd_seq_query_next_client(pAlsaSeq, pClientInfo) >= 0) { const int iAlsaClient = snd_seq_client_info_get_client(pClientInfo); QString sClient = qjackctlAliasItem::escapeRegExpDigits( QString::fromUtf8(snd_seq_client_info_get_name(pClientInfo))); if (iAlsaClient > 0) { bool bExists = false; snd_seq_port_info_set_client(pPortInfo, iAlsaClient); snd_seq_port_info_set_port(pPortInfo, -1); while (!bExists && snd_seq_query_next_port(pAlsaSeq, pPortInfo) >= 0) { const unsigned int uiPortCapability = snd_seq_port_info_get_capability(pPortInfo); if (((uiPortCapability & uiAlsaFlags) == uiAlsaFlags) && ((uiPortCapability & SND_SEQ_PORT_CAP_NO_EXPORT) == 0)) { for (int i = 0; i < m_ui.ClientNameComboBox->count() && !bExists; i++) bExists = (sClient == m_ui.ClientNameComboBox->itemText(i)); if (!bExists) { m_ui.ClientNameComboBox->addItem(icon, sClient); bExists = true; } } } } } #endif // CONFIG_ALSA_SEQ } // Socket type change slot. void qjackctlSocketForm::socketTypeChanged (void) { if (m_ppPixmaps == nullptr) return; if (m_pSocketList == nullptr) return; const bool bBlockSignals = m_ui.ClientNameComboBox->blockSignals(true); const QString sOldClientName = m_ui.ClientNameComboBox->currentText(); m_ui.ClientNameComboBox->clear(); QPixmap *pXpmSocket = nullptr; QPixmap *pXpmPlug = nullptr; const bool bReadable = m_pSocketList->isReadable(); const int iSocketType = m_pSocketTypeButtonGroup->checkedId(); switch (iSocketType) { case 0: // QJACKCTL_SOCKETTYPE_JACK_AUDIO if (m_ui.ExclusiveCheckBox->isChecked()) pXpmSocket = m_ppPixmaps[QJACKCTL_XPM_AUDIO_SOCKET_X]; else pXpmSocket = m_ppPixmaps[QJACKCTL_XPM_AUDIO_SOCKET]; m_ui.SocketTabWidget->setTabIcon(0, QIcon(*pXpmSocket)); pXpmPlug = m_ppPixmaps[QJACKCTL_XPM_AUDIO_PLUG]; updateJackClients(QJACKCTL_SOCKETTYPE_JACK_AUDIO); break; case 1: // QJACKCTL_SOCKETTYPE_JACK_MIDI if (m_ui.ExclusiveCheckBox->isChecked()) pXpmSocket = m_ppPixmaps[QJACKCTL_XPM_MIDI_SOCKET_X]; else pXpmSocket = m_ppPixmaps[QJACKCTL_XPM_MIDI_SOCKET]; m_ui.SocketTabWidget->setTabIcon(0, QIcon(*pXpmSocket)); pXpmPlug = m_ppPixmaps[QJACKCTL_XPM_MIDI_PLUG]; updateJackClients(QJACKCTL_SOCKETTYPE_JACK_MIDI); break; case 2: // QJACKCTL_SOCKETTYPE_ALSA_MIDI if (m_ui.ExclusiveCheckBox->isChecked()) pXpmSocket = m_ppPixmaps[QJACKCTL_XPM_MIDI_SOCKET_X]; else pXpmSocket = m_ppPixmaps[QJACKCTL_XPM_MIDI_SOCKET]; m_ui.SocketTabWidget->setTabIcon(0, QIcon(*pXpmSocket)); pXpmPlug = m_ppPixmaps[QJACKCTL_XPM_MIDI_PLUG]; updateAlsaClients(QJACKCTL_SOCKETTYPE_ALSA_MIDI); break; } const int iOldSocketNameChanged = m_iSocketNameChanged++; m_ui.ClientNameComboBox->setEditText(sOldClientName); clientNameChanged(); m_iSocketNameChanged = iOldSocketNameChanged; if (pXpmPlug) { const int iItemCount = m_ui.PlugListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = m_ui.PlugListView->topLevelItem(iItem); pItem->setIcon(0, QIcon(*pXpmPlug)); } } // Now the socket forward list... m_ui.SocketForwardComboBox->clear(); m_ui.SocketForwardComboBox->addItem(tr("(None)")); if (!bReadable) { QListIterator iter(m_pSocketList->sockets()); while (iter.hasNext()) { qjackctlSocketItem *pSocketItem = iter.next(); if (pSocketItem->socketType() == iSocketType && pSocketItem->socketName() != m_ui.SocketNameLineEdit->text()) { switch (iSocketType) { case 0: // QJACKCTL_SOCKETTYPE_JACK_AUDIO if (pSocketItem->isExclusive()) pXpmSocket = m_ppPixmaps[QJACKCTL_XPM_AUDIO_SOCKET_X]; else pXpmSocket = m_ppPixmaps[QJACKCTL_XPM_AUDIO_SOCKET]; break; case 1: // QJACKCTL_SOCKETTYPE_JACK_MIDI case 2: // QJACKCTL_SOCKETTYPE_ALSA_MIDI if (pSocketItem->isExclusive()) pXpmSocket = m_ppPixmaps[QJACKCTL_XPM_MIDI_SOCKET_X]; else pXpmSocket = m_ppPixmaps[QJACKCTL_XPM_MIDI_SOCKET]; break; } m_ui.SocketForwardComboBox->addItem( QIcon(*pXpmSocket), pSocketItem->socketName()); } } } const bool bEnabled = (m_ui.SocketForwardComboBox->count() > 1); m_ui.SocketForwardTextLabel->setEnabled(bEnabled); m_ui.SocketForwardComboBox->setEnabled(bEnabled); m_ui.ClientNameComboBox->blockSignals(bBlockSignals); } // Socket name change slot. void qjackctlSocketForm::socketNameChanged (void) { ++m_iSocketNameChanged; changed(); } // JACK client plugs refreshner. void qjackctlSocketForm::updateJackPlugs ( int iSocketType ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return; const char *pszJackPortType = JACK_DEFAULT_AUDIO_TYPE; int iPixmap = QJACKCTL_XPM_AUDIO_PLUG; #ifdef CONFIG_JACK_MIDI if (iSocketType == QJACKCTL_SOCKETTYPE_JACK_MIDI) { pszJackPortType = JACK_DEFAULT_MIDI_TYPE; iPixmap = QJACKCTL_XPM_MIDI_PLUG; } #endif const QString sClientName = m_ui.ClientNameComboBox->currentText(); if (sClientName.isEmpty()) return; QRegularExpression rxClientName(EXACT_PATTERN(sClientName)); const bool bReadable = m_pSocketList->isReadable(); const QIcon icon(*m_ppPixmaps[iPixmap]); const char **ppszClientPorts = jack_get_ports( pJackClient, nullptr, pszJackPortType, (bReadable ? JackPortIsOutput : JackPortIsInput)); if (ppszClientPorts) { int iClientPort = 0; while (ppszClientPorts[iClientPort]) { const QString sClientPort = QString::fromUtf8(ppszClientPorts[iClientPort]); const int iColon = sClientPort.indexOf(':'); if (iColon >= 0 && rxClientName.match(sClientPort.left(iColon)).hasMatch()) { const QString sPort = qjackctlAliasItem::escapeRegExpDigits( sClientPort.right(sClientPort.length() - iColon - 1)); if (m_ui.PlugListView->findItems(sPort, Qt::MatchExactly).isEmpty()) m_ui.PlugNameComboBox->addItem(icon, sPort); } ++iClientPort; } jack_free(ppszClientPorts); } } // ALSA client plugs refreshner. void qjackctlSocketForm::updateAlsaPlugs ( int iSocketType ) { if (iSocketType != QJACKCTL_SOCKETTYPE_ALSA_MIDI) return; #ifdef CONFIG_ALSA_SEQ qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; snd_seq_t *pAlsaSeq = pMainForm->alsaSeq(); if (pAlsaSeq == nullptr) return; const QString sClientName = m_ui.ClientNameComboBox->currentText(); if (sClientName.isEmpty()) return; QRegularExpression rxClientName(EXACT_PATTERN(sClientName)); const bool bReadable = m_pSocketList->isReadable(); const QIcon icon(*m_ppPixmaps[QJACKCTL_XPM_MIDI_PLUG]); // Fill sequencer plugs... snd_seq_client_info_t *pClientInfo; snd_seq_port_info_t *pPortInfo; unsigned int uiAlsaFlags; if (bReadable) uiAlsaFlags = SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; else uiAlsaFlags = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; snd_seq_client_info_alloca(&pClientInfo); snd_seq_port_info_alloca(&pPortInfo); snd_seq_client_info_set_client(pClientInfo, -1); while (snd_seq_query_next_client(pAlsaSeq, pClientInfo) >= 0) { const int iAlsaClient = snd_seq_client_info_get_client(pClientInfo); const QString sClient = QString::fromUtf8( snd_seq_client_info_get_name(pClientInfo)); if (iAlsaClient > 0 && rxClientName.match(sClient).hasMatch()) { snd_seq_port_info_set_client(pPortInfo, iAlsaClient); snd_seq_port_info_set_port(pPortInfo, -1); while (snd_seq_query_next_port(pAlsaSeq, pPortInfo) >= 0) { const unsigned int uiPortCapability = snd_seq_port_info_get_capability(pPortInfo); if (((uiPortCapability & uiAlsaFlags) == uiAlsaFlags) && ((uiPortCapability & SND_SEQ_PORT_CAP_NO_EXPORT) == 0)) { const QString sPort = qjackctlAliasItem::escapeRegExpDigits( QString::fromUtf8(snd_seq_port_info_get_name(pPortInfo))); if (m_ui.PlugListView->findItems(sPort, Qt::MatchExactly).isEmpty()) m_ui.PlugNameComboBox->addItem(icon, sPort); } } } } #endif // CONFIG_ALSA_SEQ } // Update client list if available. void qjackctlSocketForm::clientNameChanged (void) { if (m_ppPixmaps == nullptr) return; if (m_pSocketList == nullptr) return; m_ui.PlugNameComboBox->clear(); const int iSocketType = m_pSocketTypeButtonGroup->checkedId(); switch (iSocketType) { case 0: updateJackPlugs(QJACKCTL_SOCKETTYPE_JACK_AUDIO); break; case 1: updateJackPlugs(QJACKCTL_SOCKETTYPE_JACK_MIDI); break; case 2: updateAlsaPlugs(QJACKCTL_SOCKETTYPE_ALSA_MIDI); break; } if (m_iSocketNameChanged < 1) { // Find a new distinguishable socket name, please. QString sSocketName = m_ui.ClientNameComboBox->currentText(); if (!sSocketName.isEmpty()) { int iSocketNo = 0; QString sSocketMask = sSocketName; sSocketMask.remove(QRegularExpression("[ |0-9]+$")).append(" %1"); do { sSocketName = sSocketMask.arg(++iSocketNo); } while (m_pSocketList->findSocket(sSocketName, iSocketType)); m_ui.SocketNameLineEdit->setText(sSocketName); m_iSocketNameChanged = 0; } } changed(); } // end of qjackctlSocketForm.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlPaletteForm.h0000644000000000000000000000013214771215054017273 xustar0030 mtime=1743067692.326636579 30 atime=1743067692.326636579 30 ctime=1743067692.326636579 qjackctl-1.0.4/src/qjackctlPaletteForm.h0000644000175000001440000001703014771215054017264 0ustar00rncbcusers// qjackctlPaletteForm.h // /**************************************************************************** Copyright (C) 2005-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlPaletteForm_h #define __qjackctlPaletteForm_h #include #include #include #include #include #include // Forward decls. class QListView; class QLabel; class QToolButton; //------------------------------------------------------------------------- // qjackctlPaletteForm namespace Ui { class qjackctlPaletteForm; } class qjackctlPaletteForm: public QDialog { Q_OBJECT public: qjackctlPaletteForm(QWidget *parent = nullptr, const QPalette& pal = QPalette()); virtual ~qjackctlPaletteForm(); void setPalette(const QPalette& pal); const QPalette& palette() const; void setSettings(QSettings *settings, bool owner = false); QSettings *settings() const; void setPaletteName(const QString& name); QString paletteName() const; bool isDirty() const; static bool namedPalette(QSettings *settings, const QString& name, QPalette& pal, bool fixup = false); static QStringList namedPaletteList(QSettings *settings); static QString namedPaletteConf( QSettings *settings, const QString& name); static void addNamedPaletteConf( QSettings *settings, const QString& name, const QString& filename); static QPalette::ColorRole colorRole(const QString& name); class PaletteModel; class ColorDelegate; class ColorButton; class ColorEditor; class RoleEditor; protected slots: void nameComboChanged(const QString& name); void saveButtonClicked(); void deleteButtonClicked(); void generateButtonChanged(); void resetButtonClicked(); void detailsCheckClicked(); void importButtonClicked(); void exportButtonClicked(); void paletteChanged(const QPalette& pal); void accept(); void reject(); protected: void setPalette(const QPalette& pal, const QPalette& parentPal); bool namedPalette(const QString& name, QPalette& pal) const; QStringList namedPaletteList() const; QString namedPaletteConf(const QString& name) const; void addNamedPaletteConf(const QString& name, const QString& filename); void deleteNamedPaletteConf(const QString& name); static bool loadNamedPaletteConf( const QString& name, const QString& filename, QPalette& pal); static bool saveNamedPaletteConf( const QString& name, const QString& filename, const QPalette& pal); static bool loadNamedPalette( QSettings *settings, const QString& name, QPalette& pal); static bool saveNamedPalette( QSettings *settings, const QString& name, const QPalette& pal); void updateNamedPaletteList(); void updateGenerateButton(); void updateDialogButtons(); void setDefaultDir(const QString& dir); QString defaultDir() const; void setShowDetails(bool on); bool isShowDetails() const; void showEvent(QShowEvent *event); void resizeEvent(QResizeEvent *event); private: Ui::qjackctlPaletteForm *p_ui; Ui::qjackctlPaletteForm& m_ui; QSettings *m_settings; bool m_owner; QPalette m_palette; QPalette m_parentPalette; PaletteModel *m_paletteModel; bool m_modelUpdated; bool m_paletteUpdated; int m_dirtyCount; int m_dirtyTotal; }; //------------------------------------------------------------------------- // qjackctlPaletteForm::PaletteModel class qjackctlPaletteForm::PaletteModel : public QAbstractTableModel { Q_OBJECT Q_PROPERTY(QPalette::ColorRole colorRole READ colorRole) public: PaletteModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role) const; bool setData(const QModelIndex &index, const QVariant &value, int role); Qt::ItemFlags flags(const QModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; void setPalette(const QPalette &palette, const QPalette &parentPalette); const QPalette& palette() const; void setGenerate(bool on) { m_generate = on; } QPalette::ColorRole colorRole() const { return QPalette::NoRole; } signals: void paletteChanged(const QPalette &palette); protected: QPalette::ColorGroup columnToGroup(int index) const; int groupToColumn(QPalette::ColorGroup group) const; private: QPalette m_palette; QPalette m_parentPalette; QMap m_roleNames; int m_nrows; bool m_generate; }; //------------------------------------------------------------------------- // qjackctlPaletteForm::ColorDelegate class qjackctlPaletteForm::ColorDelegate : public QItemDelegate { public: ColorDelegate(QObject *parent = nullptr) : QItemDelegate(parent) {} QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; void setEditorData(QWidget *editor, const QModelIndex& index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem& option, const QModelIndex &index) const; virtual void paint(QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; }; //------------------------------------------------------------------------- // qjackctlPaletteForm::ColorButton class qjackctlPaletteForm::ColorButton : public QPushButton { Q_OBJECT Q_PROPERTY(QBrush brush READ brush WRITE setBrush) public: ColorButton (QWidget *parent = nullptr); const QBrush& brush() const; void setBrush(const QBrush& b); signals: void changed(); protected slots: void chooseColor(); protected: void paintEvent(QPaintEvent *event); private: QBrush m_brush; }; //------------------------------------------------------------------------- // PaleteEditor::ColorEditor class qjackctlPaletteForm::ColorEditor : public QWidget { Q_OBJECT public: ColorEditor(QWidget *parent = nullptr); void setColor(const QColor &color); QColor color() const; bool changed() const; signals: void changed(QWidget *widget); protected slots: void colorChanged(); private: qjackctlPaletteForm::ColorButton *m_button; bool m_changed; }; //------------------------------------------------------------------------- // PaleteEditor::RoleEditor class qjackctlPaletteForm::RoleEditor : public QWidget { Q_OBJECT public: RoleEditor(QWidget *parent = nullptr); void setLabel(const QString &label); void setEdited(bool on); bool edited() const; signals: void changed(QWidget *widget); protected slots: void resetProperty(); private: QLabel *m_label; QToolButton *m_button; bool m_edited; }; #endif // __qjackctlPaletteForm_h // end of qjackctlPaletteForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlMainForm.h0000644000000000000000000000013214771215054016561 xustar0030 mtime=1743067692.326636579 30 atime=1743067692.326636579 30 ctime=1743067692.326636579 qjackctl-1.0.4/src/qjackctlMainForm.h0000644000175000001440000002334214771215054016555 0ustar00rncbcusers// qjackctlMainForm.h // /**************************************************************************** Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlMainForm_h #define __qjackctlMainForm_h #include "ui_qjackctlMainForm.h" #include "qjackctlSetup.h" #include #include #include #include #include #include #ifdef CONFIG_ALSA_SEQ #include #else typedef void snd_seq_t; #endif // Forward declarations. class qjackctlSetup; class qjackctlSetupForm; class qjackctlMessagesStatusForm; class qjackctlSessionForm; class qjackctlConnectionsForm; class qjackctlPatchbayForm; class qjackctlPatchbayRack; class qjackctlGraphForm; class qjackctlGraphPort; class qjackctlPortItem; #ifdef CONFIG_SYSTEM_TRAY class qjackctlSystemTray; #endif class QSocketNotifier; class QSessionManager; #ifdef CONFIG_DBUS class QDBusInterface; class qjackctlDBusLogWatcher; #endif //---------------------------------------------------------------------------- // qjackctlMainForm -- UI wrapper form. class qjackctlMainForm : public QWidget { Q_OBJECT public: // Constructor. qjackctlMainForm(QWidget *pParent = nullptr, Qt::WindowFlags wflags = Qt::WindowFlags()); // Destructor. ~qjackctlMainForm(); static qjackctlMainForm *getInstance(); bool setup(qjackctlSetup *pSetup); qjackctlSetup *setup() const; jack_client_t *jackClient() const; snd_seq_t *alsaSeq() const; void appendMessages(const QString& s); bool isActivePatchbay(const QString& sPatchbayPath) const; void updateActivePatchbay(); void setActivePatchbay(const QString& sPatchbayPath); void setRecentPatchbays(const QStringList& patchbays); void stabilizeForm(); void stabilizeFormEx(); void stabilize(int msecs); void refreshXrunStats(); void refreshJackConnections(bool bClear = false); void refreshAlsaConnections(bool bClear = false); void refreshPatchbay(); void queryDisconnect( qjackctlGraphPort *port1, qjackctlGraphPort *port2); void queryDisconnect( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort, int iSocketType); void updateMessagesFont(); void updateMessagesLimit(); void updateMessagesLogging(); void updateConnectionsFont(); void updateConnectionsIconSize(); void updateJackClientPortAlias(); void updateJackClientPortMetadata(); void updateDisplayEffect(); void updateTimeDisplayFonts(); void updateTimeDisplayToolTips(); void updateAliases(); void updateButtons(); void updatePalette(); #ifdef CONFIG_DBUS void updateJackDBus(); #endif #ifdef CONFIG_SYSTEM_TRAY void updateSystemTray(); #endif void showDirtySetupWarning(); // Some settings that are special someway... bool resetBuffSize(jack_nframes_t nframes); // Restart JACk audio service. void restartJack(); #ifdef CONFIG_DBUS QStringList getDBusEngineDrivers(); #endif // Whether detached as client only. bool isJackDetach() const; public slots: void startJack(); void stopJack(); void toggleJack(); void showSetupForm(); void showAboutForm(); void resetXrunStats(); void commitData(QSessionManager& sm); void activatePreset(const QString&); void activatePatchbay(const QString&); protected slots: void readStdout(); void jackStarted(); void jackError(QProcess::ProcessError); void jackFinished(); void jackCleanup(); void jackStabilize(); void stdoutNotifySlot(int); void sigtermNotifySlot(int); void alsaNotifySlot(int); void timerSlot(); void jackConnectChanged(); void alsaConnectChanged(); void cableConnectSlot(const QString&, const QString&, unsigned int); void toggleMainForm(); void toggleMessagesStatusForm(); void toggleMessagesForm(); void toggleStatusForm(); void toggleSessionForm(); void toggleConnectionsForm(); void togglePatchbayForm(); void toggleGraphForm(); void transportRewind(); void transportBackward(); void transportPlay(bool); void transportStart(); void transportStop(); void transportForward(); void activatePresetsMenu(QAction *); void activatePreset(int); void quitMainForm(); protected: bool queryClose(); bool queryClosePreset(); bool queryRestart(); bool queryShutdown(); void showEvent(QShowEvent *pShowEvent); void hideEvent(QHideEvent *pHideEvent); void closeEvent(QCloseEvent *pCloseEvent); void resizeEvent(QResizeEvent *pResizeEvent); void customEvent(QEvent *pEvent); void appendStdoutBuffer(const QString& s); void processStdoutBuffer(); void flushStdoutBuffer(); bool stdoutBlock(int fd, bool bBlock) const; QString formatExitStatus(int iExitStatus) const; void shellExecute(const QString& sShellCommand, const QString& sStartMessage, const QString& sStopMessage); void stopJackServer(); QString& detectXrun(QString& s); void updateXrunStats(float fXrunLast); void appendMessagesColor(const QString& s, const QColor& rgb); void appendMessagesText(const QString& s); void appendMessagesError(const QString& s); void updateXrunCount(); QString formatTime(float secs) const; QString formatElapsedTime(int iStatusItem, const QTime& time, const QElapsedTimer& timer) const; void updateElapsedTimes(); void updateContextMenu(); void portNotifyEvent(); void xrunNotifyEvent(); void buffNotifyEvent(); void shutNotifyEvent(); void freeNotifyEvent(); void exitNotifyEvent(); #ifdef CONFIG_JACK_METADATA void propNotifyEvent(); #endif void startJackClientDelay(); bool startJackClient(bool bDetach); void stopJackClient(); void refreshConnections(); void refreshStatus(); void updateStatusItem(int iStatusItem, const QString& sText); void updateTitleStatus(); void updateServerState(int iState); void contextMenuEvent(QContextMenuEvent *); void mousePressEvent(QMouseEvent *pMouseEvent); void queryDisconnect( const QString& sOClientName, const QString& sOPortName, const QString& sIClientName, const QString& sIPortName, int iSocketType); #ifdef CONFIG_DBUS // D-BUS: Set/reset parameter values // from current selected preset options. void setDBusParameters(const qjackctlPreset& preset); // D-BUS: Set parameter values (with reset option). bool setDBusEngineParameter( const QString& param, const QVariant& value, bool bSet = true); bool setDBusDriverParameter( const QString& param, const QVariant& value, bool bSet = true); bool setDBusParameter( const QStringList& path, const QVariant& value, bool bSet = true); // D-BUS: Reset parameter (to default) values. bool resetDBusEngineParameter(const QString& param); bool resetDBusDriverParameter(const QString& param); bool resetDBusParameter(const QStringList& path); // D-BUS: Get preset options // from current parameter values. bool getDBusParameters(qjackctlPreset& preset); // D-BUS: Get parameter values. QVariant getDBusEngineParameter(const QString& param); QVariant getDBusDriverParameter(const QString& param); QVariant getDBusParameter(const QStringList& path); QStringList getDBusParameterValues(const QStringList& path); #endif // Quotes string with embedded whitespace. QString formatQuoted(const QString& s) const; // Guarded transport play/pause toggle. void transportPlayStatus(bool bOn); private: // The Qt-designer UI struct... Ui::qjackctlMainForm m_ui; // Instance variables. qjackctlSetup *m_pSetup; QProcess *m_pJack; int m_iServerState; jack_client_t *m_pJackClient; bool m_bJackDetach; bool m_bJackShutdown; bool m_bJackRestart; snd_seq_t *m_pAlsaSeq; #ifdef CONFIG_DBUS QDBusInterface *m_pDBusControl; QDBusInterface *m_pDBusConfig; qjackctlDBusLogWatcher *m_pDBusLogWatcher; bool m_bDBusStarted; bool m_bDBusDetach; #endif #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) bool m_bJackKilled; #endif int m_iStartDelay; int m_iTimerDelay; int m_iTimerRefresh; int m_iJackRefresh; int m_iAlsaRefresh; int m_iJackDirty; int m_iAlsaDirty; int m_iStatusBlink; int m_iStatusRefresh; int m_iPatchbayRefresh; int m_iJackRefreshClear; int m_iAlsaRefreshClear; QSocketNotifier *m_pStdoutNotifier; QSocketNotifier *m_pSigtermNotifier; QSocketNotifier *m_pAlsaNotifier; int m_iXrunCallbacks; int m_iXrunSkips; int m_iXrunStats; int m_iXrunCount; float m_fXrunTotal; float m_fXrunMax; float m_fXrunMin; float m_fXrunLast; QTime m_timeXrunLast; QTime m_timeResetLast; QElapsedTimer m_timerXrunLast; QElapsedTimer m_timerResetLast; qjackctlMessagesStatusForm *m_pMessagesStatusForm; qjackctlSessionForm *m_pSessionForm; qjackctlConnectionsForm *m_pConnectionsForm; qjackctlPatchbayForm *m_pPatchbayForm; qjackctlGraphForm *m_pGraphForm; qjackctlSetupForm *m_pSetupForm; qjackctlPatchbayRack *m_pPatchbayRack; qjackctlPreset m_preset; QString m_sStdoutBuffer; QString m_sJackCmdLine; #ifdef CONFIG_SYSTEM_TRAY qjackctlSystemTray *m_pSystemTray; bool m_bQuitClose; #endif bool m_bQuitForce; float m_fSkipAccel; int m_iTransportPlay; // Common context menu. QMenu m_menu; int m_iMenuRefresh; // Kind-of singleton reference. static qjackctlMainForm *g_pMainForm; }; #endif // __qjackctlMainForm_h // end of qjackctlMainForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlPatchbay.h0000644000000000000000000000012714771215054016610 xustar0029 mtime=1743067692.32863657 29 atime=1743067692.32863657 29 ctime=1743067692.32863657 qjackctl-1.0.4/src/qjackctlPatchbay.h0000644000175000001440000002632514771215054016604 0ustar00rncbcusers// qjackctlPatchbay.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlPatchbay_h #define __qjackctlPatchbay_h #include #include // Our external patchbay models. #include "qjackctlPatchbayRack.h" // QListViewItem::rtti return values. #define QJACKCTL_SOCKETITEM 2001 #define QJACKCTL_PLUGITEM 2002 // Forward declarations. class qjackctlPlugItem; class qjackctlSocketItem; class qjackctlSocketList; class qjackctlSocketListView; class qjackctlPatchworkView; class qjackctlPatchbayView; class qjackctlPatchbay; // Pixmap-set indexes. #define QJACKCTL_XPM_AUDIO_SOCKET 0 #define QJACKCTL_XPM_AUDIO_SOCKET_X 1 #define QJACKCTL_XPM_AUDIO_CLIENT 2 #define QJACKCTL_XPM_AUDIO_PLUG 3 #define QJACKCTL_XPM_MIDI_SOCKET 4 #define QJACKCTL_XPM_MIDI_SOCKET_X 5 #define QJACKCTL_XPM_MIDI_CLIENT 6 #define QJACKCTL_XPM_MIDI_PLUG 7 #define QJACKCTL_XPM_PIXMAPS 8 // Patchbay plug (port) list item. class qjackctlPlugItem : public QTreeWidgetItem { public: // Constructor. qjackctlPlugItem(qjackctlSocketItem *pSocket, const QString& sPlugName, qjackctlPlugItem *pPlugAfter); // Default destructor. ~qjackctlPlugItem(); // Instance accessors. const QString& socketName() const; const QString& plugName() const; // Patchbay socket item accessor. qjackctlSocketItem *socket() const; private: // Instance variables. qjackctlSocketItem *m_pSocket; QString m_sPlugName; }; // Patchbay socket (client) list item. class qjackctlSocketItem : public QTreeWidgetItem { public: // Constructor. qjackctlSocketItem(qjackctlSocketList *pSocketList, const QString& sSocketName, const QString& sClientName, int iSocketType,qjackctlSocketItem *pSocketAfter); // Default destructor. ~qjackctlSocketItem(); // Instance accessors. const QString& socketName() const; const QString& clientName() const; int socketType() const; bool isExclusive() const; const QString& forward() const; void setSocketName (const QString& sSocketName); void setClientName (const QString& sClientName); void setSocketType (int iSocketType); void setExclusive (bool bExclusive); void setForward (const QString& sSocketForward); // Socket flags accessor. bool isReadable() const; // Connected plug list primitives. void addConnect(qjackctlSocketItem *pSocket); void removeConnect(qjackctlSocketItem *pSocket); // Connected plug finders. qjackctlSocketItem *findConnectPtr(qjackctlSocketItem *pSocketPtr); // Connection list accessor. const QList& connects() const; // Plug list primitive methods. void addPlug(qjackctlPlugItem *pPlug); void removePlug(qjackctlPlugItem *pPlug); // Plug finder. qjackctlPlugItem *findPlug(const QString& sPlugName); // Plug list accessor. QList& plugs(); // Plug list cleaner. void clear(); // Retrieve a context pixmap. const QPixmap& pixmap(int iPixmap) const; // Update pixmap to its proper context. void updatePixmap(); // Client item openness status. void setOpen(bool bOpen); bool isOpen() const; private: // Instance variables. qjackctlSocketList *m_pSocketList; QString m_sSocketName; QString m_sClientName; int m_iSocketType; bool m_bExclusive; QString m_sSocketForward; // Plug (port) list. QList m_plugs; // Connection cache list. QList m_connects; }; // Patchbay socket (client) list. class qjackctlSocketList : public QObject { Q_OBJECT public: // Constructor. qjackctlSocketList(qjackctlSocketListView *pListView, bool bReadable); // Default destructor. ~qjackctlSocketList(); // Socket list primitive methods. void addSocket(qjackctlSocketItem *pSocket); void removeSocket(qjackctlSocketItem *pSocket); // Socket finder. qjackctlSocketItem *findSocket(const QString& sSocketName, int iSocketType); // List view accessor. qjackctlSocketListView *listView() const; // Socket flags accessor. bool isReadable() const; // Socket aesthetics accessors. const QString& socketCaption() const; // Socket list cleaner. void clear(); // Socket list accessor. QList& sockets(); // Find the current selected socket item in list. qjackctlSocketItem *selectedSocketItem() const; // Retrieve a context pixmap. const QPixmap& pixmap(int iPixmap) const; public slots: // Socket item interactivity methods. bool addSocketItem(); bool removeSocketItem(); bool editSocketItem(); bool copySocketItem(); bool exclusiveSocketItem(); bool moveUpSocketItem(); bool moveDownSocketItem(); private: // Merge two pixmaps with union of respective masks. QPixmap *createPixmapMerge(const QPixmap& xpmDst, const QPixmap& xpmSrc); // Instance variables. qjackctlSocketListView *m_pListView; bool m_bReadable; QString m_sSocketCaption; QPixmap *m_apPixmaps[QJACKCTL_XPM_PIXMAPS]; QList m_sockets; }; //---------------------------------------------------------------------------- // qjackctlSocketListView -- Socket list view, supporting drag-n-drop. class qjackctlSocketListView : public QTreeWidget { Q_OBJECT public: // Constructor. qjackctlSocketListView(qjackctlPatchbayView *pPatchbayView, bool bReadable); // Default destructor. ~qjackctlSocketListView(); // Patchbay dirty flag accessors. void setDirty (bool bDirty); bool dirty() const; // Auto-open timer methods. void setAutoOpenTimeout(int iAutoOpenTimeout); int autoOpenTimeout() const; protected slots: // Auto-open timeout slot. void timeoutSlot(); protected: // Trap for help/tool-tip events. bool eventFilter(QObject *pObject, QEvent *pEvent); // Drag-n-drop stuff. QTreeWidgetItem *dragDropItem(const QPoint& pos); // Drag-n-drop stuff -- reimplemented virtual methods. void dragEnterEvent(QDragEnterEvent *pDragEnterEvent); void dragMoveEvent(QDragMoveEvent *pDragMoveEvent); void dragLeaveEvent(QDragLeaveEvent *); void dropEvent(QDropEvent *pDropEvent); // Handle mouse events for drag-and-drop stuff. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); // Context menu request event handler. void contextMenuEvent(QContextMenuEvent *); private: // Bindings. qjackctlPatchbayView *m_pPatchbayView; bool m_bReadable; // Auto-open timer. int m_iAutoOpenTimeout; QTimer *m_pAutoOpenTimer; // Items we'll eventually drop something. QTreeWidgetItem *m_pDragItem; QTreeWidgetItem *m_pDropItem; // The point from where drag started. QPoint m_posDrag; }; //---------------------------------------------------------------------------- // qjackctlPatchworkView -- Socket plugging connector widget. class qjackctlPatchworkView : public QWidget { Q_OBJECT public: // Constructor. qjackctlPatchworkView(qjackctlPatchbayView *pPatchbayView); // Default destructor. ~qjackctlPatchworkView(); protected slots: // Useful slots (should this be protected?). void contentsChanged(); protected: // Draw visible port connection relation arrows. void paintEvent(QPaintEvent *); // Context menu request event handler. void contextMenuEvent(QContextMenuEvent *); private: // Legal socket item position helper. int itemY(QTreeWidgetItem *pItem) const; // Drawing methods. void drawForwardLine(QPainter *pPainter, int x, int dx, int y1, int y2, int h); void drawConnectionLine(QPainter *pPainter, int x1, int y1, int x2, int y2, int h1, int h2); // Local instance variables. qjackctlPatchbayView *m_pPatchbayView; }; //---------------------------------------------------------------------------- // qjackctlPatchbayView -- Patchbay integrated widget. class qjackctlPatchbayView : public QSplitter { Q_OBJECT public: // Constructor. qjackctlPatchbayView(QWidget *pParent = 0); // Default destructor. ~qjackctlPatchbayView(); // Widget accesors. qjackctlSocketListView *OListView() { return m_pOListView; } qjackctlSocketListView *IListView() { return m_pIListView; } qjackctlPatchworkView *PatchworkView() { return m_pPatchworkView; } // Patchbay object binding methods. void setBinding(qjackctlPatchbay *pPatchbay); qjackctlPatchbay *binding() const; // Socket list accessors. qjackctlSocketList *OSocketList() const; qjackctlSocketList *ISocketList() const; // Patchbay dirty flag accessors. void setDirty (bool bDirty); bool dirty() const; signals: // Contents change signal. void contentsChanged(); public slots: // Common context menu slots. void contextMenu(const QPoint& pos, qjackctlSocketList *pSocketList); void activateForwardMenu(QAction *); private: // Child controls. qjackctlSocketListView *m_pOListView; qjackctlSocketListView *m_pIListView; qjackctlPatchworkView *m_pPatchworkView; // The main binding object. qjackctlPatchbay *m_pPatchbay; // The obnoxious dirty flag. bool m_bDirty; }; //---------------------------------------------------------------------------- // qjackctlPatchbay -- Patchbay integrated object. class qjackctlPatchbay : public QObject { Q_OBJECT public: // Constructor. qjackctlPatchbay(qjackctlPatchbayView *pPatchbayView); // Default destructor. ~qjackctlPatchbay(); // Explicit connection tests. bool canConnectSelected(); bool canDisconnectSelected(); bool canDisconnectAll(); // Socket list accessors. qjackctlSocketList *OSocketList() const; qjackctlSocketList *ISocketList() const; // External rack transfer methods. void loadRack(qjackctlPatchbayRack *pPatchbayRack); void saveRack(qjackctlPatchbayRack *pPatchbayRack); public slots: // Complete contents refreshner. void refresh(); // Explicit connection slots. bool connectSelected(); bool disconnectSelected(); bool disconnectAll(); // Expand all socket items. void expandAll(); // Complete patchbay clearer. void clear(); // Do actual and complete connections snapshot. void connectionsSnapshot(); private: // Internal rack transfer methods. void loadRackSockets (qjackctlSocketList *pSocketList, QList& socketlist); void saveRackSockets (qjackctlSocketList *pSocketList, QList& socketlist); // Connect/Disconnection primitives. void connectSockets(qjackctlSocketItem *pOSocket, qjackctlSocketItem *pISocket); void disconnectSockets(qjackctlSocketItem *pOSocket, qjackctlSocketItem *pISocket); // Instance variables. qjackctlPatchbayView *m_pPatchbayView; qjackctlSocketList *m_pOSocketList; qjackctlSocketList *m_pISocketList; }; #endif // __qjackctlPatchbay_h // end of qjackctlPatchbay.h qjackctl-1.0.4/src/PaxHeaders/qjackctlGraphCommand.h0000644000000000000000000000013214771215054017411 xustar0030 mtime=1743067692.325636584 30 atime=1743067692.324636588 30 ctime=1743067692.325636584 qjackctl-1.0.4/src/qjackctlGraphCommand.h0000644000175000001440000001172314771215054017405 0ustar00rncbcusers// qjackctlGraphCommand.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlGraphCommand_h #define __qjackctlGraphCommand_h #include "qjackctlGraph.h" #include #include #include //---------------------------------------------------------------------------- // qgraph1_command -- Generic graph command pattern class qjackctlGraphCommand : public QUndoCommand { public: // Constructor. qjackctlGraphCommand(qjackctlGraphCanvas *canvas, QUndoCommand *parent = nullptr); // Accessors. qjackctlGraphCanvas *canvas() const { return m_canvas; } // Command methods. void undo(); void redo(); protected: // Command executive method. virtual bool execute(bool is_undo = false) = 0; private: // Command arguments. qjackctlGraphCanvas *m_canvas; }; //---------------------------------------------------------------------------- // qjackctlGraphConnectCommand -- Connect graph command class qjackctlGraphConnectCommand : public qjackctlGraphCommand { public: // Constructor. qjackctlGraphConnectCommand(qjackctlGraphCanvas *canvas, qjackctlGraphPort *port1, qjackctlGraphPort *port2, bool is_connect, qjackctlGraphCommand *parent = nullptr); protected: // Command item address struct Addr { // Constructors. Addr(qjackctlGraphPort *port) { qjackctlGraphNode *node = port->portNode(); node_name = node->nodeName(); node_type = node->nodeType(); port_name = port->portName(); port_type = port->portType(); } // Copy constructor. Addr(const Addr& addr) { node_name = addr.node_name; node_type = addr.node_type; port_name = addr.port_name; port_type = addr.port_type; } // Member fields. QString node_name; uint node_type; QString port_name; uint port_type; }; // Command item descriptor struct Item { // Constructor. Item(qjackctlGraphPort *port1, qjackctlGraphPort *port2, bool is_connect) : addr1(port1), addr2(port2), m_connect(is_connect) {} // Copy constructor. Item(const Item& item) : addr1(item.addr1), addr2(item.addr2), m_connect(item.is_connect()) {} // Accessors. bool is_connect() const { return m_connect; } // Public member fields. Addr addr1; Addr addr2; private: // Private member fields. bool m_connect; }; // Command executive method. bool execute(bool is_undo); private: // Command arguments. Item m_item; }; //---------------------------------------------------------------------------- // qjackctlGraphMoveCommand -- Move (node) graph command class qjackctlGraphMoveCommand : public qjackctlGraphCommand { public: // Constructor. qjackctlGraphMoveCommand(qjackctlGraphCanvas *canvas, const QList& nodes, const QPointF& pos1, const QPointF& pos2, qjackctlGraphCommand *parent = nullptr); // Destructor. ~qjackctlGraphMoveCommand(); // Add/replace (an already moved) node position for undo/redo... void addItem(qjackctlGraphNode *node, const QPointF& pos1, const QPointF& pos2); protected: // Command item descriptor struct Item { QString node_name; qjackctlGraphItem::Mode node_mode; uint node_type; QPointF node_pos1; QPointF node_pos2; }; // Command executive method. bool execute(bool is_undo); private: // Command arguments. QHash m_items; int m_nexec; }; //---------------------------------------------------------------------------- // qjackctlGraphRenameCommand -- Rename (item) graph command class qjackctlGraphRenameCommand : public qjackctlGraphCommand { public: // Constructor. qjackctlGraphRenameCommand(qjackctlGraphCanvas *canvas, qjackctlGraphItem *item, const QString& name, qjackctlGraphCommand *parent = nullptr); protected: // Command item descriptor struct Item { int item_type; QString node_name; qjackctlGraphItem::Mode node_mode; uint node_type; QString port_name; qjackctlGraphItem::Mode port_mode; uint port_type; }; // Command executive method. bool execute(bool is_undo); private: // Command arguments. Item m_item; QString m_name; }; #endif // __qjackctlGraphCommand_h // end of qjackctlGraphCommand.h qjackctl-1.0.4/src/PaxHeaders/qjackctlAboutForm.h0000644000000000000000000000013214771215054016747 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlAboutForm.h0000644000175000001440000000277714771215054016754 0ustar00rncbcusers// qjackctlAboutForm.h // /**************************************************************************** Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlAboutForm_h #define __qjackctlAboutForm_h #include "ui_qjackctlAboutForm.h" //---------------------------------------------------------------------------- // qjackctlAboutForm -- UI wrapper form. class qjackctlAboutForm : public QDialog { Q_OBJECT public: // Constructor. qjackctlAboutForm(QWidget *pParent = nullptr); // Destructor. ~qjackctlAboutForm(); public slots: void aboutQt(); private: // The Qt-designer UI struct... Ui::qjackctlAboutForm m_ui; }; #endif // __qjackctlAboutForm_h // end of qjackctlAboutForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlPatchbayRack.cpp0000644000000000000000000000012714771215054017744 xustar0029 mtime=1743067692.32863657 29 atime=1743067692.32863657 29 ctime=1743067692.32863657 qjackctl-1.0.4/src/qjackctlPatchbayRack.cpp0000644000175000001440000013510014771215054017730 0ustar00rncbcusers// qjackctlPatchbayRack.cpp // /**************************************************************************** Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlPatchbayRack.h" // Aliases accessors. #include "qjackctlAliases.h" #include // QRegularExpression exact match pattern wrapper. #if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) #define EXACT_PATTERN(s) ('^' + s + '$') #else #define EXACT_PATTERN(s) QRegularExpression::anchoredPattern(s) #endif //---------------------------------------------------------------------- // class qjackctlPatchbaySnapshot -- Patchbay snapshot infrastructure. // #include class qjackctlPatchbaySnapshot { public: // Constructor. qjackctlPatchbaySnapshot() {} // Cleanup. void clear() { m_hash.clear(); } // Prepare/add snapshot connection item. void append ( const QString& sOClientName, const QString& sOPortName, const QString& sIClientName, const QString& sIPortName ) { Ports& ports = m_hash[sOClientName + ':' + sIClientName]; ports.outs.append(sOPortName); ports.ins.append(sIPortName); } // Commit snapshot into patchbay rack. void commit ( qjackctlPatchbayRack *pRack, int iSocketType ) { QHash::Iterator iter = m_hash.begin(); for ( ; iter != m_hash.end(); ++iter) { const QString& sKey = iter.key(); const QString& sOClient = sKey.section(':', 0, 0); const QString& sIClient = sKey.section(':', 1); Ports& ports = iter.value(); qjackctlPatchbaySocket *pOSocket = get_socket( pRack->osocketlist(), sOClient, ports.outs, iSocketType); qjackctlPatchbaySocket *pISocket = get_socket( pRack->isocketlist(), sIClient, ports.ins, iSocketType); pRack->addCable(new qjackctlPatchbayCable(pOSocket, pISocket)); } m_hash.clear(); } // Find first existing socket. static qjackctlPatchbaySocket *find_socket ( QList& socketlist, const QString& sClientName, int iSocketType ) { QListIterator iter(socketlist); while (iter.hasNext()) { qjackctlPatchbaySocket *pSocket = iter.next(); QRegularExpression rxSocket(EXACT_PATTERN(pSocket->clientName())); if (rxSocket.match(sClientName).hasMatch() && pSocket->type() == iSocketType) { return pSocket; } } return nullptr; } // Add socket plug. static void add_socket ( QList& socketlist, const QString& sClientName, const QString& sPortName, int iSocketType ) { qjackctlPatchbaySocket *pSocket = find_socket(socketlist, sClientName, iSocketType); if (pSocket == nullptr) { pSocket = new qjackctlPatchbaySocket(sClientName, qjackctlAliasItem::escapeRegExpDigits(sClientName), iSocketType); socketlist.append(pSocket); } pSocket->addPlug( qjackctlAliasItem::escapeRegExpDigits(sPortName)); } // Get client socket into rack (socket list). static qjackctlPatchbaySocket *get_socket ( QList& socketlist, const QString& sClientName, const QStringList& ports, int iSocketType ) { int iSocket = 0; qjackctlPatchbaySocket *pSocket = nullptr; QListIterator iter(socketlist); while (iter.hasNext()) { pSocket = iter.next(); QRegularExpression rxSocket(EXACT_PATTERN(pSocket->clientName())); if (rxSocket.match(sClientName).hasMatch() && pSocket->type() == iSocketType) { QStringListIterator plug_iter(pSocket->pluglist()); QStringListIterator port_iter(ports); bool bMatch = true; while (bMatch && plug_iter.hasNext() && port_iter.hasNext()) { const QString& sPlug = plug_iter.next(); const QString& sPort = port_iter.next(); QRegularExpression rxPlug(EXACT_PATTERN(sPlug)); bMatch = (rxPlug.match(sPort).hasMatch()); } if (bMatch) return pSocket; iSocket++; } } QString sSocketName = sClientName; if (iSocket > 0) sSocketName += ' ' + QString::number(iSocket + 1); pSocket = new qjackctlPatchbaySocket(sSocketName, qjackctlAliasItem::escapeRegExpDigits(sClientName), iSocketType); QStringListIterator port_iter(ports); while (port_iter.hasNext()) { pSocket->addPlug( qjackctlAliasItem::escapeRegExpDigits(port_iter.next())); } socketlist.append(pSocket); return pSocket; } private: // Snapshot instance variables. struct Ports { QStringList outs; QStringList ins; }; QHash m_hash; }; //---------------------------------------------------------------------- // class qjackctlPatchbaySocket -- Patchbay socket implementation. // // Constructor. qjackctlPatchbaySocket::qjackctlPatchbaySocket ( const QString& sSocketName, const QString& sClientName, int iSocketType ) { m_sSocketName = sSocketName; m_sClientName = sClientName; m_iSocketType = iSocketType; m_bExclusive = false; m_sSocketForward.clear(); } // Default destructor. qjackctlPatchbaySocket::~qjackctlPatchbaySocket (void) { m_pluglist.clear(); } // Socket property accessors. const QString& qjackctlPatchbaySocket::name (void) const { return m_sSocketName; } const QString& qjackctlPatchbaySocket::clientName (void) const { return m_sClientName; } int qjackctlPatchbaySocket::type (void) const { return m_iSocketType; } bool qjackctlPatchbaySocket::isExclusive (void) const { return m_bExclusive; } const QString& qjackctlPatchbaySocket::forward (void) const { return m_sSocketForward; } // Slot property methods. void qjackctlPatchbaySocket::setName ( const QString& sSocketName ) { m_sSocketName = sSocketName; } void qjackctlPatchbaySocket::setClientName ( const QString& sClientName ) { m_sClientName = sClientName; } void qjackctlPatchbaySocket::setType ( int iSocketType ) { m_iSocketType = iSocketType; } void qjackctlPatchbaySocket::setExclusive ( bool bExclusive ) { m_bExclusive = bExclusive; } void qjackctlPatchbaySocket::setForward ( const QString& sSocketForward ) { m_sSocketForward = sSocketForward; } // Plug list primitive methods. void qjackctlPatchbaySocket::addPlug ( const QString& sPlugName ) { m_pluglist.append(sPlugName); } void qjackctlPatchbaySocket::removePlug ( const QString& sPlugName ) { int iPlug = m_pluglist.indexOf(sPlugName); if (iPlug >= 0) m_pluglist.removeAt(iPlug); } // Plug list accessor. QStringList& qjackctlPatchbaySocket::pluglist (void) { return m_pluglist; } // Simple socket type methods. int qjackctlPatchbaySocket::typeFromText ( const QString& sSocketType ) { int iSocketType = QJACKCTL_SOCKETTYPE_DEFAULT; if (sSocketType == "jack-audio" || sSocketType == "audio") iSocketType = QJACKCTL_SOCKETTYPE_JACK_AUDIO; else if (sSocketType == "jack-midi") iSocketType = QJACKCTL_SOCKETTYPE_JACK_MIDI; else if (sSocketType == "alsa-midi" || sSocketType == "midi") iSocketType = QJACKCTL_SOCKETTYPE_ALSA_MIDI; return iSocketType; } QString qjackctlPatchbaySocket::textFromType ( int iSocketType ) { QString sSocketType; switch (iSocketType) { case QJACKCTL_SOCKETTYPE_JACK_AUDIO: sSocketType = "jack-audio"; break; case QJACKCTL_SOCKETTYPE_JACK_MIDI: sSocketType = "jack-midi"; break; case QJACKCTL_SOCKETTYPE_ALSA_MIDI: sSocketType = "alsa-midi"; break; default: break; } return sSocketType; } //---------------------------------------------------------------------- // class qjackctlPatchbaySlot -- Patchbay socket slot implementation. // // Constructor. qjackctlPatchbaySlot::qjackctlPatchbaySlot ( const QString& sSlotName, int iSlotMode ) { m_pOutputSocket = nullptr; m_pInputSocket = nullptr; m_sSlotName = sSlotName; m_iSlotMode = iSlotMode; } // Default destructor. qjackctlPatchbaySlot::~qjackctlPatchbaySlot (void) { setOutputSocket(nullptr); setInputSocket(nullptr); } // Slot property accessors. const QString& qjackctlPatchbaySlot::name (void) const { return m_sSlotName; } int qjackctlPatchbaySlot::mode (void) const { return m_iSlotMode; } // Slot property methods. void qjackctlPatchbaySlot::setName ( const QString& sSlotName ) { m_sSlotName = sSlotName; } void qjackctlPatchbaySlot::setMode ( int iSlotMode ) { m_iSlotMode = iSlotMode; } // Socket methods. void qjackctlPatchbaySlot::setOutputSocket ( qjackctlPatchbaySocket *pSocket ) { m_pOutputSocket = pSocket; } void qjackctlPatchbaySlot::setInputSocket ( qjackctlPatchbaySocket *pSocket ) { m_pInputSocket = pSocket; } // Socket accessors. qjackctlPatchbaySocket *qjackctlPatchbaySlot::outputSocket (void) const { return m_pOutputSocket; } qjackctlPatchbaySocket *qjackctlPatchbaySlot::inputSocket (void) const { return m_pInputSocket; } //---------------------------------------------------------------------- // class qjackctlPatchbayCable -- Patchbay cable connection implementation. // // Constructor. qjackctlPatchbayCable::qjackctlPatchbayCable ( qjackctlPatchbaySocket *pOutputSocket, qjackctlPatchbaySocket *pInputSocket ) { m_pOutputSocket = pOutputSocket; m_pInputSocket = pInputSocket; } // Default destructor. qjackctlPatchbayCable::~qjackctlPatchbayCable (void) { setOutputSocket(nullptr); setInputSocket(nullptr); } // Socket methods. void qjackctlPatchbayCable::setOutputSocket ( qjackctlPatchbaySocket *pSocket ) { m_pOutputSocket = pSocket; } void qjackctlPatchbayCable::setInputSocket ( qjackctlPatchbaySocket *pSocket ) { m_pInputSocket = pSocket; } // Socket accessors. qjackctlPatchbaySocket *qjackctlPatchbayCable::outputSocket (void) const { return m_pOutputSocket; } qjackctlPatchbaySocket *qjackctlPatchbayCable::inputSocket (void) const { return m_pInputSocket; } //---------------------------------------------------------------------- // class qjackctlPatchbayRack -- Patchbay rack profile implementation. // // Constructor. qjackctlPatchbayRack::qjackctlPatchbayRack (void) { m_pJackClient = nullptr; m_ppszOAudioPorts = nullptr; m_ppszIAudioPorts = nullptr; m_ppszOMidiPorts = nullptr; m_ppszIMidiPorts = nullptr; // MIDI connection persistence cache variables. m_pAlsaSeq = nullptr; } // Default destructor. qjackctlPatchbayRack::~qjackctlPatchbayRack (void) { clear(); } // Common socket list primitive methods. void qjackctlPatchbayRack::addSocket ( QList& socketlist, qjackctlPatchbaySocket *pSocket ) { qjackctlPatchbaySocket *pSocketPtr = findSocket(socketlist, pSocket->name()); if (pSocketPtr) removeSocket(socketlist, pSocketPtr); socketlist.append(pSocket); } void qjackctlPatchbayRack::removeSocket ( QList& socketlist, qjackctlPatchbaySocket *pSocket ) { int iSocket = socketlist.indexOf(pSocket); if (iSocket >= 0) { socketlist.removeAt(iSocket); delete pSocket; } } // Slot list primitive methods. void qjackctlPatchbayRack::addSlot ( qjackctlPatchbaySlot *pSlot ) { qjackctlPatchbaySlot *pSlotPtr = findSlot(pSlot->name()); if (pSlotPtr) removeSlot(pSlotPtr); m_slotlist.append(pSlot); } void qjackctlPatchbayRack::removeSlot ( qjackctlPatchbaySlot *pSlot ) { int iSlot = m_slotlist.indexOf(pSlot); if (iSlot >= 0) { m_slotlist.removeAt(iSlot); delete pSlot; } } // Cable list primitive methods. void qjackctlPatchbayRack::addCable ( qjackctlPatchbayCable *pCable ) { qjackctlPatchbayCable *pCablePtr = findCable(pCable); if (pCablePtr) removeCable(pCablePtr); m_cablelist.append(pCable); } void qjackctlPatchbayRack::removeCable ( qjackctlPatchbayCable *pCable ) { int iCable = m_cablelist.indexOf(pCable); if (iCable >= 0) { m_cablelist.removeAt(iCable); delete pCable; } } // Common socket finders. qjackctlPatchbaySocket *qjackctlPatchbayRack::findSocket ( QList& socketlist, const QString& sSocketName, int iSocketType ) { QListIterator iter(socketlist); while (iter.hasNext()) { qjackctlPatchbaySocket *pSocket = iter.next(); if (sSocketName == pSocket->name() && (iSocketType == QJACKCTL_SOCKETTYPE_DEFAULT || iSocketType == pSocket->type())) return pSocket; } return nullptr; } // Patchbay socket slot finders. qjackctlPatchbaySlot *qjackctlPatchbayRack::findSlot ( const QString& sSlotName ) { QListIterator iter(m_slotlist); while (iter.hasNext()) { qjackctlPatchbaySlot *pSlot = iter.next(); if (sSlotName == pSlot->name()) return pSlot; } return nullptr; } // Cable finders. qjackctlPatchbayCable *qjackctlPatchbayRack::findCable ( const QString& sOutputSocket, const QString& sInputSocket ) { qjackctlPatchbaySocket *pSocket; QListIterator iter(m_cablelist); while (iter.hasNext()) { qjackctlPatchbayCable *pCable = iter.next(); pSocket = pCable->outputSocket(); if (pSocket && sOutputSocket == pSocket->name()) { pSocket = pCable->inputSocket(); if (pSocket && sInputSocket == pSocket->name()) return pCable; } } return nullptr; } qjackctlPatchbayCable *qjackctlPatchbayRack::findCable ( qjackctlPatchbayCable *pCablePtr ) { QString sOutputSocket; if (pCablePtr->outputSocket()) sOutputSocket = pCablePtr->outputSocket()->name(); QString sInputSocket; if (pCablePtr->inputSocket()) sInputSocket = pCablePtr->inputSocket()->name(); return findCable(sOutputSocket, sInputSocket); } // Cable finder (logical matching by client/port names). qjackctlPatchbayCable *qjackctlPatchbayRack::findCable ( const QString& sOClientName, const QString& sOPortName, const QString& sIClientName, const QString& sIPortName, int iSocketType ) { // This is a regex prefix needed for ALSA MDII // as client and port names include id-number+colon... QString sPrefix; if (iSocketType == QJACKCTL_SOCKETTYPE_ALSA_MIDI) sPrefix = "[0-9]+:"; // Scan from output-socket list... QListIterator osocket(m_osocketlist); while (osocket.hasNext()) { qjackctlPatchbaySocket *pOSocket = osocket.next(); if (pOSocket->type() != iSocketType) continue; // Output socket client name match? QRegularExpression rxOSocket(EXACT_PATTERN(sPrefix + pOSocket->clientName())); if (!rxOSocket.match(sOClientName).hasMatch()) continue; // Output plug port names match? QStringListIterator oplug(pOSocket->pluglist()); while (oplug.hasNext()) { QRegularExpression rxOPlug(EXACT_PATTERN(sPrefix + oplug.next())); if (!rxOPlug.match(sOPortName).hasMatch()) continue; // Scan for output-socket cable... QListIterator cable(m_cablelist); while (cable.hasNext()) { qjackctlPatchbayCable *pCable = cable.next(); if (pCable->outputSocket() != pOSocket) continue; qjackctlPatchbaySocket *pISocket = pCable->inputSocket(); // Input socket client name match? QRegularExpression rxISocket(EXACT_PATTERN(sPrefix + pISocket->clientName())); if (!rxISocket.match(sIClientName).hasMatch()) continue; // Input plug port names match? QStringListIterator iplug(pISocket->pluglist()); while (iplug.hasNext()) { // Found it? QRegularExpression rxIPlug(EXACT_PATTERN(sPrefix + iplug.next())); if (rxIPlug.match(sIPortName).hasMatch()) return pCable; } } } } // No matching cable was found. return nullptr; } // Patckbay cleaners. void qjackctlPatchbayRack::clear (void) { qDeleteAll(m_cablelist); m_cablelist.clear(); qDeleteAll(m_slotlist); m_slotlist.clear(); qDeleteAll(m_isocketlist); m_isocketlist.clear(); qDeleteAll(m_osocketlist); m_osocketlist.clear(); } // Patchbay rack output sockets list accessor. QList& qjackctlPatchbayRack::osocketlist (void) { return m_osocketlist; } // Patchbay rack input sockets list accessor. QList& qjackctlPatchbayRack::isocketlist (void) { return m_isocketlist; } // Patchbay rack slots list accessor. QList& qjackctlPatchbayRack::slotlist (void) { return m_slotlist; } // Patchbay cable connections list accessor. QList& qjackctlPatchbayRack::cablelist (void) { return m_cablelist; } // Lookup for the n-th JACK client port // that matches the given regular expression... const char *qjackctlPatchbayRack::findJackPort ( const char **ppszJackPorts, const QString& sClientName, const QString& sPortName, int n ) { QRegularExpression rxClientName(EXACT_PATTERN(sClientName)); QRegularExpression rxPortName(EXACT_PATTERN(sPortName)); int i = 0; int iClientPort = 0; while (ppszJackPorts[iClientPort]) { const QString sClientPort = QString::fromUtf8(ppszJackPorts[iClientPort]); const int iColon = sClientPort.indexOf(':'); if (iColon >= 0) { if (rxClientName.match(sClientPort.left(iColon)).hasMatch() && rxPortName.match(sClientPort.right( sClientPort.length() - iColon - 1)).hasMatch()) { if (++i > n) return ppszJackPorts[iClientPort]; } } ++iClientPort; } return nullptr; } // JACK port-pair connection executive IS DEPRECATED! void qjackctlPatchbayRack::connectJackPorts ( const char *pszOutputPort, const char *pszInputPort ) { unsigned int uiCableFlags = QJACKCTL_CABLE_FAILED; if (jack_connect(m_pJackClient, pszOutputPort, pszInputPort) == 0) uiCableFlags = QJACKCTL_CABLE_CONNECTED; emit cableConnected( pszOutputPort, pszInputPort, uiCableFlags); } // JACK port-pair disconnection executive. void qjackctlPatchbayRack::disconnectJackPorts ( const char *pszOutputPort, const char *pszInputPort ) { unsigned int uiCableFlags = QJACKCTL_CABLE_FAILED; if (jack_disconnect(m_pJackClient, pszOutputPort, pszInputPort) == 0) uiCableFlags = QJACKCTL_CABLE_DISCONNECTED; emit cableConnected( pszOutputPort, pszInputPort, uiCableFlags); } // JACK port-pair connection notifier. void qjackctlPatchbayRack::checkJackPorts ( const char *pszOutputPort, const char *pszInputPort ) { emit cableConnected( pszOutputPort, pszInputPort, QJACKCTL_CABLE_CHECKED); } // Check and enforce if an audio output client:port is connected to one input. void qjackctlPatchbayRack::connectJackSocketPorts ( qjackctlPatchbaySocket *pOutputSocket, const char *pszOutputPort, qjackctlPatchbaySocket *pInputSocket, const char *pszInputPort ) { bool bConnected = false; // Check for inputs from output... const char **ppszInputPorts = jack_port_get_all_connections( m_pJackClient, jack_port_by_name(m_pJackClient, pszOutputPort)); if (ppszInputPorts) { for (int i = 0 ; ppszInputPorts[i]; i++) { if (strcmp(ppszInputPorts[i], pszInputPort) == 0) bConnected = true; else if (pOutputSocket->isExclusive()) disconnectJackPorts(pszOutputPort, ppszInputPorts[i]); } jack_free(ppszInputPorts); } // Check for outputs from input, if the input socket is on exclusive mode... if (pInputSocket->isExclusive()) { const char **ppszOutputPorts = jack_port_get_all_connections( m_pJackClient, jack_port_by_name(m_pJackClient, pszInputPort)); if (ppszOutputPorts) { for (int i = 0 ; ppszOutputPorts[i]; i++) { if (strcmp(ppszOutputPorts[i], pszOutputPort) == 0) bConnected = true; else disconnectJackPorts(ppszOutputPorts[i], pszInputPort); } jack_free(ppszOutputPorts); } } // Finally do the connection?... if (!bConnected) { connectJackPorts(pszOutputPort, pszInputPort); } else { emit cableConnected( pszOutputPort, pszInputPort, QJACKCTL_CABLE_CHECKED); } } // Check and maint whether an JACK socket pair is fully connected. void qjackctlPatchbayRack::connectJackCable ( qjackctlPatchbaySocket *pOutputSocket, qjackctlPatchbaySocket *pInputSocket ) { if (pOutputSocket == nullptr || pInputSocket == nullptr) return; if (pOutputSocket->type() != pInputSocket->type()) return; const char **ppszOutputPorts = nullptr; const char **ppszInputPorts = nullptr; if (pOutputSocket->type() == QJACKCTL_SOCKETTYPE_JACK_AUDIO) { ppszOutputPorts = m_ppszOAudioPorts; ppszInputPorts = m_ppszIAudioPorts; } else if (pOutputSocket->type() == QJACKCTL_SOCKETTYPE_JACK_MIDI) { ppszOutputPorts = m_ppszOMidiPorts; ppszInputPorts = m_ppszIMidiPorts; } if (ppszOutputPorts == nullptr || ppszInputPorts == nullptr) return; // Iterate on each corresponding plug... QStringListIterator iterOutputPlug(pOutputSocket->pluglist()); QStringListIterator iterInputPlug(pInputSocket->pluglist()); while (iterOutputPlug.hasNext() && iterInputPlug.hasNext()) { const QString& sOutputPlug = iterOutputPlug.next(); const QString& sInputPlug = iterInputPlug.next(); // Check audio port connection sequentially... int iOPort = 0; const char *pszOutputPort; while ((pszOutputPort = findJackPort(ppszOutputPorts, pOutputSocket->clientName(), sOutputPlug, iOPort)) != nullptr) { int iIPort = 0; const char *pszInputPort; while ((pszInputPort = findJackPort(ppszInputPorts, pInputSocket->clientName(), sInputPlug, iIPort)) != nullptr) { connectJackSocketPorts( pOutputSocket, pszOutputPort, pInputSocket, pszInputPort); iIPort++; } iOPort++; } } } // Main JACK cable connect persistance scan cycle. void qjackctlPatchbayRack::connectJackScan ( jack_client_t *pJackClient ) { if (pJackClient == nullptr || m_pJackClient) return; // Cache client descriptor. m_pJackClient = pJackClient; // Cache all current audio client-ports... m_ppszOAudioPorts = jack_get_ports(m_pJackClient, 0, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput); m_ppszIAudioPorts = jack_get_ports(m_pJackClient, 0, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput); #ifdef CONFIG_JACK_MIDI // Cache all current MIDI client-ports... m_ppszOMidiPorts = jack_get_ports(m_pJackClient, 0, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput); m_ppszIMidiPorts = jack_get_ports(m_pJackClient, 0, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput); #else m_ppszOMidiPorts = nullptr; m_ppszIMidiPorts = nullptr; #endif // Start looking for connections... QListIterator iter(m_cablelist); while (iter.hasNext()) { qjackctlPatchbayCable *pCable = iter.next(); connectJackCable( pCable->outputSocket(), pCable->inputSocket()); } // Forward sockets... connectForwardScan(QJACKCTL_SOCKETTYPE_JACK_AUDIO); #ifdef CONFIG_JACK_MIDI connectForwardScan(QJACKCTL_SOCKETTYPE_JACK_MIDI); #endif // Free client-ports caches... if (m_ppszOAudioPorts) jack_free(m_ppszOAudioPorts); if (m_ppszIAudioPorts) jack_free(m_ppszIAudioPorts); #ifdef CONFIG_JACK_MIDI if (m_ppszOMidiPorts) jack_free(m_ppszOMidiPorts); if (m_ppszIMidiPorts) jack_free(m_ppszIMidiPorts); #endif // Reset cached pointers. m_ppszOAudioPorts = nullptr; m_ppszIAudioPorts = nullptr; m_ppszOMidiPorts = nullptr; m_ppszIMidiPorts = nullptr; m_pJackClient = nullptr; } // JACK socket/ports forwarding scan... void qjackctlPatchbayRack::connectJackForwardPorts ( const char *pszPort, const char *pszPortForward ) { // Check for outputs from forwarded input... const char **ppszOutputPorts = jack_port_get_all_connections( m_pJackClient, jack_port_by_name(m_pJackClient, pszPortForward)); if (ppszOutputPorts) { // Grab current connections of target port... const char **ppszPorts = jack_port_get_all_connections( m_pJackClient, jack_port_by_name(m_pJackClient, pszPort)); for (int i = 0 ; ppszOutputPorts[i]; i++) { // Need to lookup if already connected... bool bConnected = false; for (int j = 0; ppszPorts && ppszPorts[j]; j++) { if (strcmp(ppszOutputPorts[i], ppszPorts[j]) == 0) { bConnected = true; break; } } // Make or just report the connection... if (bConnected) { checkJackPorts(ppszOutputPorts[i], pszPort); } else { connectJackPorts(ppszOutputPorts[i], pszPort); } } // Free provided arrays... if (ppszPorts) jack_free(ppszPorts); jack_free(ppszOutputPorts); } } void qjackctlPatchbayRack::connectJackForward ( qjackctlPatchbaySocket *pSocket, qjackctlPatchbaySocket *pSocketForward ) { if (pSocket == nullptr || pSocketForward == nullptr) return; if (pSocket->type() != pSocketForward->type()) return; const char **ppszOutputPorts = nullptr; const char **ppszInputPorts = nullptr; if (pSocket->type() == QJACKCTL_SOCKETTYPE_JACK_AUDIO) { ppszOutputPorts = m_ppszOAudioPorts; ppszInputPorts = m_ppszIAudioPorts; } else if (pSocket->type() == QJACKCTL_SOCKETTYPE_JACK_MIDI) { ppszOutputPorts = m_ppszOMidiPorts; ppszInputPorts = m_ppszIMidiPorts; } if (ppszOutputPorts == nullptr || ppszInputPorts == nullptr) return; QStringListIterator iterPlug(pSocket->pluglist()); QStringListIterator iterPlugForward(pSocketForward->pluglist()); while (iterPlug.hasNext() && iterPlugForward.hasNext()) { // Check audio port connection sequentially... const QString& sPlug = iterPlug.next(); const QString& sPlugForward = iterPlugForward.next(); const char *pszPortForward = findJackPort(ppszInputPorts, pSocketForward->clientName(), sPlugForward, 0); if (pszPortForward) { const char *pszPort = findJackPort(ppszInputPorts, pSocket->clientName(), sPlug, 0); if (pszPort) connectJackForwardPorts(pszPort, pszPortForward); } } } #ifndef CONFIG_ALSA_SEQ #if defined(Q_CC_GNU) || defined(Q_CC_MINGW) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif #endif // Load all midi available midi ports of a given type. void qjackctlPatchbayRack::loadAlsaPorts ( QList& midiports, bool bReadable ) { if (m_pAlsaSeq == nullptr) return; qDeleteAll(midiports); midiports.clear(); #ifdef CONFIG_ALSA_SEQ unsigned int uiAlsaFlags; if (bReadable) uiAlsaFlags = SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; else uiAlsaFlags = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; snd_seq_client_info_t *pClientInfo; snd_seq_port_info_t *pPortInfo; snd_seq_client_info_alloca(&pClientInfo); snd_seq_port_info_alloca(&pPortInfo); snd_seq_client_info_set_client(pClientInfo, -1); while (snd_seq_query_next_client(m_pAlsaSeq, pClientInfo) >= 0) { int iAlsaClient = snd_seq_client_info_get_client(pClientInfo); if (iAlsaClient > 0) { QString sClientName = snd_seq_client_info_get_name(pClientInfo); snd_seq_port_info_set_client(pPortInfo, iAlsaClient); snd_seq_port_info_set_port(pPortInfo, -1); while (snd_seq_query_next_port(m_pAlsaSeq, pPortInfo) >= 0) { unsigned int uiPortCapability = snd_seq_port_info_get_capability(pPortInfo); if (((uiPortCapability & uiAlsaFlags) == uiAlsaFlags) && ((uiPortCapability & SND_SEQ_PORT_CAP_NO_EXPORT) == 0)) { qjackctlAlsaMidiPort *pMidiPort = new qjackctlAlsaMidiPort; pMidiPort->sClientName = sClientName; pMidiPort->iAlsaClient = iAlsaClient; pMidiPort->sPortName = snd_seq_port_info_get_name(pPortInfo); pMidiPort->iAlsaPort = snd_seq_port_info_get_port(pPortInfo); midiports.append(pMidiPort); } } } } #endif // CONFIG_ALSA_SEQ } // Get current connections from given MIDI port. void qjackctlPatchbayRack::loadAlsaConnections ( QList& midiports, qjackctlAlsaMidiPort *pMidiPort, bool bReadable ) { qDeleteAll(midiports); midiports.clear(); #ifdef CONFIG_ALSA_SEQ snd_seq_query_subs_type_t snd_subs_type; if (bReadable) snd_subs_type = SND_SEQ_QUERY_SUBS_READ; else snd_subs_type = SND_SEQ_QUERY_SUBS_WRITE; snd_seq_query_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_query_subscribe_alloca(&pAlsaSubs); snd_seq_query_subscribe_set_type(pAlsaSubs, snd_subs_type); snd_seq_query_subscribe_set_index(pAlsaSubs, 0); seq_addr.client = pMidiPort->iAlsaClient; seq_addr.port = pMidiPort->iAlsaPort; snd_seq_query_subscribe_set_root(pAlsaSubs, &seq_addr); while (snd_seq_query_port_subscribers(m_pAlsaSeq, pAlsaSubs) >= 0) { seq_addr = *snd_seq_query_subscribe_get_addr(pAlsaSubs); qjackctlAlsaMidiPort *pPort = new qjackctlAlsaMidiPort; setAlsaPort(pPort, seq_addr.client, seq_addr.port); midiports.append(pPort); snd_seq_query_subscribe_set_index(pAlsaSubs, snd_seq_query_subscribe_get_index(pAlsaSubs) + 1); } #endif // CONFIG_ALSA_SEQ } // Lookup for the n-th MIDI client port that matches the given regular expression... qjackctlAlsaMidiPort *qjackctlPatchbayRack::findAlsaPort ( QList& midiports, const QString& sClientName, const QString& sPortName, int n ) { QRegularExpression rxClientName(EXACT_PATTERN(sClientName)); QRegularExpression rxPortName(EXACT_PATTERN(sPortName)); int i = 0; // For each port... QListIterator iter(midiports); while (iter.hasNext()) { qjackctlAlsaMidiPort *pMidiPort = iter.next(); if (rxClientName.match(pMidiPort->sClientName).hasMatch() && rxPortName.match(pMidiPort->sPortName).hasMatch()) { if (++i > n) return pMidiPort; } } return nullptr; } // MIDI port-pair name string. QString qjackctlPatchbayRack::getAlsaPortName ( qjackctlAlsaMidiPort *pMidiPort ) { return QString::number(pMidiPort->iAlsaClient) + ':' + QString::number(pMidiPort->iAlsaPort) + ' ' + pMidiPort->sClientName; } // MIDI port-pair name string. void qjackctlPatchbayRack::setAlsaPort ( qjackctlAlsaMidiPort *pMidiPort, int iAlsaClient, int iAlsaPort ) { #ifdef CONFIG_ALSA_SEQ snd_seq_client_info_t *pClientInfo; snd_seq_port_info_t *pPortInfo; snd_seq_client_info_alloca(&pClientInfo); snd_seq_port_info_alloca(&pPortInfo); pMidiPort->iAlsaClient = iAlsaClient; pMidiPort->iAlsaPort = iAlsaPort; if (snd_seq_get_any_client_info(m_pAlsaSeq, iAlsaClient, pClientInfo) == 0) pMidiPort->sClientName = snd_seq_client_info_get_name(pClientInfo); if (snd_seq_get_any_port_info(m_pAlsaSeq, iAlsaClient, iAlsaPort, pPortInfo) == 0) pMidiPort->sPortName = snd_seq_port_info_get_name(pPortInfo); #endif // CONFIG_ALSA_SEQ } // MIDI port-pair connection executive. void qjackctlPatchbayRack::connectAlsaPorts ( qjackctlAlsaMidiPort *pOutputPort, qjackctlAlsaMidiPort *pInputPort ) { #ifdef CONFIG_ALSA_SEQ unsigned int uiCableFlags = QJACKCTL_CABLE_FAILED; snd_seq_port_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_alloca(&pAlsaSubs); seq_addr.client = pOutputPort->iAlsaClient; seq_addr.port = pOutputPort->iAlsaPort; snd_seq_port_subscribe_set_sender(pAlsaSubs, &seq_addr); seq_addr.client = pInputPort->iAlsaClient; seq_addr.port = pInputPort->iAlsaPort; snd_seq_port_subscribe_set_dest(pAlsaSubs, &seq_addr); if (snd_seq_subscribe_port(m_pAlsaSeq, pAlsaSubs) == 0) uiCableFlags = QJACKCTL_CABLE_CONNECTED; emit cableConnected( getAlsaPortName(pOutputPort), getAlsaPortName(pInputPort), uiCableFlags); #endif // CONFIG_ALSA_SEQ } // MIDI port-pair disconnection executive. void qjackctlPatchbayRack::disconnectAlsaPorts ( qjackctlAlsaMidiPort *pOutputPort, qjackctlAlsaMidiPort *pInputPort ) { #ifdef CONFIG_ALSA_SEQ unsigned int uiCableFlags = QJACKCTL_CABLE_FAILED; snd_seq_port_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_alloca(&pAlsaSubs); seq_addr.client = pOutputPort->iAlsaClient; seq_addr.port = pOutputPort->iAlsaPort; snd_seq_port_subscribe_set_sender(pAlsaSubs, &seq_addr); seq_addr.client = pInputPort->iAlsaClient; seq_addr.port = pInputPort->iAlsaPort; snd_seq_port_subscribe_set_dest(pAlsaSubs, &seq_addr); if (snd_seq_unsubscribe_port(m_pAlsaSeq, pAlsaSubs) == 0) uiCableFlags = QJACKCTL_CABLE_DISCONNECTED; emit cableConnected( getAlsaPortName(pOutputPort), getAlsaPortName(pInputPort), uiCableFlags); #endif // CONFIG_ALSA_SEQ } // MIDI port-pair disconnection notifier. void qjackctlPatchbayRack::checkAlsaPorts ( qjackctlAlsaMidiPort *pOutputPort, qjackctlAlsaMidiPort *pInputPort ) { emit cableConnected( getAlsaPortName(pOutputPort), getAlsaPortName(pInputPort), QJACKCTL_CABLE_CHECKED); } // Check and enforce if a midi output client:port is connected to one input. void qjackctlPatchbayRack::connectAlsaSocketPorts ( qjackctlPatchbaySocket *pOutputSocket, qjackctlAlsaMidiPort *pOutputPort, qjackctlPatchbaySocket *pInputSocket, qjackctlAlsaMidiPort *pInputPort ) { #ifdef CONFIG_ALSA_SEQ bool bConnected = false; snd_seq_query_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_query_subscribe_alloca(&pAlsaSubs); // Check for inputs from output... snd_seq_query_subscribe_set_type(pAlsaSubs, SND_SEQ_QUERY_SUBS_READ); snd_seq_query_subscribe_set_index(pAlsaSubs, 0); seq_addr.client = pOutputPort->iAlsaClient; seq_addr.port = pOutputPort->iAlsaPort; snd_seq_query_subscribe_set_root(pAlsaSubs, &seq_addr); while (snd_seq_query_port_subscribers(m_pAlsaSeq, pAlsaSubs) >= 0) { seq_addr = *snd_seq_query_subscribe_get_addr(pAlsaSubs); if (seq_addr.client == pInputPort->iAlsaClient && seq_addr.port == pInputPort->iAlsaPort) bConnected = true; else if (pOutputSocket->isExclusive()) { qjackctlAlsaMidiPort iport; setAlsaPort(&iport, seq_addr.client, seq_addr.port); disconnectAlsaPorts(pOutputPort, &iport); } snd_seq_query_subscribe_set_index(pAlsaSubs, snd_seq_query_subscribe_get_index(pAlsaSubs) + 1); } // Check for outputs from input, if the input socket is on exclusive mode... if (pInputSocket->isExclusive()) { snd_seq_query_subscribe_set_type(pAlsaSubs, SND_SEQ_QUERY_SUBS_WRITE); snd_seq_query_subscribe_set_index(pAlsaSubs, 0); seq_addr.client = pInputPort->iAlsaClient; seq_addr.port = pInputPort->iAlsaPort; snd_seq_query_subscribe_set_root(pAlsaSubs, &seq_addr); while (snd_seq_query_port_subscribers(m_pAlsaSeq, pAlsaSubs) >= 0) { seq_addr = *snd_seq_query_subscribe_get_addr(pAlsaSubs); if (seq_addr.client == pOutputPort->iAlsaClient && seq_addr.port == pOutputPort->iAlsaPort) bConnected = true; else if (pInputSocket->isExclusive()) { qjackctlAlsaMidiPort oport; setAlsaPort(&oport, seq_addr.client, seq_addr.port); disconnectAlsaPorts(&oport, pInputPort); } snd_seq_query_subscribe_set_index(pAlsaSubs, snd_seq_query_subscribe_get_index(pAlsaSubs) + 1); } } // Finally do the connection?... if (!bConnected) { connectAlsaPorts(pOutputPort, pInputPort); } else { emit cableConnected( getAlsaPortName(pOutputPort), getAlsaPortName(pInputPort), QJACKCTL_CABLE_CHECKED); } #endif // CONFIG_ALSA_SEQ } // Check and maint whether a MIDI socket pair is fully connected. void qjackctlPatchbayRack::connectAlsaCable ( qjackctlPatchbaySocket *pOutputSocket, qjackctlPatchbaySocket *pInputSocket ) { if (pOutputSocket == nullptr || pInputSocket == nullptr) return; if (pOutputSocket->type() != pInputSocket->type() || pOutputSocket->type() != QJACKCTL_SOCKETTYPE_ALSA_MIDI) return; // Iterate on each corresponding plug... QStringListIterator iterOutputPlug(pOutputSocket->pluglist()); QStringListIterator iterInputPlug(pInputSocket->pluglist()); while (iterOutputPlug.hasNext() && iterInputPlug.hasNext()) { const QString& sOutputPlug = iterOutputPlug.next(); const QString& sInputPlug = iterInputPlug.next(); // Check MIDI port connection sequentially... int iOPort = 0; qjackctlAlsaMidiPort *pOutputPort; while ((pOutputPort = findAlsaPort(m_omidiports, pOutputSocket->clientName(), sOutputPlug, iOPort)) != nullptr) { int iIPort = 0; qjackctlAlsaMidiPort *pInputPort; while ((pInputPort = findAlsaPort(m_imidiports, pInputSocket->clientName(), sInputPlug, iIPort)) != nullptr) { connectAlsaSocketPorts( pOutputSocket, pOutputPort, pInputSocket, pInputPort); iIPort++; } iOPort++; } } } // Overloaded MIDI cable connect persistance scan cycle. void qjackctlPatchbayRack::connectAlsaScan ( snd_seq_t *pAlsaSeq ) { if (pAlsaSeq == nullptr || m_pAlsaSeq) return; // Cache sequencer descriptor. m_pAlsaSeq = pAlsaSeq; // Cache all current output client-ports... loadAlsaPorts(m_omidiports, true); loadAlsaPorts(m_imidiports, false); // Run the MIDI cable scan... QListIterator iter(m_cablelist); while (iter.hasNext()) { qjackctlPatchbayCable *pCable = iter.next(); connectAlsaCable( pCable->outputSocket(), pCable->inputSocket()); } // Forward MIDI sockets... connectForwardScan(QJACKCTL_SOCKETTYPE_ALSA_MIDI); // Free client-ports caches... qDeleteAll(m_omidiports); m_omidiports.clear(); qDeleteAll(m_imidiports); m_imidiports.clear(); m_pAlsaSeq = nullptr; } // ALSA socket/ports forwarding scan... void qjackctlPatchbayRack::connectAlsaForwardPorts ( qjackctlAlsaMidiPort *pPort, qjackctlAlsaMidiPort *pPortForward ) { #ifdef CONFIG_ALSA_SEQ // Grab current connections of target port... QList midiports; loadAlsaConnections(midiports, pPort, false); snd_seq_query_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_query_subscribe_alloca(&pAlsaSubs); // Check for inputs from output... snd_seq_query_subscribe_set_type(pAlsaSubs, SND_SEQ_QUERY_SUBS_WRITE); snd_seq_query_subscribe_set_index(pAlsaSubs, 0); seq_addr.client = pPortForward->iAlsaClient; seq_addr.port = pPortForward->iAlsaPort; snd_seq_query_subscribe_set_root(pAlsaSubs, &seq_addr); while (snd_seq_query_port_subscribers(m_pAlsaSeq, pAlsaSubs) >= 0) { seq_addr = *snd_seq_query_subscribe_get_addr(pAlsaSubs); // Need to lookup if already connected... bool bConnected = false; QListIterator iter(midiports); while (iter.hasNext()) { qjackctlAlsaMidiPort *pMidiPort = iter.next(); if (pMidiPort->iAlsaClient == seq_addr.client && pMidiPort->iAlsaPort == seq_addr.port) { bConnected = true; break; } } // Make and/or just report the connection... qjackctlAlsaMidiPort oport; setAlsaPort(&oport, seq_addr.client, seq_addr.port); if (bConnected) { checkAlsaPorts(&oport, pPort); } else { connectAlsaPorts(&oport, pPort); } snd_seq_query_subscribe_set_index(pAlsaSubs, snd_seq_query_subscribe_get_index(pAlsaSubs) + 1); } qDeleteAll(midiports); midiports.clear(); #endif // CONFIG_ALSA_SEQ } void qjackctlPatchbayRack::connectAlsaForward ( qjackctlPatchbaySocket *pSocket, qjackctlPatchbaySocket *pSocketForward ) { if (pSocket == nullptr || pSocketForward == nullptr) return; if (pSocket->type() != pSocketForward->type() || pSocket->type() != QJACKCTL_SOCKETTYPE_ALSA_MIDI) return; QStringListIterator iterPlug(pSocket->pluglist()); QStringListIterator iterPlugForward(pSocketForward->pluglist()); while (iterPlug.hasNext() && iterPlugForward.hasNext()) { // Check MIDI port connection sequentially... const QString& sPlug = iterPlug.next(); const QString& sPlugForward = iterPlugForward.next(); qjackctlAlsaMidiPort *pPortForward = findAlsaPort(m_imidiports, pSocketForward->clientName(), sPlugForward, 0); if (pPortForward) { qjackctlAlsaMidiPort *pPort = findAlsaPort(m_imidiports, pSocket->clientName(), sPlug, 0); if (pPort) connectAlsaForwardPorts(pPort, pPortForward); } } } #ifndef CONFIG_ALSA_SEQ #if defined(Q_CC_GNU) || defined(Q_CC_MINGW) #pragma GCC diagnostic pop #endif #endif // Common socket forwrading scan... void qjackctlPatchbayRack::connectForwardScan ( int iSocketType ) { // First, make a copy of a seriously forwarded socket list... QList socketlist; QListIterator isocket(m_isocketlist); while (isocket.hasNext()) { qjackctlPatchbaySocket *pSocket = isocket.next(); if (pSocket->type() != iSocketType) continue; if (pSocket->forward().isEmpty()) continue; socketlist.append(pSocket); } // Second, scan for input forwarded sockets... QListIterator iter(socketlist); while (iter.hasNext()) { qjackctlPatchbaySocket *pSocket = iter.next(); qjackctlPatchbaySocket *pSocketForward = findSocket(m_isocketlist, pSocket->forward()); if (pSocketForward == nullptr) continue; switch (iSocketType) { case QJACKCTL_SOCKETTYPE_JACK_AUDIO: case QJACKCTL_SOCKETTYPE_JACK_MIDI: connectJackForward(pSocket, pSocketForward); break; case QJACKCTL_SOCKETTYPE_ALSA_MIDI: connectAlsaForward(pSocket, pSocketForward); break; } } } //---------------------------------------------------------------------- // JACK snapshot. void qjackctlPatchbayRack::connectJackSnapshotEx ( int iSocketType ) { if (m_pJackClient == nullptr) return; const char *pszJackPortType = JACK_DEFAULT_AUDIO_TYPE; #ifdef CONFIG_JACK_MIDI if (iSocketType == QJACKCTL_SOCKETTYPE_JACK_MIDI) pszJackPortType = JACK_DEFAULT_MIDI_TYPE; #endif const char **ppszInputPorts = jack_get_ports(m_pJackClient, 0, pszJackPortType, JackPortIsInput); if (ppszInputPorts) { for (int i = 0; ppszInputPorts[i]; ++i) { const char *pszInputPort = ppszInputPorts[i]; const QString sInputPort = QString::fromUtf8(pszInputPort); const QString& sIClient = sInputPort.section(':', 0, 0); const QString& sIPort = sInputPort.section(':', 1); qjackctlPatchbaySnapshot::add_socket( isocketlist(), sIClient, sIPort, iSocketType); } jack_free(ppszInputPorts); } const char **ppszOutputPorts = jack_get_ports(m_pJackClient, 0, pszJackPortType, JackPortIsOutput); if (ppszOutputPorts == nullptr) return; qjackctlPatchbaySnapshot snapshot; for (int i = 0; ppszOutputPorts[i]; ++i) { const char *pszOutputPort = ppszOutputPorts[i]; const QString sOutputPort = QString::fromUtf8(pszOutputPort); const QString& sOClient = sOutputPort.section(':', 0, 0); const QString& sOPort = sOutputPort.section(':', 1); qjackctlPatchbaySnapshot::add_socket( osocketlist(), sOClient, sOPort, iSocketType); // Check for inputs from output... ppszInputPorts = jack_port_get_all_connections( m_pJackClient, jack_port_by_name(m_pJackClient, pszOutputPort)); if (ppszInputPorts == nullptr) continue; for (int j = 0 ; ppszInputPorts[j]; ++j) { const char *pszInputPort = ppszInputPorts[j]; const QString sInputPort = QString::fromUtf8(pszInputPort); const QString& sIClient = sInputPort.section(':', 0, 0); const QString& sIPort = sInputPort.section(':', 1); snapshot.append(sOClient, sOPort, sIClient, sIPort); } jack_free(ppszInputPorts); } jack_free(ppszOutputPorts); snapshot.commit(this, iSocketType); } void qjackctlPatchbayRack::connectJackSnapshot ( jack_client_t *pJackClient ) { if (pJackClient == nullptr || m_pJackClient) return; // Cache JACK client descriptor. m_pJackClient = pJackClient; connectJackSnapshotEx(QJACKCTL_SOCKETTYPE_JACK_AUDIO); connectJackSnapshotEx(QJACKCTL_SOCKETTYPE_JACK_MIDI); // Done. m_pJackClient = nullptr; } //---------------------------------------------------------------------- // ALSA snapshot. void qjackctlPatchbayRack::connectAlsaSnapshot ( snd_seq_t *pAlsaSeq ) { if (pAlsaSeq == nullptr || m_pAlsaSeq) return; // Cache sequencer descriptor. m_pAlsaSeq = pAlsaSeq; #ifdef CONFIG_ALSA_SEQ QList imidiports; loadAlsaPorts(imidiports, false); QListIterator iport(imidiports); while (iport.hasNext()) { qjackctlAlsaMidiPort *pIPort = iport.next(); qjackctlPatchbaySnapshot::add_socket( isocketlist(), pIPort->sClientName, pIPort->sPortName, QJACKCTL_SOCKETTYPE_ALSA_MIDI); } qDeleteAll(imidiports); imidiports.clear(); qjackctlPatchbaySnapshot snapshot; QList omidiports; loadAlsaPorts(omidiports, true); QListIterator oport(omidiports); while (oport.hasNext()) { qjackctlAlsaMidiPort *pOPort = oport.next(); qjackctlPatchbaySnapshot::add_socket( osocketlist(), pOPort->sClientName, pOPort->sPortName, QJACKCTL_SOCKETTYPE_ALSA_MIDI); loadAlsaConnections(imidiports, pOPort, true); QListIterator iport(imidiports); while (iport.hasNext()) { qjackctlAlsaMidiPort *pIPort = iport.next(); snapshot.append( pOPort->sClientName, pOPort->sPortName, pIPort->sClientName, pIPort->sPortName); } qDeleteAll(imidiports); imidiports.clear(); } qDeleteAll(omidiports); omidiports.clear(); snapshot.commit(this, QJACKCTL_SOCKETTYPE_ALSA_MIDI); #endif // Done. m_pAlsaSeq = nullptr; } //---------------------------------------------------------------------- // JACK reset/disconnect-all. void qjackctlPatchbayRack::disconnectAllJackPortsEx ( int iSocketType ) { if (m_pJackClient == nullptr) return; const char *pszJackPortType = JACK_DEFAULT_AUDIO_TYPE; #ifdef CONFIG_JACK_MIDI if (iSocketType == QJACKCTL_SOCKETTYPE_JACK_MIDI) pszJackPortType = JACK_DEFAULT_MIDI_TYPE; #endif const char **ppszOutputPorts = jack_get_ports(m_pJackClient, 0, pszJackPortType, JackPortIsOutput); if (ppszOutputPorts) { for (int i = 0; ppszOutputPorts[i]; ++i) { const char *pszOutputPort = ppszOutputPorts[i]; const char **ppszInputPorts = jack_port_get_all_connections( m_pJackClient, jack_port_by_name(m_pJackClient, pszOutputPort)); if (ppszInputPorts == nullptr) continue; for (int j = 0 ; ppszInputPorts[j]; ++j) { const char *pszInputPort = ppszInputPorts[j]; jack_disconnect(m_pJackClient, pszOutputPort, pszInputPort); } jack_free(ppszInputPorts); } jack_free(ppszOutputPorts); } } void qjackctlPatchbayRack::disconnectAllJackPorts ( jack_client_t *pJackClient ) { if (pJackClient == nullptr || m_pJackClient) return; // Cache JACK client descriptor. m_pJackClient = pJackClient; disconnectAllJackPortsEx(QJACKCTL_SOCKETTYPE_JACK_AUDIO); disconnectAllJackPortsEx(QJACKCTL_SOCKETTYPE_JACK_MIDI); // Done. m_pJackClient = nullptr; } //---------------------------------------------------------------------- // ALSA reset/disconnect-all. void qjackctlPatchbayRack::disconnectAllAlsaPorts ( snd_seq_t *pAlsaSeq ) { if (pAlsaSeq == nullptr || m_pAlsaSeq) return; // Cache sequencer descriptor. m_pAlsaSeq = pAlsaSeq; #ifdef CONFIG_ALSA_SEQ QList omidiports; loadAlsaPorts(omidiports, true); QListIterator oport(omidiports); while (oport.hasNext()) { qjackctlAlsaMidiPort *pOPort = oport.next(); QList imidiports; loadAlsaConnections(imidiports, pOPort, true); QListIterator iport(imidiports); while (iport.hasNext()) { qjackctlAlsaMidiPort *pIPort = iport.next(); snd_seq_port_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_alloca(&pAlsaSubs); seq_addr.client = pOPort->iAlsaClient; seq_addr.port = pOPort->iAlsaPort; snd_seq_port_subscribe_set_sender(pAlsaSubs, &seq_addr); seq_addr.client = pIPort->iAlsaClient; seq_addr.port = pIPort->iAlsaPort; snd_seq_port_subscribe_set_dest(pAlsaSubs, &seq_addr); snd_seq_unsubscribe_port(m_pAlsaSeq, pAlsaSubs); } qDeleteAll(imidiports); imidiports.clear(); } qDeleteAll(omidiports); omidiports.clear(); #endif // Done. m_pAlsaSeq = nullptr; } // qjackctlPatchbayRack.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlConnect.h0000644000000000000000000000013214771215054016442 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlConnect.h0000644000175000001440000003200214771215054016427 0ustar00rncbcusers// qjackctlConnect.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlConnect_h #define __qjackctlConnect_h #include "qjackctlAliases.h" #include #include // QListViewItem::rtti return values. #define QJACKCTL_CLIENTITEM 1001 #define QJACKCTL_PORTITEM 1002 // Forward declarations. class qjackctlPortItem; class qjackctlClientItem; class qjackctlClientList; class qjackctlClientListView; class qjackctlConnectorView; class qjackctlConnectView; class qjackctlConnect; // Port list item. class qjackctlPortItem : public QTreeWidgetItem { public: // Constructor. qjackctlPortItem(qjackctlClientItem *pClient); // Default destructor. virtual ~qjackctlPortItem(); // Instance accessors. void setPortName(const QString& sPortName); const QString& clientName() const; const QString& portName() const; // Port name alias accessors. void setPortNameAlias(const QString& sPortNameAlias); QString portNameAlias(bool *pbRenameEnabled) const; // Proto-pretty/display name accessors. virtual void updatePortName(bool bRename = false); // Tooltip text building. virtual QString tooltip() const; // Complete client:port name helper. QString clientPortName() const; // Connections client item method. qjackctlClientItem *client() const; // Client port cleanup marker. void markPort(int iMark); void markClientPort(int iMark); int portMark() const; // Connected port list primitives. void addConnect(qjackctlPortItem *pPort); void removeConnect(qjackctlPortItem *pPort); // Connected port finders. qjackctlPortItem *findConnect(const QString& sClientPortName); qjackctlPortItem *findConnectPtr(qjackctlPortItem *pPortPtr); // Connection list accessor. const QList& connects() const; // Connectiopn highlight methods. bool isHilite() const; void setHilite (bool bHilite); // Proxy sort override method. // - Natural decimal sorting comparator. bool operator< (const QTreeWidgetItem& other) const; protected: // Port name display name accessors. void setPortText(const QString& sPortText, bool bRenameEnabled); QString portText() const; private: // Instance variables. qjackctlClientItem *m_pClient; QString m_sPortName; int m_iPortMark; bool m_bHilite; // Connection cache list. QList m_connects; }; // Client list item. class qjackctlClientItem : public QTreeWidgetItem { public: // Constructor. qjackctlClientItem(qjackctlClientList *pClientList); // Default destructor. virtual ~qjackctlClientItem(); // Port list primitive methods. void addPort(qjackctlPortItem *pPort); void removePort(qjackctlPortItem *pPort); // Port finder. qjackctlPortItem *findPort(const QString& sPortName); // Instance accessors. void setClientName(const QString& sClientName); const QString& clientName() const; // Client name alias accessors. void setClientNameAlias(const QString& sClientNameAlias); QString clientNameAlias(bool *pbRenameEnabled) const; // Proto-pretty/display name method. virtual void updateClientName(bool bRename = false); // Readable flag accessor. bool isReadable() const; // Client list accessor. qjackctlClientList *clientList() const; // Port list accessor. QList& ports(); // Client port cleanup marker. void markClient(int iMark); void markClientPorts(int iMark); int cleanClientPorts(int iMark); int clientMark() const; // Connectiopn highlight methods. bool isHilite() const; void setHilite (bool bHilite); // Client item openness status. void setOpen(bool bOpen); bool isOpen() const; // Proxy sort override method. // - Natural decimal sorting comparator. bool operator< (const QTreeWidgetItem& other) const; protected: // Client name display name accessors. void setClientText(const QString& sClientText, bool bRenameEnabled); QString clientText() const; private: // Instance variables. qjackctlClientList *m_pClientList; QString m_sClientName; int m_iClientMark; int m_iHilite; QList m_ports; }; // Jack client list. class qjackctlClientList : public QObject { public: // Constructor. qjackctlClientList(qjackctlClientListView *pListView, bool bReadable); // Default destructor. ~qjackctlClientList(); // Do proper contents cleanup. void clear(); // Client list primitive methods. void addClient(qjackctlClientItem *pClient); void removeClient(qjackctlClientItem *pClient); // Client finder. qjackctlClientItem *findClient(const QString& sClientName); // Client:port finder. qjackctlPortItem *findClientPort(const QString& sClientPort); // List view accessor. qjackctlClientListView *listView() const; // Readable flag accessor. bool isReadable() const; // Client list accessor. QList& clients(); // Client ports cleanup marker. void markClientPorts(int iMark); int cleanClientPorts(int iMark); // Client:port refreshner (return newest item count). virtual int updateClientPorts() = 0; // Client:port hilite update stabilization. void hiliteClientPorts (void); // Do proper contents refresh/update. void refresh(); // Natural decimal sorting comparator. static bool lessThan( const QTreeWidgetItem& item1, const QTreeWidgetItem& item2); private: // Instance variables. qjackctlClientListView *m_pListView; bool m_bReadable; QList m_clients; QTreeWidgetItem *m_pHiliteItem; }; //---------------------------------------------------------------------------- // qjackctlClientListView -- Client list view, supporting drag-n-drop. class qjackctlClientListView : public QTreeWidget { Q_OBJECT public: // Constructor. qjackctlClientListView(qjackctlConnectView *pConnectView, bool bReadable); // Default destructor. ~qjackctlClientListView(); // Auto-open timer methods. void setAutoOpenTimeout(int iAutoOpenTimeout); int autoOpenTimeout() const; // Aliasing support methods. void setAliasList(qjackctlAliasList *pAliasList, bool bRenameEnabled); qjackctlAliasList *aliasList() const; bool isRenameEnabled() const; // Binding indirect accessor. qjackctlConnect *binding() const; // Dirty aliases notification. void emitAliasesChanged(); protected slots: // In-place aliasing slots. void startRenameSlot(); void renamedSlot(); // Auto-open timeout slot. void timeoutSlot(); protected: // Trap for help/tool-tip events. bool eventFilter(QObject *pObject, QEvent *pEvent); // Drag-n-drop stuff. QTreeWidgetItem *dragDropItem(const QPoint& pos); // Drag-n-drop stuff -- reimplemented virtual methods. void dragEnterEvent(QDragEnterEvent *pDragEnterEvent); void dragMoveEvent(QDragMoveEvent *pDragMoveEvent); void dragLeaveEvent(QDragLeaveEvent *); void dropEvent(QDropEvent *pDropEvent); // Handle mouse events for drag-and-drop stuff. void mousePressEvent(QMouseEvent *pMouseEvent); void mouseMoveEvent(QMouseEvent *pMouseEvent); // Context menu request event handler. void contextMenuEvent(QContextMenuEvent *); private: // Bindings. qjackctlConnectView *m_pConnectView; // Auto-open timer. int m_iAutoOpenTimeout; QTimer *m_pAutoOpenTimer; // Items we'll eventually drop something. QTreeWidgetItem *m_pDragItem; QTreeWidgetItem *m_pDropItem; // The point from where drag started. QPoint m_posDrag; // Aliasing support. qjackctlAliasList *m_pAliasList; bool m_bRenameEnabled; }; //---------------------------------------------------------------------------- // qjackctlConnectorView -- Jack port connector widget. class qjackctlConnectorView : public QWidget { Q_OBJECT public: // Constructor. qjackctlConnectorView(qjackctlConnectView *pConnectView); // Default destructor. ~qjackctlConnectorView(); protected slots: // Useful slots (should this be protected?). void contentsChanged(); protected: // Draw visible port connection relation arrows. void paintEvent(QPaintEvent *); // Context menu request event handler. virtual void contextMenuEvent(QContextMenuEvent *); private: // Legal client/port item position helper. int itemY(QTreeWidgetItem *pItem) const; // Drawing methods. void drawConnectionLine(QPainter *pPainter, int x1, int y1, int x2, int y2, int h1, int h2, const QPen& pen); // Local instance variables. qjackctlConnectView *m_pConnectView; // Connector line color map/persistence. QHash m_colorMap; }; //---------------------------------------------------------------------------- // qjackctlConnectView -- Connections view integrated widget. class qjackctlConnectView : public QSplitter { Q_OBJECT public: // Constructor. qjackctlConnectView(QWidget *pParent = 0); // Default destructor. ~qjackctlConnectView(); // Widget accesors. qjackctlClientListView *OListView() const { return m_pOListView; } qjackctlClientListView *IListView() const { return m_pIListView; } qjackctlConnectorView *connectorView() const { return m_pConnectorView; } // Connections object binding methods. void setBinding(qjackctlConnect *pConnect); qjackctlConnect *binding() const; // Client list accessors. qjackctlClientList *OClientList() const; qjackctlClientList *IClientList() const; // Common icon size pixmap accessors. void setIconSize (int iIconSize); int iconSize (void) const; // Dirty aliases notification. void emitAliasesChanged(); signals: // Contents change signal. void aliasesChanged(); private: // Child controls. qjackctlClientListView *m_pOListView; qjackctlClientListView *m_pIListView; qjackctlConnectorView *m_pConnectorView; // The main binding object. qjackctlConnect *m_pConnect; // How large will be those icons. // 0 = 16x16 (default), 1 = 32x32, 2 = 64x64. int m_iIconSize; // The obnoxious dirty flag. bool m_bDirty; }; //---------------------------------------------------------------------------- // qjackctlConnect -- Connections model integrated object. class qjackctlConnect : public QObject { Q_OBJECT public: // Constructor. qjackctlConnect(qjackctlConnectView *pConnectView); // Default destructor. ~qjackctlConnect(); // Explicit connection tests. bool canConnectSelected(); bool canDisconnectSelected(); bool canDisconnectAll(); // Client list accessors. qjackctlClientList *OClientList() const; qjackctlClientList *IClientList() const; public slots: // Incremental contents refreshner; check dirty status. void refresh(); // Explicit connection slots. bool connectSelected(); bool disconnectSelected(); bool disconnectAll(); // Expand all client ports. void expandAll(); // Complete/incremental contents rebuilder; check dirty status if incremental. void updateContents(bool bClear); signals: // Connection change signal. void connectChanged(); // Pre-notification of (dis)connection. void connecting(qjackctlPortItem *, qjackctlPortItem *); void disconnecting(qjackctlPortItem *, qjackctlPortItem *); protected: // Connect/Disconnection primitives. virtual bool connectPorts( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort) = 0; virtual bool disconnectPorts( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort) = 0; // Update port connection references. virtual void updateConnections() = 0; // These must be accessed by the descendant constructor. qjackctlConnectView *connectView() const; void setOClientList(qjackctlClientList *pOClientList); void setIClientList(qjackctlClientList *pIClientList); // Common pixmap factory helper-method. QPixmap *createIconPixmap (const QString& sIconName); // Update icon size implementation. virtual void updateIconPixmaps() = 0; private: // Dunno. But this may avoid some conflicts. bool startMutex(); void endMutex(); // Connection methods (unguarded). bool canConnectSelectedEx(); bool canDisconnectSelectedEx(); bool canDisconnectAllEx(); bool connectSelectedEx(); bool disconnectSelectedEx(); bool disconnectAllEx(); // Connect/Disconnection local primitives. bool connectPortsEx(qjackctlPortItem *pOPort, qjackctlPortItem *pIPort); bool disconnectPortsEx(qjackctlPortItem *pOPort, qjackctlPortItem *pIPort); // Instance variables. qjackctlConnectView *m_pConnectView; // These must be created on the descendant constructor. qjackctlClientList *m_pOClientList; qjackctlClientList *m_pIClientList; int m_iMutex; }; #endif // __qjackctlConnect_h // end of qjackctlConnect.h qjackctl-1.0.4/src/PaxHeaders/qjackctlSessionSaveForm.ui0000644000000000000000000000013214771215054020325 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSessionSaveForm.ui0000644000175000001440000001243614771215054020323 0ustar00rncbcusers rncbc aka Rui Nuno Capela qjackctl - An Audio/MIDI multi-track sequencer. Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlSessionSaveForm 0 0 360 180 Qt::StrongFocus Session :/images/session1.png &Name: SessionNameLineEdit 320 0 Session name 0 &Directory: SessionDirComboBox Qt::Horizontal 20 8 0 320 0 Session directory true 22 22 24 24 Qt::TabFocus Browse for session directory ... Qt::Vertical 20 8 0 Save session versioning &Versioning Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok SessionNameLineEdit SessionDirComboBox SessionDirToolButton SessionVersioningCheckBox DialogButtonBox qjackctl-1.0.4/src/PaxHeaders/qjackctlPatchbayFile.cpp0000644000000000000000000000012714771215054017743 xustar0029 mtime=1743067692.32863657 29 atime=1743067692.32863657 29 ctime=1743067692.32863657 qjackctl-1.0.4/src/qjackctlPatchbayFile.cpp0000644000175000001440000002254014771215054017732 0ustar00rncbcusers// qjackctlPatchbayFile.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAbout.h" #include "qjackctlPatchbayFile.h" #include #include #include // Deprecated QTextStreamFunctions/Qt namespaces workaround. #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) #define endl Qt::endl #endif //---------------------------------------------------------------------- // Specific patchbay socket list save (write) subroutine. static void load_socketlist ( QList& socketlist, QDomElement& eSockets ) { for (QDomNode nSocket = eSockets.firstChild(); !nSocket.isNull(); nSocket = nSocket.nextSibling()) { // Convert slot node to element... QDomElement eSocket = nSocket.toElement(); if (eSocket.isNull()) continue; if (eSocket.tagName() == "socket") { QString sSocketName = eSocket.attribute("name"); QString sClientName = eSocket.attribute("client"); QString sSocketType = eSocket.attribute("type"); QString sExclusive = eSocket.attribute("exclusive"); QString sSocketForward = eSocket.attribute("forward"); int iSocketType = qjackctlPatchbaySocket::typeFromText(sSocketType); bool bExclusive = (sExclusive == "on" || sExclusive == "yes" || sExclusive == "1"); qjackctlPatchbaySocket *pSocket = new qjackctlPatchbaySocket(sSocketName, sClientName, iSocketType); if (pSocket) { pSocket->setExclusive(bExclusive); pSocket->setForward(sSocketForward); // Now's time to handle pluglist... for (QDomNode nPlug = eSocket.firstChild(); !nPlug.isNull(); nPlug = nPlug.nextSibling()) { // Convert plug node to element... QDomElement ePlug = nPlug.toElement(); if (ePlug.isNull()) continue; if (ePlug.tagName() == "plug") pSocket->addPlug(ePlug.text()); } socketlist.append(pSocket); } } } } //---------------------------------------------------------------------- // Specific patchbay socket list save (write) subroutine. static void save_socketlist ( QList& socketlist, QDomElement& eSockets, QDomDocument& doc ) { QListIterator sockit(socketlist); while (sockit.hasNext()) { qjackctlPatchbaySocket *pSocket = sockit.next(); QDomElement eSocket = doc.createElement("socket"); eSocket.setAttribute("name", pSocket->name()); eSocket.setAttribute("client", pSocket->clientName()); eSocket.setAttribute("type", qjackctlPatchbaySocket::textFromType(pSocket->type())); eSocket.setAttribute("exclusive", (pSocket->isExclusive() ? "on" : "off")); if (!pSocket->forward().isEmpty()) eSocket.setAttribute("forward", pSocket->forward()); QDomElement ePlug; QStringListIterator iter(pSocket->pluglist()); while (iter.hasNext()) { const QString& sPlug = iter.next(); QDomElement ePlug = doc.createElement("plug"); QDomText text = doc.createTextNode(sPlug); ePlug.appendChild(text); eSocket.appendChild(ePlug); } eSockets.appendChild(eSocket); } } //---------------------------------------------------------------------- // class qjackctlPatchbayFile -- Patchbay file helper implementation. // // Specific patchbay load (read) method. bool qjackctlPatchbayFile::load ( qjackctlPatchbayRack *pPatchbay, const QString& sFilename ) { // Open file... QFile file(sFilename); if (!file.open(QIODevice::ReadOnly)) return false; // Parse it a-la-DOM :-) QDomDocument doc("patchbay"); if (!doc.setContent(&file)) { file.close(); return false; } file.close(); // Now e're better reset any old patchbay settings. pPatchbay->clear(); // Get root element. QDomElement eDoc = doc.documentElement(); // Now parse for slots, sockets and cables... for (QDomNode nRoot = eDoc.firstChild(); !nRoot.isNull(); nRoot = nRoot.nextSibling()) { // Convert node to element, if any. QDomElement eRoot = nRoot.toElement(); if (eRoot.isNull()) continue; // Check for output-socket spec lists... if (eRoot.tagName() == "output-sockets") load_socketlist(pPatchbay->osocketlist(), eRoot); else // Check for input-socket spec lists... if (eRoot.tagName() == "input-sockets") load_socketlist(pPatchbay->isocketlist(), eRoot); else // Check for slots spec list... if (eRoot.tagName() == "slots") { for (QDomNode nSlot = eRoot.firstChild(); !nSlot.isNull(); nSlot = nSlot.nextSibling()) { // Convert slot node to element... QDomElement eSlot = nSlot.toElement(); if (eSlot.isNull()) continue; if (eSlot.tagName() == "slot") { QString sSlotName = eSlot.attribute("name"); QString sSlotMode = eSlot.attribute("mode"); int iSlotMode = QJACKCTL_SLOTMODE_OPEN; if (sSlotMode == "half") iSlotMode = QJACKCTL_SLOTMODE_HALF; else if (sSlotMode == "full") iSlotMode = QJACKCTL_SLOTMODE_FULL; qjackctlPatchbaySlot *pSlot = new qjackctlPatchbaySlot(sSlotName, iSlotMode); pSlot->setOutputSocket( pPatchbay->findSocket(pPatchbay->osocketlist(), eSlot.attribute("output"))); pSlot->setInputSocket( pPatchbay->findSocket(pPatchbay->isocketlist(), eSlot.attribute("input"))); pPatchbay->addSlot(pSlot); } } } else // Check for cable spec list... if (eRoot.tagName() == "cables") { for (QDomNode nCable = eRoot.firstChild(); !nCable.isNull(); nCable = nCable.nextSibling()) { // Convert cable node to element... QDomElement eCable = nCable.toElement(); if (eCable.isNull()) continue; if (eCable.tagName() == "cable") { int iSocketType = qjackctlPatchbaySocket::typeFromText( eCable.attribute("type")); qjackctlPatchbaySocket *pOutputSocket = pPatchbay->findSocket(pPatchbay->osocketlist(), eCable.attribute("output"), iSocketType); qjackctlPatchbaySocket *pIntputSocket = pPatchbay->findSocket(pPatchbay->isocketlist(), eCable.attribute("input"), iSocketType); if (pOutputSocket && pIntputSocket) { pPatchbay->addCable( new qjackctlPatchbayCable( pOutputSocket, pIntputSocket)); } } } } } return true; } // Specific patchbay save (write) method. bool qjackctlPatchbayFile::save ( qjackctlPatchbayRack *pPatchbay, const QString& sFilename ) { QFileInfo fi(sFilename); QDomDocument doc("patchbay"); QDomElement eRoot = doc.createElement("patchbay"); eRoot.setAttribute("name", fi.baseName()); eRoot.setAttribute("version", PROJECT_VERSION); doc.appendChild(eRoot); // Save output-sockets spec... QDomElement eOutputSockets = doc.createElement("output-sockets"); save_socketlist(pPatchbay->osocketlist(), eOutputSockets, doc); eRoot.appendChild(eOutputSockets); // Save input-sockets spec... QDomElement eInputSockets = doc.createElement("input-sockets"); save_socketlist(pPatchbay->isocketlist(), eInputSockets, doc); eRoot.appendChild(eInputSockets); // Save slots spec... QDomElement eSlots = doc.createElement("slots"); QListIterator slotit(pPatchbay->slotlist()); while (slotit.hasNext()) { qjackctlPatchbaySlot *pSlot = slotit.next(); QDomElement eSlot = doc.createElement("slot"); eSlot.setAttribute("name", pSlot->name()); QString sSlotMode = "open"; switch (pSlot->mode()) { case QJACKCTL_SLOTMODE_HALF: sSlotMode = "half"; break; case QJACKCTL_SLOTMODE_FULL: sSlotMode = "full"; break; } eSlot.setAttribute("mode", sSlotMode); if (pSlot->outputSocket()) eSlot.setAttribute("output", pSlot->outputSocket()->name()); if (pSlot->inputSocket()) eSlot.setAttribute("input", pSlot->inputSocket()->name()); // Add this slot... eSlots.appendChild(eSlot); } eRoot.appendChild(eSlots); // Save cables spec... QDomElement eCables = doc.createElement("cables"); QListIterator cablit(pPatchbay->cablelist()); while (cablit.hasNext()) { qjackctlPatchbayCable *pCable = cablit.next(); if (pCable->outputSocket() && pCable->inputSocket()) { QDomElement eCable = doc.createElement("cable"); eCable.setAttribute("type", qjackctlPatchbaySocket::textFromType( pCable->outputSocket()->type())); eCable.setAttribute("output", pCable->outputSocket()->name()); eCable.setAttribute("input", pCable->inputSocket()->name()); eCables.appendChild(eCable); } } eRoot.appendChild(eCables); // Finally, we're ready to save to external file. QFile file(sFilename); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return false; QTextStream ts(&file); ts << doc.toString() << endl; file.close(); return true; } // qjackctlPatchbayFile.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlPatchbayFile.h0000644000000000000000000000012714771215054017410 xustar0029 mtime=1743067692.32863657 29 atime=1743067692.32863657 29 ctime=1743067692.32863657 qjackctl-1.0.4/src/qjackctlPatchbayFile.h0000644000175000001440000000260214771215054017374 0ustar00rncbcusers// qjackctlPatchbayFile.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlPatchbayFile_h #define __qjackctlPatchbayFile_h #include "qjackctlPatchbayRack.h" // Patchbay XML definition. class qjackctlPatchbayFile { public: // Simple patchbay I/O methods. static bool load (qjackctlPatchbayRack *pPatchbay, const QString& sFilename); static bool save (qjackctlPatchbayRack *pPatchbay, const QString& sFilename); }; #endif // __qjackctlPatchbayFile_h // qjackctlPatchbayFile.h qjackctl-1.0.4/src/PaxHeaders/qjackctlAboutForm.ui0000644000000000000000000000013214771215054017135 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlAboutForm.ui0000644000175000001440000001071414771215054017130 0ustar00rncbcusers rncbc aka Rui Nuno Capela JACK Audio Connection Kit - Qt GUI Interface. Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlAboutForm 0 0 520 280 About :/images/about1.png true 4 4 4 4 4 Qt::Horizontal 8 8 &Close Qt::TabFocus About Qt :/images/qtlogo1.png Qt::Vertical 8 8 1 false true true 32 32 QFrame::NoFrame :/images/qjackctl.svg true Qt::AlignCenter false 2 AboutTextView AboutQtButton ClosePushButton qjackctl-1.0.4/src/PaxHeaders/qjackctlSetupForm.h0000644000000000000000000000013214771215054016775 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSetupForm.h0000644000175000001440000000745614771215054017001 0ustar00rncbcusers// qjackctlSetupForm.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlSetupForm_h #define __qjackctlSetupForm_h #include "ui_qjackctlSetupForm.h" // Forward declarations. class qjackctlSetup; class qjackctlPreset; class QButtonGroup; class QAbstractButton; //---------------------------------------------------------------------------- // qjackctlSetupForm -- UI wrapper form. class qjackctlSetupForm : public QDialog { Q_OBJECT public: // Constructor. qjackctlSetupForm(QWidget *pParent = nullptr); // Destructor. ~qjackctlSetupForm(); void setup(qjackctlSetup *pSetup); void updateCurrentPreset(); bool queryClose(); protected slots: void changeCurrentPreset(const QString&); void clearCurrentPreset(); void saveCurrentPreset(); void deleteCurrentPreset(); void changeDrivers(); void changeAudio(int); void changeDriver(int); void symbolStartupScript(); void symbolPostStartupScript(); void symbolShutdownScript(); void symbolPostShutdownScript(); void browseStartupScript(); void browsePostStartupScript(); void browseShutdownScript(); void browsePostShutdownScript(); void browseActivePatchbayPath(); void browseMessagesLogPath(); void chooseDisplayFont1(); void chooseDisplayFont2(); void toggleDisplayEffect(bool); void chooseMessagesFont(); void chooseConnectionsFont(); void editCustomColorThemes(); void buffSizeChanged(); void settingsChanged(); void optionsChanged(); void apply(); void discard(); void accept(); void reject(); void buttonClicked(QAbstractButton *); protected: // A combo-box text/data item setter helper. void setComboBoxCurrentText ( QComboBox *pComboBox, const QString& sText ) const; void setComboBoxCurrentData ( QComboBox *pComboBox, const QVariant& data ) const; void setCurrentPreset(const qjackctlPreset& preset); bool getCurrentPreset(qjackctlPreset& preset); void changePreset(const QString& sPreset); bool savePreset(const QString& sPreset); bool deletePreset(const QString& sPreset); void resetPresets(); void updateDrivers(); void updateBuffSize(); void computeLatency(); void changeDriverAudio(const QString& sDriver, int iAudio); void changeDriverUpdate(const QString& sDriver, bool bUpdate); void symbolMenu(QLineEdit * pLineEdit, QToolButton * pToolButton); // Custom color/style themes settlers. void resetCustomColorThemes(const QString& sCustomColorTheme); void resetCustomStyleThemes(const QString& sCustomStyleTheme); void updatePalette(); void stabilizeForm(); void showEvent(QShowEvent *); void hideEvent(QHideEvent *); private: // The Qt-designer UI struct... Ui::qjackctlSetupForm m_ui; // Instance variables. qjackctlSetup *m_pSetup; QButtonGroup *m_pTimeDisplayButtonGroup; int m_iDirtySetup; int m_iDirtyPreset; int m_iDirtyBuffSize; int m_iDirtySettings; int m_iDirtyOptions; QString m_sPreset; QStringList m_drivers; }; #endif // __qjackctlSetupForm_h // end of qjackctlSetupForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlPatchbayForm.ui0000644000000000000000000000012714771215054017622 xustar0029 mtime=1743067692.32863657 29 atime=1743067692.32863657 29 ctime=1743067692.32863657 qjackctl-1.0.4/src/qjackctlPatchbayForm.ui0000644000175000001440000004147714771215054017623 0ustar00rncbcusers rncbc aka Rui Nuno Capela JACK Audio Connection Kit - Qt GUI Interface. Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlPatchbayForm 0 0 520 320 1 1 0 0 Patchbay :/images/patchbay1.png 4 4 Qt::Horizontal Qt::Horizontal QSizePolicy::Fixed 80 8 4 4 7 7 0 0 Qt::TabFocus Move currently selected output socket down one position Down :/images/down1.png Create a new output socket Add... :/images/add1.png Qt::Vertical QSizePolicy::Expanding 8 42 Edit currently selected input socket properties Edit... :/images/edit1.png Qt::Vertical QSizePolicy::Expanding 8 42 Move currently selected output socket up one position Up :/images/up1.png Remove currently selected output socket Remove :/images/remove1.png Duplicate (copy) currently selected output socket Copy... :/images/copy1.png Move currently selected output socket down one position Down :/images/down1.png Remove currently selected input socket Remove :/images/remove1.png Duplicate (copy) currently selected input socket Copy... :/images/copy1.png Create a new input socket Add... :/images/add1.png Edit currently selected output socket properties Edit... :/images/edit1.png Move currently selected output socket up one position Up :/images/up1.png Qt::Horizontal QSizePolicy::Fixed 80 8 4 4 Connect currently selected sockets &Connect :/images/connect1.png Disconnect currently selected sockets &Disconnect :/images/disconnect1.png Disconnect all currently connected sockets Disconnect &All :/images/disconnect1.png Qt::Horizontal QSizePolicy::Expanding 8 8 Expand all items E&xpand All :/images/expandall1.png Qt::Horizontal QSizePolicy::Expanding 8 8 Refresh current patchbay view &Refresh :/images/refresh1.png true 4 4 Create a new patchbay profile &New :/images/new1.png false Load patchbay profile &Load... :/images/open1.png false Save current patchbay profile &Save... :/images/save1.png false 7 5 0 0 75 true Current (recent) patchbay profile(s) Toggle activation of current patchbay profile Acti&vate :/images/apply1.png true false qjackctlPatchbayView QWidget
qjackctlPatchbay.h
NewPatchbayPushButton LoadPatchbayPushButton SavePatchbayPushButton PatchbayComboBox ActivatePatchbayPushButton OSocketAddPushButton OSocketEditPushButton OSocketCopyPushButton OSocketRemovePushButton OSocketMoveUpPushButton OSocketMoveDownPushButton PatchbayView ISocketAddPushButton ISocketEditPushButton ISocketCopyPushButton ISocketRemovePushButton ISocketMoveUpPushButton ISocketMoveDownPushButton ConnectPushButton DisconnectPushButton DisconnectAllPushButton ExpandAllPushButton RefreshPushButton
qjackctl-1.0.4/src/PaxHeaders/qjackctlJackGraph.cpp0000644000000000000000000000013214771215054017236 xustar0030 mtime=1743067692.325636584 30 atime=1743067692.325636584 30 ctime=1743067692.325636584 qjackctl-1.0.4/src/qjackctlJackGraph.cpp0000644000175000001440000004221214771215054017227 0ustar00rncbcusers// qjackctlJackGraph.cpp // /**************************************************************************** Copyright (C) 2003-2023, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlJackGraph.h" #include "qjackctlMainForm.h" #include //---------------------------------------------------------------------------- // qjackctlJackGraph -- JACK graph driver #ifdef CONFIG_JACK_METADATA // JACK client/port meta-data property helpers. // #include #include static QString qjackctlJackGraph_get_property ( jack_uuid_t uuid, const char *key, const QString& name ) { QString property = name; char *value = nullptr; char *type = nullptr; if (::jack_get_property(uuid, key, &value, &type) == 0) { if (value) { property = QString::fromUtf8(value); ::jack_free(value); } if (type) ::jack_free(type); } return property; } static void qjackctlJackGraph_set_property ( jack_client_t *client, jack_uuid_t uuid, const char *key, const QString& property ) { const QByteArray aValue = property.toUtf8(); const char *value = aValue.constData(); ::jack_set_property(client, uuid, key, value, NULL); } static void qjackctlJackGraph_remove_property ( jack_client_t *client, jack_uuid_t uuid, const char *key ) { ::jack_remove_property(client, uuid, key); } // Pretty-name property accessors. // static QString qjackctlJackGraph_pretty_name ( jack_uuid_t uuid, const QString& pretty_name ) { return qjackctlJackGraph_get_property(uuid, JACK_METADATA_PRETTY_NAME, pretty_name); } static void qjackctlJackGraph_set_pretty_name ( jack_client_t *client, jack_uuid_t uuid, const QString& pretty_name ) { qjackctlJackGraph_set_property(client, uuid, JACK_METADATA_PRETTY_NAME, pretty_name); } static void qjackctlJackGraph_remove_pretty_name ( jack_client_t *client, jack_uuid_t uuid ) { qjackctlJackGraph_remove_property(client, uuid, JACK_METADATA_PRETTY_NAME); } // Port-index property accessors. // #ifndef JACKEY_ORDER #define JACKEY_ORDER "http://jackaudio.org/metadata/order" #endif static int qjackctlJackGraph_port_index ( jack_uuid_t uuid, int index ) { return qjackctlJackGraph_get_property(uuid, JACKEY_ORDER, QString::number(index)).toInt(); } #ifdef CONFIG_JACK_CV // Signal-type property accessors (audio|"cv"). // #ifndef JACKEY_SIGNAL_TYPE #define JACKEY_SIGNAL_TYPE "http://jackaudio.org/metadata/signal-type" #endif static QString qjackctlJackGraph_signal_type ( jack_uuid_t uuid ) { return qjackctlJackGraph_get_property(uuid, JACKEY_SIGNAL_TYPE, QString()).toLower(); } static bool qjackctlJackGraph_port_is_cv ( jack_uuid_t uuid ) { return qjackctlJackGraph_signal_type(uuid) == "cv"; } #endif // CONFIG_JACK_CV #ifdef CONFIG_JACK_OSC // Event-types property accessors (MIDI|"osc"). // #ifndef JACKEY_EVENT_TYPES #define JACKEY_EVENT_TYPES "http://jackaudio.org/metadata/event-types" #endif static QStringList qjackctlJackGraph_event_types ( jack_uuid_t uuid ) { return qjackctlJackGraph_get_property(uuid, JACKEY_EVENT_TYPES, QString("midi")).toLower().split(','); } static bool qjackctlJackGraph_port_is_osc ( jack_uuid_t uuid ) { return qjackctlJackGraph_event_types(uuid).contains("osc"); } #endif // CONFIG_JACK_OSC #endif // CONFIG_JACK_METADATA // Constructor. qjackctlJackGraph::qjackctlJackGraph ( qjackctlGraphCanvas *canvas ) : qjackctlGraphSect(canvas) { resetPortTypeColors(); } // JACK port (dis)connection. void qjackctlJackGraph::connectPorts ( qjackctlGraphPort *port1, qjackctlGraphPort *port2, bool is_connect ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; jack_client_t *client = pMainForm->jackClient(); if (client == nullptr) return; if (port1 == nullptr || port2 == nullptr) return; const qjackctlGraphNode *node1 = port1->portNode(); const qjackctlGraphNode *node2 = port2->portNode(); if (node1 == nullptr || node2 == nullptr) return; QMutexLocker locker(&m_mutex); const QByteArray client_port1 = QString(node1->nodeName() + ':' + port1->portName()).toUtf8(); const QByteArray client_port2 = QString(node2->nodeName() + ':' + port2->portName()).toUtf8(); const char *client_port_name1 = client_port1.constData(); const char *client_port_name2 = client_port2.constData(); #ifdef CONFIG_DEBUG qDebug("qjackctlJackGraph::connectPorts(\"%s\", \"%s\", %d)", client_port_name1, client_port_name2, is_connect); #endif if (is_connect) { ::jack_connect(client, client_port_name1, client_port_name2); } else { ::jack_disconnect(client, client_port_name1, client_port_name2); } } // JACK node type inquirer. (static) bool qjackctlJackGraph::isNodeType ( uint node_type ) { return (node_type == qjackctlJackGraph::nodeType()); } // JACK node type. uint qjackctlJackGraph::nodeType (void) { static const uint JackNodeType = qjackctlGraphItem::itemType("JACK_NODE_TYPE"); return JackNodeType; } // JACK port type(s) inquirer. (static) bool qjackctlJackGraph::isPortType ( uint port_type ) { return port_type == audioPortType() || port_type == midiPortType() #ifdef CONFIG_JACK_CV || port_type == cvPortType() #endif #ifdef CONFIG_JACK_OSC || port_type == oscPortType() #endif ; } uint qjackctlJackGraph::audioPortType (void) { return qjackctlGraphItem::itemType(JACK_DEFAULT_AUDIO_TYPE); } uint qjackctlJackGraph::midiPortType (void) { return qjackctlGraphItem::itemType(JACK_DEFAULT_MIDI_TYPE); } uint qjackctlJackGraph::cvPortType (void) { return qjackctlGraphItem::itemType("JACK_SIGNAL_TYPE_CV"); } uint qjackctlJackGraph::oscPortType (void) { return qjackctlGraphItem::itemType("JACK_EVENT_TYPE_OSC"); } // JACK client:port finder and creator if not existing. bool qjackctlJackGraph::findClientPort ( jack_client_t *client, const char *client_port, qjackctlGraphItem::Mode port_mode, qjackctlGraphNode **node, qjackctlGraphPort **port, bool add_new ) { jack_port_t *jack_port = ::jack_port_by_name(client, client_port); if (jack_port == nullptr) return false; const QString& client_port_name = QString::fromUtf8(client_port); const int colon = client_port_name.indexOf(':'); if (colon < 0) return false; const QString& client_name = client_port_name.left(colon); const QString& port_name = client_port_name.right(client_port_name.length() - colon - 1); const uint node_type = qjackctlJackGraph::nodeType(); const char *port_type_name = ::jack_port_type(jack_port); uint port_type = qjackctlGraphItem::itemType(port_type_name); #ifdef CONFIG_JACK_METADATA const jack_uuid_t port_uuid = ::jack_port_uuid(jack_port); #ifdef CONFIG_JACK_CV if (port_type == audioPortType() && qjackctlJackGraph_port_is_cv(port_uuid)) port_type = cvPortType(); #endif #ifdef CONFIG_JACK_OSC if (port_type == midiPortType() && qjackctlJackGraph_port_is_osc(port_uuid)) port_type = oscPortType(); #endif #endif // CONFIG_JACK_METADATA qjackctlGraphItem::Mode node_mode = port_mode; *node = qjackctlGraphSect::findNode(client_name, node_mode, node_type); *port = nullptr; if (*node == nullptr) { const unsigned long port_flags = ::jack_port_flags(jack_port); const unsigned long port_flags_mask = (JackPortIsPhysical | JackPortIsTerminal); if ((port_flags & port_flags_mask) != port_flags_mask) { node_mode = qjackctlGraphItem::Duplex; *node = qjackctlGraphSect::findNode(client_name, node_mode, node_type); } } if (*node) *port = (*node)->findPort(port_name, port_mode, port_type); if (add_new && *node == nullptr) { *node = new qjackctlGraphNode(client_name, node_mode, node_type); (*node)->setNodeIcon(QIcon(":/images/graphJack.png")); qjackctlGraphSect::addItem(*node); } if (add_new && *port == nullptr && *node) { *port = (*node)->addPort(port_name, port_mode, port_type); (*port)->updatePortTypeColors(qjackctlGraphSect::canvas()); } if (add_new && *node) { int nchanged = 0; QString node_title = (*node)->nodeTitle(); #ifdef CONFIG_JACK_METADATA const char *client_uuid_name = ::jack_get_uuid_for_client_name(client, client_name.toUtf8().constData()); if (client_uuid_name) { jack_uuid_t client_uuid = 0; ::jack_uuid_parse(client_uuid_name, &client_uuid); const QString& pretty_name = qjackctlJackGraph_pretty_name(client_uuid, client_name); if (!pretty_name.isEmpty()) node_title = pretty_name; ::jack_free((void *) client_uuid_name); } #endif // CONFIG_JACK_METADATA foreach (qjackctlAliasList *node_aliases, item_aliases(*node)) node_title = node_aliases->clientAlias(client_name); if ((*node)->nodeTitle() != node_title) { (*node)->setNodeTitle(node_title); ++nchanged; } if (*port) { QString port_title = (*port)->portTitle(); #ifdef CONFIG_JACK_METADATA const QString& pretty_name = qjackctlJackGraph_pretty_name(port_uuid, port_name); if (!pretty_name.isEmpty()) port_title = pretty_name; const int port_index = qjackctlJackGraph_port_index(port_uuid, 0); if ((*port)->portIndex() != port_index) { (*port)->setPortIndex(port_index); ++nchanged; } #endif // CONFIG_JACK_METADATA foreach (qjackctlAliasList *port_aliases, item_aliases(*port)) port_title = port_aliases->portAlias(client_name, port_name); if ((*port)->portTitle() != port_title) { (*port)->setPortTitle(port_title); ++nchanged; } } if (nchanged > 0) (*node)->updatePath(); } return (*node && *port); } // JACK graph updaters. void qjackctlJackGraph::updateItems (void) { QMutexLocker locker(&m_mutex); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; jack_client_t *client = pMainForm->jackClient(); if (client == nullptr) return; #ifdef CONFIG_DEBUG_0 qDebug("qjackctlJackGraph::updateItems()"); #endif // 1. Client/ports inventory... // const char **client_ports1 = ::jack_get_ports(client, nullptr, nullptr, 0); if (client_ports1 == nullptr) return; for (int i = 0; client_ports1[i]; ++i) { const char *client_port1 = client_ports1[i]; jack_port_t *jack_port1 = ::jack_port_by_name(client, client_port1); if (jack_port1 == nullptr) continue; const unsigned long port_flags1 = ::jack_port_flags(jack_port1); qjackctlGraphItem::Mode port_mode1 = qjackctlGraphItem::None; if (port_flags1 & JackPortIsInput) port_mode1 = qjackctlGraphItem::Input; else if (port_flags1 & JackPortIsOutput) port_mode1 = qjackctlGraphItem::Output; qjackctlGraphNode *node1 = nullptr; qjackctlGraphPort *port1 = nullptr; if (findClientPort(client, client_port1, port_mode1, &node1, &port1, true)) { node1->setMarked(true); port1->setMarked(true); } } // 2. Connections inventory... // for (int i = 0; client_ports1[i]; ++i) { const char *client_port1 = client_ports1[i]; jack_port_t *jack_port1 = ::jack_port_by_name(client, client_port1); if (jack_port1 == nullptr) continue; const unsigned long port_flags1 = ::jack_port_flags(jack_port1); if (port_flags1 & JackPortIsOutput) { const qjackctlGraphItem::Mode port_mode1 = qjackctlGraphItem::Output; const char **client_ports2 = ::jack_port_get_all_connections(client, jack_port1); if (client_ports2 == nullptr) continue; qjackctlGraphNode *node1 = nullptr; qjackctlGraphPort *port1 = nullptr; if (findClientPort(client, client_port1, port_mode1, &node1, &port1, false)) { for (int j = 0; client_ports2[j]; ++j) { const char *client_port2 = client_ports2[j]; const qjackctlGraphItem::Mode port_mode2 = qjackctlGraphItem::Input; qjackctlGraphNode *node2 = nullptr; qjackctlGraphPort *port2 = nullptr; if (findClientPort(client, client_port2, port_mode2, &node2, &port2, false)) { qjackctlGraphConnect *connect = port1->findConnect(port2); if (connect == nullptr) { connect = new qjackctlGraphConnect(); connect->setPort1(port1); connect->setPort2(port2); connect->updatePortTypeColors(); connect->updatePath(); qjackctlGraphSect::addItem(connect); } if (connect) connect->setMarked(true); } } } jack_free(client_ports2); } } jack_free(client_ports1); // 3. Clean-up all un-marked items... // qjackctlGraphSect::resetItems(qjackctlJackGraph::nodeType()); } void qjackctlJackGraph::clearItems (void) { QMutexLocker locker(&m_mutex); #ifdef CONFIG_DEBUG_0 qDebug("qjackctlJackGraph::clearItems()"); #endif qjackctlGraphSect::clearItems(qjackctlJackGraph::nodeType()); } // Special port-type colors defaults (virtual). void qjackctlJackGraph::resetPortTypeColors (void) { qjackctlGraphCanvas *canvas = qjackctlGraphSect::canvas(); if (canvas) { canvas->setPortTypeColor( qjackctlJackGraph::audioPortType(), QColor(Qt::darkGreen).darker(120)); canvas->setPortTypeColor( qjackctlJackGraph::midiPortType(), QColor(Qt::darkRed).darker(120)); #ifdef CONFIG_JACK_CV canvas->setPortTypeColor( qjackctlJackGraph::cvPortType(), QColor(Qt::darkCyan).darker(120)); #endif #ifdef CONFIG_JACK_OSC canvas->setPortTypeColor( qjackctlJackGraph::oscPortType(), QColor(Qt::darkYellow).darker(120)); #endif } } // Client/port item aliases accessor. QList qjackctlJackGraph::item_aliases ( qjackctlGraphItem *item ) const { QList alist; qjackctlAliases *aliases = nullptr; qjackctlGraphCanvas *canvas = qjackctlGraphSect::canvas(); if (canvas) aliases = canvas->aliases(); if (aliases == nullptr) return alist; // empty! uint item_type = 0; qjackctlGraphItem::Mode item_mode = qjackctlGraphItem::None; bool is_node = false; if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node && qjackctlJackGraph::isNodeType(node->nodeType())) { item_type = node->nodeType(); item_mode = node->nodeMode(); is_node = true; } } else if (item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port = static_cast (item); if (port) { item_type = port->portType(); item_mode = port->portMode(); } } if (!item_type || !item_mode) return alist; // empty again! if (is_node || item_type == qjackctlJackGraph::audioPortType()) { // JACK audio type... if (item_mode & qjackctlGraphItem::Input) alist.append(&(aliases->audioInputs)); if (item_mode & qjackctlGraphItem::Output) alist.append(&(aliases->audioOutputs)); } if (is_node || item_type == qjackctlJackGraph::midiPortType()) { // JACK MIDI type... if (item_mode & qjackctlGraphItem::Input) alist.append(&(aliases->midiInputs)); if (item_mode & qjackctlGraphItem::Output) alist.append(&(aliases->midiOutputs)); } return alist; // hopefully non empty! } // Client/port renaming method (virtual override). void qjackctlJackGraph::renameItem ( qjackctlGraphItem *item, const QString& name ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; jack_client_t *client = pMainForm->jackClient(); if (client == nullptr) return; #ifdef CONFIG_JACK_METADATA qjackctlGraphNode *node = nullptr; if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node) { const QString& node_name = node->nodeName(); const QByteArray client_name = node_name.toUtf8(); const char *client_uuid_name = ::jack_get_uuid_for_client_name(client, client_name.constData()); if (client_uuid_name) { jack_uuid_t client_uuid = 0; ::jack_uuid_parse(client_uuid_name, &client_uuid); if (name.isEmpty()) qjackctlJackGraph_remove_pretty_name(client, client_uuid); else qjackctlJackGraph_set_pretty_name(client, client_uuid, name); ::jack_free((void *) client_uuid_name); } } } else if (item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port = static_cast (item); if (port) node = port->portNode(); if (port && node) { const QString& port_name = port->portName(); const QString& client_port = node->nodeName() + ':' + port_name; const QByteArray client_port_name = client_port.toUtf8(); jack_port_t *jack_port = ::jack_port_by_name(client, client_port_name.constData()); if (jack_port) { jack_uuid_t port_uuid = ::jack_port_uuid(jack_port); if (name.isEmpty()) qjackctlJackGraph_remove_pretty_name(client, port_uuid); else qjackctlJackGraph_set_pretty_name(client, port_uuid, name); } } } #endif // CONFIG_JACK_METADATA qjackctlGraphSect::renameItem(item, name); } // end of qjackctlJackGraph.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlAlsaConnect.cpp0000644000000000000000000000013214771215054017576 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlAlsaConnect.cpp0000644000175000001440000002777214771215054017605 0ustar00rncbcusers// qjackctlAlsaConnect.cpp // /**************************************************************************** Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAlsaConnect.h" #include "qjackctlMainForm.h" #include //---------------------------------------------------------------------- // class qjackctlAlsaPort -- Alsa port list item. // // Constructor. qjackctlAlsaPort::qjackctlAlsaPort ( qjackctlAlsaClient *pClient ) : qjackctlPortItem(pClient) { qjackctlAlsaConnect *pAlsaConnect = static_cast ( ((pClient->clientList())->listView())->binding()); if (pAlsaConnect) { if (pClient->isReadable()) { QTreeWidgetItem::setIcon(0, QIcon(pAlsaConnect->pixmap(QJACKCTL_ALSA_PORTO))); } else { QTreeWidgetItem::setIcon(0, QIcon(pAlsaConnect->pixmap(QJACKCTL_ALSA_PORTI))); } } } // Default destructor. qjackctlAlsaPort::~qjackctlAlsaPort (void) { } // Alsa handles accessors. int qjackctlAlsaPort::alsaClient (void) const { return (static_cast (client()))->alsaClient(); } int qjackctlAlsaPort::alsaPort (void) const { return portName().section(':', 0, 0).toInt(); } //---------------------------------------------------------------------- // class qjackctlAlsaClient -- Alsa client list item. // // Constructor. qjackctlAlsaClient::qjackctlAlsaClient ( qjackctlAlsaClientList *pClientList ) : qjackctlClientItem(pClientList) { qjackctlAlsaConnect *pAlsaConnect = static_cast ( (pClientList->listView())->binding()); if (pAlsaConnect) { if (pClientList->isReadable()) { QTreeWidgetItem::setIcon(0, QIcon(pAlsaConnect->pixmap(QJACKCTL_ALSA_CLIENTO))); } else { QTreeWidgetItem::setIcon(0, QIcon(pAlsaConnect->pixmap(QJACKCTL_ALSA_CLIENTI))); } } } // Default destructor. qjackctlAlsaClient::~qjackctlAlsaClient (void) { } // Jack client accessor. int qjackctlAlsaClient::alsaClient (void) const { return clientName().section(':', 0, 0).toInt(); } // Derived port finder. qjackctlAlsaPort *qjackctlAlsaClient::findPort ( int iAlsaPort ) { QListIterator iter(ports()); while (iter.hasNext()) { qjackctlAlsaPort *pPort = static_cast (iter.next()); if (iAlsaPort == pPort->alsaPort()) return pPort; } return nullptr; } //---------------------------------------------------------------------- // qjackctlAlsaClientList -- Jack client list. // // Constructor. qjackctlAlsaClientList::qjackctlAlsaClientList ( qjackctlClientListView *pListView, bool bReadable ) : qjackctlClientList(pListView, bReadable) { } // Default destructor. qjackctlAlsaClientList::~qjackctlAlsaClientList (void) { } // Client finder by id. qjackctlAlsaClient *qjackctlAlsaClientList::findClient ( int iAlsaClient ) { QListIterator iter(clients()); while (iter.hasNext()) { qjackctlAlsaClient *pClient = static_cast (iter.next()); if (iAlsaClient == pClient->alsaClient()) return pClient; } return nullptr; } // Client port finder by id. qjackctlAlsaPort *qjackctlAlsaClientList::findClientPort ( int iAlsaClient, int iAlsaPort ) { qjackctlAlsaClient *pClient = findClient(iAlsaClient); if (pClient == nullptr) return nullptr; return pClient->findPort(iAlsaPort); } // Client:port refreshner. int qjackctlAlsaClientList::updateClientPorts (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return 0; snd_seq_t *pAlsaSeq = pMainForm->alsaSeq(); if (pAlsaSeq == nullptr) return 0; int iDirtyCount = 0; markClientPorts(0); #ifdef CONFIG_ALSA_SEQ unsigned int uiAlsaFlags; if (isReadable()) uiAlsaFlags = SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; else uiAlsaFlags = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; snd_seq_client_info_t *pClientInfo; snd_seq_port_info_t *pPortInfo; snd_seq_client_info_alloca(&pClientInfo); snd_seq_port_info_alloca(&pPortInfo); snd_seq_client_info_set_client(pClientInfo, -1); while (snd_seq_query_next_client(pAlsaSeq, pClientInfo) >= 0) { const int iAlsaClient = snd_seq_client_info_get_client(pClientInfo); if (iAlsaClient > 0) { qjackctlAlsaClient *pClient = findClient(iAlsaClient); snd_seq_port_info_set_client(pPortInfo, iAlsaClient); snd_seq_port_info_set_port(pPortInfo, -1); while (snd_seq_query_next_port(pAlsaSeq, pPortInfo) >= 0) { const unsigned int uiPortCapability = snd_seq_port_info_get_capability(pPortInfo); if (((uiPortCapability & uiAlsaFlags) == uiAlsaFlags) && ((uiPortCapability & SND_SEQ_PORT_CAP_NO_EXPORT) == 0)) { QString sClientName = QString::number(iAlsaClient) + ':'; sClientName += QString::fromUtf8( snd_seq_client_info_get_name(pClientInfo)); qjackctlAlsaPort *pPort = 0; const int iAlsaPort = snd_seq_port_info_get_port(pPortInfo); if (pClient == 0) { pClient = new qjackctlAlsaClient(this); pClient->setClientName(sClientName); iDirtyCount++; } else { pPort = pClient->findPort(iAlsaPort); if (sClientName != pClient->clientName()) { pClient->setClientName(sClientName); iDirtyCount++; } } if (pClient) { QString sPortName = QString::number(iAlsaPort) + ':'; sPortName += QString::fromUtf8( snd_seq_port_info_get_name(pPortInfo)); if (pPort == 0) { pPort = new qjackctlAlsaPort(pClient); pPort->setPortName(sPortName); iDirtyCount++; } else if (sPortName != pPort->portName()) { pPort->setPortName(sPortName); iDirtyCount++; } } if (pPort) pPort->markClientPort(1); } } } } #endif // CONFIG_ALSA_SEQ iDirtyCount += cleanClientPorts(0); return iDirtyCount; } //---------------------------------------------------------------------- // qjackctlAlsaConnect -- Output-to-Input client/ports connection object. // // Constructor. qjackctlAlsaConnect::qjackctlAlsaConnect ( qjackctlConnectView *pConnectView ) : qjackctlConnect(pConnectView) { createIconPixmaps(); setOClientList(new qjackctlAlsaClientList( connectView()->OListView(), true)); setIClientList(new qjackctlAlsaClientList( connectView()->IListView(), false)); } // Default destructor. qjackctlAlsaConnect::~qjackctlAlsaConnect (void) { deleteIconPixmaps(); } // Common pixmap accessor (static). const QPixmap& qjackctlAlsaConnect::pixmap ( int iPixmap ) const { return *m_apPixmaps[iPixmap]; } // Local pixmap-set janitor methods. void qjackctlAlsaConnect::createIconPixmaps (void) { m_apPixmaps[QJACKCTL_ALSA_CLIENTI] = createIconPixmap("mclienti"); m_apPixmaps[QJACKCTL_ALSA_CLIENTO] = createIconPixmap("mcliento"); m_apPixmaps[QJACKCTL_ALSA_PORTI] = createIconPixmap("mporti"); m_apPixmaps[QJACKCTL_ALSA_PORTO] = createIconPixmap("mporto"); } void qjackctlAlsaConnect::deleteIconPixmaps (void) { for (int i = 0; i < QJACKCTL_ALSA_PIXMAPS; i++) { if (m_apPixmaps[i]) delete m_apPixmaps[i]; m_apPixmaps[i] = nullptr; } } #ifndef CONFIG_ALSA_SEQ #if defined(Q_CC_GNU) || defined(Q_CC_MINGW) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif #endif // Connection primitive. bool qjackctlAlsaConnect::connectPorts ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort ) { #ifdef CONFIG_ALSA_SEQ qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return false; snd_seq_t *pAlsaSeq = pMainForm->alsaSeq(); if (pAlsaSeq == nullptr) return false; qjackctlAlsaPort *pOAlsa = static_cast (pOPort); qjackctlAlsaPort *pIAlsa = static_cast (pIPort); snd_seq_port_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_alloca(&pAlsaSubs); seq_addr.client = pOAlsa->alsaClient(); seq_addr.port = pOAlsa->alsaPort(); snd_seq_port_subscribe_set_sender(pAlsaSubs, &seq_addr); seq_addr.client = pIAlsa->alsaClient(); seq_addr.port = pIAlsa->alsaPort(); snd_seq_port_subscribe_set_dest(pAlsaSubs, &seq_addr); return (snd_seq_subscribe_port(pAlsaSeq, pAlsaSubs) >= 0); #else return false; #endif // CONFIG_ALSA_SEQ } // Disconnection primitive. bool qjackctlAlsaConnect::disconnectPorts ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort ) { #ifdef CONFIG_ALSA_SEQ qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return false; snd_seq_t *pAlsaSeq = pMainForm->alsaSeq(); if (pAlsaSeq == nullptr) return false; qjackctlAlsaPort *pOAlsa = static_cast (pOPort); qjackctlAlsaPort *pIAlsa = static_cast (pIPort); snd_seq_port_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_alloca(&pAlsaSubs); seq_addr.client = pOAlsa->alsaClient(); seq_addr.port = pOAlsa->alsaPort(); snd_seq_port_subscribe_set_sender(pAlsaSubs, &seq_addr); seq_addr.client = pIAlsa->alsaClient(); seq_addr.port = pIAlsa->alsaPort(); snd_seq_port_subscribe_set_dest(pAlsaSubs, &seq_addr); return (snd_seq_unsubscribe_port(pAlsaSeq, pAlsaSubs) >= 0); #else return false; #endif // CONFIG_ALSA_SEQ } // Update port connection references. void qjackctlAlsaConnect::updateConnections (void) { #ifdef CONFIG_ALSA_SEQ qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; snd_seq_t *pAlsaSeq = pMainForm->alsaSeq(); if (pAlsaSeq == nullptr) return; snd_seq_query_subscribe_t *pAlsaSubs; snd_seq_addr_t seq_addr; snd_seq_query_subscribe_alloca(&pAlsaSubs); // Proper type casts. qjackctlAlsaClientList *pOClientList = static_cast (OClientList()); qjackctlAlsaClientList *pIClientList = static_cast (IClientList()); // For each output client item... QListIterator oclient(pOClientList->clients()); while (oclient.hasNext()) { qjackctlClientItem *pOClient = oclient.next(); // For each output port item... QListIterator oport(pOClient->ports()); while (oport.hasNext()) { qjackctlPortItem *pOPort = oport.next(); // Are there already any connections? if (pOPort->connects().count() > 0) continue; // Hava a proper type cast. qjackctlAlsaPort *pOAlsa = static_cast (pOPort); // Get port connections... snd_seq_query_subscribe_set_type(pAlsaSubs, SND_SEQ_QUERY_SUBS_READ); snd_seq_query_subscribe_set_index(pAlsaSubs, 0); seq_addr.client = pOAlsa->alsaClient(); seq_addr.port = pOAlsa->alsaPort(); snd_seq_query_subscribe_set_root(pAlsaSubs, &seq_addr); while (snd_seq_query_port_subscribers(pAlsaSeq, pAlsaSubs) >= 0) { seq_addr = *snd_seq_query_subscribe_get_addr(pAlsaSubs); qjackctlPortItem *pIPort = pIClientList->findClientPort( seq_addr.client, seq_addr.port); if (pIPort) { pOPort->addConnect(pIPort); pIPort->addConnect(pOPort); } snd_seq_query_subscribe_set_index(pAlsaSubs, snd_seq_query_subscribe_get_index(pAlsaSubs) + 1); } } } #endif // CONFIG_ALSA_SEQ } #ifndef CONFIG_ALSA_SEQ #if defined(Q_CC_GNU) || defined(Q_CC_MINGW) #pragma GCC diagnostic pop #endif #endif // Update icon size implementation. void qjackctlAlsaConnect::updateIconPixmaps (void) { deleteIconPixmaps(); createIconPixmaps(); } // end of qjackctlAlsaConnect.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlAliases.h0000644000000000000000000000013214771215054016432 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlAliases.h0000644000175000001440000000660514771215054016431 0ustar00rncbcusers// qjackctlAliases.h // /**************************************************************************** Copyright (C) 2003-2020, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlAliases_h #define __qjackctlAliases_h #include #include #include // Client/port item alias map. class qjackctlAliasItem { public: // Constructor. qjackctlAliasItem(const QString& sClientName, const QString& sClientAlias = QString()); // Default destructor. ~qjackctlAliasItem(); // Client name accessor. QString clientName() const; // Client name matcher. bool matchClientName(const QString& sClientName) const; // Client aliasing methods. const QString& clientAlias() const; void setClientAlias(const QString& sClientAlias); // Port aliasing methods. QString portAlias(const QString& sPortName) const; void setPortAlias(const QString& sPortName, const QString& sPortAlias); // Save client/port aliases definitions. void saveSettings(QSettings& settings, const QString& sClientKey); // Need for generic sort. bool operator< (const qjackctlAliasItem& other); // Escape and format a string as a regular expresion. static QString escapeRegExpDigits(const QString& s, int iThreshold = 3); private: // Client name regexp. QRegularExpression m_rxClientName; // Client alias. QString m_sClientAlias; // Port aliases map. QMap m_ports; }; // Client/port list alias map. class qjackctlAliasList : public QList { public: // Constructor. qjackctlAliasList(); // Default destructor. ~qjackctlAliasList(); // Client aliasing methods. QString clientAlias(const QString& sClientName); void setClientAlias(const QString& sClientName, const QString& sClientAlias); // Port aliasing methods. QString portAlias(const QString& sClientName, const QString& sPortName); void setPortAlias(const QString& sClientName, const QString& sPortName,const QString& sPortAlias); // Load/save aliases definitions. void loadSettings(QSettings& settings, const QString& sAliasesKey); void saveSettings(QSettings& settings, const QString& sAliasesKey); private: // Client item finder. qjackctlAliasItem *findClientName (const QString& sClientName); }; // Client/port alias map. class qjackctlAliases { public: // Constructor. qjackctlAliases() : dirty(false) {} qjackctlAliasList audioOutputs; qjackctlAliasList audioInputs; qjackctlAliasList midiOutputs; qjackctlAliasList midiInputs; qjackctlAliasList alsaOutputs; qjackctlAliasList alsaInputs; QString key; bool dirty; }; #endif // __qjackctlAliases_h // end of qjackctlAliases.h qjackctl-1.0.4/src/PaxHeaders/qjackctl.cpp0000644000000000000000000000013214771215054015463 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctl.cpp0000644000175000001440000004451014771215054015457 0ustar00rncbcusers// qjackctl.cpp // /**************************************************************************** Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctl.h" #include "qjackctlMainForm.h" #include "qjackctlPaletteForm.h" #include #include #include #include #include #include #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) #ifdef CONFIG_JACK_VERSION #include #endif #endif #if QT_VERSION < QT_VERSION_CHECK(4, 5, 0) namespace Qt { const WindowFlags WindowCloseButtonHint = WindowFlags(0x08000000); } #endif #ifndef CONFIG_PREFIX #define CONFIG_PREFIX "/usr/local" #endif #ifndef CONFIG_BINDIR #define CONFIG_BINDIR CONFIG_PREFIX "/bin" #endif #ifndef CONFIG_DATADIR #define CONFIG_DATADIR CONFIG_PREFIX "/share" #endif #ifndef CONFIG_LIBDIR #if defined(__x86_64__) #define CONFIG_LIBDIR CONFIG_PREFIX "/lib64" #else #define CONFIG_LIBDIR CONFIG_PREFIX "/lib" #endif #endif #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #define CONFIG_PLUGINSDIR CONFIG_LIBDIR "/qt4/plugins" #elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #define CONFIG_PLUGINSDIR CONFIG_LIBDIR "/qt5/plugins" #else #define CONFIG_PLUGINSDIR CONFIG_LIBDIR "/qt6/plugins" #endif //------------------------------------------------------------------------- // Singleton application instance stuff (Qt/X11 only atm.) // #ifdef CONFIG_XUNIQUE #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #ifdef CONFIG_X11 #define QJACKCTL_XUNIQUE "qjackctlApplication" #include /* for gethostname() */ #include #include #endif // CONFIG_X11 #else #include #if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) #include #endif #include #include #include #endif #endif // CONFIG_XUNIQUE // Constructor. qjackctlApplication::qjackctlApplication ( int& argc, char **argv ) : QApplication(argc, argv), m_pQtTranslator(nullptr), m_pMyTranslator(nullptr), m_pWidget(nullptr) #ifdef CONFIG_XUNIQUE #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #ifdef CONFIG_X11 , m_pDisplay(nullptr) , m_aUnique(0) , m_wOwner(0) #endif // CONFIG_X11 #else , m_pMemory(nullptr) , m_pServer(nullptr) #endif #endif // CONFIG_XUNIQUE { #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) QApplication::setApplicationName(QJACKCTL_TITLE); QApplication::setApplicationDisplayName(QJACKCTL_TITLE); // QJACKCTL_TITLE " - " + QObject::tr(QJACKCTL_SUBTITLE)); #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) QApplication::setDesktopFileName( QString("org.rncbc.%1").arg(PROJECT_NAME)); #endif QApplication::setApplicationVersion(PROJECT_VERSION); #endif // Load translation support. QLocale loc; if (loc.language() != QLocale::C) { // Try own Qt translation... m_pQtTranslator = new QTranslator(this); QString sLocName = "qt_" + loc.name(); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) QString sLocPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath); #else QString sLocPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); #endif if (m_pQtTranslator->load(sLocName, sLocPath)) { QApplication::installTranslator(m_pQtTranslator); } else { delete m_pQtTranslator; m_pQtTranslator = nullptr; #ifdef CONFIG_DEBUG qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", loc.name().toUtf8().constData(), sLocPath.toUtf8().constData(), sLocName.toUtf8().constData()); #endif } // Try own application translation... m_pMyTranslator = new QTranslator(this); sLocName = "qjackctl_" + loc.name(); if (m_pMyTranslator->load(sLocName, sLocPath)) { QApplication::installTranslator(m_pMyTranslator); } else { sLocPath = QApplication::applicationDirPath(); #ifndef _WIN32 sLocPath.remove(CONFIG_BINDIR); sLocPath.append(CONFIG_DATADIR "/qjackctl/translations"); #else sLocPath.append("/translations"); #endif if (m_pMyTranslator->load(sLocName, sLocPath)) { QApplication::installTranslator(m_pMyTranslator); } else { delete m_pMyTranslator; m_pMyTranslator = nullptr; #ifdef CONFIG_DEBUG qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", loc.name().toUtf8().constData(), sLocPath.toUtf8().constData(), sLocName.toUtf8().constData()); #endif } } } } // Destructor. qjackctlApplication::~qjackctlApplication (void) { #ifdef CONFIG_XUNIQUE #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) clearServer(); #endif #endif // CONFIG_XUNIQUE if (m_pMyTranslator) delete m_pMyTranslator; if (m_pQtTranslator) delete m_pQtTranslator; } // Main application widget accessors. void qjackctlApplication::setMainWidget ( QWidget *pWidget ) { m_pWidget = pWidget; #ifdef CONFIG_XUNIQUE #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #ifdef CONFIG_X11 m_wOwner = m_pWidget->winId(); if (m_pDisplay && m_wOwner) { XGrabServer(m_pDisplay); XSetSelectionOwner(m_pDisplay, m_aUnique, m_wOwner, CurrentTime); XUngrabServer(m_pDisplay); } #endif // CONFIG_X11 #endif #endif // CONFIG_XUNIQUE } // Check if another instance is running, // and raise its proper main widget... bool qjackctlApplication::setup ( const QString& sServerName ) { #ifdef CONFIG_XUNIQUE m_sServerName = sServerName; #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #ifdef CONFIG_X11 m_pDisplay = QX11Info::display(); if (m_pDisplay) { QString sUnique = QJACKCTL_XUNIQUE; QString sUserName = QString::fromUtf8(::getenv("USER")); if (sUserName.isEmpty()) sUserName = QString::fromUtf8(::getenv("USERNAME")); if (!sUserName.isEmpty()) { sUnique += ':'; sUnique += sUserName; } if (sServerName.isEmpty()) { const char *pszServerName = ::getenv("JACK_DEFAULT_SERVER"); if (pszServerName && ::strcmp("default", pszServerName)) { sUnique += '_'; sUnique += QString::fromUtf8(pszServerName); } } else { sUnique += '_'; sUnique += sServerName; } char szHostName[255]; if (::gethostname(szHostName, sizeof(szHostName)) == 0) { sUnique += '@'; sUnique += szHostName; } m_aUnique = XInternAtom(m_pDisplay, sUnique.toUtf8().constData(), false); XGrabServer(m_pDisplay); m_wOwner = XGetSelectionOwner(m_pDisplay, m_aUnique); XUngrabServer(m_pDisplay); if (m_wOwner != None) { // First, notify any freedesktop.org WM // that we're about to show the main widget... Screen *pScreen = XDefaultScreenOfDisplay(m_pDisplay); int iScreen = XScreenNumberOfScreen(pScreen); XEvent ev; memset(&ev, 0, sizeof(ev)); ev.xclient.type = ClientMessage; ev.xclient.display = m_pDisplay; ev.xclient.window = m_wOwner; ev.xclient.message_type = XInternAtom(m_pDisplay, "_NET_ACTIVE_WINDOW", false); ev.xclient.format = 32; ev.xclient.data.l[0] = 0; // Source indication. ev.xclient.data.l[1] = 0; // Timestamp. ev.xclient.data.l[2] = 0; // Requestor's currently active window (none) ev.xclient.data.l[3] = 0; ev.xclient.data.l[4] = 0; XSelectInput(m_pDisplay, m_wOwner, StructureNotifyMask); XSendEvent(m_pDisplay, RootWindow(m_pDisplay, iScreen), false, (SubstructureNotifyMask | SubstructureRedirectMask), &ev); XSync(m_pDisplay, false); XRaiseWindow(m_pDisplay, m_wOwner); // And then, let it get caught on destination // by QApplication::native/x11EventFilter... const QByteArray value = QJACKCTL_XUNIQUE; XChangeProperty( m_pDisplay, m_wOwner, m_aUnique, m_aUnique, 8, PropModeReplace, (unsigned char *) value.data(), value.length()); // Done. return true; } } #endif // CONFIG_X11 return false; #else return setupServer(); #endif #else return false; #endif // !CONFIG_XUNIQUE } #ifdef CONFIG_XUNIQUE #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #ifdef CONFIG_X11 void qjackctlApplication::x11PropertyNotify ( Window w ) { if (m_pDisplay && m_pWidget && m_wOwner == w) { // Always check whether our property-flag is still around... Atom aType; int iFormat = 0; unsigned long iItems = 0; unsigned long iAfter = 0; unsigned char *pData = 0; if (XGetWindowProperty( m_pDisplay, m_wOwner, m_aUnique, 0, 1024, false, m_aUnique, &aType, &iFormat, &iItems, &iAfter, &pData) == Success && aType == m_aUnique && iItems > 0 && iAfter == 0) { // Avoid repeating it-self... XDeleteProperty(m_pDisplay, m_wOwner, m_aUnique); // Just make it always shows up fine... m_pWidget->showNormal(); m_pWidget->raise(); m_pWidget->activateWindow(); // FIXME: Do our best speciality, although it should be // done iif configuration says so, we'll do it anyway! qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->startJack(); } // Free any left-overs... if (iItems > 0 && pData) XFree(pData); } } bool qjackctlApplication::x11EventFilter ( XEvent *pEv ) { if (pEv->type == PropertyNotify && pEv->xproperty.state == PropertyNewValue) x11PropertyNotify(pEv->xproperty.window); return QApplication::x11EventFilter(pEv); } #endif // CONFIG_X11 #else // Local server/shmem setup. bool qjackctlApplication::setupServer (void) { clearServer(); m_sUnique = QCoreApplication::applicationName(); if (!m_sServerName.isEmpty()) { m_sUnique += '-'; m_sUnique += m_sServerName; } QString sUserName = QString::fromUtf8(::getenv("USER")); if (sUserName.isEmpty()) sUserName = QString::fromUtf8(::getenv("USERNAME")); if (!sUserName.isEmpty()) { m_sUnique += ':'; m_sUnique += sUserName; } m_sUnique += '@'; m_sUnique += QHostInfo::localHostName(); #if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) const QNativeIpcKey nativeKey = QSharedMemory::legacyNativeKey(m_sUnique); #if defined(Q_OS_UNIX) m_pMemory = new QSharedMemory(nativeKey); m_pMemory->attach(); delete m_pMemory; #endif m_pMemory = new QSharedMemory(nativeKey); #else #if defined(Q_OS_UNIX) m_pMemory = new QSharedMemory(m_sUnique); m_pMemory->attach(); delete m_pMemory; #endif m_pMemory = new QSharedMemory(m_sUnique); #endif bool bServer = false; const qint64 pid = QCoreApplication::applicationPid(); struct Data { qint64 pid; }; if (m_pMemory->create(sizeof(Data))) { m_pMemory->lock(); Data *pData = static_cast (m_pMemory->data()); if (pData) { pData->pid = pid; bServer = true; } m_pMemory->unlock(); } else if (m_pMemory->attach()) { m_pMemory->lock(); // maybe not necessary? Data *pData = static_cast (m_pMemory->data()); if (pData) bServer = (pData->pid == pid); m_pMemory->unlock(); } if (bServer) { QLocalServer::removeServer(m_sUnique); m_pServer = new QLocalServer(); m_pServer->setSocketOptions(QLocalServer::UserAccessOption); m_pServer->listen(m_sUnique); QObject::connect(m_pServer, SIGNAL(newConnection()), SLOT(newConnectionSlot())); } else { QLocalSocket socket; socket.connectToServer(m_sUnique); if (socket.state() == QLocalSocket::ConnectingState) socket.waitForConnected(200); if (socket.state() == QLocalSocket::ConnectedState) { socket.write(QCoreApplication::arguments().join(' ').toUtf8()); socket.flush(); socket.waitForBytesWritten(200); } } return !bServer; } // Local server/shmem cleanup. void qjackctlApplication::clearServer (void) { if (m_pServer) { m_pServer->close(); delete m_pServer; m_pServer = nullptr; } if (m_pMemory) { delete m_pMemory; m_pMemory = nullptr; } m_sUnique.clear(); } // Local server conection slot. void qjackctlApplication::newConnectionSlot (void) { QLocalSocket *pSocket = m_pServer->nextPendingConnection(); QObject::connect(pSocket, SIGNAL(readyRead()), SLOT(readyReadSlot())); } // Local server data-ready slot. void qjackctlApplication::readyReadSlot (void) { QLocalSocket *pSocket = qobject_cast (sender()); if (pSocket) { const qint64 nread = pSocket->bytesAvailable(); if (nread > 0) { const QByteArray data = pSocket->read(nread); // Just make it always shows up fine... if (m_pWidget) { m_pWidget->showNormal(); m_pWidget->raise(); m_pWidget->activateWindow(); } // FIXME: Do our best speciality, although it should be // done iif configuration says so, we'll do it anyway! qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) { // Parse the pass-through command line arguments... const QStringList& args = QString::fromUtf8(data).split(' '); const int argc = args.count(); for (int i = 1; i < argc; ++i) { QString sArg = args.at(i); QString sVal; const int iEqual = sArg.indexOf('='); if (iEqual >= 0) { sVal = sArg.right(sArg.length() - iEqual - 1); sArg = sArg.left(iEqual); } else if (i < argc - 1) sVal = args.at(i + 1); if (sArg == "-s" || sArg == "--start") { pMainForm->startJack(); } else if (sArg == "-p" || sArg == "--preset") { if (!sVal.isEmpty()) pMainForm->activatePreset(sVal); if (iEqual < 0) ++i; } else if (sArg == "-a" || sArg == "--active-patchbay") { if (!sVal.isEmpty()) pMainForm->activatePatchbay(sVal); if (iEqual < 0) ++i; } } } // Reset the server... setupServer(); } } } #endif #endif // CONFIG_XUNIQUE //------------------------------------------------------------------------- // stacktrace - Signal crash handler. // #ifdef CONFIG_STACKTRACE #if defined(__GNUC__) && defined(Q_OS_LINUX) #include #include #include #include #include void stacktrace ( int signo ) { pid_t pid; int rc; int status = 0; char cmd[80]; // Reinstall default handler; prevent race conditions... ::signal(signo, SIG_DFL); static const char *shell = "/bin/sh"; static const char *format = "gdb -q --batch --pid=%d" " --eval-command='thread apply all bt'"; snprintf(cmd, sizeof(cmd), format, (int) getpid()); pid = fork(); // Fork failure! if (pid < 0) return; // Fork child... if (pid == 0) { execl(shell, shell, "-c", cmd, nullptr); _exit(1); return; } // Parent here: wait for child to terminate... do { rc = waitpid(pid, &status, 0); } while ((rc < 0) && (errno == EINTR)); // Dispatch any logging, if any... QApplication::processEvents(QEventLoop::AllEvents, 3000); // Make sure everyone terminates... kill(pid, SIGTERM); _exit(1); } #endif #endif //------------------------------------------------------------------------- // main - The main program trunk. // int main ( int argc, char **argv ) { Q_INIT_RESOURCE(qjackctl); #ifdef CONFIG_STACKTRACE #if defined(__GNUC__) && defined(Q_OS_LINUX) ::signal(SIGILL, stacktrace); ::signal(SIGFPE, stacktrace); ::signal(SIGSEGV, stacktrace); ::signal(SIGABRT, stacktrace); ::signal(SIGBUS, stacktrace); #endif #endif #if defined(Q_OS_LINUX) && !defined(CONFIG_WAYLAND) ::setenv("QT_QPA_PLATFORM", "xcb", 0); #endif #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif #endif qjackctlApplication app(argc, argv); // Construct default settings; override with command line arguments. qjackctlSetup setup; if (!setup.parse_args(app.arguments())) { app.quit(); return 1; } // Check if we'll just start an external program... if (!setup.cmdLine.isEmpty()) { jack_client_t *pJackClient = jack_client_open("qjackctl-start", JackNoStartServer, nullptr); if (pJackClient) { jack_client_close(pJackClient); const int iExitStatus = ::system(setup.cmdLine.join(' ').toUtf8().constData()); app.quit(); return iExitStatus; } } // Have another instance running? if (setup.bSingleton) { if (app.setup(setup.sServerName)) { app.quit(); return 2; } } // Special custom styles... if (QDir(CONFIG_PLUGINSDIR).exists()) app.addLibraryPath(CONFIG_PLUGINSDIR); if (!setup.sCustomStyleTheme.isEmpty()) app.setStyle(QStyleFactory::create(setup.sCustomStyleTheme)); // Custom color theme (eg. "KXStudio")... const QChar sep = QDir::separator(); QString sPalettePath = QApplication::applicationDirPath(); sPalettePath.remove(CONFIG_BINDIR); sPalettePath.append(CONFIG_DATADIR); sPalettePath.append(sep); sPalettePath.append(PROJECT_NAME); sPalettePath.append(sep); sPalettePath.append("palette"); if (QDir(sPalettePath).exists()) { QStringList names; names.append("KXStudio"); names.append("Wonton Soup"); QStringListIterator name_iter(names); while (name_iter.hasNext()) { const QString& name = name_iter.next(); const QFileInfo fi(sPalettePath, name + ".conf"); if (fi.isReadable()) { qjackctlPaletteForm::addNamedPaletteConf( &setup.settings(), name, fi.absoluteFilePath()); } } } QPalette pal(app.palette()); if (qjackctlPaletteForm::namedPalette( &setup.settings(), setup.sCustomColorTheme, pal)) app.setPalette(pal); // Set default base font... if (setup.iBaseFontSize > 0) app.setFont(QFont(app.font().family(), setup.iBaseFontSize)); // What style do we create these forms? Qt::WindowFlags wflags = Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint; if (setup.bKeepOnTop) wflags |= Qt::Tool; // Construct the main form, and show it to the world. qjackctlMainForm w(0, wflags); w.setup(&setup); // If we have a systray icon, we'll skip this. if (!setup.bSystemTray) { w.show(); w.adjustSize(); } // Settle this one as application main widget... app.setMainWidget(&w); // Settle session manager shutdown (eg. logoff)... QObject::connect( &app, SIGNAL(commitDataRequest(QSessionManager&)), &w, SLOT(commitData(QSessionManager&)), Qt::DirectConnection); // Register the quit signal/slot. app.setQuitOnLastWindowClosed(false); return app.exec(); } // end of qjackctl.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlGraphForm.h0000644000000000000000000000013214771215054016736 xustar0030 mtime=1743067692.325636584 30 atime=1743067692.325636584 30 ctime=1743067692.325636584 qjackctl-1.0.4/src/qjackctlGraphForm.h0000644000175000001440000001330214771215054016725 0ustar00rncbcusers// qjackctlGraphForm.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlGraphForm_h #define __qjackctlGraphForm_h #include "ui_qjackctlGraphForm.h" // Forward decls. class qjackctlGraphConfig; class qjackctlGraphSect; class qjackctlAlsaGraph; class qjackctlJackGraph; class qjackctlGraphPort; class qjackctlGraphConnect; class qjackctlGraphThumb; class qjackctlSetup; class QResizeEvent; class QCloseEvent; class QSlider; class QSpinBox; class QActionGroup; // Forwards decls. class QSettings; class QMainWindow; //---------------------------------------------------------------------------- // qjackctlGraphForm -- UI wrapper form. class qjackctlGraphForm : public QMainWindow { Q_OBJECT public: // Constructor. qjackctlGraphForm(QWidget *parent = nullptr, Qt::WindowFlags wflags = Qt::WindowFlags()); // Destructor. ~qjackctlGraphForm(); // Initializer. void setup(qjackctlSetup *pSetup); // Update the canvas palette. void updatePalette(); public slots: // Graph view change slot. void changed(); // Graph section slots. void jack_shutdown(); void jack_changed(); void alsa_changed(); // Graph refreshner. void refresh(); protected slots: // Node life-cycle slots void added(qjackctlGraphNode *node); void updated(qjackctlGraphNode *node); void removed(qjackctlGraphNode *node); // Port (dis)connection slots. void connected(qjackctlGraphPort *port1, qjackctlGraphPort *port2); void disconnected(qjackctlGraphPort *port1, qjackctlGraphPort *port2); void connected(qjackctlGraphConnect *connect); // Item renaming slot. void renamed(qjackctlGraphItem *item, const QString& name); // Graph selection change slot. void stabilize(); // Tool-bar orientation change slot. void orientationChanged(Qt::Orientation orientation); // Main menu slots. void viewMenubar(bool on); void viewToolbar(bool on); void viewStatusbar(bool on); void viewThumbviewAction(); void viewThumbview(int thumbview); void viewTextBesideIcons(bool on); void viewCenter(); void viewRefresh(); void viewZoomRange(bool on); void viewSortTypeAction(); void viewSortOrderAction(); void viewColorsAction(); void viewColorsReset(); void viewRepelOverlappingNodes(bool on); void viewConnectThroughNodes(bool on); void helpAbout(); void helpAboutQt(); void thumbviewContextMenu(const QPoint& pos); void zoomValueChanged(int zoom_value); protected: // Context-menu event handler. void contextMenuEvent(QContextMenuEvent *pContextMenuEvent); // Widget resize event handler. void resizeEvent(QResizeEvent *pResizeEvent); // Widget show/hide/close event handlers. void showEvent(QShowEvent *pShowEvent); void hideEvent(QHideEvent *pHideEvent); void closeEvent(QCloseEvent *pCloseEvent); // Special port-type color method. void updateViewColorsAction(QAction *action); void updateViewColors(); // Item sect predicate. qjackctlGraphSect *item_sect(qjackctlGraphItem *item) const; private: // The Qt-designer UI struct... Ui::qjackctlGraphForm m_ui; // Instance variables. qjackctlGraphConfig *m_config; // Instance variables. qjackctlJackGraph *m_jack; qjackctlAlsaGraph *m_alsa; int m_jack_changed; int m_alsa_changed; int m_ins, m_mids, m_outs; int m_repel_overlapping_nodes; QSlider *m_zoom_slider; QSpinBox *m_zoom_spinbox; QActionGroup *m_sort_type; QActionGroup *m_sort_order; QActionGroup *m_thumb_mode; qjackctlGraphThumb *m_thumb; int m_thumb_update; }; //---------------------------------------------------------------------------- // qjackctlGraphConfig -- Canvas state memento. class qjackctlGraphConfig { public: // Constructor. qjackctlGraphConfig(QSettings *settings); // Accessors. QSettings *settings() const; void setMenubar(bool menubar); bool isMenubar() const; void setToolbar(bool toolbar); bool isToolbar() const; void setStatusbar(bool statusbar); bool isStatusbar() const; void setThumbview(int thumbview); int thumbview() const; void setTextBesideIcons(bool texticons); bool isTextBesideIcons() const; void setZoomRange(bool zoomrange); bool isZoomRange() const; void setSortType(int sorttype); int sortType() const; void setSortOrder(int sortorder); int sortOrder() const; void setRepelOverlappingNodes(bool repelnodes); bool isRepelOverlappingNodes() const; void setConnectThroughNodes(bool repelnodes); bool isConnectThroughNodes() const; // Graph main-widget state methods. bool restoreState(QMainWindow *widget); bool saveState(QMainWindow *widget) const; private: // Instance variables. QSettings *m_settings; bool m_menubar; bool m_toolbar; bool m_statusbar; int m_thumbview; bool m_texticons; bool m_zoomrange; int m_sorttype; int m_sortorder; bool m_repelnodes; bool m_cthrunodes; }; #endif // __qjackctlGraphForm_h // end of qjackctlGraphForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlGraphCommand.cpp0000644000000000000000000000013214771215054017744 xustar0030 mtime=1743067692.324636588 30 atime=1743067692.324636588 30 ctime=1743067692.324636588 qjackctl-1.0.4/src/qjackctlGraphCommand.cpp0000644000175000001440000001643314771215054017743 0ustar00rncbcusers// qjackctlGraphCommand.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAbout.h" #include "qjackctlGraphCommand.h" //---------------------------------------------------------------------------- // qjackctlGraphCommand -- Generic graph command pattern // Constructor. qjackctlGraphCommand::qjackctlGraphCommand ( qjackctlGraphCanvas *canvas, QUndoCommand *parent ) : QUndoCommand(parent), m_canvas(canvas) { } // Command methods. void qjackctlGraphCommand::undo (void) { execute(true); } void qjackctlGraphCommand::redo (void) { execute(false); } //---------------------------------------------------------------------------- // qjackctlGraphConnectCommand -- Connect graph command pattern // Constructor. qjackctlGraphConnectCommand::qjackctlGraphConnectCommand ( qjackctlGraphCanvas *canvas, qjackctlGraphPort *port1, qjackctlGraphPort *port2, bool is_connect, qjackctlGraphCommand *parent ) : qjackctlGraphCommand(canvas, parent), m_item(port1, port2, is_connect) { } // Command executive bool qjackctlGraphConnectCommand::execute ( bool is_undo ) { qjackctlGraphCanvas *canvas = qjackctlGraphCommand::canvas(); if (canvas == nullptr) return false; qjackctlGraphNode *node1 = canvas->findNode( m_item.addr1.node_name, qjackctlGraphItem::Output, m_item.addr1.node_type); if (node1 == nullptr) node1 = canvas->findNode( m_item.addr1.node_name, qjackctlGraphItem::Duplex, m_item.addr1.node_type); if (node1 == nullptr) return false; qjackctlGraphPort *port1 = node1->findPort( m_item.addr1.port_name, qjackctlGraphItem::Output, m_item.addr1.port_type); if (port1 == nullptr) return false; qjackctlGraphNode *node2 = canvas->findNode( m_item.addr2.node_name, qjackctlGraphItem::Input, m_item.addr2.node_type); if (node2 == nullptr) node2 = canvas->findNode( m_item.addr2.node_name, qjackctlGraphItem::Duplex, m_item.addr2.node_type); if (node2 == nullptr) return false; qjackctlGraphPort *port2 = node2->findPort( m_item.addr2.port_name, qjackctlGraphItem::Input, m_item.addr2.port_type); if (port2 == nullptr) return false; const bool is_connect = (m_item.is_connect() && !is_undo) || (!m_item.is_connect() && is_undo); if (is_connect) canvas->emitConnected(port1, port2); else canvas->emitDisconnected(port1, port2); return true; } //---------------------------------------------------------------------------- // qjackctlGraphMoveCommand -- Move (node) graph command // Constructor. qjackctlGraphMoveCommand::qjackctlGraphMoveCommand ( qjackctlGraphCanvas *canvas, const QList& nodes, const QPointF& pos1, const QPointF& pos2, qjackctlGraphCommand *parent ) : qjackctlGraphCommand(canvas, parent), m_nexec(0) { qjackctlGraphCommand::setText(QObject::tr("Move")); const QPointF delta = (pos1 - pos2); foreach (qjackctlGraphNode *node, nodes) { Item *item = new Item; item->node_name = node->nodeName(); item->node_mode = node->nodeMode(); item->node_type = node->nodeType(); const QPointF& pos = node->pos(); item->node_pos1 = pos + delta; item->node_pos2 = pos; m_items.insert(node, item); } if (canvas && canvas->isRepelOverlappingNodes()) { foreach (qjackctlGraphNode *node, nodes) canvas->repelOverlappingNodes(node, this); } } // Destructor. qjackctlGraphMoveCommand::~qjackctlGraphMoveCommand (void) { qDeleteAll(m_items); m_items.clear(); } // Add/replace (an already moved) node position for undo/redo... void qjackctlGraphMoveCommand::addItem ( qjackctlGraphNode *node, const QPointF& pos1, const QPointF& pos2 ) { Item *item = m_items.value(node, nullptr); if (item) { // item->node_pos1 = pos1; item->node_pos2 = pos2;//node->pos(); } else { item = new Item; item->node_name = node->nodeName(); item->node_mode = node->nodeMode(); item->node_type = node->nodeType(); item->node_pos1 = pos1; item->node_pos2 = pos2;//node->pos(); m_items.insert(node, item); } } // Command executive method. bool qjackctlGraphMoveCommand::execute ( bool /* is_undo */ ) { qjackctlGraphCanvas *canvas = qjackctlGraphCommand::canvas(); if (canvas == nullptr) return false; if (++m_nexec > 1) { foreach (qjackctlGraphNode *key, m_items.keys()) { Item *item = m_items.value(key, nullptr); if (item) { qjackctlGraphNode *node = canvas->findNode( item->node_name, item->node_mode, item->node_type); if (node) { const QPointF pos1 = item->node_pos1; node->setPos(pos1); item->node_pos1 = item->node_pos2; item->node_pos2 = pos1; } } } } canvas->emitChanged(); return true; } //---------------------------------------------------------------------------- // qjackctlGraphRenameCommand -- Rename (item) graph command // Constructor. qjackctlGraphRenameCommand::qjackctlGraphRenameCommand ( qjackctlGraphCanvas *canvas, qjackctlGraphItem *item, const QString& name, qjackctlGraphCommand *parent ) : qjackctlGraphCommand(canvas, parent), m_name(name) { qjackctlGraphCommand::setText(QObject::tr("Rename")); m_item.item_type = item->type(); qjackctlGraphNode *node = nullptr; qjackctlGraphPort *port = nullptr; if (m_item.item_type == qjackctlGraphNode::Type) node = static_cast (item); else if (m_item.item_type == qjackctlGraphPort::Type) port = static_cast (item); if (port) node = port->portNode(); if (node) { m_item.node_name = node->nodeName(); m_item.node_mode = node->nodeMode(); m_item.node_type = node->nodeType(); } if (port) { m_item.port_name = port->portName(); m_item.port_mode = port->portMode(); m_item.port_type = port->portType(); } } // Command executive method. bool qjackctlGraphRenameCommand::execute ( bool /*is_undo*/ ) { qjackctlGraphCanvas *canvas = qjackctlGraphCommand::canvas(); if (canvas == nullptr) return false; QString name = m_name; qjackctlGraphItem *item = nullptr; qjackctlGraphNode *node = canvas->findNode( m_item.node_name, m_item.node_mode, m_item.node_type); if (m_item.item_type == qjackctlGraphNode::Type && node) { m_name = node->nodeTitle(); item = node; } else if (m_item.item_type == qjackctlGraphPort::Type && node) { qjackctlGraphPort *port = node->findPort( m_item.port_name, m_item.port_mode, m_item.port_type); if (port) { m_name = port->portTitle(); item = port; } } if (item == nullptr) return false; canvas->emitRenamed(item, name); return true; } // end of qjackctlGraphCommand.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlJackConnect.cpp0000644000000000000000000000013214771215054017566 xustar0030 mtime=1743067692.325636584 30 atime=1743067692.325636584 30 ctime=1743067692.325636584 qjackctl-1.0.4/src/qjackctlJackConnect.cpp0000644000175000001440000004577214771215054017575 0ustar00rncbcusers// qjackctlJackConnect.cpp // /**************************************************************************** Copyright (C) 2003-2023, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlJackConnect.h" #include "qjackctlMainForm.h" #include #ifdef CONFIG_JACK_METADATA #include #include static QString prettyName ( jack_uuid_t uuid ) { QString sPrettyName; char *pszValue = nullptr; char *pszType = nullptr; if (::jack_get_property(uuid, JACK_METADATA_PRETTY_NAME, &pszValue, &pszType) == 0) { if (pszValue) { sPrettyName = QString::fromUtf8(pszValue); ::jack_free(pszValue); } if (pszType) ::jack_free(pszType); } return sPrettyName; } static void setPrettyName ( jack_client_t *pJackClient, jack_uuid_t uuid, const QString& sPrettyName ) { const QByteArray aPrettyName = sPrettyName.toUtf8(); ::jack_set_property(pJackClient, uuid, JACK_METADATA_PRETTY_NAME, aPrettyName.constData(), nullptr); } static void removePrettyName ( jack_client_t *pJackClient, jack_uuid_t uuid ) { ::jack_remove_property(pJackClient, uuid, JACK_METADATA_PRETTY_NAME); } #endif //---------------------------------------------------------------------- // class qjackctlJackPort -- Jack port list item. // // Constructor. qjackctlJackPort::qjackctlJackPort ( qjackctlJackClient *pClient, unsigned long ulPortFlags ) : qjackctlPortItem(pClient) { qjackctlJackConnect *pJackConnect = static_cast ( ((pClient->clientList())->listView())->binding()); if (pJackConnect) { if (ulPortFlags & JackPortIsInput) { if (ulPortFlags & JackPortIsTerminal) { QTreeWidgetItem::setIcon(0, QIcon(pJackConnect->pixmap( ulPortFlags & JackPortIsPhysical ? QJACKCTL_JACK_PORTPTI : QJACKCTL_JACK_PORTLTI))); } else { QTreeWidgetItem::setIcon(0, QIcon(pJackConnect->pixmap( ulPortFlags & JackPortIsPhysical ? QJACKCTL_JACK_PORTPNI : QJACKCTL_JACK_PORTLNI))); } } else if (ulPortFlags & JackPortIsOutput) { if (ulPortFlags & JackPortIsTerminal) { QTreeWidgetItem::setIcon(0, QIcon(pJackConnect->pixmap( ulPortFlags & JackPortIsPhysical ? QJACKCTL_JACK_PORTPTO : QJACKCTL_JACK_PORTLTO))); } else { QTreeWidgetItem::setIcon(0, QIcon(pJackConnect->pixmap( ulPortFlags & JackPortIsPhysical ? QJACKCTL_JACK_PORTPNO : QJACKCTL_JACK_PORTLNO))); } } } } // Default destructor. qjackctlJackPort::~qjackctlJackPort (void) { } // Pretty/display name method (virtual override). void qjackctlJackPort::updatePortName ( bool bRename ) { #ifdef CONFIG_JACK_METADATA jack_client_t *pJackClient = nullptr; qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pJackClient = pMainForm->jackClient(); if (pJackClient && qjackctlJackClientList::isJackClientPortMetadata()) { bool bRenameEnabled = false; QString sPortNameEx = portNameAlias(&bRenameEnabled); const QString& sPortName = portName(); const QString& sClientPort = clientName() + ':' + sPortName; const QByteArray aClientPort = sClientPort.toUtf8(); const char *pszClientPort = aClientPort.constData(); jack_port_t *pJackPort = jack_port_by_name(pJackClient, pszClientPort); if (pJackPort) { jack_uuid_t port_uuid = ::jack_port_uuid(pJackPort); const QString& sPrettyName = prettyName(port_uuid); if (sPortNameEx != sPortName && sPortNameEx != sPrettyName) { if (sPrettyName.isEmpty() || bRename) { setPrettyName(pJackClient, port_uuid, sPortNameEx); } else { sPortNameEx = sPrettyName; setPortNameAlias(sPortNameEx); } } else if (sPortNameEx == sPortName && !sPrettyName.isEmpty() && bRename) { removePrettyName(pJackClient, port_uuid); } setPortText(sPortNameEx, bRenameEnabled); } } else #endif qjackctlPortItem::updatePortName(bRename); } // Tooltip text builder (virtual override). QString qjackctlJackPort::tooltip (void) const { jack_client_t *pJackClient = nullptr; qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pJackClient = pMainForm->jackClient(); if (pJackClient) { const QString& sPortName = portName(); const QString& sClientPort = clientName() + ':' + sPortName; const QByteArray aClientPort = sClientPort.toUtf8(); const char *pszClientPort = aClientPort.constData(); jack_port_t *pJackPort = jack_port_by_name(pJackClient, pszClientPort); if (pJackPort) { jack_latency_range_t latency_range; jack_port_get_latency_range(pJackPort, client()->isReadable() ? JackCaptureLatency : JackPlaybackLatency, &latency_range); QString sLatency = QString::number(latency_range.min); if (latency_range.max > latency_range.min) sLatency += '-' + QString::number(latency_range.max); return QObject::tr("%1 (%2 frames)").arg(portName()).arg(sLatency); } } return portName(); } //---------------------------------------------------------------------- // class qjackctlJackClient -- Jack client list item. // // Constructor. qjackctlJackClient::qjackctlJackClient ( qjackctlJackClientList *pClientList ) : qjackctlClientItem(pClientList) { qjackctlJackConnect *pJackConnect = static_cast ( (pClientList->listView())->binding()); if (pJackConnect) { if (pClientList->isReadable()) { QTreeWidgetItem::setIcon(0, QIcon(pJackConnect->pixmap(QJACKCTL_JACK_CLIENTO))); } else { QTreeWidgetItem::setIcon(0, QIcon(pJackConnect->pixmap(QJACKCTL_JACK_CLIENTI))); } } } // Default destructor. qjackctlJackClient::~qjackctlJackClient (void) { } // Jack port lookup. qjackctlJackPort *qjackctlJackClient::findJackPort ( const QString& sPortName ) { QListIterator iter(ports()); while (iter.hasNext()) { qjackctlJackPort *pPort = static_cast (iter.next()); if (pPort && pPort->portName() == sPortName) return pPort; } return nullptr; } // Pretty/display name method (virtual override). void qjackctlJackClient::updateClientName ( bool bRename ) { #ifdef CONFIG_JACK_METADATA jack_client_t *pJackClient = nullptr; qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pJackClient = pMainForm->jackClient(); if (pJackClient && qjackctlJackClientList::isJackClientPortMetadata()) { bool bRenameEnabled = false; QString sClientNameEx = clientNameAlias(&bRenameEnabled); const QString& sClientName = clientName(); const QByteArray aClientName = sClientName.toUtf8(); const char *pszClientUuid = ::jack_get_uuid_for_client_name(pJackClient, aClientName.constData()); if (pszClientUuid) { jack_uuid_t client_uuid = 0; ::jack_uuid_parse(pszClientUuid, &client_uuid); const QString& sPrettyName = prettyName(client_uuid); if (sClientNameEx != sClientName && sClientNameEx != sPrettyName) { if (sPrettyName.isEmpty() || bRename) { setPrettyName(pJackClient, client_uuid, sClientNameEx); } else { sClientNameEx = sPrettyName; setClientNameAlias(sClientNameEx); } } else if (sClientNameEx == sClientName && !sPrettyName.isEmpty() && bRename) { removePrettyName(pJackClient, client_uuid); } ::jack_free((void *) pszClientUuid); } setClientText(sClientNameEx, bRenameEnabled); } else #endif qjackctlClientItem::updateClientName(bRename); } //---------------------------------------------------------------------- // qjackctlJackClientList -- Jack client list. // // Constructor. qjackctlJackClientList::qjackctlJackClientList ( qjackctlClientListView *pListView, bool bReadable ) : qjackctlClientList(pListView, bReadable) { } // Default destructor. qjackctlJackClientList::~qjackctlJackClientList (void) { } // Jack port lookup. qjackctlJackPort *qjackctlJackClientList::findJackClientPort ( const QString& sClientPort ) { const int iColon = sClientPort.indexOf(':'); if (iColon < 0) return nullptr; const QString& sClientName = sClientPort.left(iColon); const QString& sPortName = sClientPort.right(sClientPort.length() - iColon - 1); QListIterator iter(clients()); while (iter.hasNext()) { qjackctlJackClient *pClient = static_cast (iter.next()); if (pClient && pClient->clientName() == sClientName) { qjackctlJackPort *pPort = pClient->findJackPort(sPortName); if (pPort) return pPort; } } return nullptr; } // Client:port refreshner. int qjackctlJackClientList::updateClientPorts (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return 0; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return 0; qjackctlJackConnect *pJackConnect = static_cast (listView()->binding()); if (pJackConnect == nullptr) return 0; const char *pszJackType = JACK_DEFAULT_AUDIO_TYPE; #ifdef CONFIG_JACK_MIDI if (pJackConnect->jackType() == QJACKCTL_JACK_MIDI) pszJackType = JACK_DEFAULT_MIDI_TYPE; #endif #ifdef CONFIG_JACK_PORT_ALIASES char *aliases[2]; if (g_iJackClientPortAlias > 0) { const unsigned short alias_size = jack_port_name_size() + 1; aliases[0] = new char [alias_size]; aliases[1] = new char [alias_size]; } #endif int iDirtyCount = 0; markClientPorts(0); const char **ppszClientPorts = jack_get_ports(pJackClient, 0, pszJackType, isReadable() ? JackPortIsOutput : JackPortIsInput); if (ppszClientPorts) { for (int iClientPort = 0; ppszClientPorts[iClientPort]; ++iClientPort) { QString sClientPort = QString::fromUtf8(ppszClientPorts[iClientPort]); qjackctlJackClient *pClient = nullptr; qjackctlJackPort *pPort = nullptr; jack_port_t *pJackPort = jack_port_by_name(pJackClient, ppszClientPorts[iClientPort]); #ifdef CONFIG_JACK_PORT_ALIASES if (g_iJackClientPortAlias > 0 && jack_port_get_aliases(pJackPort, aliases) >= g_iJackClientPortAlias) sClientPort = QString::fromUtf8(aliases[g_iJackClientPortAlias - 1]); #endif const int iColon = sClientPort.indexOf(':'); if (pJackPort && iColon >= 0) { QString sClientName = sClientPort.left(iColon); QString sPortName = sClientPort.right(sClientPort.length() - iColon - 1); pClient = static_cast (findClient(sClientName)); if (pClient) pPort = static_cast (pClient->findPort(sPortName)); if (pClient == nullptr) { pClient = new qjackctlJackClient(this); pClient->setClientName(sClientName); ++iDirtyCount; } if (pClient && pPort == nullptr) { pPort = new qjackctlJackPort(pClient, jack_port_flags(pJackPort)); pPort->setPortName(sPortName); ++iDirtyCount; } if (pPort) pPort->markClientPort(1); } } jack_free(ppszClientPorts); } iDirtyCount += cleanClientPorts(0); #ifdef CONFIG_JACK_PORT_ALIASES if (g_iJackClientPortAlias > 0) { delete [] aliases[0]; delete [] aliases[1]; } #endif return iDirtyCount; } // Jack client port aliases mode. int qjackctlJackClientList::g_iJackClientPortAlias = 0; void qjackctlJackClientList::setJackClientPortAlias ( int iJackClientPortAlias ) { g_iJackClientPortAlias = iJackClientPortAlias; if (g_iJackClientPortAlias > 0) g_bJackClientPortMetadata = false; } int qjackctlJackClientList::jackClientPortAlias (void) { return g_iJackClientPortAlias; } // Jack client port pretty-names (metadata) mode. bool qjackctlJackClientList::g_bJackClientPortMetadata = false; void qjackctlJackClientList::setJackClientPortMetadata ( bool bJackClientPortMetadata ) { g_bJackClientPortMetadata = bJackClientPortMetadata; if (g_bJackClientPortMetadata) g_iJackClientPortAlias = 0; } bool qjackctlJackClientList::isJackClientPortMetadata (void) { return g_bJackClientPortMetadata; } //---------------------------------------------------------------------- // qjackctlJackConnect -- Output-to-Input client/ports connection object. // // Constructor. qjackctlJackConnect::qjackctlJackConnect ( qjackctlConnectView *pConnectView, int iJackType ) : qjackctlConnect(pConnectView) { m_iJackType = iJackType; createIconPixmaps(); setOClientList(new qjackctlJackClientList( connectView()->OListView(), true)); setIClientList(new qjackctlJackClientList( connectView()->IListView(), false)); } // Default destructor. qjackctlJackConnect::~qjackctlJackConnect (void) { deleteIconPixmaps(); } // Connection type accessors. int qjackctlJackConnect::jackType (void) const { return m_iJackType; } // Local pixmap-set janitor methods. void qjackctlJackConnect::createIconPixmaps (void) { switch (m_iJackType) { case QJACKCTL_JACK_MIDI: m_apPixmaps[QJACKCTL_JACK_CLIENTI] = createIconPixmap("mclienti"); m_apPixmaps[QJACKCTL_JACK_CLIENTO] = createIconPixmap("mcliento"); m_apPixmaps[QJACKCTL_JACK_PORTPTI] = createIconPixmap("mporti"); m_apPixmaps[QJACKCTL_JACK_PORTPTO] = createIconPixmap("mporto"); m_apPixmaps[QJACKCTL_JACK_PORTPNI] = createIconPixmap("mporti"); m_apPixmaps[QJACKCTL_JACK_PORTPNO] = createIconPixmap("mporto"); m_apPixmaps[QJACKCTL_JACK_PORTLTI] = createIconPixmap("mporti"); m_apPixmaps[QJACKCTL_JACK_PORTLTO] = createIconPixmap("mporto"); m_apPixmaps[QJACKCTL_JACK_PORTLNI] = createIconPixmap("mporti"); m_apPixmaps[QJACKCTL_JACK_PORTLNO] = createIconPixmap("mporto"); break; case QJACKCTL_JACK_AUDIO: default: m_apPixmaps[QJACKCTL_JACK_CLIENTI] = createIconPixmap("aclienti"); m_apPixmaps[QJACKCTL_JACK_CLIENTO] = createIconPixmap("acliento"); m_apPixmaps[QJACKCTL_JACK_PORTPTI] = createIconPixmap("aportpti"); m_apPixmaps[QJACKCTL_JACK_PORTPTO] = createIconPixmap("aportpto"); m_apPixmaps[QJACKCTL_JACK_PORTPNI] = createIconPixmap("aportpni"); m_apPixmaps[QJACKCTL_JACK_PORTPNO] = createIconPixmap("aportpno"); m_apPixmaps[QJACKCTL_JACK_PORTLTI] = createIconPixmap("aportlti"); m_apPixmaps[QJACKCTL_JACK_PORTLTO] = createIconPixmap("aportlto"); m_apPixmaps[QJACKCTL_JACK_PORTLNI] = createIconPixmap("aportlni"); m_apPixmaps[QJACKCTL_JACK_PORTLNO] = createIconPixmap("aportlno"); break; } } void qjackctlJackConnect::deleteIconPixmaps (void) { for (int i = 0; i < QJACKCTL_JACK_PIXMAPS; i++) { if (m_apPixmaps[i]) delete m_apPixmaps[i]; m_apPixmaps[i] = nullptr; } } // Common pixmap accessor (static). const QPixmap& qjackctlJackConnect::pixmap ( int iPixmap ) const { return *m_apPixmaps[iPixmap]; } // Connection primitive. bool qjackctlJackConnect::connectPorts ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return false; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return false; qjackctlJackPort *pOJack = static_cast (pOPort); qjackctlJackPort *pIJack = static_cast (pIPort); return (jack_connect(pJackClient, pOJack->clientPortName().toUtf8().constData(), pIJack->clientPortName().toUtf8().constData()) == 0); } // Disconnection primitive. bool qjackctlJackConnect::disconnectPorts ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return false; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return false; qjackctlJackPort *pOJack = static_cast (pOPort); qjackctlJackPort *pIJack = static_cast (pIPort); return (jack_disconnect(pJackClient, pOJack->clientPortName().toUtf8().constData(), pIJack->clientPortName().toUtf8().constData()) == 0); } // Update port connection references. void qjackctlJackConnect::updateConnections (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return; qjackctlJackClientList *pIClientList = static_cast (IClientList()); if (pIClientList == nullptr) return; #ifdef CONFIG_JACK_PORT_ALIASES const int iJackClientPortAlias = qjackctlJackClientList::jackClientPortAlias(); #endif // For each output client item... QListIterator oclient(OClientList()->clients()); while (oclient.hasNext()) { qjackctlClientItem *pOClient = oclient.next(); // For each output port item... QListIterator oport(pOClient->ports()); while (oport.hasNext()) { qjackctlPortItem *pOPort = oport.next(); // Are there already any connections? if (pOPort->connects().count() > 0) continue; // Hava a proper type cast. qjackctlJackPort *pOJack = static_cast (pOPort); // Get port connections... const QString& sClientPort = pOJack->clientName() + ':' + pOJack->portName(); const QByteArray aClientPort = sClientPort.toUtf8(); const char *pszClientPort = aClientPort.constData(); jack_port_t *pJackPort = jack_port_by_name(pJackClient, pszClientPort); if (pJackPort) { const char **ppszClientPorts = jack_port_get_all_connections(pJackClient, pJackPort); if (ppszClientPorts) { // Now, for each input client port... for (int iClientPort = 0; ppszClientPorts[iClientPort]; ++iClientPort) { qjackctlPortItem *pIPort = nullptr; #ifdef CONFIG_JACK_PORT_ALIASES if (iJackClientPortAlias > 0) { // If Jack aliases are in effect, look for those if present -ag jack_port_t *pIJackPort = jack_port_by_name(pJackClient, ppszClientPorts[iClientPort]); if (pIJackPort) { char *aliases[2]; const unsigned short alias_size = jack_port_name_size() + 1; aliases[0] = new char [alias_size]; aliases[1] = new char [alias_size]; if (jack_port_get_aliases(pIJackPort, aliases) >= iJackClientPortAlias) { pIPort = pIClientList->findJackClientPort(aliases[iJackClientPortAlias - 1]); } delete [] aliases[0]; delete [] aliases[1]; } // Otherwise we fall through to the default case below // which looks for the port under its real name } #endif if (!pIPort) { pIPort = pIClientList->findJackClientPort( ppszClientPorts[iClientPort]); } if (pIPort) { pOPort->addConnect(pIPort); pIPort->addConnect(pOPort); } } jack_free(ppszClientPorts); } } } } } // Update icon size implementation. void qjackctlJackConnect::updateIconPixmaps (void) { deleteIconPixmaps(); createIconPixmaps(); } // end of qjackctlJackConnect.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlAboutForm.cpp0000644000000000000000000000013214771215054017302 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlAboutForm.cpp0000644000175000001440000001007514771215054017275 0ustar00rncbcusers// qjackctlAboutForm.cpp // /**************************************************************************** Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAbout.h" #include "qjackctlAboutForm.h" #include #ifdef CONFIG_JACK_VERSION #include #endif //---------------------------------------------------------------------------- // qjackctlAboutForm -- UI wrapper form. // Constructor. qjackctlAboutForm::qjackctlAboutForm ( QWidget *pParent ) : QDialog(pParent) { // Setup UI struct... m_ui.setupUi(this); #if QT_VERSION < QT_VERSION_CHECK(6, 1, 0) QDialog::setWindowIcon(QIcon(":/images/qjackctl.png")); #endif QStringList list; #ifdef CONFIG_DEBUG list << tr("Debugging option enabled."); #endif #ifndef CONFIG_SYSTEM_TRAY list << tr("System tray disabled."); #endif #ifndef CONFIG_JACK_TRANSPORT list << tr("Transport status control disabled."); #endif #ifndef CONFIG_JACK_REALTIME list << tr("Realtime status disabled."); #endif #ifndef CONFIG_JACK_XRUN_DELAY list << tr("XRUN delay status disabled."); #endif #ifndef CONFIG_JACK_MAX_DELAY list << tr("Maximum delay status disabled."); #endif #ifndef CONFIG_JACK_PORT_ALIASES list << tr("JACK Port aliases support disabled."); #endif #ifndef CONFIG_JACK_MIDI list << tr("JACK MIDI support disabled."); #endif #ifndef CONFIG_JACK_SESSION list << tr("JACK Session support disabled."); #endif #ifndef CONFIG_ALSA_SEQ #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32) && !defined(__APPLE__) list << tr("ALSA/MIDI sequencer support disabled."); #endif #endif #ifndef CONFIG_DBUS #if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32) && !defined(__APPLE__) list << tr("D-Bus interface support disabled."); #endif #endif // Stuff the about box... QString sText = "


\n"; sText += "" QJACKCTL_TITLE " - " + tr(QJACKCTL_SUBTITLE) + "
\n"; sText += "
\n"; sText += tr("Version") + ": " PROJECT_VERSION "
\n"; // sText += "" + tr("Build") + ": " CONFIG_BUILD_DATE "
\n"; if (!list.isEmpty()) { sText += ""; sText += list.join("
\n"); sText += "
"; } sText += "
\n"; sText += tr("Using: Qt %1").arg(qVersion()); #if defined(QT_STATIC) sText += "-static"; #endif #ifdef CONFIG_JACK_VERSION sText += ", "; sText += tr("JACK %1").arg(jack_get_version_string()); #endif sText += "
\n"; sText += "
\n"; sText += tr("Website") + ": " QJACKCTL_WEBSITE "
\n"; sText += "
\n"; sText += ""; sText += QJACKCTL_COPYRIGHT "
\n"; sText += "
\n"; sText += tr("This program is free software; you can redistribute it and/or modify it") + "
\n"; sText += tr("under the terms of the GNU General Public License version 2 or later."); sText += "
"; sText += "

\n"; m_ui.AboutTextView->setText(sText); // UI connections... QObject::connect(m_ui.AboutQtButton, SIGNAL(clicked()), SLOT(aboutQt())); QObject::connect(m_ui.ClosePushButton, SIGNAL(clicked()), SLOT(close())); } // Destructor. qjackctlAboutForm::~qjackctlAboutForm (void) { } // About Qt request. void qjackctlAboutForm::aboutQt() { QMessageBox::aboutQt(this); } // end of qjackctlAboutForm.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlAbout.h0000644000000000000000000000013214771215054016123 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlAbout.h0000644000175000001440000000246414771215054016121 0ustar00rncbcusers// qjackctlAbout.h // /**************************************************************************** Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlAbout_h #define __qjackctlAbout_h #include "config.h" #define QJACKCTL_TITLE PROJECT_TITLE #define QJACKCTL_SUBTITLE PROJECT_DESCRIPTION #define QJACKCTL_WEBSITE PROJECT_HOMEPAGE_URL #define QJACKCTL_COPYRIGHT PROJECT_COPYRIGHT #define QJACKCTL_DOMAIN PROJECT_DOMAIN #endif // __qjackctlAbout_h // end of qjackctlAbout.h qjackctl-1.0.4/src/PaxHeaders/qjackctlConnectionsForm.cpp0000644000000000000000000000013214771215054020512 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlConnectionsForm.cpp0000644000175000001440000005065114771215054020511 0ustar00rncbcusers// qjackctlConnectionsForm.cpp // /**************************************************************************** Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlConnectionsForm.h" #include "qjackctlMainForm.h" #include "qjackctlPatchbay.h" #include #include #include //---------------------------------------------------------------------------- // qjackctlConnectionsForm -- UI wrapper form. // Constructor. qjackctlConnectionsForm::qjackctlConnectionsForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QWidget(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); m_pAudioConnect = new qjackctlJackConnect( m_ui.AudioConnectView, QJACKCTL_JACK_AUDIO); #ifdef CONFIG_JACK_MIDI m_pMidiConnect = new qjackctlJackConnect( m_ui.MidiConnectView, QJACKCTL_JACK_MIDI); #else m_pMidiConnect = nullptr; #endif #ifdef CONFIG_ALSA_SEQ m_pAlsaConnect = new qjackctlAlsaConnect(m_ui.AlsaConnectView); #else m_pAlsaConnect = nullptr; #endif m_pSetup = nullptr; // UI connections... QObject::connect(m_ui.AudioConnectPushButton, SIGNAL(clicked()), SLOT(audioConnectSelected())); QObject::connect(m_ui.AudioDisconnectPushButton, SIGNAL(clicked()), SLOT(audioDisconnectSelected())); QObject::connect(m_ui.AudioDisconnectAllPushButton, SIGNAL(clicked()), SLOT(audioDisconnectAll())); QObject::connect(m_ui.AudioExpandAllPushButton, SIGNAL(clicked()), SLOT(audioExpandAll())); QObject::connect(m_ui.AudioRefreshPushButton, SIGNAL(clicked()), SLOT(audioRefresh())); QObject::connect(m_ui.MidiConnectPushButton, SIGNAL(clicked()), SLOT(midiConnectSelected())); QObject::connect(m_ui.MidiDisconnectPushButton, SIGNAL(clicked()), SLOT(midiDisconnectSelected())); QObject::connect(m_ui.MidiDisconnectAllPushButton, SIGNAL(clicked()), SLOT(midiDisconnectAll())); QObject::connect(m_ui.MidiExpandAllPushButton, SIGNAL(clicked()), SLOT(midiExpandAll())); QObject::connect(m_ui.MidiRefreshPushButton, SIGNAL(clicked()), SLOT(midiRefresh())); QObject::connect(m_ui.AlsaConnectPushButton, SIGNAL(clicked()), SLOT(alsaConnectSelected())); QObject::connect(m_ui.AlsaDisconnectPushButton, SIGNAL(clicked()), SLOT(alsaDisconnectSelected())); QObject::connect(m_ui.AlsaDisconnectAllPushButton, SIGNAL(clicked()), SLOT(alsaDisconnectAll())); QObject::connect(m_ui.AlsaExpandAllPushButton, SIGNAL(clicked()), SLOT(alsaExpandAll())); QObject::connect(m_ui.AlsaRefreshPushButton, SIGNAL(clicked()), SLOT(alsaRefresh())); // Connect it to some UI feedback slots. QObject::connect(m_ui.AudioConnectView->OListView(), SIGNAL(itemSelectionChanged()), SLOT(audioStabilize())); QObject::connect(m_ui.AudioConnectView->IListView(), SIGNAL(itemSelectionChanged()), SLOT(audioStabilize())); QObject::connect(m_ui.MidiConnectView->OListView(), SIGNAL(itemSelectionChanged()), SLOT(midiStabilize())); QObject::connect(m_ui.MidiConnectView->IListView(), SIGNAL(itemSelectionChanged()), SLOT(midiStabilize())); QObject::connect(m_ui.AlsaConnectView->OListView(), SIGNAL(itemSelectionChanged()), SLOT(alsaStabilize())); QObject::connect(m_ui.AlsaConnectView->IListView(), SIGNAL(itemSelectionChanged()), SLOT(alsaStabilize())); QObject::connect(m_ui.AudioConnectView->OListView(), SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(audioStabilize())); QObject::connect(m_ui.AudioConnectView->IListView(), SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(audioStabilize())); QObject::connect(m_ui.MidiConnectView->OListView(), SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(midiStabilize())); QObject::connect(m_ui.MidiConnectView->IListView(), SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(midiStabilize())); QObject::connect(m_ui.AlsaConnectView->OListView(), SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(alsaStabilize())); QObject::connect(m_ui.AlsaConnectView->IListView(), SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(alsaStabilize())); // Dirty dispatcher (refresh deferral). QObject::connect(m_ui.AudioConnectView, SIGNAL(aliasesChanged()), SLOT(audioAliasesChanged())); QObject::connect(m_ui.MidiConnectView, SIGNAL(aliasesChanged()), SLOT(midiAliasesChanged())); QObject::connect(m_ui.AlsaConnectView, SIGNAL(aliasesChanged()), SLOT(alsaAliasesChanged())); // Actual connections... QObject::connect(m_pAudioConnect, SIGNAL(disconnecting(qjackctlPortItem *, qjackctlPortItem *)), SLOT(audioDisconnecting(qjackctlPortItem *, qjackctlPortItem *))); #ifdef CONFIG_JACK_MIDI QObject::connect(m_pMidiConnect, SIGNAL(disconnecting(qjackctlPortItem *, qjackctlPortItem *)), SLOT(midiDisconnecting(qjackctlPortItem *, qjackctlPortItem *))); #endif #ifdef CONFIG_ALSA_SEQ QObject::connect(m_pAlsaConnect, SIGNAL(disconnecting(qjackctlPortItem *, qjackctlPortItem *)), SLOT(alsaDisconnecting(qjackctlPortItem *, qjackctlPortItem *))); #endif #ifndef CONFIG_JACK_MIDI m_ui.ConnectionsTabWidget->setTabEnabled(1, false); #endif #ifndef CONFIG_ALSA_SEQ // m_ui.ConnectionsTabWidget->setTabEnabled(2, false); m_ui.ConnectionsTabWidget->removeTab(2); #endif // Start disabled. stabilizeAudio(false); stabilizeMidi(false); stabilizeAlsa(false); } // Destructor. qjackctlConnectionsForm::~qjackctlConnectionsForm (void) { // Destroy our connections view... if (m_pAudioConnect) delete m_pAudioConnect; #ifdef CONFIG_JACK_MIDI if (m_pMidiConnect) delete m_pMidiConnect; #endif #ifdef CONFIG_ALSA_SEQ if (m_pAlsaConnect) delete m_pAlsaConnect; #endif } // Notify our parent that we're emerging. void qjackctlConnectionsForm::showEvent ( QShowEvent *pShowEvent ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); audioRefresh(); midiRefresh(); alsaRefresh(); QWidget::showEvent(pShowEvent); } // Notify our parent that we're closing. void qjackctlConnectionsForm::hideEvent ( QHideEvent *pHideEvent ) { QWidget::hideEvent(pHideEvent); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); } // Just about to notify main-window that we're closing. void qjackctlConnectionsForm::closeEvent ( QCloseEvent *pCloseEvent ) { // Save current tab page and splitter sizes... if (m_pSetup) { m_pSetup->iConnectionsTabPage = tabPage(); m_pSetup->saveSplitterSizes(m_ui.AudioConnectView); m_pSetup->saveSplitterSizes(m_ui.MidiConnectView); m_pSetup->saveSplitterSizes(m_ui.AlsaConnectView); } QWidget::closeEvent(pCloseEvent); } // Set reference to global options, mostly needed for the // initial sizes of the main splitter views and those // client/port aliasing feature. void qjackctlConnectionsForm::setup ( qjackctlSetup *pSetup ) { m_pSetup = pSetup; qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) { QObject::connect(m_pAudioConnect, SIGNAL(connectChanged()), pMainForm, SLOT(jackConnectChanged())); #ifdef CONFIG_JACK_MIDI QObject::connect(m_pMidiConnect, SIGNAL(connectChanged()), pMainForm, SLOT(jackConnectChanged())); #endif #ifdef CONFIG_ALSA_SEQ QObject::connect(m_pAlsaConnect, SIGNAL(connectChanged()), pMainForm, SLOT(alsaConnectChanged())); #endif } // Load some splitter sizes... if (m_pSetup) { QList sizes; sizes.append(180); sizes.append(60); sizes.append(180); m_pSetup->loadSplitterSizes(m_ui.AudioConnectView, sizes); m_pSetup->loadSplitterSizes(m_ui.MidiConnectView, sizes); m_pSetup->loadSplitterSizes(m_ui.AlsaConnectView, sizes); #ifdef CONFIG_ALSA_SEQ if (!m_pSetup->bAlsaSeqEnabled) { // m_ui.ConnectionsTabWidget->setTabEnabled(2, false); m_ui.ConnectionsTabWidget->removeTab(2); } #endif } // Update initial client/port aliases... updateAliases(); } // Connector view accessors. qjackctlConnectView *qjackctlConnectionsForm::audioConnectView (void) const { return m_ui.AudioConnectView; } qjackctlConnectView *qjackctlConnectionsForm::midiConnectView (void) const { return m_ui.MidiConnectView; } qjackctlConnectView *qjackctlConnectionsForm::alsaConnectView (void) const { return m_ui.AlsaConnectView; } // Tab page accessors. void qjackctlConnectionsForm::setTabPage ( int iTabPage ) { m_ui.ConnectionsTabWidget->setCurrentIndex(iTabPage); } int qjackctlConnectionsForm::tabPage (void) const { return m_ui.ConnectionsTabWidget->currentIndex(); } // Connections view font accessors. QFont qjackctlConnectionsForm::connectionsFont (void) const { // Elect one list view to retrieve current font. return m_ui.AudioConnectView->OListView()->font(); } void qjackctlConnectionsForm::setConnectionsFont ( const QFont & font ) { // Set fonts of all listviews... m_ui.AudioConnectView->OListView()->setFont(font); m_ui.AudioConnectView->IListView()->setFont(font); m_ui.MidiConnectView->OListView()->setFont(font); m_ui.MidiConnectView->IListView()->setFont(font); m_ui.AlsaConnectView->OListView()->setFont(font); m_ui.AlsaConnectView->IListView()->setFont(font); } // Connections view icon size accessor. void qjackctlConnectionsForm::setConnectionsIconSize ( int iIconSize ) { // Set icon sizes of all views... m_ui.AudioConnectView->setIconSize(iIconSize); m_ui.MidiConnectView->setIconSize(iIconSize); m_ui.AlsaConnectView->setIconSize(iIconSize); } // Check if there's JACK audio connections. bool qjackctlConnectionsForm::isAudioConnected (void) const { bool bIsAudioConnected = false; if (m_pAudioConnect) bIsAudioConnected = m_pAudioConnect->canDisconnectAll(); return bIsAudioConnected; } // Connect current selected JACK audio ports. void qjackctlConnectionsForm::audioConnectSelected (void) { if (m_pAudioConnect) { if (m_pAudioConnect->connectSelected()) refreshAudio(false); } } // Disconnect current selected JACK audio ports. void qjackctlConnectionsForm::audioDisconnectSelected (void) { if (m_pAudioConnect) { if (m_pAudioConnect->disconnectSelected()) refreshAudio(false); } } // Disconnect all connected JACK audio ports. void qjackctlConnectionsForm::audioDisconnectAll (void) { if (m_pAudioConnect) { if (m_pAudioConnect->disconnectAll()) refreshAudio(false); } } // Expand all JACK audio client ports. void qjackctlConnectionsForm::audioExpandAll (void) { if (m_pAudioConnect) { m_pAudioConnect->expandAll(); stabilizeAudio(true); } } // JACK audio ports disconnecting. void qjackctlConnectionsForm::audioDisconnecting ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->queryDisconnect(pOPort, pIPort, QJACKCTL_SOCKETTYPE_JACK_AUDIO); } // JACK audio client/port aliases have changed. void qjackctlConnectionsForm::audioAliasesChanged (void) { if (m_pSetup) m_pSetup->aliases.dirty = true; audioRefresh(); } // Refresh JACK audio form by notifying the parent form. void qjackctlConnectionsForm::audioRefresh (void) { refreshAudio(false); } // A JACK audio helper stabilization slot. void qjackctlConnectionsForm::audioStabilize (void) { stabilizeAudio(true); } // Connect current selected JACK MIDI ports. void qjackctlConnectionsForm::midiConnectSelected (void) { if (m_pMidiConnect) { if (m_pMidiConnect->connectSelected()) refreshMidi(false); } } // Check if there's JACK MIDI connections. bool qjackctlConnectionsForm::isMidiConnected (void) const { bool bIsMidiConnected = false; if (m_pMidiConnect) bIsMidiConnected = m_pMidiConnect->canDisconnectAll(); return bIsMidiConnected; } // Disconnect current selected JACK MIDI ports. void qjackctlConnectionsForm::midiDisconnectSelected (void) { if (m_pMidiConnect) { if (m_pMidiConnect->disconnectSelected()) refreshMidi(false); } } // Disconnect all connected JACK MIDI ports. void qjackctlConnectionsForm::midiDisconnectAll (void) { if (m_pMidiConnect) { if (m_pMidiConnect->disconnectAll()) refreshMidi(false); } } // Expand all JACK MIDI client ports. void qjackctlConnectionsForm::midiExpandAll (void) { if (m_pMidiConnect) { m_pMidiConnect->expandAll(); stabilizeMidi(true); } } // JACK MIDI ports disconnecting. void qjackctlConnectionsForm::midiDisconnecting ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->queryDisconnect(pOPort, pIPort, QJACKCTL_SOCKETTYPE_JACK_MIDI); } // JACK MIDI client/port aliases have changed. void qjackctlConnectionsForm::midiAliasesChanged (void) { if (m_pSetup) m_pSetup->aliases.dirty = true; midiRefresh(); } // Refresh JACK MIDI form by notifying the parent form. void qjackctlConnectionsForm::midiRefresh (void) { refreshMidi(false); } // A JACK MIDI helper stabilization slot. void qjackctlConnectionsForm::midiStabilize (void) { stabilizeMidi(true); } // Check if there's ALSA MIDI connections. bool qjackctlConnectionsForm::isAlsaConnected (void) const { bool bIsAlsaConnected = false; if (m_pAlsaConnect) bIsAlsaConnected = m_pAlsaConnect->canDisconnectAll(); return bIsAlsaConnected; } // Connect current selected ALSA MIDI ports. void qjackctlConnectionsForm::alsaConnectSelected (void) { if (m_pAlsaConnect) { if (m_pAlsaConnect->connectSelected()) refreshAlsa(false); } } // Disconnect current selected ALSA MIDI ports. void qjackctlConnectionsForm::alsaDisconnectSelected (void) { if (m_pAlsaConnect) { if (m_pAlsaConnect->disconnectSelected()) refreshAlsa(false); } } // Disconnect all connected ALSA MIDI ports. void qjackctlConnectionsForm::alsaDisconnectAll (void) { if (m_pAlsaConnect) { if (m_pAlsaConnect->disconnectAll()) refreshAlsa(false); } } // Expand all ALSA MIDI client ports. void qjackctlConnectionsForm::alsaExpandAll (void) { if (m_pAlsaConnect) { m_pAlsaConnect->expandAll(); stabilizeAlsa(true); } } // ALSA MIDI ports disconnecting. void qjackctlConnectionsForm::alsaDisconnecting ( qjackctlPortItem *pOPort, qjackctlPortItem *pIPort ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->queryDisconnect(pOPort, pIPort, QJACKCTL_SOCKETTYPE_ALSA_MIDI); } // ALSA MIDI client/port aliases have changed. void qjackctlConnectionsForm::alsaAliasesChanged (void) { if (m_pSetup) m_pSetup->aliases.dirty = true; alsaRefresh(); } // Refresh complete form by notifying the parent form. void qjackctlConnectionsForm::alsaRefresh (void) { refreshAlsa(false); } // A helper stabilization slot. void qjackctlConnectionsForm::alsaStabilize (void) { stabilizeAlsa(true); } // Either rebuild all connections now // or notify main form for doing that later. void qjackctlConnectionsForm::refreshAudio ( bool bEnabled, bool bClear ) { if (m_pAudioConnect == nullptr) return; if (bEnabled) { // m_pAudioConnect->refresh(); stabilizeAudio(bEnabled, bClear); } else { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->refreshJackConnections(); } } void qjackctlConnectionsForm::refreshMidi ( bool bEnabled, bool bClear ) { if (m_pMidiConnect == nullptr) return; if (bEnabled) { // m_pMidiConnect->refresh(); stabilizeMidi(bEnabled, bClear); } else { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->refreshJackConnections(); } } void qjackctlConnectionsForm::refreshAlsa ( bool bEnabled, bool bClear ) { if (m_pAlsaConnect == nullptr) return; if (bEnabled) { // m_pAlsaConnect->refresh(); stabilizeAlsa(bEnabled, bClear); } else { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->refreshAlsaConnections(); } } // Proper enablement of connections command controls. void qjackctlConnectionsForm::stabilizeAudio ( bool bEnabled, bool bClear ) { if (m_pAudioConnect) m_pAudioConnect->updateContents(!bEnabled || bClear); if (m_pAudioConnect && bEnabled) { m_ui.AudioConnectPushButton->setEnabled( m_pAudioConnect->canConnectSelected()); m_ui.AudioDisconnectPushButton->setEnabled( m_pAudioConnect->canDisconnectSelected()); m_ui.AudioDisconnectAllPushButton->setEnabled( m_pAudioConnect->canDisconnectAll()); m_ui.AudioExpandAllPushButton->setEnabled(true); m_ui.AudioRefreshPushButton->setEnabled(true); } else { m_ui.AudioConnectPushButton->setEnabled(false); m_ui.AudioDisconnectPushButton->setEnabled(false); m_ui.AudioDisconnectAllPushButton->setEnabled(false); m_ui.AudioExpandAllPushButton->setEnabled(false); m_ui.AudioRefreshPushButton->setEnabled(false); } } void qjackctlConnectionsForm::stabilizeMidi ( bool bEnabled, bool bClear ) { if (m_pMidiConnect) m_pMidiConnect->updateContents(!bEnabled || bClear); if (m_pMidiConnect && bEnabled) { m_ui.MidiConnectPushButton->setEnabled( m_pMidiConnect->canConnectSelected()); m_ui.MidiDisconnectPushButton->setEnabled( m_pMidiConnect->canDisconnectSelected()); m_ui.MidiDisconnectAllPushButton->setEnabled( m_pMidiConnect->canDisconnectAll()); m_ui.MidiExpandAllPushButton->setEnabled(true); m_ui.MidiRefreshPushButton->setEnabled(true); } else { m_ui.MidiConnectPushButton->setEnabled(false); m_ui.MidiDisconnectPushButton->setEnabled(false); m_ui.MidiDisconnectAllPushButton->setEnabled(false); m_ui.MidiExpandAllPushButton->setEnabled(false); m_ui.MidiRefreshPushButton->setEnabled(false); } } void qjackctlConnectionsForm::stabilizeAlsa ( bool bEnabled, bool bClear ) { if (m_pAlsaConnect) m_pAlsaConnect->updateContents(!bEnabled || bClear); if (m_pAlsaConnect && bEnabled) { m_ui.AlsaConnectPushButton->setEnabled( m_pAlsaConnect->canConnectSelected()); m_ui.AlsaDisconnectPushButton->setEnabled( m_pAlsaConnect->canDisconnectSelected()); m_ui.AlsaDisconnectAllPushButton->setEnabled( m_pAlsaConnect->canDisconnectAll()); m_ui.AlsaExpandAllPushButton->setEnabled(true); m_ui.AlsaRefreshPushButton->setEnabled(true); } else { m_ui.AlsaConnectPushButton->setEnabled(false); m_ui.AlsaDisconnectPushButton->setEnabled(false); m_ui.AlsaDisconnectAllPushButton->setEnabled(false); m_ui.AlsaExpandAllPushButton->setEnabled(false); m_ui.AlsaRefreshPushButton->setEnabled(false); } } // Client/port aliasing feature update. void qjackctlConnectionsForm::updateAliases (void) { // Set alias maps for all listviews... if (m_pSetup && m_pSetup->bAliasesEnabled) { const bool bRenameEnabled = m_pSetup->bAliasesEditing; m_ui.AudioConnectView->OListView()->setAliasList( &(m_pSetup->aliases.audioOutputs), bRenameEnabled); m_ui.AudioConnectView->IListView()->setAliasList( &(m_pSetup->aliases.audioInputs), bRenameEnabled); m_ui.MidiConnectView->OListView()->setAliasList( &(m_pSetup->aliases.midiOutputs), bRenameEnabled); m_ui.MidiConnectView->IListView()->setAliasList( &(m_pSetup->aliases.midiInputs), bRenameEnabled); m_ui.AlsaConnectView->OListView()->setAliasList( &(m_pSetup->aliases.alsaOutputs), bRenameEnabled); m_ui.AlsaConnectView->IListView()->setAliasList( &(m_pSetup->aliases.alsaInputs), bRenameEnabled); } else { m_ui.AudioConnectView->OListView()->setAliasList(nullptr, false); m_ui.AudioConnectView->IListView()->setAliasList(nullptr, false); m_ui.MidiConnectView->OListView()->setAliasList(nullptr, false); m_ui.MidiConnectView->IListView()->setAliasList(nullptr, false); m_ui.AlsaConnectView->OListView()->setAliasList(nullptr, false); m_ui.AlsaConnectView->IListView()->setAliasList(nullptr, false); } } // Keyboard event handler. void qjackctlConnectionsForm::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qjackctlConnectionsForm::keyPressEvent(%d)", pKeyEvent->key()); #endif int iKey = pKeyEvent->key(); switch (iKey) { case Qt::Key_Escape: close(); break; default: QWidget::keyPressEvent(pKeyEvent); break; } } // end of qjackctlConnectionsForm.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlJackGraph.h0000644000000000000000000000013214771215054016703 xustar0030 mtime=1743067692.325636584 30 atime=1743067692.325636584 30 ctime=1743067692.325636584 qjackctl-1.0.4/src/qjackctlJackGraph.h0000644000175000001440000000507514771215054016702 0ustar00rncbcusers// qjackctlJackGraph.h // /**************************************************************************** Copyright (C) 2003-2023, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlJackGraph_h #define __qjackctlJackGraph_h #include "qjackctlAbout.h" #include "qjackctlGraph.h" #include #include //---------------------------------------------------------------------------- // qjackctlJackGraph -- JACK graph driver class qjackctlJackGraph : public qjackctlGraphSect { public: // Constructor. qjackctlJackGraph(qjackctlGraphCanvas *canvas); // JACK port (dis)connection. void connectPorts( qjackctlGraphPort *port1, qjackctlGraphPort *port2, bool is_connect); // JACK graph updaters. void updateItems(); void clearItems(); // Special port-type colors defaults (virtual). void resetPortTypeColors(); // JACK node type inquirer. static bool isNodeType(uint node_type); // JACK node type. static uint nodeType(); // JACK port type(s) inquirer. static bool isPortType(uint port_type); // JACK port types. static uint audioPortType(); static uint midiPortType(); // JACK port (meta-data provided) types. static uint cvPortType(); static uint oscPortType(); // Client/port renaming method (virtual override). void renameItem(qjackctlGraphItem *item, const QString& name); protected: // JACK client:port finder and creator if not existing. bool findClientPort(jack_client_t *client, const char *client_port, qjackctlGraphItem::Mode port_mode, qjackctlGraphNode **node, qjackctlGraphPort **port, bool add_new); // Client/port item aliases accessor. QList item_aliases(qjackctlGraphItem *item) const; private: // Callback sanity mutex. QMutex m_mutex; }; #endif // __qjackctlJackGraph_h // end of qjackctlJackGraph.h qjackctl-1.0.4/src/PaxHeaders/qjackctlAlsaGraph.cpp0000644000000000000000000000013214771215054017246 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlAlsaGraph.cpp0000644000175000001440000003006614771215054017243 0ustar00rncbcusers// qjackctlAlsaGraph.cpp // /**************************************************************************** Copyright (C) 2003-2023, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAlsaGraph.h" #include "qjackctlMainForm.h" #ifdef CONFIG_ALSA_SEQ #include //---------------------------------------------------------------------------- // qjackctlAlsaGraph -- ALSA graph driver // Constructor. qjackctlAlsaGraph::qjackctlAlsaGraph ( qjackctlGraphCanvas *canvas ) : qjackctlGraphSect(canvas) { resetPortTypeColors(); } // ALSA port (dis)connection. void qjackctlAlsaGraph::connectPorts ( qjackctlGraphPort *port1, qjackctlGraphPort *port2, bool is_connect ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; snd_seq_t *seq = pMainForm->alsaSeq(); if (seq == nullptr) return; if (port1 == nullptr || port2 == nullptr) return; const qjackctlGraphNode *node1 = port1->portNode(); const qjackctlGraphNode *node2 = port2->portNode(); if (node1 == nullptr || node2 == nullptr) return; QMutexLocker locker(&m_mutex); const int client_id1 = node1->nodeName().section(':', 0, 0).toInt(); const int port_id1 = port1->portName().section(':', 0, 0).toInt(); const int client_id2 = node2->nodeName().section(':', 0, 0).toInt(); const int port_id2 = port2->portName().section(':', 0, 0).toInt(); #ifdef CONFIG_DEBUG qDebug("qjackctlAlsaGraph::connectPorts(%d:%d, %d:%d, %d)", client_id1, port_id1, client_id2, port_id2, is_connect); #endif snd_seq_port_subscribe_t *seq_subs; snd_seq_addr_t seq_addr; snd_seq_port_subscribe_alloca(&seq_subs); seq_addr.client = client_id1; seq_addr.port = port_id1; snd_seq_port_subscribe_set_sender(seq_subs, &seq_addr); seq_addr.client = client_id2; seq_addr.port = port_id2; snd_seq_port_subscribe_set_dest(seq_subs, &seq_addr); if (is_connect) { snd_seq_subscribe_port(seq, seq_subs); } else { snd_seq_unsubscribe_port(seq, seq_subs); } } // ALSA node type inquirer. (static) bool qjackctlAlsaGraph::isNodeType ( uint node_type ) { return (node_type == qjackctlAlsaGraph::nodeType()); } // ALSA node type. uint qjackctlAlsaGraph::nodeType (void) { static const uint AlsaNodeType = qjackctlGraphItem::itemType("ALSA_NODE_TYPE"); return AlsaNodeType; } // ALSA port type inquirer. (static) bool qjackctlAlsaGraph::isPortType ( uint port_type ) { return (port_type == qjackctlAlsaGraph::midiPortType()); } // ALSA port type. uint qjackctlAlsaGraph::midiPortType (void) { static const uint AlsaMidiPortType = qjackctlGraphItem::itemType("ALSA_PORT_TYPE"); return AlsaMidiPortType; } // ALSA client:port finder and creator if not existing. bool qjackctlAlsaGraph::findClientPort ( snd_seq_client_info_t *client_info, snd_seq_port_info_t *port_info, qjackctlGraphItem::Mode port_mode, qjackctlGraphNode **node, qjackctlGraphPort **port, bool add_new ) { const int client_id = snd_seq_client_info_get_client(client_info); const int port_id = snd_seq_port_info_get_port(port_info); const QString& client_name = QString::number(client_id) + ':' + QString::fromUtf8(snd_seq_client_info_get_name(client_info)); const QString& port_name = QString::number(port_id) + ':' + QString::fromUtf8(snd_seq_port_info_get_name(port_info)); const uint node_type = qjackctlAlsaGraph::nodeType(); const uint port_type = qjackctlAlsaGraph::midiPortType(); qjackctlGraphItem::Mode node_mode = port_mode; *node = qjackctlGraphSect::findNode(client_name, node_mode, node_type); *port = nullptr; if (*node == nullptr && client_id >= 128) { node_mode = qjackctlGraphItem::Duplex; *node = qjackctlGraphSect::findNode(client_name, node_mode, node_type); } if (*node) *port = (*node)->findPort(port_name, port_mode, port_type); if (add_new && *node == nullptr) { *node = new qjackctlGraphNode(client_name, node_mode, node_type); (*node)->setNodeIcon(QIcon(":/images/graphAlsa.png")); qjackctlGraphSect::addItem(*node); } if (add_new && *port == nullptr && *node) { *port = (*node)->addPort(port_name, port_mode, port_type); (*port)->updatePortTypeColors(qjackctlGraphSect::canvas()); } if (add_new && *node) { int nchanged = 0; QString node_title = (*node)->nodeTitle(); foreach (qjackctlAliasList *node_aliases, item_aliases(*node)) node_title = node_aliases->clientAlias(client_name); if ((*node)->nodeTitle() != node_title) { (*node)->setNodeTitle(node_title); ++nchanged; } if (*port) { QString port_title = (*port)->portTitle(); foreach (qjackctlAliasList *port_aliases, item_aliases(*port)) port_title = port_aliases->portAlias(client_name, port_name); if ((*port)->portTitle() != port_title) { (*port)->setPortTitle(port_title); ++nchanged; } } if (nchanged > 0) (*node)->updatePath(); } return (*node && *port); } // ALSA graph updater. void qjackctlAlsaGraph::updateItems (void) { QMutexLocker locker(&m_mutex); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; snd_seq_t *seq = pMainForm->alsaSeq(); if (seq == nullptr) return; #ifdef CONFIG_DEBUG_0 qDebug("qjackctlAlsaGraph::updateItems()"); #endif // 1. Client/ports inventory... // snd_seq_client_info_t *client_info1; snd_seq_port_info_t *port_info1; snd_seq_client_info_alloca(&client_info1); snd_seq_port_info_alloca(&port_info1); snd_seq_client_info_set_client(client_info1, -1); while (snd_seq_query_next_client(seq, client_info1) >= 0) { const int client_id = snd_seq_client_info_get_client(client_info1); if (0 >= client_id) // Skip 0:System client... continue; snd_seq_port_info_set_client(port_info1, client_id); snd_seq_port_info_set_port(port_info1, -1); while (snd_seq_query_next_port(seq, port_info1) >= 0) { const unsigned int port_caps1 = snd_seq_port_info_get_capability(port_info1); if (port_caps1 & SND_SEQ_PORT_CAP_NO_EXPORT) continue; qjackctlGraphItem::Mode port_mode1 = qjackctlGraphItem::None; const unsigned int port_is_input = (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE); if ((port_caps1 & port_is_input) == port_is_input) { port_mode1 = qjackctlGraphItem::Input; qjackctlGraphNode *node1 = nullptr; qjackctlGraphPort *port1 = nullptr; if (findClientPort(client_info1, port_info1, port_mode1, &node1, &port1, true)) { node1->setMarked(true); port1->setMarked(true); } } const unsigned int port_is_output = (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ); if ((port_caps1 & port_is_output) == port_is_output) { port_mode1 = qjackctlGraphItem::Output; qjackctlGraphNode *node1 = nullptr; qjackctlGraphPort *port1 = nullptr; if (findClientPort(client_info1, port_info1, port_mode1, &node1, &port1, true)) { node1->setMarked(true); port1->setMarked(true); } } } } // 2. Connections inventory... // snd_seq_client_info_t *client_info2; snd_seq_port_info_t *port_info2; snd_seq_client_info_alloca(&client_info2); snd_seq_port_info_alloca(&port_info2); snd_seq_query_subscribe_t *seq_subs; snd_seq_addr_t seq_addr; snd_seq_query_subscribe_alloca(&seq_subs); snd_seq_client_info_set_client(client_info1, -1); while (snd_seq_query_next_client(seq, client_info1) >= 0) { const int client_id = snd_seq_client_info_get_client(client_info1); if (0 >= client_id) // Skip 0:system client... continue; snd_seq_port_info_set_client(port_info1, client_id); snd_seq_port_info_set_port(port_info1, -1); while (snd_seq_query_next_port(seq, port_info1) >= 0) { const unsigned int port_caps1 = snd_seq_port_info_get_capability(port_info1); if (port_caps1 & SND_SEQ_PORT_CAP_NO_EXPORT) continue; if (port_caps1 & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) { const qjackctlGraphItem::Mode port_mode1 = qjackctlGraphItem::Output; qjackctlGraphNode *node1 = nullptr; qjackctlGraphPort *port1 = nullptr; if (!findClientPort(client_info1, port_info1, port_mode1, &node1, &port1, false)) continue; snd_seq_query_subscribe_set_type(seq_subs, SND_SEQ_QUERY_SUBS_READ); snd_seq_query_subscribe_set_index(seq_subs, 0); seq_addr.client = client_id; seq_addr.port = snd_seq_port_info_get_port(port_info1); snd_seq_query_subscribe_set_root(seq_subs, &seq_addr); while (snd_seq_query_port_subscribers(seq, seq_subs) >= 0) { seq_addr = *snd_seq_query_subscribe_get_addr(seq_subs); if (snd_seq_get_any_client_info(seq, seq_addr.client, client_info2) >= 0 && snd_seq_get_any_port_info(seq, seq_addr.client, seq_addr.port, port_info2) >= 0) { const qjackctlGraphItem::Mode port_mode2 = qjackctlGraphItem::Input; qjackctlGraphNode *node2 = nullptr; qjackctlGraphPort *port2 = nullptr; if (findClientPort(client_info2, port_info2, port_mode2, &node2, &port2, false)) { qjackctlGraphConnect *connect = port1->findConnect(port2); if (connect == nullptr) { connect = new qjackctlGraphConnect(); connect->setPort1(port1); connect->setPort2(port2); connect->updatePortTypeColors(); connect->updatePath(); qjackctlGraphSect::addItem(connect); } if (connect) connect->setMarked(true); } } snd_seq_query_subscribe_set_index(seq_subs, snd_seq_query_subscribe_get_index(seq_subs) + 1); } } } } // 3. Clean-up all un-marked items... // qjackctlGraphSect::resetItems(qjackctlAlsaGraph::nodeType()); } void qjackctlAlsaGraph::clearItems (void) { QMutexLocker locker(&m_mutex); #ifdef CONFIG_DEBUG_0 qDebug("qjackctlAlsaGraph::clearItems()"); #endif qjackctlGraphSect::clearItems(qjackctlAlsaGraph::nodeType()); } // Special port-type colors defaults (virtual). void qjackctlAlsaGraph::resetPortTypeColors (void) { qjackctlGraphCanvas *canvas = qjackctlGraphSect::canvas(); if (canvas) { canvas->setPortTypeColor( qjackctlAlsaGraph::midiPortType(), QColor(Qt::darkMagenta).darker(120)); } } // Client/port item aliases accessor. QList qjackctlAlsaGraph::item_aliases ( qjackctlGraphItem *item ) const { QList alist; qjackctlAliases *aliases = nullptr; qjackctlGraphCanvas *canvas = qjackctlGraphSect::canvas(); if (canvas) aliases = canvas->aliases(); if (aliases == nullptr) return alist; // empty! uint item_type = 0; qjackctlGraphItem::Mode item_mode = qjackctlGraphItem::None; bool is_node = false; if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node && qjackctlAlsaGraph::isNodeType(node->nodeType())) { item_type = node->nodeType(); item_mode = node->nodeMode(); is_node = true; } } else if (item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port = static_cast (item); if (port) { item_type = port->portType(); item_mode = port->portMode(); } } if (!item_type || !item_mode) return alist; // empty again! if (is_node || item_type == qjackctlAlsaGraph::midiPortType()) { // ALSA MIDI type... if (item_mode & qjackctlGraphItem::Input) alist.append(&(aliases->alsaInputs)); if (item_mode & qjackctlGraphItem::Output) alist.append(&(aliases->alsaOutputs)); } return alist; // hopefully non empty! } #endif // CONFIG_ALSA_SEQ // end of qjackctlAlsaGraph.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlPaletteForm.ui0000644000000000000000000000013214771215054017461 xustar0030 mtime=1743067692.327636574 30 atime=1743067692.326636579 30 ctime=1743067692.327636574 qjackctl-1.0.4/src/qjackctlPaletteForm.ui0000644000175000001440000001723114771215054017455 0ustar00rncbcusers rncbc aka Rui Nuno Capela JACK Audio Connection Kit - Qt GUI Interface. Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlPaletteForm 0 0 534 640 0 0 Color Themes Name 0 0 320 0 Current color palette name true QComboBox::NoInsert Save current color palette name Save :/images/formSave.png Delete current color palette name Delete :/images/formRemove.png Palette 280 360 Current color palette true Generate: 0 0 Qt::StrongFocus Base color to generate palette Reset all current palette colors Reset :/images/itemReset.png Qt::Horizontal 8 20 Import a custom color theme (palette) from file Import... :/images/formOpen.png Export a custom color theme (palette) to file Export... :/images/formSave.png Qt::Horizontal 8 20 Show Details Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qjackctlPaletteForm::ColorButton nameCombo saveButton deleteButton paletteView generateButton resetButton importButton exportButton detailsCheck dialogButtons qjackctl-1.0.4/src/PaxHeaders/qjackctlSessionFile.txt0000644000000000000000000000013214771215054017664 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSessionFile.txt0000644000175000001440000000123014771215054017650 0ustar00rncbcusersqjackctlSession format specification ------------------------------------ client-command . . . . . . . . . session-name := string-literal client-name := string-literal client-uuid := string-literal client-command := string-literal port-name := string-literal port-type := "in" | "out" qjackctl-1.0.4/src/PaxHeaders/qjackctlInterfaceComboBox.cpp0000644000000000000000000000013214771215054020735 xustar0030 mtime=1743067692.325636584 30 atime=1743067692.325636584 30 ctime=1743067692.325636584 qjackctl-1.0.4/src/qjackctlInterfaceComboBox.cpp0000644000175000001440000003265314771215054020736 0ustar00rncbcusers// qjackctlInterfaceComboBox.cpp // /**************************************************************************** Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. Copyright (C) 2015, Kjetil Matheussen. (portaudio_probe_thread) Copyright (C) 2013, Arnout Engelen. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlInterfaceComboBox.h" #include "qjackctlSetup.h" #include #include #include #include #include #include #ifdef CONFIG_COREAUDIO #include #include #include #include #include #endif #ifdef CONFIG_PORTAUDIO #include #include #include #ifdef WIN32 #include #endif #endif #ifdef CONFIG_ALSA_SEQ #include #endif // Constructor. qjackctlInterfaceComboBox::qjackctlInterfaceComboBox ( QWidget *pParent ) : QComboBox(pParent) { QTreeView *pTreeView = new QTreeView(this); pTreeView->header()->hide(); pTreeView->setRootIsDecorated(false); pTreeView->setAllColumnsShowFocus(true); pTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); pTreeView->setSelectionMode(QAbstractItemView::SingleSelection); pTreeView->setModel(new QStandardItemModel()); // pTreeView->setMinimumWidth(320); QComboBox::setView(pTreeView); } void qjackctlInterfaceComboBox::showPopup (void) { populateModel(); QComboBox::showPopup(); } QStandardItemModel *qjackctlInterfaceComboBox::model (void) const { return static_cast (QComboBox::model()); } void qjackctlInterfaceComboBox::setup ( QComboBox *pDriverComboBox, int iAudio, const QString& sDefName ) { m_pDriverComboBox = pDriverComboBox; m_iAudio = iAudio; m_sDefName = sDefName; } void qjackctlInterfaceComboBox::clearCards (void) { model()->clear(); } void qjackctlInterfaceComboBox::addCard ( const QString& sName, const QString& sDescription ) { QList items; if (sName == m_sDefName || sName.isEmpty()) items.append(new QStandardItem(m_sDefName)); else items.append(new QStandardItem(QIcon(":/images/device1.png"), sName)); items.append(new QStandardItem(sDescription)); model()->appendRow(items); } #ifdef CONFIG_COREAUDIO // borrowed from jackpilot source static OSStatus getDeviceUIDFromID( AudioDeviceID id, char *name, UInt32 nsize ) { UInt32 size = sizeof(CFStringRef); CFStringRef UI; OSStatus res = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceUID, &size, &UI); if (res == noErr) CFStringGetCString(UI,name,nsize,CFStringGetSystemEncoding()); CFRelease(UI); return res; } #endif // CONFIG_COREAUDIO #ifdef CONFIG_PORTAUDIO #include #include #include #include namespace { class PortAudioProber : public QThread { public: static QStringList getNames(QWidget *pParent) { { QMutexLocker locker(&PortAudioProber::mutex); if (!PortAudioProber::names.isEmpty()) return PortAudioProber::names; } QMessageBox mbox(QMessageBox::Information, tr("Probing..."), tr("Please wait, PortAudio is probing audio hardware."), QMessageBox::Abort, pParent); // Make it impossible to start another PortAudioProber while waiting. mbox.setWindowModality(Qt::WindowModal); PortAudioProber *pab = new PortAudioProber; pab->start(); bool bTimedOut = true; for (int i = 0; i < 100; ++i) { if (mbox.isVisible()) QApplication::processEvents(); QThread::msleep(50); if (i == 10) // wait 1/2 second before showing message box mbox.show(); if (mbox.clickedButton() != nullptr) { bTimedOut = false; break; } if (pab->isFinished()) { bTimedOut = false; break; } } if (bTimedOut) { QMessageBox::warning(pParent, tr("Warning"), tr("Audio hardware probing timed out.")); } { QMutexLocker locker(&PortAudioProber::mutex); return names; } } private: PortAudioProber() {} ~PortAudioProber() {} static QMutex mutex; static QStringList names; void run() { if (Pa_Initialize() == paNoError) { // Fill HostApi info... const PaHostApiIndex iNumHostApi = Pa_GetHostApiCount(); QString *hostNames = new QString[iNumHostApi]; for (PaHostApiIndex i = 0; i < iNumHostApi; ++i) hostNames[i] = QString(Pa_GetHostApiInfo(i)->name); // Fill device info... const PaDeviceIndex iNumDevice = Pa_GetDeviceCount(); { #ifdef WIN32 wchar_t wideDeviceName[MAX_PATH]; #endif QMutexLocker locker(&PortAudioProber::mutex); if (PortAudioProber::names.isEmpty()) { for (PaDeviceIndex i = 0; i < iNumDevice; ++i) { PaDeviceInfo *pDeviceInfo = const_cast (Pa_GetDeviceInfo(i)); if (strcmp(pDeviceInfo->name, "JackRouter") == 0) continue; #ifdef WIN32 MultiByteToWideChar(CP_UTF8, 0, pDeviceInfo->name, -1, wideDeviceName, MAX_PATH-1); const QString sName = hostNames[pDeviceInfo->hostApi] + "::" + QString::fromWCharArray(wideDeviceName); #else const QString sName = hostNames[pDeviceInfo->hostApi] + "::" + QString(pDeviceInfo->name); #endif PortAudioProber::names.push_back(sName); } } } delete [] hostNames; Pa_Terminate(); } } }; QMutex PortAudioProber::mutex; QStringList PortAudioProber::names; } // namespace #endif // CONFIG_PORTAUDIO void qjackctlInterfaceComboBox::populateModel (void) { const bool bBlockSignals = QComboBox::blockSignals(true); QComboBox::setUpdatesEnabled(false); QComboBox::setDuplicatesEnabled(false); QLineEdit *pLineEdit = QComboBox::lineEdit(); // FIXME: Only valid for ALSA, Sun and OSS devices, // for the time being... and also CoreAudio ones too. const QString& sDriver = m_pDriverComboBox->currentText(); const bool bAlsa = (sDriver == "alsa"); const bool bSun = (sDriver == "sun"); const bool bOss = (sDriver == "oss"); #ifdef CONFIG_COREAUDIO const bool bCoreaudio = (sDriver == "coreaudio"); std::map coreaudioIdMap; #endif #ifdef CONFIG_PORTAUDIO const bool bPortaudio = (sDriver == "portaudio"); #endif QString sCurName = pLineEdit->text(); QString sName, sSubName; int iCards = 0; clearCards(); int iCurCard = -1; if (bAlsa) { #ifdef CONFIG_ALSA_SEQ // Enumerate the ALSA cards and PCM harfware devices... snd_ctl_t *handle; snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; snd_ctl_card_info_alloca(&info); snd_pcm_info_alloca(&pcminfo); const QString sPrefix("hw:%1"); const QString sSuffix(" (%1)"); const QString sSubSuffix("%1,%2"); QString sName2, sSubName2; bool bCapture, bPlayback; int iCard = -1; while (snd_card_next(&iCard) >= 0 && iCard >= 0) { sName = sPrefix.arg(iCard); if (snd_ctl_open(&handle, sName.toUtf8().constData(), 0) >= 0 && snd_ctl_card_info(handle, info) >= 0) { sName2 = sPrefix.arg(snd_ctl_card_info_get_id(info)); addCard(sName2, snd_ctl_card_info_get_name(info) + sSuffix.arg(sName)); if (sCurName == sName || sCurName == sName2) iCurCard = iCards; ++iCards; int iDevice = -1; while (snd_ctl_pcm_next_device(handle, &iDevice) >= 0 && iDevice >= 0) { // Capture devices.. bCapture = false; if (m_iAudio == QJACKCTL_CAPTURE || m_iAudio == QJACKCTL_DUPLEX) { snd_pcm_info_set_device(pcminfo, iDevice); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE); bCapture = (snd_ctl_pcm_info(handle, pcminfo) >= 0); } // Playback devices.. bPlayback = false; if (m_iAudio == QJACKCTL_PLAYBACK || m_iAudio == QJACKCTL_DUPLEX) { snd_pcm_info_set_device(pcminfo, iDevice); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK); bPlayback = (snd_ctl_pcm_info(handle, pcminfo) >= 0); } // List iif compliant with the audio mode criteria... if ((m_iAudio == QJACKCTL_CAPTURE && bCapture && !bPlayback) || (m_iAudio == QJACKCTL_PLAYBACK && !bCapture && bPlayback) || (m_iAudio == QJACKCTL_DUPLEX && bCapture && bPlayback)) { sSubName = sSubSuffix.arg(sName).arg(iDevice); sSubName2 = sSubSuffix.arg(sName2).arg(iDevice); addCard(sSubName2, snd_pcm_info_get_name(pcminfo) + sSuffix.arg(sSubName)); if (sCurName == sSubName || sCurName == sSubName2) iCurCard = iCards; ++iCards; } } snd_ctl_close(handle); } } #endif // CONFIG_ALSA_SEQ } else if (bSun) { QFile file("/var/run/dmesg.boot"); if (file.open(QIODevice::ReadOnly)) { QTextStream stream(&file); QString sLine; QRegularExpression rxDevice("audio([0-9]) at (.*)"); QRegularExpressionMatch match; while (!stream.atEnd()) { sLine = stream.readLine(); match = rxDevice.match(sLine); if (match.hasMatch()) { sName = "/dev/audio" + match.captured(1); addCard(sName, match.captured(2)); if (sCurName == sName) iCurCard = iCards; ++iCards; } } file.close(); } } else if (bOss) { // Enumerate the OSS Audio devices... QFile file("/dev/sndstat"); if (file.open(QIODevice::ReadOnly)) { QTextStream stream(&file); QString sLine; bool bAudioDevices = false; QRegularExpression rxHeader("Audio devices.*", QRegularExpression::CaseInsensitiveOption); QRegularExpression rxDevice("([0-9]+):[ ]+(.*)"); QRegularExpressionMatch match; while (!stream.atEnd()) { sLine = stream.readLine(); if (bAudioDevices) { match = rxDevice.match(sLine); if (match.hasMatch()) { sName = "/dev/dsp" + match.captured(1); addCard(sName, match.captured(2)); if (sCurName == sName) iCurCard = iCards; ++iCards; } else break; } else { match = rxHeader.match(sLine); if (match.hasMatch()) bAudioDevices = true; } } file.close(); } } #ifdef CONFIG_COREAUDIO else if (bCoreaudio) { // Find out how many Core Audio devices are there, if any... // (code snippet gently "borrowed" from Stephane Letz jackdmp;) OSStatus err; Boolean isWritable; UInt32 outSize = sizeof(isWritable); err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &outSize, &isWritable); if (err == noErr) { // Calculate the number of device available... int numCoreDevices = outSize / sizeof(AudioDeviceID); // Make space for the devices we are about to get... AudioDeviceID *coreDeviceIDs = new AudioDeviceID [numCoreDevices]; err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &outSize, (void *) coreDeviceIDs); if (err == noErr) { // Look for the CoreAudio device name... char coreDeviceName[256]; UInt32 nameSize = 256; for (int i = 0; i < numCoreDevices; i++) { err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i], 0, true, kAudioDevicePropertyDeviceName, &outSize, &isWritable); if (err == noErr) { err = AudioDeviceGetProperty(coreDeviceIDs[i], 0, true, kAudioDevicePropertyDeviceName, &nameSize, (void *) coreDeviceName); if (err == noErr) { char drivername[128]; UInt32 dnsize = 128; // this returns the unique id for the device // that must be used on the commandline for jack if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, dnsize) == noErr) { sName = drivername; } else { sName = "Error"; } coreaudioIdMap[sName] = coreDeviceIDs[i]; // TODO: hide this ugly ID from the user, // only show human readable name // humanreadable \t UID sSubName = QString(coreDeviceName); addCard(sName, sSubName); if (sCurName == sName || sCurName == sSubName) iCurCard = iCards; ++iCards; } } } } delete [] coreDeviceIDs; } } #endif // CONFIG_COREAUDIO #ifdef CONFIG_PORTAUDIO else if (bPortaudio) { const QStringList& names = PortAudioProber::getNames(this); const int iCards = names.size(); for (int i = 0; i < iCards; ++i) { const QString& sName = names[i]; if (sCurName == sName) iCurCard = iCards; addCard(sName, QString()); } } #endif // CONFIG_PORTAUDIO addCard(m_sDefName, QString()); if (sCurName == m_sDefName || sCurName.isEmpty()) iCurCard = iCards; ++iCards; QTreeView *pTreeView = static_cast (QComboBox::view()); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) pTreeView->header()->setResizeMode(QHeaderView::ResizeToContents); #else pTreeView->header()->resizeSections(QHeaderView::ResizeToContents); #endif pTreeView->setMinimumWidth( pTreeView->sizeHint().width() + QComboBox::iconSize().width()); QComboBox::setCurrentIndex(iCurCard); pLineEdit->setText(sCurName); QComboBox::setUpdatesEnabled(true); QComboBox::blockSignals(bBlockSignals); } // end of qjackctlInterfaceComboBox.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlSocketForm.h0000644000000000000000000000012714771215054017131 xustar0029 mtime=1743067692.33063656 29 atime=1743067692.33063656 29 ctime=1743067692.33063656 qjackctl-1.0.4/src/qjackctlSocketForm.h0000644000175000001440000000551314771215054017121 0ustar00rncbcusers// qjackctlSocketForm.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlSocketForm_h #define __qjackctlSocketForm_h #include "ui_qjackctlSocketForm.h" #include "qjackctlJackConnect.h" #include "qjackctlAlsaConnect.h" // Forward declarations. class qjackctlPatchbay; class qjackctlPatchbaySocket; class qjackctlSocketList; class QButtonGroup; class QPixmap; //---------------------------------------------------------------------------- // qjackctlSocketForm -- UI wrapper form. class qjackctlSocketForm : public QDialog { Q_OBJECT public: // Constructor. qjackctlSocketForm(QWidget *pParent = nullptr); // Destructor. ~qjackctlSocketForm(); void setSocketCaption(const QString& sSocketCaption); void setSocketList(qjackctlSocketList *pSocketList); void setSocketNew(bool bSocketNew); void setPixmaps(QPixmap **ppPixmaps); void setConnectCount(int iConnectCount); void load(qjackctlPatchbaySocket *pSocket); void save(qjackctlPatchbaySocket *pSocket); public slots: void changed(); void addPlug(); void editPlug(); void removePlug(); void moveUpPlug(); void moveDownPlug(); void selectedPlug(); void activateAddPlugMenu(QAction *); void customContextMenu(const QPoint&); void socketTypeChanged(); void socketNameChanged(); void clientNameChanged(); void stabilizeForm(); protected slots: void accept(); void reject(); protected: void updateJackClients(int iSocketType); void updateAlsaClients(int iSocketType); void updateJackPlugs(int iSocketType); void updateAlsaPlugs(int iSocketType); bool validateForm(); private: // The Qt-designer UI struct... Ui::qjackctlSocketForm m_ui; // Instance variables. qjackctlSocketList *m_pSocketList; bool m_bSocketNew; int m_iSocketNameChanged; QPixmap **m_ppPixmaps; int m_iDirtyCount; QButtonGroup *m_pSocketTypeButtonGroup; }; #endif // __qjackctlSocketForm_h // end of qjackctlSocketForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlSession.cpp0000644000000000000000000000013114771215054017026 xustar0030 mtime=1743067692.329636565 29 atime=1743067692.32863657 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSession.cpp0000644000175000001440000004327014771215054017025 0ustar00rncbcusers// qjackctlSession.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAbout.h" #include "qjackctlSession.h" #include "qjackctlMainForm.h" #ifdef CONFIG_JACK_SESSION #include #include #endif #include #include #include #include #include #include #include #include // Deprecated QTextStreamFunctions/Qt namespaces workaround. #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) #define endl Qt::endl #endif //---------------------------------------------------------------------------- // qjackctlSession -- JACK session container. // Constructor. qjackctlSession::qjackctlSession (void) { } // Destructor. qjackctlSession::~qjackctlSession (void) { clearInfraClients(); clear(); } // Client list accessor (read-only) const qjackctlSession::ClientList& qjackctlSession::clients (void) const { return m_clients; } // House-keeper. void qjackctlSession::clear (void) { qDeleteAll(m_clients); m_clients.clear(); } #ifdef CONFIG_JACK_SESSION #if defined(Q_CC_GNU) || defined(Q_CC_MINGW) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif #endif // Critical methods. bool qjackctlSession::save ( const QString& sSessionDir, SaveType stype ) { // We're always best to // reset old session settings. clear(); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return false; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return false; const QString sSessionPath = sSessionDir + '/'; // First pass: get all client/port connections, no matter what... const char **ports = ::jack_get_ports(pJackClient, nullptr, nullptr, 0); if (ports) { for (int i = 0; ports[i]; ++i) { const char *pszSrcClientPort = ports[i]; const QString sSrcClientPort = QString::fromLocal8Bit(pszSrcClientPort); const QString sSrcClient = sSrcClientPort.section(':', 0, 0); ClientItem *pClientItem; if (m_clients.contains(sSrcClient)) { pClientItem = m_clients.value(sSrcClient); } else { pClientItem = new ClientItem; pClientItem->client_name = sSrcClient; m_clients.insert(pClientItem->client_name, pClientItem); } PortItem *pPortItem = new PortItem; pPortItem->port_name = sSrcClientPort.section(':', 1); jack_port_t *pJackPort = ::jack_port_by_name(pJackClient, pszSrcClientPort); pPortItem->port_type = (::jack_port_flags(pJackPort) & JackPortIsInput); const char **connections = ::jack_port_get_all_connections(pJackClient, pJackPort); if (connections) { for (int j = 0; connections[j]; ++j) { const QString sDstClientPort = QString::fromLocal8Bit(connections[j]); ConnectItem *pConnectItem = new ConnectItem; pConnectItem->client_name = sDstClientPort.section(':', 0, 0); pConnectItem->port_name = sDstClientPort.section(':', 1); pConnectItem->connected = true; pPortItem->connects.append(pConnectItem); // pPortItem->connected++; } ::jack_free(connections); } pClientItem->ports.append(pPortItem); // pClientItem->connected += pPortItem->connected; } ::jack_free(ports); } #ifdef CONFIG_JACK_SESSION // Second pass: get all session client commands... jack_session_event_type_t etype = JackSessionSave; switch (stype) { case SaveType::Save: default: break; case SaveType::SaveAndQuit: etype = JackSessionSaveAndQuit; break; case SaveType::SaveTemplate: etype = JackSessionSaveTemplate; break; } const QByteArray aSessionPath = sSessionPath.toLocal8Bit(); const char *pszSessionPath = aSessionPath.constData(); jack_session_command_t *commands = ::jack_session_notify(pJackClient, nullptr, etype, pszSessionPath); if (commands == nullptr) return false; // Second pass... for (int k = 0; commands[k].uuid; ++k) { jack_session_command_t *pCommand = &commands[k]; const QString sClientName = QString::fromLocal8Bit(pCommand->client_name); ClientItem *pClientItem; if (m_clients.contains(sClientName)) { pClientItem = m_clients.value(sClientName); } else { pClientItem = new ClientItem; pClientItem->client_name = sClientName; m_clients.insert(pClientItem->client_name, pClientItem); } pClientItem->client_uuid = QString::fromLocal8Bit(pCommand->uuid); pClientItem->client_command = QString::fromLocal8Bit(pCommand->command); } ::jack_session_commands_free(commands); #endif // CONFIG_JACK_SESSION // Third pass: check whether there are registered infra-clients... ClientList::ConstIterator iter = m_clients.constBegin(); const ClientList::ConstIterator& iter_end = m_clients.constEnd(); for ( ; iter != iter_end; ++iter) { ClientItem *pClientItem = iter.value(); if (pClientItem->client_command.isEmpty()) { const QString& sClientName = pClientItem->client_name; if (sClientName == "system") continue; InfraClientItem *pInfraClientItem = m_infra_clients.value(sClientName, nullptr); if (pInfraClientItem) { pClientItem->client_command = pInfraClientItem->client_command; } else { pInfraClientItem = new InfraClientItem; pInfraClientItem->client_name = sClientName; pInfraClientItem->client_command = pClientItem->client_command; m_infra_clients.insert(sClientName, pInfraClientItem); } } } // Finally: save to file, immediate... return saveFile(sSessionPath + "session.xml"); } bool qjackctlSession::load ( const QString& sSessionDir ) { // Load from file, immediate... const QString sSessionPath = sSessionDir + '/'; if (!loadFile(sSessionPath + "session.xml")) return false; // Start/load clients... ClientList::ConstIterator iter = m_clients.constBegin(); const ClientList::ConstIterator& iter_end = m_clients.constEnd(); for ( ; iter != iter_end; ++iter) { const ClientItem *pClientItem = iter.value(); const QString& sClientName = pClientItem->client_name; QString sCommand = pClientItem->client_command; if (sCommand.isEmpty()) { // Maybe a registered infra-client command... InfraClientItem *pInfraClientItem = m_infra_clients.value(sClientName, nullptr); if (pInfraClientItem && !isJackClient(sClientName)) sCommand = pInfraClientItem->client_command; } else if (!pClientItem->client_uuid.isEmpty()){ // Sure a legit session-client command... const QString& sClientDir = sSessionPath + pClientItem->client_name + '/'; sCommand.replace("${SESSION_DIR}", sClientDir); } // Launch command and wait a litle bit before continue... if (!sCommand.isEmpty()) { QStringList cmd_args = sCommand.split(' '); sCommand = cmd_args.at(0); cmd_args.removeAt(0); if (QProcess::startDetached(sCommand, cmd_args)) { QElapsedTimer timer; timer.start(); while (timer.elapsed() < 200) QApplication::processEvents(); } } } // Initial reconnection. update(); // Formerly successful. return true; } #ifdef CONFIG_JACK_SESSION #if defined(Q_CC_GNU) || defined(Q_CC_MINGW) #pragma GCC diagnostic pop #endif #endif // Update (re)connections utility method. bool qjackctlSession::update (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return false; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return false; // We'll count how many connection updates... int iUpdate = 0; // Now, make the saved connections... ClientList::ConstIterator iter = m_clients.constBegin(); const ClientList::ConstIterator& iter_end = m_clients.constEnd(); for ( ; iter != iter_end; ++iter) { ClientItem *pClientItem = iter.value(); if (pClientItem->connected < 1) continue; QString sSrcClient = pClientItem->client_name; #ifdef CONFIG_JACK_SESSION if (!pClientItem->client_uuid.isEmpty()) { const QByteArray aSrcUuid = pClientItem->client_uuid.toLocal8Bit(); const char *pszSrcUuid = aSrcUuid.constData(); const char *pszSrcClient = ::jack_get_client_name_by_uuid(pJackClient, pszSrcUuid); if (pszSrcClient) { sSrcClient = QString::fromLocal8Bit(pszSrcClient); ::jack_free((void *) pszSrcClient); } } #endif QListIterator iterPort(pClientItem->ports); while (iterPort.hasNext()) { PortItem *pPortItem = iterPort.next(); if (pPortItem->connected < 1) continue; const QString sSrcPort = pPortItem->port_name; const QString sSrcClientPort = sSrcClient + ':' + sSrcPort; const QByteArray aSrcClientPort = sSrcClientPort.toLocal8Bit(); QListIterator iterConnect(pPortItem->connects); while (iterConnect.hasNext()) { ConnectItem *pConnectItem = iterConnect.next(); if (pConnectItem->connected) continue; QString sDstClient = pConnectItem->client_name; #ifdef CONFIG_JACK_SESSION if (m_clients.contains(sDstClient)) { const QString sDstUuid = m_clients.value(sDstClient)->client_uuid; const QByteArray aDstUuid = sDstUuid.toLocal8Bit(); const char *pszDstUuid = aDstUuid.constData(); const char *pszDstClient = ::jack_get_client_name_by_uuid(pJackClient, pszDstUuid); if (pszDstClient) { sDstClient = QString::fromLocal8Bit(pszDstClient); ::jack_free((void *) pszDstClient); } } #endif const QString sDstPort = pConnectItem->port_name; const QString sDstClientPort = sDstClient + ':' + sDstPort; const QByteArray aDstClientPort = sDstClientPort.toLocal8Bit(); int retc; if (pPortItem->port_type) { // Input port... retc = ::jack_connect(pJackClient, aDstClientPort.constData(), aSrcClientPort.constData()); #ifdef CONFIG_DEBUG qDebug("qjackctlSession::update() " "jack_connect: \"%s\" => \"%s\" (%d)", aDstClientPort.constData(), aSrcClientPort.constData(), retc); #endif } else { // Output port... retc = ::jack_connect(pJackClient, aSrcClientPort.constData(), aDstClientPort.constData()); #ifdef CONFIG_DEBUG qDebug("qjackctlSession::update() " "jack_connect: \"%s\" => \"%s\" (%d)", aSrcClientPort.constData(), aDstClientPort.constData(), retc); #endif } // Comply with connection result... if (retc == 0 || retc == EEXIST) { pConnectItem->connected = true; pPortItem->connected--; pClientItem->connected--; iUpdate++; } } } } // Report back. return (iUpdate > 0); } // Specific session file load (read) method. bool qjackctlSession::loadFile ( const QString& sFilename ) { // Open file... QFile file(sFilename); if (!file.open(QIODevice::ReadOnly)) return false; // Parse it a-la-DOM :-) QDomDocument doc("qjackctlSession"); if (!doc.setContent(&file)) { file.close(); return false; } file.close(); // Now, we're always best to // reset old session settings. clear(); // Get root element. QDomElement eDoc = doc.documentElement(); // Parse for clients... for (QDomNode nClient = eDoc.firstChild(); !nClient.isNull(); nClient = nClient.nextSibling()) { // Client element... QDomElement eClient = nClient.toElement(); if (eClient.isNull()) continue; if (eClient.tagName() != "client") continue; ClientItem *pClientItem = new ClientItem; pClientItem->client_name = eClient.attribute("name"); pClientItem->client_uuid = eClient.attribute("uuid"); // Client properties... for (QDomNode nChild = eClient.firstChild(); !nChild.isNull(); nChild = nChild.nextSibling()) { // Client child element... QDomElement eChild = nChild.toElement(); if (eChild.isNull()) continue; if (eChild.tagName() == "command") pClientItem->client_command = eChild.text(); else if (eChild.tagName() == "port") { // Port properties... PortItem *pPortItem = new PortItem; pPortItem->port_name = eChild.attribute("name"); pPortItem->port_type = (eChild.attribute("type") == "in"); // Connection child element... for (QDomNode nConnect = eChild.firstChild(); !nConnect.isNull(); nConnect = nConnect.nextSibling()) { QDomElement eConnect = nConnect.toElement(); if (eConnect.isNull()) continue; if (eConnect.tagName() != "connect") continue; ConnectItem *pConnectItem = new ConnectItem; pConnectItem->client_name = eConnect.attribute("client"); pConnectItem->port_name = eConnect.attribute("port"); pConnectItem->connected = false; pPortItem->connects.append(pConnectItem); pPortItem->connected++; } pClientItem->ports.append(pPortItem); pClientItem->connected += pPortItem->connected; } } m_clients.insert(pClientItem->client_name, pClientItem); } return true; } // Specific session file save (write) method. bool qjackctlSession::saveFile ( const QString& sFilename ) { QFileInfo fi(sFilename); QDomDocument doc("qjackctlSession"); QDomElement eSession = doc.createElement("session"); eSession.setAttribute("name", QFileInfo(fi.absolutePath()).baseName()); doc.appendChild(eSession); // Save clients spec... ClientList::ConstIterator iter = m_clients.constBegin(); const ClientList::ConstIterator& iter_end = m_clients.constEnd(); for ( ; iter != iter_end; ++iter) { const ClientItem *pClientItem = iter.value(); QDomElement eClient = doc.createElement("client"); eClient.setAttribute("name", pClientItem->client_name); if (!pClientItem->client_uuid.isEmpty()) eClient.setAttribute("uuid", pClientItem->client_uuid); if (!pClientItem->client_command.isEmpty()) { QDomElement eCommand = doc.createElement("command"); eCommand.appendChild(doc.createTextNode(pClientItem->client_command)); eClient.appendChild(eCommand); } QListIterator iterPort(pClientItem->ports); while (iterPort.hasNext()) { const PortItem *pPortItem = iterPort.next(); QDomElement ePort = doc.createElement("port"); ePort.setAttribute("name", pPortItem->port_name); ePort.setAttribute("type", pPortItem->port_type ? "in" : "out"); QListIterator iterConnect(pPortItem->connects); while (iterConnect.hasNext()) { const ConnectItem *pConnectItem = iterConnect.next(); QDomElement eConnect = doc.createElement("connect"); eConnect.setAttribute("client", pConnectItem->client_name); eConnect.setAttribute("port", pConnectItem->port_name); ePort.appendChild(eConnect); } eClient.appendChild(ePort); } eSession.appendChild(eClient); } // Finally, save to external file. QFile file(sFilename); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) return false; QTextStream ts(&file); ts << doc.toString() << endl; file.close(); return true; } // Infra-client list accessor (read-only) qjackctlSession::InfraClientList& qjackctlSession::infra_clients (void) { return m_infra_clients; } // Load all infra-clients from configuration file. void qjackctlSession::loadInfraClients ( QSettings& settings ) { clearInfraClients(); settings.beginGroup("/InfraClients"); const QStringList& keys = settings.childKeys(); QStringListIterator iter(keys); while (iter.hasNext()) { const QString& sKey = iter.next(); const QString& sValue = settings.value(sKey).toString(); if (!sValue.isEmpty()) { InfraClientItem *pInfraClientItem = new InfraClientItem; pInfraClientItem->client_name = sKey; pInfraClientItem->client_command = sValue; m_infra_clients.insert(sKey, pInfraClientItem); } } settings.endGroup(); } // Save all infra-clients to configuration file. void qjackctlSession::saveInfraClients ( QSettings& settings ) { settings.beginGroup("/InfraClients"); settings.remove(QString()); // Remove all current keys. InfraClientList::ConstIterator iter = m_infra_clients.constBegin(); const InfraClientList::ConstIterator& iter_end = m_infra_clients.constEnd(); for ( ; iter != iter_end; ++iter) { const QString& sKey = iter.key(); const QString& sValue = iter.value()->client_command; if (!sValue.isEmpty()) settings.setValue(sKey, sValue); } settings.endGroup(); } // Clear infra-client table. void qjackctlSession::clearInfraClients (void) { qDeleteAll(m_infra_clients); m_infra_clients.clear(); } // Check whether a given JACK client name exists... bool qjackctlSession::isJackClient ( const QString& sClientName ) const { const QByteArray aClientName = sClientName.toUtf8(); #ifdef CONFIG_JACK_SESSION qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return false; jack_client_t *pJackClient = pMainForm->jackClient(); if (pJackClient == nullptr) return false; const char *client_uuid = ::jack_get_uuid_for_client_name( pJackClient, aClientName.constData()); if (client_uuid) { ::jack_free((void *) client_uuid); return true; } return false; #endif jack_client_t *pIsJackClient = ::jack_client_open(aClientName.constData(), jack_options_t(JackNoStartServer | JackUseExactName), nullptr); if (pIsJackClient) { ::jack_client_close(pIsJackClient); return true; } return false; } // end of qjackctlSession.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlSessionSaveForm.cpp0000644000000000000000000000013214771215054020472 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSessionSaveForm.cpp0000644000175000001440000001571014771215054020466 0ustar00rncbcusers// qjackctlSessionSaveForm.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlSessionSaveForm.h" #include "qjackctlAbout.h" #include "qjackctlSetup.h" #include #include #include #include #include //---------------------------------------------------------------------------- // qjackctlSessionSaveForm -- UI wrapper form. // Constructor. qjackctlSessionSaveForm::qjackctlSessionSaveForm ( QWidget *pParent, const QString& sTitle, const QStringList& sessionDirs ) : QDialog(pParent) { // Setup UI struct... m_ui.setupUi(this); // Setup UI entities... QDialog::setWindowTitle(sTitle); m_ui.SessionNameLineEdit->setValidator( new QRegularExpressionValidator( QRegularExpression("[^/]+"), m_ui.SessionNameLineEdit)); #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) m_ui.SessionDirComboBox->lineEdit()->setClearButtonEnabled(true); #endif if (!sessionDirs.isEmpty()) { m_ui.SessionDirComboBox->addItems(sessionDirs); const QFileInfo fi(sessionDirs.first()); m_sSessionDir = fi.absoluteFilePath(); if (m_sSessionDir != QDir::homePath()) m_ui.SessionNameLineEdit->setText(fi.fileName()); } if (m_sSessionDir.isEmpty()) m_sSessionDir = QDir::homePath(); m_ui.SessionDirComboBox->setEditText(m_sSessionDir); adjustSize(); // UI signal/slot connections... QObject::connect(m_ui.SessionNameLineEdit, SIGNAL(textChanged(const QString&)), SLOT(changeSessionName(const QString&))); QObject::connect(m_ui.SessionDirComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changeSessionDir(const QString&))); QObject::connect(m_ui.SessionDirToolButton, SIGNAL(clicked()), SLOT(browseSessionDir())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); // Done. stabilizeForm(); } // Destructor. qjackctlSessionSaveForm::~qjackctlSessionSaveForm (void) { } // Retrieve the accepted session directory, if the case arises. const QString& qjackctlSessionSaveForm::sessionDir (void) const { return m_sSessionDir; } // Session directory versioning option. void qjackctlSessionSaveForm::setSessionSaveVersion ( bool bSessionSaveVersion ) { m_ui.SessionSaveVersionCheckBox->setChecked(bSessionSaveVersion); } bool qjackctlSessionSaveForm::isSessionSaveVersion (void) const { return m_ui.SessionSaveVersionCheckBox->isChecked(); } // Accept settings (OK button slot). void qjackctlSessionSaveForm::accept (void) { // Check if session directory is new... const QString& sSessionDir = m_ui.SessionDirComboBox->currentText(); if (sSessionDir.isEmpty()) return; QDir dir; while (!dir.exists(sSessionDir)) { // Ask user... if (QMessageBox::warning(this, tr("Warning"), tr("Session directory does not exist:\n\n" "\"%1\"\n\n" "Do you want to create it?").arg(sSessionDir), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; // Proceed... dir.mkpath(sSessionDir); } // Save options... m_sSessionDir = sSessionDir; // Just go with dialog acceptance. QDialog::accept(); } // Reject settings (Cancel button slot). void qjackctlSessionSaveForm::reject (void) { QDialog::reject(); } // Session name in-flight change. void qjackctlSessionSaveForm::changeSessionName ( const QString& sSessionName ) { QFileInfo fi(m_ui.SessionDirComboBox->currentText()); if (fi.canonicalFilePath() == QDir::homePath()) fi.setFile(QDir(fi.absoluteFilePath()), sSessionName); else fi.setFile(QDir(fi.absolutePath()), sSessionName); const bool bBlockSignals = m_ui.SessionDirComboBox->blockSignals(true); m_ui.SessionDirComboBox->setEditText(fi.absoluteFilePath()); m_ui.SessionDirComboBox->blockSignals(bBlockSignals); stabilizeForm(); } // Session directory in-flight change. void qjackctlSessionSaveForm::changeSessionDir ( const QString& sSessionDir ) { if (sSessionDir.isEmpty()) { m_ui.SessionDirComboBox->setEditText(m_sSessionDir); } else { QString sSessionName; const QFileInfo fi(sSessionDir); if (fi.canonicalFilePath() != QDir::homePath()) sSessionName = fi.fileName(); const bool bBlockSignals = m_ui.SessionNameLineEdit->blockSignals(true); m_ui.SessionNameLineEdit->setText(sSessionName); m_ui.SessionNameLineEdit->blockSignals(bBlockSignals); } stabilizeForm(); } // Browse for session directory. void qjackctlSessionSaveForm::browseSessionDir (void) { const QString& sTitle = tr("Session Directory"); QString sSessionDir = m_ui.SessionDirComboBox->currentText(); #if 0//QT_VERSION < QT_VERSION_CHECK(4, 4, 0) // Construct open-directory dialog... QFileDialog fileDialog(pParentWidget, sTitle, sSessionDir); // Set proper open-file modes... fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::DirectoryOnly); // Stuff sidebar... QList urls(fileDialog.sidebarUrls()); urls.append(QUrl::fromLocalFile(sSessionDir); fileDialog.setSidebarUrls(urls); fileDialog.setOptions(options); // Show dialog... if (!fileDialog.exec()) return; sSessionDir = fileDialog.selectedFiles().first(); #else sSessionDir = QFileDialog::getExistingDirectory(this, sTitle, sSessionDir); #endif if (sSessionDir.isEmpty()) return; changeSessionDir(sSessionDir); const bool bBlockSignals = m_ui.SessionDirComboBox->blockSignals(true); m_ui.SessionDirComboBox->setEditText(sSessionDir); m_ui.SessionDirComboBox->blockSignals(bBlockSignals); m_ui.SessionDirComboBox->setFocus(); stabilizeForm(); } // Stabilize current form state. void qjackctlSessionSaveForm::stabilizeForm (void) { const QString& sSessionDir = m_ui.SessionDirComboBox->currentText(); bool bValid = !m_ui.SessionNameLineEdit->text().isEmpty(); bValid = bValid && !sSessionDir.isEmpty(); if (bValid) { QFileInfo fi(sSessionDir); bValid = bValid && (fi.canonicalFilePath() != QDir::homePath()); while (bValid && !fi.exists()) fi.setFile(fi.path()); bValid = bValid && fi.isDir() && fi.isReadable() && fi.isWritable(); } m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(bValid); } // end of qjackctlSessionSaveForm.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctl.qrc0000644000000000000000000000013214771215054015466 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctl.qrc0000644000175000001440000001047214771215054015462 0ustar00rncbcusers images/qjackctl.png images/qjackctl.svg images/about1.png images/accept1.png images/aclienti.png images/aclienti_32x32.png images/aclienti_64x64.png images/acliento.png images/acliento_32x32.png images/acliento_64x64.png images/add1.png images/aportlni.png images/aportlni_32x32.png images/aportlni_64x64.png images/aportlno.png images/aportlno_32x32.png images/aportlno_64x64.png images/aportlti.png images/aportlti_32x32.png images/aportlti_64x64.png images/aportlto.png images/aportlto_32x32.png images/aportlto_64x64.png images/aportpni.png images/aportpni_32x32.png images/aportpni_64x64.png images/aportpno.png images/aportpno_32x32.png images/aportpno_64x64.png images/aportpti.png images/aportpti_32x32.png images/aportpti_64x64.png images/aportpto.png images/aportpto_32x32.png images/aportpto_64x64.png images/apply1.png images/asocketi.png images/asocketo.png images/backward1.png images/clear1.png images/client1.png images/connect1.png images/connections1.png images/copy1.png images/device1.png images/disconnect1.png images/disconnectall1.png images/displaybg1.png images/down1.png images/edit1.png images/error1.png images/expandall1.png images/forward1.png images/graph1.png images/graphAlsa.png images/graphCenter.png images/graphColors.png images/graphConnect.png images/graphDisconnect.png images/graphRename.png images/graphFind.png images/graphJack.png images/graphRedo.png images/graphUndo.png images/graphThumbview.png images/graphZoomFit.png images/graphZoomIn.png images/graphZoomOut.png images/graphZoomReset.png images/graphZoomRange.png images/graphZoomTool.png images/mclienti.png images/mclienti_32x32.png images/mclienti_64x64.png images/mcliento.png images/mcliento_32x32.png images/mcliento_64x64.png images/messages1.png images/messagesstatus1.png images/mporti.png images/mporti_32x32.png images/mporti_64x64.png images/mporto.png images/mporto_32x32.png images/mporto_64x64.png images/msocketi.png images/msocketo.png images/new1.png images/open1.png images/patchbay1.png images/pause1.png images/play1.png images/port1.png images/quit1.png images/refresh1.png images/remove1.png images/reset1.png images/rewind1.png images/save1.png images/session1.png images/setup1.png images/socket1.png images/start1.png images/status1.png images/stop1.png images/up1.png images/xactivating1.png images/xactive1.png images/xinactive1.png images/xsocket1.png images/xstarted1.png images/xstarting1.png images/xstopped1.png images/xstopping1.png images/formOpen.png images/formRemove.png images/formSave.png images/itemReset.png images/qtlogo1.png qjackctl-1.0.4/src/PaxHeaders/qjackctlStatus.h0000644000000000000000000000012714771215054016340 xustar0029 mtime=1743067692.33063656 29 atime=1743067692.33063656 29 ctime=1743067692.33063656 qjackctl-1.0.4/src/qjackctlStatus.h0000644000175000001440000000363614771215054016334 0ustar00rncbcusers// qjackctlStatus.h // /**************************************************************************** Copyright (C) 2003-2010, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlStatus_h #define __qjackctlStatus_h // List view statistics item indexes #define STATUS_SERVER_NAME 0 #define STATUS_SERVER_STATE 1 #define STATUS_DSP_LOAD 2 #define STATUS_SAMPLE_RATE 3 #define STATUS_BUFFER_SIZE 4 #define STATUS_REALTIME 5 #define STATUS_TRANSPORT_STATE 6 #define STATUS_TRANSPORT_TIME 7 #define STATUS_TRANSPORT_BBT 8 #define STATUS_TRANSPORT_BPM 9 #define STATUS_XRUN_COUNT 10 #define STATUS_XRUN_TIME 11 #define STATUS_XRUN_LAST 12 #define STATUS_XRUN_MAX 13 #define STATUS_XRUN_MIN 14 #define STATUS_XRUN_AVG 15 #define STATUS_XRUN_TOTAL 16 #define STATUS_RESET_TIME 17 #define STATUS_MAX_DELAY 18 // (Big)Time display identifiers. #define DISPLAY_TRANSPORT_TIME 0 #define DISPLAY_TRANSPORT_BBT 1 #define DISPLAY_RESET_TIME 2 #define DISPLAY_XRUN_TIME 3 #endif // __qjackctlStatus_h // end of qjackctlStatus.h qjackctl-1.0.4/src/PaxHeaders/qjackctlPatchbay.cpp0000644000000000000000000000013014771215054017135 xustar0029 mtime=1743067692.32863657 30 atime=1743067692.327636574 29 ctime=1743067692.32863657 qjackctl-1.0.4/src/qjackctlPatchbay.cpp0000644000175000001440000015056214771215054017140 0ustar00rncbcusers// qjackctlPatchbay.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlPatchbay.h" #include "qjackctlMainForm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) #include #include #endif // Interactivity socket form. #include "qjackctlSocketForm.h" // External patchbay loader. #include "qjackctlPatchbayFile.h" //---------------------------------------------------------------------- // class qjackctlPlugItem -- Socket plug list item. // // Constructor. qjackctlPlugItem::qjackctlPlugItem ( qjackctlSocketItem *pSocket, const QString& sPlugName, qjackctlPlugItem *pPlugAfter ) : QTreeWidgetItem(pSocket, pPlugAfter, QJACKCTL_PLUGITEM) { QTreeWidgetItem::setText(0, sPlugName); m_pSocket = pSocket; m_sPlugName = sPlugName; m_pSocket->plugs().append(this); int iPixmap; if (pSocket->socketType() == QJACKCTL_SOCKETTYPE_JACK_AUDIO) iPixmap = QJACKCTL_XPM_AUDIO_PLUG; else iPixmap = QJACKCTL_XPM_MIDI_PLUG; QTreeWidgetItem::setIcon(0, QIcon(pSocket->pixmap(iPixmap))); QTreeWidgetItem::setFlags(QTreeWidgetItem::flags() & ~Qt::ItemIsSelectable); } // Default destructor. qjackctlPlugItem::~qjackctlPlugItem (void) { const int iPlug = m_pSocket->plugs().indexOf(this); if (iPlug >= 0) m_pSocket->plugs().removeAt(iPlug); } // Instance accessors. const QString& qjackctlPlugItem::socketName (void) const { return m_pSocket->socketName(); } const QString& qjackctlPlugItem::plugName (void) const { return m_sPlugName; } // Patchbay socket item accessor. qjackctlSocketItem *qjackctlPlugItem::socket (void) const { return m_pSocket; } //---------------------------------------------------------------------- // class qjackctlSocketItem -- Jack client list item. // // Constructor. qjackctlSocketItem::qjackctlSocketItem ( qjackctlSocketList *pSocketList, const QString& sSocketName, const QString& sClientName, int iSocketType, qjackctlSocketItem *pSocketAfter ) : QTreeWidgetItem(pSocketList->listView(), pSocketAfter, QJACKCTL_SOCKETITEM) { QTreeWidgetItem::setText(0, sSocketName); m_pSocketList = pSocketList; m_sSocketName = sSocketName; m_sClientName = sClientName; m_iSocketType = iSocketType; m_bExclusive = false; m_sSocketForward.clear(); m_pSocketList->sockets().append(this); updatePixmap(); } // Default destructor. qjackctlSocketItem::~qjackctlSocketItem (void) { QListIterator iter(m_connects); while (iter.hasNext()) (iter.next())->removeConnect(this); m_connects.clear(); m_plugs.clear(); const int iSocket = m_pSocketList->sockets().indexOf(this); if (iSocket >= 0) m_pSocketList->sockets().removeAt(iSocket); } // Instance accessors. const QString& qjackctlSocketItem::socketName (void) const { return m_sSocketName; } const QString& qjackctlSocketItem::clientName (void) const { return m_sClientName; } int qjackctlSocketItem::socketType (void) const { return m_iSocketType; } bool qjackctlSocketItem::isExclusive (void) const { return m_bExclusive; } const QString& qjackctlSocketItem::forward (void) const { return m_sSocketForward; } void qjackctlSocketItem::setSocketName ( const QString& sSocketName ) { m_sSocketName = sSocketName; } void qjackctlSocketItem::setClientName ( const QString& sClientName ) { m_sClientName = sClientName; } void qjackctlSocketItem::setSocketType ( int iSocketType ) { m_iSocketType = iSocketType; } void qjackctlSocketItem::setExclusive ( bool bExclusive ) { m_bExclusive = bExclusive; } void qjackctlSocketItem::setForward ( const QString& sSocketForward ) { m_sSocketForward = sSocketForward; } // Socket flags accessor. bool qjackctlSocketItem::isReadable (void) const { return m_pSocketList->isReadable(); } // Plug finder. qjackctlPlugItem *qjackctlSocketItem::findPlug ( const QString& sPlugName ) { QListIterator iter(m_plugs); while (iter.hasNext()) { qjackctlPlugItem *pPlug = iter.next(); if (sPlugName == pPlug->plugName()) return pPlug; } return nullptr; } // Plug list accessor. QList& qjackctlSocketItem::plugs (void) { return m_plugs; } // Connected socket list primitives. void qjackctlSocketItem::addConnect( qjackctlSocketItem *pSocket ) { m_connects.append(pSocket); } void qjackctlSocketItem::removeConnect( qjackctlSocketItem *pSocket ) { int iSocket = m_connects.indexOf(pSocket); if (iSocket >= 0) m_connects.removeAt(iSocket); } // Connected socket finder. qjackctlSocketItem *qjackctlSocketItem::findConnectPtr ( qjackctlSocketItem *pSocketPtr ) { QListIterator iter(m_connects); while (iter.hasNext()) { qjackctlSocketItem *pSocket = iter.next(); if (pSocketPtr == pSocket) return pSocket; } return nullptr; } // Connection cache list accessor. const QList& qjackctlSocketItem::connects (void) const { return m_connects; } // Plug list cleaner. void qjackctlSocketItem::clear (void) { qDeleteAll(m_plugs); m_plugs.clear(); } // Socket item pixmap peeker. const QPixmap& qjackctlSocketItem::pixmap ( int iPixmap ) const { return m_pSocketList->pixmap(iPixmap); } // Update pixmap to its proper context. void qjackctlSocketItem::updatePixmap (void) { int iPixmap; if (m_iSocketType == QJACKCTL_SOCKETTYPE_JACK_AUDIO) { iPixmap = (m_bExclusive ? QJACKCTL_XPM_AUDIO_SOCKET_X : QJACKCTL_XPM_AUDIO_SOCKET); } else { iPixmap = (m_bExclusive ? QJACKCTL_XPM_MIDI_SOCKET_X : QJACKCTL_XPM_MIDI_SOCKET); } QTreeWidgetItem::setIcon(0, QIcon(pixmap(iPixmap))); } // Socket item openness status. void qjackctlSocketItem::setOpen ( bool bOpen ) { QTreeWidgetItem::setExpanded(bOpen); } bool qjackctlSocketItem::isOpen (void) const { return QTreeWidgetItem::isExpanded(); } //---------------------------------------------------------------------- // qjackctlSocketList -- Jack client list. // // Constructor. qjackctlSocketList::qjackctlSocketList ( qjackctlSocketListView *pListView, bool bReadable ) { QPixmap pmXSocket1(":/images/xsocket1.png"); m_pListView = pListView; m_bReadable = bReadable; if (bReadable) { m_sSocketCaption = tr("Output"); m_apPixmaps[QJACKCTL_XPM_AUDIO_SOCKET] = new QPixmap(":/images/asocketo.png"); m_apPixmaps[QJACKCTL_XPM_AUDIO_SOCKET_X] = createPixmapMerge(*m_apPixmaps[QJACKCTL_XPM_AUDIO_SOCKET], pmXSocket1); m_apPixmaps[QJACKCTL_XPM_AUDIO_CLIENT] = new QPixmap(":/images/acliento.png"); m_apPixmaps[QJACKCTL_XPM_AUDIO_PLUG] = new QPixmap(":/images/aportlno.png"); m_apPixmaps[QJACKCTL_XPM_MIDI_SOCKET] = new QPixmap(":/images/msocketo.png"); m_apPixmaps[QJACKCTL_XPM_MIDI_SOCKET_X] = createPixmapMerge(*m_apPixmaps[QJACKCTL_XPM_MIDI_SOCKET], pmXSocket1); m_apPixmaps[QJACKCTL_XPM_MIDI_CLIENT] = new QPixmap(":/images/mcliento.png"); m_apPixmaps[QJACKCTL_XPM_MIDI_PLUG] = new QPixmap(":/images/mporto.png"); } else { m_sSocketCaption = tr("Input"); m_apPixmaps[QJACKCTL_XPM_AUDIO_SOCKET] = new QPixmap(":/images/asocketi.png"); m_apPixmaps[QJACKCTL_XPM_AUDIO_SOCKET_X] = createPixmapMerge(*m_apPixmaps[QJACKCTL_XPM_AUDIO_SOCKET], pmXSocket1); m_apPixmaps[QJACKCTL_XPM_AUDIO_CLIENT] = new QPixmap(":/images/aclienti.png"); m_apPixmaps[QJACKCTL_XPM_AUDIO_PLUG] = new QPixmap(":/images/aportlni.png"); m_apPixmaps[QJACKCTL_XPM_MIDI_SOCKET] = new QPixmap(":/images/msocketi.png"); m_apPixmaps[QJACKCTL_XPM_MIDI_SOCKET_X] = createPixmapMerge(*m_apPixmaps[QJACKCTL_XPM_MIDI_SOCKET], pmXSocket1); m_apPixmaps[QJACKCTL_XPM_MIDI_CLIENT] = new QPixmap(":/images/mclienti.png"); m_apPixmaps[QJACKCTL_XPM_MIDI_PLUG] = new QPixmap(":/images/mporti.png"); } if (!m_sSocketCaption.isEmpty()) m_sSocketCaption += ' '; m_sSocketCaption += tr("Socket"); } // Default destructor. qjackctlSocketList::~qjackctlSocketList (void) { clear(); for (int iPixmap = 0; iPixmap < QJACKCTL_XPM_PIXMAPS; iPixmap++) delete m_apPixmaps[iPixmap]; } // Client finder. qjackctlSocketItem *qjackctlSocketList::findSocket ( const QString& sSocketName, int iSocketType ) { QListIterator iter(m_sockets); while (iter.hasNext()) { qjackctlSocketItem *pSocket = iter.next(); if (sSocketName == pSocket->socketName() && iSocketType == pSocket->socketType()) return pSocket; } return nullptr; } // Socket list accessor. QList& qjackctlSocketList::sockets (void) { return m_sockets; } // List view accessor. qjackctlSocketListView *qjackctlSocketList::listView (void) const { return m_pListView; } // Socket flags accessor. bool qjackctlSocketList::isReadable (void) const { return m_bReadable; } // Socket caption titler. const QString& qjackctlSocketList::socketCaption (void) const { return m_sSocketCaption; } // Socket list cleaner. void qjackctlSocketList::clear (void) { qDeleteAll(m_sockets); m_sockets.clear(); } // Socket list pixmap peeker. const QPixmap& qjackctlSocketList::pixmap ( int iPixmap ) const { return *m_apPixmaps[iPixmap]; } // Merge two pixmaps with union of respective masks. QPixmap *qjackctlSocketList::createPixmapMerge ( const QPixmap& xpmDst, const QPixmap& xpmSrc ) { QPixmap *pXpmMerge = new QPixmap(xpmDst); if (pXpmMerge) { QBitmap bmMask = xpmDst.mask(); QPainter(&bmMask).drawPixmap(0, 0, xpmSrc.mask()); pXpmMerge->setMask(bmMask); QPainter(pXpmMerge).drawPixmap(0, 0, xpmSrc); } return pXpmMerge; } // Return currently selected socket item. qjackctlSocketItem *qjackctlSocketList::selectedSocketItem (void) const { qjackctlSocketItem *pSocketItem = nullptr; QTreeWidgetItem *pItem = m_pListView->currentItem(); if (pItem) { if (pItem->type() == QJACKCTL_PLUGITEM) { pSocketItem = static_cast (pItem->parent()); } else { pSocketItem = static_cast (pItem); } } return pSocketItem; } // Add a new socket item, using interactive form. bool qjackctlSocketList::addSocketItem (void) { bool bResult = false; qjackctlSocketForm socketForm(m_pListView); socketForm.setWindowTitle(tr(" - %1").arg(m_sSocketCaption)); socketForm.setSocketCaption(m_sSocketCaption); socketForm.setPixmaps(m_apPixmaps); socketForm.setSocketList(this); socketForm.setSocketNew(true); qjackctlPatchbaySocket socket(m_sSocketCaption + ' ' + QString::number(m_sockets.count() + 1), QString(), QJACKCTL_SOCKETTYPE_JACK_AUDIO); socketForm.load(&socket); if (socketForm.exec()) { socketForm.save(&socket); qjackctlSocketItem *pSocketItem = selectedSocketItem(); // m_pListView->setUpdatesEnabled(false); if (pSocketItem) pSocketItem->setSelected(false); pSocketItem = new qjackctlSocketItem(this, socket.name(), socket.clientName(), socket.type(), pSocketItem); if (pSocketItem) { pSocketItem->setExclusive(socket.isExclusive()); pSocketItem->setForward(socket.forward()); qjackctlPlugItem *pPlugItem = nullptr; QStringListIterator iter(socket.pluglist()); while (iter.hasNext()) { pPlugItem = new qjackctlPlugItem( pSocketItem, iter.next(), pPlugItem); } bResult = true; } pSocketItem->setSelected(true); m_pListView->setCurrentItem(pSocketItem); // m_pListView->setUpdatesEnabled(true); // m_pListView->update(); m_pListView->setDirty(true); } return bResult; } // Remove (delete) currently selected socket item. bool qjackctlSocketList::removeSocketItem (void) { bool bResult = false; qjackctlSocketItem *pSocketItem = selectedSocketItem(); if (pSocketItem) { if (QMessageBox::warning(m_pListView, tr("Warning") + " - " QJACKCTL_TITLE, tr("%1 about to be removed:\n\n" "\"%2\"\n\nAre you sure?") .arg(m_sSocketCaption) .arg(pSocketItem->socketName()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { delete pSocketItem; bResult = true; m_pListView->setDirty(true); } } return bResult; } // View or change the properties of currently selected socket item. bool qjackctlSocketList::editSocketItem (void) { bool bResult = false; qjackctlSocketItem *pSocketItem = selectedSocketItem(); if (pSocketItem) { qjackctlSocketForm socketForm(m_pListView); socketForm.setWindowTitle(pSocketItem->socketName() + " - " + m_sSocketCaption); socketForm.setSocketCaption(m_sSocketCaption); socketForm.setPixmaps(m_apPixmaps); socketForm.setSocketList(this); socketForm.setSocketNew(false); qjackctlPatchbaySocket socket(pSocketItem->socketName(), pSocketItem->clientName(), pSocketItem->socketType()); socket.setExclusive(pSocketItem->isExclusive()); socket.setForward(pSocketItem->forward()); QListIterator iter(pSocketItem->plugs()); while (iter.hasNext()) socket.pluglist().append((iter.next())->plugName()); socketForm.load(&socket); socketForm.setConnectCount(pSocketItem->connects().count()); if (socketForm.exec()) { socketForm.save(&socket); // m_pListView->setUpdatesEnabled(false); pSocketItem->clear(); pSocketItem->setText(0, socket.name()); pSocketItem->setSocketName(socket.name()); pSocketItem->setClientName(socket.clientName()); pSocketItem->setSocketType(socket.type()); pSocketItem->setExclusive(socket.isExclusive()); pSocketItem->setForward(socket.forward()); pSocketItem->updatePixmap(); qjackctlPlugItem *pPlugItem = nullptr; QStringListIterator iter(socket.pluglist()); while (iter.hasNext()) { pPlugItem = new qjackctlPlugItem( pSocketItem, iter.next(), pPlugItem); } pSocketItem->setSelected(true); m_pListView->setCurrentItem(pSocketItem); // m_pListView->setUpdatesEnabled(true); // m_pListView->triggerUpdate(); m_pListView->setDirty(true); bResult = true; } } return bResult; } // Duplicate and change the properties of currently selected socket item. bool qjackctlSocketList::copySocketItem (void) { bool bResult = false; qjackctlSocketItem *pSocketItem = selectedSocketItem(); if (pSocketItem) { qjackctlSocketForm socketForm(m_pListView); // Find a new distinguishable socket name, please. int iSocketNo = 1; QString sSocketName = pSocketItem->socketName();; QString sSocketMask = sSocketName; sSocketMask.remove(QRegularExpression("[ |0-9]+$")).append(" %1"); const int iSocketType = pSocketItem->socketType(); do { sSocketName = sSocketMask.arg(++iSocketNo); } while (findSocket(sSocketName, iSocketType)); // Show up as a new socket... socketForm.setWindowTitle(tr("%1 - %2") .arg(pSocketItem->socketName()).arg(m_sSocketCaption)); socketForm.setSocketCaption(m_sSocketCaption); socketForm.setPixmaps(m_apPixmaps); socketForm.setSocketList(this); socketForm.setSocketNew(true); qjackctlPatchbaySocket socket(sSocketName, pSocketItem->clientName(), iSocketType); if (pSocketItem->isExclusive()) socket.setExclusive(true); QListIterator iter(pSocketItem->plugs()); while (iter.hasNext()) socket.pluglist().append((iter.next())->plugName()); socketForm.load(&socket); if (socketForm.exec()) { socketForm.save(&socket); pSocketItem = new qjackctlSocketItem(this, socket.name(), socket.clientName(), socket.type(), pSocketItem); if (pSocketItem) { pSocketItem->setExclusive(socket.isExclusive()); pSocketItem->setForward(socket.forward()); qjackctlPlugItem *pPlugItem = nullptr; QStringListIterator iter(socket.pluglist()); while (iter.hasNext()) { pPlugItem = new qjackctlPlugItem( pSocketItem, iter.next(), pPlugItem); } bResult = true; } pSocketItem->setSelected(true); m_pListView->setCurrentItem(pSocketItem); // m_pListView->setUpdatesEnabled(true); // m_pListView->triggerUpdate(); m_pListView->setDirty(true); } } return bResult; } // Toggle exclusive currently selected socket item. bool qjackctlSocketList::exclusiveSocketItem (void) { bool bResult = false; qjackctlSocketItem *pSocketItem = selectedSocketItem(); if (pSocketItem) { pSocketItem->setExclusive(!pSocketItem->isExclusive()); pSocketItem->updatePixmap(); bResult = true; m_pListView->setDirty(true); } return bResult; } // Move current selected socket item up one position. bool qjackctlSocketList::moveUpSocketItem (void) { bool bResult = false; qjackctlSocketItem *pSocketItem = selectedSocketItem(); if (pSocketItem) { const int iItem = m_pListView->indexOfTopLevelItem(pSocketItem); if (iItem > 0) { QTreeWidgetItem *pItem = m_pListView->takeTopLevelItem(iItem); if (pItem) { m_pListView->insertTopLevelItem(iItem - 1, pItem); pSocketItem->setSelected(true); m_pListView->setCurrentItem(pSocketItem); // m_pListView->setUpdatesEnabled(true); // m_pListView->update(); m_pListView->setDirty(true); bResult = true; } } } return bResult; } // Move current selected socket item down one position. bool qjackctlSocketList::moveDownSocketItem (void) { bool bResult = false; qjackctlSocketItem *pSocketItem = selectedSocketItem(); if (pSocketItem) { const int iItem = m_pListView->indexOfTopLevelItem(pSocketItem); const int iItemCount = m_pListView->topLevelItemCount(); if (iItem < iItemCount - 1) { QTreeWidgetItem *pItem = m_pListView->takeTopLevelItem(iItem); if (pItem) { m_pListView->insertTopLevelItem(iItem + 1, pItem); pSocketItem->setSelected(true); m_pListView->setCurrentItem(pSocketItem); // m_pListView->setUpdatesEnabled(true); // m_pListView->update(); m_pListView->setDirty(true); bResult = true; } } } return bResult; } //---------------------------------------------------------------------------- // qjackctlSocketListView -- Socket list view, supporting drag-n-drop. // Constructor. qjackctlSocketListView::qjackctlSocketListView ( qjackctlPatchbayView *pPatchbayView, bool bReadable ) : QTreeWidget(pPatchbayView) { m_pPatchbayView = pPatchbayView; m_bReadable = bReadable; m_pAutoOpenTimer = 0; m_iAutoOpenTimeout = 0; m_pDragItem = nullptr; m_pDropItem = nullptr; QHeaderView *pHeader = QTreeWidget::header(); // pHeader->setDefaultAlignment(Qt::AlignLeft); // pHeader->setDefaultSectionSize(120); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionsMovable(false); pHeader->setSectionsClickable(true); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setMovable(false); pHeader->setClickable(true); #endif // pHeader->setSortIndicatorShown(true); pHeader->setStretchLastSection(true); QTreeWidget::setRootIsDecorated(true); QTreeWidget::setUniformRowHeights(true); // QTreeWidget::setDragEnabled(true); QTreeWidget::setAcceptDrops(true); QTreeWidget::setDropIndicatorShown(true); QTreeWidget::setAutoScroll(true); QTreeWidget::setSelectionMode(QAbstractItemView::SingleSelection); QTreeWidget::setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); QTreeWidget::setSortingEnabled(false); QTreeWidget::setMinimumWidth(120); QTreeWidget::setColumnCount(1); // Trap for help/tool-tips events. QTreeWidget::viewport()->installEventFilter(this); QString sText; if (m_bReadable) sText = tr("Output Sockets / Plugs"); else sText = tr("Input Sockets / Plugs"); QTreeWidget::headerItem()->setText(0, sText); QTreeWidget::setToolTip(sText); setAutoOpenTimeout(800); } // Default destructor. qjackctlSocketListView::~qjackctlSocketListView (void) { setAutoOpenTimeout(0); } // Patchbay view dirty flag accessors. void qjackctlSocketListView::setDirty ( bool bDirty ) { m_pPatchbayView->setDirty(bDirty); } bool qjackctlSocketListView::dirty (void) const { return m_pPatchbayView->dirty(); } // Auto-open timeout method. void qjackctlSocketListView::setAutoOpenTimeout ( int iAutoOpenTimeout ) { m_iAutoOpenTimeout = iAutoOpenTimeout; if (m_pAutoOpenTimer) delete m_pAutoOpenTimer; m_pAutoOpenTimer = nullptr; if (m_iAutoOpenTimeout > 0) { m_pAutoOpenTimer = new QTimer(this); QObject::connect(m_pAutoOpenTimer, SIGNAL(timeout()), SLOT(timeoutSlot())); } } // Auto-open timeout accessor. int qjackctlSocketListView::autoOpenTimeout (void) const { return m_iAutoOpenTimeout; } // Auto-open timer slot. void qjackctlSocketListView::timeoutSlot (void) { if (m_pAutoOpenTimer) { m_pAutoOpenTimer->stop(); if (m_pDropItem && m_pDropItem->type() == QJACKCTL_SOCKETITEM) { qjackctlSocketItem *pSocketItem = static_cast (m_pDropItem); if (pSocketItem && !pSocketItem->isOpen()) pSocketItem->setOpen(true); } } } // Trap for help/tool-tip events. bool qjackctlSocketListView::eventFilter ( QObject *pObject, QEvent *pEvent ) { QWidget *pViewport = QTreeWidget::viewport(); if (static_cast (pObject) == pViewport && pEvent->type() == QEvent::ToolTip) { QHelpEvent *pHelpEvent = static_cast (pEvent); if (pHelpEvent) { QTreeWidgetItem *pItem = QTreeWidget::itemAt(pHelpEvent->pos()); if (pItem && pItem->type() == QJACKCTL_SOCKETITEM) { qjackctlSocketItem *pSocketItem = static_cast (pItem); if (pSocketItem) { QToolTip::showText(pHelpEvent->globalPos(), pSocketItem->clientName(), pViewport); return true; } } else if (pItem && pItem->type() == QJACKCTL_PLUGITEM) { qjackctlPlugItem *pPlugItem = static_cast (pItem); if (pPlugItem) { QToolTip::showText(pHelpEvent->globalPos(), pPlugItem->plugName(), pViewport); return true; } } } } // Not handled here. return QTreeWidget::eventFilter(pObject, pEvent); } // Drag-n-drop stuff. QTreeWidgetItem *qjackctlSocketListView::dragDropItem ( const QPoint& pos ) { QTreeWidgetItem *pItem = QTreeWidget::itemAt(pos); if (pItem) { if (m_pDropItem != pItem) { QTreeWidget::setCurrentItem(pItem); m_pDropItem = pItem; if (m_pAutoOpenTimer) m_pAutoOpenTimer->start(m_iAutoOpenTimeout); qjackctlPatchbay *pPatchbay = m_pPatchbayView->binding(); if ((pItem->flags() & Qt::ItemIsDropEnabled) == 0 || pPatchbay == nullptr || !pPatchbay->canConnectSelected()) pItem = nullptr; } } else { m_pDropItem = nullptr; if (m_pAutoOpenTimer) m_pAutoOpenTimer->stop(); } return pItem; } void qjackctlSocketListView::dragEnterEvent ( QDragEnterEvent *pDragEnterEvent ) { if (pDragEnterEvent->source() != this && pDragEnterEvent->mimeData()->hasText() && #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) dragDropItem(pDragEnterEvent->position().toPoint())) { #else dragDropItem(pDragEnterEvent->pos())) { #endif pDragEnterEvent->accept(); } else { pDragEnterEvent->ignore(); } } void qjackctlSocketListView::dragMoveEvent ( QDragMoveEvent *pDragMoveEvent ) { if (pDragMoveEvent->source() != this && pDragMoveEvent->mimeData()->hasText() && #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) dragDropItem(pDragMoveEvent->position().toPoint())) { #else dragDropItem(pDragMoveEvent->pos())) { #endif pDragMoveEvent->accept(); } else { pDragMoveEvent->ignore(); } } void qjackctlSocketListView::dragLeaveEvent ( QDragLeaveEvent * ) { m_pDropItem = 0; if (m_pAutoOpenTimer) m_pAutoOpenTimer->stop(); } void qjackctlSocketListView::dropEvent ( QDropEvent *pDropEvent ) { if (pDropEvent->source() != this && pDropEvent->mimeData()->hasText() && #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) dragDropItem(pDropEvent->position().toPoint())) { #else dragDropItem(pDropEvent->pos())) { #endif const QString sText = pDropEvent->mimeData()->text(); qjackctlPatchbay *pPatchbay = m_pPatchbayView->binding(); if (!sText.isEmpty() && pPatchbay) pPatchbay->connectSelected(); } dragLeaveEvent(nullptr); } // Handle mouse events for drag-and-drop stuff. void qjackctlSocketListView::mousePressEvent ( QMouseEvent *pMouseEvent ) { QTreeWidget::mousePressEvent(pMouseEvent); if (pMouseEvent->button() == Qt::LeftButton) { m_posDrag = pMouseEvent->pos(); m_pDragItem = QTreeWidget::itemAt(m_posDrag); } } void qjackctlSocketListView::mouseMoveEvent ( QMouseEvent *pMouseEvent ) { QTreeWidget::mouseMoveEvent(pMouseEvent); if ((pMouseEvent->buttons() & Qt::LeftButton) && m_pDragItem && ((pMouseEvent->pos() - m_posDrag).manhattanLength() >= QApplication::startDragDistance())) { // We'll start dragging something alright... QMimeData *pMimeData = new QMimeData(); pMimeData->setText(m_pDragItem->text(0)); QDrag *pDrag = new QDrag(this); pDrag->setMimeData(pMimeData); pDrag->setPixmap(m_pDragItem->icon(0).pixmap(16)); pDrag->setHotSpot(QPoint(-4, -12)); pDrag->exec(Qt::LinkAction); // We've dragged and maybe dropped it by now... m_pDragItem = nullptr; } } // Context menu request event handler. void qjackctlSocketListView::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { m_pPatchbayView->contextMenu( pContextMenuEvent->globalPos(), (m_bReadable ? m_pPatchbayView->OSocketList() : m_pPatchbayView->ISocketList()) ); } //---------------------------------------------------------------------- // qjackctlPatchworkView -- Socket connector widget. // // Constructor. qjackctlPatchworkView::qjackctlPatchworkView ( qjackctlPatchbayView *pPatchbayView ) : QWidget(pPatchbayView) { m_pPatchbayView = pPatchbayView; QWidget::setMinimumWidth(20); // QWidget::setMaximumWidth(120); QWidget::setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); } // Default destructor. qjackctlPatchworkView::~qjackctlPatchworkView (void) { } // Legal socket item position helper. int qjackctlPatchworkView::itemY ( QTreeWidgetItem *pItem ) const { QRect rect; QTreeWidget *pList = pItem->treeWidget(); QTreeWidgetItem *pParent = pItem->parent(); qjackctlSocketItem *pSocketItem = nullptr; if (pParent && pParent->type() == QJACKCTL_SOCKETITEM) pSocketItem = static_cast (pParent); if (pSocketItem && !pSocketItem->isOpen()) { rect = pList->visualItemRect(pParent); } else { rect = pList->visualItemRect(pItem); } return rect.top() + rect.height() / 2; } // Draw visible socket connection relation lines void qjackctlPatchworkView::drawConnectionLine ( QPainter *pPainter, int x1, int y1, int x2, int y2, int h1, int h2 ) { // Account for list view headers. y1 += h1; y2 += h2; // Invisible output plugs don't get a connecting dot. if (y1 > h1) pPainter->drawLine(x1, y1, x1 + 4, y1); // Setup control points QPolygon spline(4); const int cp = int(float(x2 - x1 - 8) * 0.4f); spline.putPoints(0, 4, x1 + 4, y1, x1 + 4 + cp, y1, x2 - 4 - cp, y2, x2 - 4, y2); // The connection line, it self. QPainterPath path; path.moveTo(spline.at(0)); path.cubicTo(spline.at(1), spline.at(2), spline.at(3)); pPainter->strokePath(path, pPainter->pen()); // Invisible input plugs don't get a connecting dot. if (y2 > h2) pPainter->drawLine(x2 - 4, y2, x2, y2); } // Draw socket forwrading line (for input sockets / right pane only) void qjackctlPatchworkView::drawForwardLine ( QPainter *pPainter, int x, int dx, int y1, int y2, int h ) { // Account for list view headers. y1 += h; y2 += h; dx += 4; // Draw it... if (y1 < y2) { pPainter->drawLine(x - dx, y1 + 4, x, y1); pPainter->drawLine(x - dx, y1 + 4, x - dx, y2 - 4); pPainter->drawLine(x - dx, y2 - 4, x, y2); // Down arrow... pPainter->drawLine(x - dx, y2 - 8, x - dx - 2, y2 - 12); pPainter->drawLine(x - dx, y2 - 8, x - dx + 2, y2 - 12); } else { pPainter->drawLine(x - dx, y1 - 4, x, y1); pPainter->drawLine(x - dx, y1 - 4, x - dx, y2 + 4); pPainter->drawLine(x - dx, y2 + 4, x, y2); // Up arrow... pPainter->drawLine(x - dx, y2 + 8, x - dx - 2, y2 + 12); pPainter->drawLine(x - dx, y2 + 8, x - dx + 2, y2 + 12); } } // Draw visible socket connection relation arrows. void qjackctlPatchworkView::paintEvent ( QPaintEvent * ) { if (m_pPatchbayView->OSocketList() == nullptr || m_pPatchbayView->ISocketList() == nullptr) return; QPainter painter(this); int x1, y1, h1; int x2, y2, h2; int i, rgb[3] = { 0x99, 0x66, 0x33 }; // Draw all lines anti-aliased... painter.setRenderHint(QPainter::Antialiasing); // Inline adaptive to darker background themes... if (QWidget::palette().window().color().value() < 0x7f) for (i = 0; i < 3; ++i) rgb[i] += 0x33; // Initialize color changer. i = 0; // Almost constants. x1 = 0; x2 = width(); h1 = ((m_pPatchbayView->OListView())->header())->sizeHint().height(); h2 = ((m_pPatchbayView->IListView())->header())->sizeHint().height(); // For each client item... qjackctlSocketItem *pOSocket, *pISocket; QListIterator osocket( (m_pPatchbayView->OSocketList())->sockets()); while (osocket.hasNext()) { pOSocket = osocket.next(); // Set new connector color. ++i; painter.setPen(QColor(rgb[i % 3], rgb[(i / 3) % 3], rgb[(i / 9) % 3])); // Get starting connector arrow coordinates. y1 = itemY(pOSocket); // Get input socket connections... QListIterator isocket(pOSocket->connects()); while (isocket.hasNext()) { pISocket = isocket.next(); // Obviously, there is a connection from pOPlug to pIPlug items: y2 = itemY(pISocket); drawConnectionLine(&painter, x1, y1, x2, y2, h1, h2); } } // Look for forwarded inputs... QList iforwards; // Make a local copy of just the forwarding socket list, if any... QListIterator isocket( (m_pPatchbayView->ISocketList())->sockets()); while (isocket.hasNext()) { pISocket = isocket.next(); // Check if its forwarded... if (pISocket->forward().isEmpty()) continue; iforwards.append(pISocket); } // (Re)initialize color changer. i = 0; // Now traverse those for proper connection drawing... int dx = 0; QListIterator iter(iforwards); while (iter.hasNext()) { pISocket = iter.next(); qjackctlSocketItem *pISocketForward = m_pPatchbayView->ISocketList()->findSocket( pISocket->forward(), pISocket->socketType()); if (pISocketForward == nullptr) continue; // Set new connector color. ++i; painter.setPen(QColor(rgb[i % 3], rgb[(i / 3) % 3], rgb[(i / 9) % 3])); // Get starting connector arrow coordinates. y1 = itemY(pISocketForward); y2 = itemY(pISocket); drawForwardLine(&painter, x2, dx, y1, y2, h2); dx += 2; } } // Context menu request event handler. void qjackctlPatchworkView::contextMenuEvent ( QContextMenuEvent *pContextMenuEvent ) { m_pPatchbayView->contextMenu(pContextMenuEvent->globalPos(), nullptr); } // Widget event slots... void qjackctlPatchworkView::contentsChanged (void) { QWidget::update(); } //---------------------------------------------------------------------------- // qjackctlPatchbayView -- Integrated patchbay widget. // Constructor. qjackctlPatchbayView::qjackctlPatchbayView ( QWidget *pParent ) : QSplitter(Qt::Horizontal, pParent) { m_pOListView = new qjackctlSocketListView(this, true); m_pPatchworkView = new qjackctlPatchworkView(this); m_pIListView = new qjackctlSocketListView(this, false); m_pPatchbay = nullptr; QSplitter::setHandleWidth(2); QObject::connect(m_pOListView, SIGNAL(itemExpanded(QTreeWidgetItem *)), m_pPatchworkView, SLOT(contentsChanged())); QObject::connect(m_pOListView, SIGNAL(itemCollapsed(QTreeWidgetItem *)), m_pPatchworkView, SLOT(contentsChanged())); QObject::connect(m_pOListView->verticalScrollBar(), SIGNAL(valueChanged(int)), m_pPatchworkView, SLOT(contentsChanged())); // QObject::connect(m_pOListView->header(), SIGNAL(sectionClicked(int)), // m_pPatchworkView, SLOT(contentsChanged())); QObject::connect(m_pIListView, SIGNAL(itemExpanded(QTreeWidgetItem *)), m_pPatchworkView, SLOT(contentsChanged())); QObject::connect(m_pIListView, SIGNAL(itemCollapsed(QTreeWidgetItem *)), m_pPatchworkView, SLOT(contentsChanged())); QObject::connect(m_pIListView->verticalScrollBar(), SIGNAL(valueChanged(int)), m_pPatchworkView, SLOT(contentsChanged())); // QObject::connect(m_pIListView->header(), SIGNAL(sectionClicked(int)), // m_pPatchworkView, SLOT(contentsChanged())); m_bDirty = false; } // Default destructor. qjackctlPatchbayView::~qjackctlPatchbayView (void) { } // Common context menu slot. void qjackctlPatchbayView::contextMenu ( const QPoint& pos, qjackctlSocketList *pSocketList ) { qjackctlPatchbay *pPatchbay = binding(); if (pPatchbay == nullptr) return; QMenu menu(this); QAction *pAction; if (pSocketList) { qjackctlSocketItem *pSocketItem = pSocketList->selectedSocketItem(); bool bEnabled = (pSocketItem != nullptr); pAction = menu.addAction(QIcon(":/images/add1.png"), tr("Add..."), pSocketList, SLOT(addSocketItem())); pAction = menu.addAction(QIcon(":/images/edit1.png"), tr("Edit..."), pSocketList, SLOT(editSocketItem())); pAction->setEnabled(bEnabled); pAction = menu.addAction(QIcon(":/images/copy1.png"), tr("Copy..."), pSocketList, SLOT(copySocketItem())); pAction->setEnabled(bEnabled); pAction = menu.addAction(QIcon(":/images/remove1.png"), tr("Remove"), pSocketList, SLOT(removeSocketItem())); pAction->setEnabled(bEnabled); menu.addSeparator(); pAction = menu.addAction( tr("Exclusive"), pSocketList, SLOT(exclusiveSocketItem())); pAction->setCheckable(true); pAction->setChecked(bEnabled && pSocketItem->isExclusive()); pAction->setEnabled(bEnabled && (pSocketItem->connects().count() < 2)); // Construct the forwarding menu, // overriding the last one, if any... QMenu *pForwardMenu = menu.addMenu(tr("Forward")); // Assume sockets iteration follows item index order (0,1,2...) // and remember that we only do this for input sockets... int iIndex = 0; if (pSocketItem && pSocketList == ISocketList()) { QListIterator isocket(ISocketList()->sockets()); while (isocket.hasNext()) { qjackctlSocketItem *pISocket = isocket.next(); // Must be of same type of target one... int iSocketType = pISocket->socketType(); if (iSocketType != pSocketItem->socketType()) continue; const QString& sSocketName = pISocket->socketName(); if (pSocketItem->socketName() == sSocketName) continue; int iPixmap = 0; switch (iSocketType) { case QJACKCTL_SOCKETTYPE_JACK_AUDIO: iPixmap = (pISocket->isExclusive() ? QJACKCTL_XPM_AUDIO_SOCKET_X : QJACKCTL_XPM_AUDIO_SOCKET); break; case QJACKCTL_SOCKETTYPE_JACK_MIDI: case QJACKCTL_SOCKETTYPE_ALSA_MIDI: iPixmap = (pISocket->isExclusive() ? QJACKCTL_XPM_MIDI_SOCKET_X : QJACKCTL_XPM_MIDI_SOCKET); break; } pAction = pForwardMenu->addAction( QIcon(ISocketList()->pixmap(iPixmap)), sSocketName); pAction->setChecked(pSocketItem->forward() == sSocketName); pAction->setData(iIndex); ++iIndex; } // nullptr forward always present, // and has invalid index parameter (-1)... if (iIndex > 0) pForwardMenu->addSeparator(); pAction = pForwardMenu->addAction(tr("(None)")); pAction->setCheckable(true); pAction->setChecked(pSocketItem->forward().isEmpty()); pAction->setData(-1); // We have something here... QObject::connect(pForwardMenu, SIGNAL(triggered(QAction*)), SLOT(activateForwardMenu(QAction*))); } pForwardMenu->setEnabled(iIndex > 0); menu.addSeparator(); const int iItem = (pSocketList->listView())->indexOfTopLevelItem(pSocketItem); const int iItemCount = (pSocketList->listView())->topLevelItemCount(); pAction = menu.addAction(QIcon(":/images/up1.png"), tr("Move Up"), pSocketList, SLOT(moveUpSocketItem())); pAction->setEnabled(bEnabled && iItem > 0); pAction = menu.addAction(QIcon(":/images/down1.png"), tr("Move Down"), pSocketList, SLOT(moveDownSocketItem())); pAction->setEnabled(bEnabled && iItem < iItemCount - 1); menu.addSeparator(); } #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) pAction = menu.addAction(QIcon(":/images/connect1.png"), tr("&Connect"), tr("Alt+C", "Connect"), pPatchbay, SLOT(connectSelected())); pAction->setEnabled(pPatchbay->canConnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnect1.png"), tr("&Disconnect"), tr("Alt+D", "Disconnect"), pPatchbay, SLOT(disconnectSelected())); pAction->setEnabled(pPatchbay->canDisconnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnectall1.png"), tr("Disconnect &All"), tr("Alt+A", "Disconnect All"), pPatchbay, SLOT(disconnectAll())); pAction->setEnabled(pPatchbay->canDisconnectAll()); menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/refresh1.png"), tr("&Refresh"), tr("Alt+R", "Refresh"), pPatchbay, SLOT(refresh())); #else pAction = menu.addAction(QIcon(":/images/connect1.png"), tr("&Connect"), pPatchbay, SLOT(connectSelected()), tr("Alt+C", "Connect")); pAction->setEnabled(pPatchbay->canConnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnect1.png"), tr("&Disconnect"), pPatchbay, SLOT(disconnectSelected()), tr("Alt+D", "Disconnect")); pAction->setEnabled(pPatchbay->canDisconnectSelected()); pAction = menu.addAction(QIcon(":/images/disconnectall1.png"), tr("Disconnect &All"), pPatchbay, SLOT(disconnectAll()), tr("Alt+A", "Disconnect All")); pAction->setEnabled(pPatchbay->canDisconnectAll()); menu.addSeparator(); pAction = menu.addAction(QIcon(":/images/refresh1.png"), tr("&Refresh"), pPatchbay, SLOT(refresh()), tr("Alt+R", "Refresh")); #endif menu.exec(pos); } // Select the forwarding socket name from context menu. void qjackctlPatchbayView::activateForwardMenu ( QAction *pAction ) { int iIndex = pAction->data().toInt(); // Get currently input socket (assume its nicely selected) qjackctlSocketItem *pSocketItem = ISocketList()->selectedSocketItem(); if (pSocketItem) { // Check first for forward from nil... if (iIndex < 0) { pSocketItem->setForward(QString()); setDirty(true); return; } // Hopefully, its a real socket about to be forwraded... QListIterator isocket(ISocketList()->sockets()); while (isocket.hasNext()) { qjackctlSocketItem *pISocket = isocket.next(); // Must be of same type of target one... if (pISocket->socketType() != pSocketItem->socketType()) continue; const QString& sSocketName = pISocket->socketName(); if (pSocketItem->socketName() == sSocketName) continue; if (iIndex == 0) { pSocketItem->setForward(sSocketName); setDirty(true); break; } --iIndex; } } } // Patchbay binding methods. void qjackctlPatchbayView::setBinding ( qjackctlPatchbay *pPatchbay ) { m_pPatchbay = pPatchbay; } qjackctlPatchbay *qjackctlPatchbayView::binding (void) const { return m_pPatchbay; } // Patchbay client list accessors. qjackctlSocketList *qjackctlPatchbayView::OSocketList (void) const { if (m_pPatchbay) return m_pPatchbay->OSocketList(); else return nullptr; } qjackctlSocketList *qjackctlPatchbayView::ISocketList (void) const { if (m_pPatchbay) return m_pPatchbay->ISocketList(); else return nullptr; } // Dirty flag methods. void qjackctlPatchbayView::setDirty ( bool bDirty ) { m_bDirty = bDirty; if (bDirty) emit contentsChanged(); } bool qjackctlPatchbayView::dirty (void) const { return m_bDirty; } //---------------------------------------------------------------------- // qjackctlPatchbay -- Output-to-Input client/plugs connection object. // // Constructor. qjackctlPatchbay::qjackctlPatchbay ( qjackctlPatchbayView *pPatchbayView ) { m_pPatchbayView = pPatchbayView; m_pOSocketList = new qjackctlSocketList(m_pPatchbayView->OListView(), true); m_pISocketList = new qjackctlSocketList(m_pPatchbayView->IListView(), false); m_pPatchbayView->setBinding(this); } // Default destructor. qjackctlPatchbay::~qjackctlPatchbay (void) { m_pPatchbayView->setBinding(nullptr); delete m_pOSocketList; m_pOSocketList = nullptr; delete m_pISocketList; m_pISocketList = nullptr; (m_pPatchbayView->PatchworkView())->update(); } // Connection primitive. void qjackctlPatchbay::connectSockets ( qjackctlSocketItem *pOSocket, qjackctlSocketItem *pISocket ) { if (pOSocket->findConnectPtr(pISocket) == nullptr) { pOSocket->addConnect(pISocket); pISocket->addConnect(pOSocket); } } // Disconnection primitive. void qjackctlPatchbay::disconnectSockets ( qjackctlSocketItem *pOSocket, qjackctlSocketItem *pISocket ) { if (pOSocket->findConnectPtr(pISocket) != nullptr) { pOSocket->removeConnect(pISocket); pISocket->removeConnect(pOSocket); } } // Test if selected plugs are connectable. bool qjackctlPatchbay::canConnectSelected (void) { QTreeWidgetItem *pOItem = (m_pOSocketList->listView())->currentItem(); if (pOItem == nullptr) return false; QTreeWidgetItem *pIItem = (m_pISocketList->listView())->currentItem(); if (pIItem == nullptr) return false; qjackctlSocketItem *pOSocket = nullptr; switch (pOItem->type()) { case QJACKCTL_SOCKETITEM: pOSocket = static_cast (pOItem); break; case QJACKCTL_PLUGITEM: pOSocket = (static_cast (pOItem))->socket(); break; default: return false; } qjackctlSocketItem *pISocket = nullptr; switch (pIItem->type()) { case QJACKCTL_SOCKETITEM: pISocket = static_cast (pIItem); break; case QJACKCTL_PLUGITEM: pISocket = (static_cast (pIItem))->socket(); break; default: return false; } // Sockets must be of the same type... if (pOSocket->socketType() != pISocket->socketType()) return false; // Exclusive sockets may not accept more than one cable. if (pOSocket->isExclusive() && pOSocket->connects().count() > 0) return false; if (pISocket->isExclusive() && pISocket->connects().count() > 0) return false; // One-to-one connection... return (pOSocket->findConnectPtr(pISocket) == nullptr); } // Connect current selected plugs. bool qjackctlPatchbay::connectSelected (void) { QTreeWidgetItem *pOItem = (m_pOSocketList->listView())->currentItem(); if (pOItem == nullptr) return false; QTreeWidgetItem *pIItem = (m_pISocketList->listView())->currentItem(); if (pIItem == nullptr) return false; qjackctlSocketItem *pOSocket = nullptr; switch (pOItem->type()) { case QJACKCTL_SOCKETITEM: pOSocket = static_cast (pOItem); break; case QJACKCTL_PLUGITEM: pOSocket = (static_cast (pOItem))->socket(); break; default: return false; } qjackctlSocketItem *pISocket = nullptr; switch (pIItem->type()) { case QJACKCTL_SOCKETITEM: pISocket = static_cast (pIItem); break; case QJACKCTL_PLUGITEM: pISocket = (static_cast (pIItem))->socket(); break; default: return false; } // Sockets must be of the same type... if (pOSocket->socketType() != pISocket->socketType()) return false; // Exclusive sockets may not accept more than one cable. if (pOSocket->isExclusive() && pOSocket->connects().count() > 0) return false; if (pISocket->isExclusive() && pISocket->connects().count() > 0) return false; // One-to-one connection... connectSockets(pOSocket, pISocket); // Making one list dirty will take care of the rest... m_pPatchbayView->setDirty(true); return true; } // Test if selected plugs are disconnectable. bool qjackctlPatchbay::canDisconnectSelected (void) { QTreeWidgetItem *pOItem = (m_pOSocketList->listView())->currentItem(); if (pOItem == nullptr) return false; QTreeWidgetItem *pIItem = (m_pISocketList->listView())->currentItem(); if (pIItem == nullptr) return false; qjackctlSocketItem *pOSocket = nullptr; switch (pOItem->type()) { case QJACKCTL_SOCKETITEM: pOSocket = static_cast (pOItem); break; case QJACKCTL_PLUGITEM: pOSocket = (static_cast (pOItem))->socket(); break; default: return false; } qjackctlSocketItem *pISocket = nullptr; switch (pIItem->type()) { case QJACKCTL_SOCKETITEM: pISocket = static_cast (pIItem); break; case QJACKCTL_PLUGITEM: pISocket = (static_cast (pIItem))->socket(); break; default: return false; } // Sockets must be of the same type... if (pOSocket->socketType() != pISocket->socketType()) return false; return (pOSocket->findConnectPtr(pISocket) != 0); } // Disconnect current selected plugs. bool qjackctlPatchbay::disconnectSelected (void) { QTreeWidgetItem *pOItem = (m_pOSocketList->listView())->currentItem(); if (!pOItem) return false; QTreeWidgetItem *pIItem = (m_pISocketList->listView())->currentItem(); if (!pIItem) return false; qjackctlSocketItem *pOSocket = nullptr; switch (pOItem->type()) { case QJACKCTL_SOCKETITEM: pOSocket = static_cast (pOItem); break; case QJACKCTL_PLUGITEM: pOSocket = (static_cast (pOItem))->socket(); break; default: return false; } qjackctlSocketItem *pISocket = nullptr; switch (pIItem->type()) { case QJACKCTL_SOCKETITEM: pISocket = static_cast (pIItem); break; case QJACKCTL_PLUGITEM: pISocket = (static_cast (pIItem))->socket(); break; default: return false; } // Sockets must be of the same type... if (pOSocket->socketType() != pISocket->socketType()) return false; // One-to-one disconnection... disconnectSockets(pOSocket, pISocket); // Making one list dirty will take care of the rest... m_pPatchbayView->setDirty(true); return true; } // Test if any plug is disconnectable. bool qjackctlPatchbay::canDisconnectAll (void) { QListIterator osocket(m_pOSocketList->sockets()); while (osocket.hasNext()) { qjackctlSocketItem *pOSocket = osocket.next(); if (pOSocket->connects().count() > 0) return true; } return false; } // Disconnect all plugs. bool qjackctlPatchbay::disconnectAll (void) { if (QMessageBox::warning(m_pPatchbayView, tr("Warning") + " - " QJACKCTL_TITLE, tr("This will disconnect all sockets.\n\n" "Are you sure?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { return false; } QListIterator osocket(m_pOSocketList->sockets()); while (osocket.hasNext()) { qjackctlSocketItem *pOSocket = osocket.next(); QListIterator isocket(pOSocket->connects()); while (isocket.hasNext()) disconnectSockets(pOSocket, isocket.next()); } // Making one list dirty will take care of the rest... m_pPatchbayView->setDirty(true); return true; } // Expand all socket items. void qjackctlPatchbay::expandAll (void) { (m_pOSocketList->listView())->expandAll(); (m_pISocketList->listView())->expandAll(); (m_pPatchbayView->PatchworkView())->update(); } // Complete contents rebuilder. void qjackctlPatchbay::refresh (void) { (m_pOSocketList->listView())->update(); (m_pISocketList->listView())->update(); (m_pPatchbayView->PatchworkView())->update(); } // Complete contents clearer. void qjackctlPatchbay::clear (void) { // Clear socket lists. m_pOSocketList->clear(); m_pISocketList->clear(); // Reset dirty flag. m_pPatchbayView->setDirty(false); // May refresh everything. refresh(); } // Patchbay client list accessors. qjackctlSocketList *qjackctlPatchbay::OSocketList (void) const { return m_pOSocketList; } qjackctlSocketList *qjackctlPatchbay::ISocketList (void) const { return m_pISocketList; } // External rack transfer method: copy patchbay structure from master rack model. void qjackctlPatchbay::loadRackSockets ( qjackctlSocketList *pSocketList, QList& socketlist ) { pSocketList->clear(); qjackctlSocketItem *pSocketItem = nullptr; QListIterator sockit(socketlist); while (sockit.hasNext()) { qjackctlPatchbaySocket *pSocket = sockit.next(); pSocketItem = new qjackctlSocketItem(pSocketList, pSocket->name(), pSocket->clientName(), pSocket->type(), pSocketItem); if (pSocketItem) { pSocketItem->setExclusive(pSocket->isExclusive()); pSocketItem->setForward(pSocket->forward()); pSocketItem->updatePixmap(); qjackctlPlugItem *pPlugItem = nullptr; QStringListIterator iter(pSocket->pluglist()); while (iter.hasNext()) { pPlugItem = new qjackctlPlugItem( pSocketItem, iter.next(), pPlugItem); } } } } void qjackctlPatchbay::loadRack ( qjackctlPatchbayRack *pPatchbayRack ) { (m_pOSocketList->listView())->setUpdatesEnabled(false); (m_pISocketList->listView())->setUpdatesEnabled(false); // Load ouput sockets. loadRackSockets(m_pOSocketList, pPatchbayRack->osocketlist()); // Load input sockets. loadRackSockets(m_pISocketList, pPatchbayRack->isocketlist()); // Now ready to load from cable model. QListIterator iter(pPatchbayRack->cablelist()); while (iter.hasNext()) { qjackctlPatchbayCable *pCable = iter.next(); // Get proper sockets... qjackctlPatchbaySocket *pOSocket = pCable->outputSocket(); qjackctlPatchbaySocket *pISocket = pCable->inputSocket(); if (pOSocket && pISocket) { qjackctlSocketItem *pOSocketItem = m_pOSocketList->findSocket(pOSocket->name(), pOSocket->type()); qjackctlSocketItem *pISocketItem = m_pISocketList->findSocket(pISocket->name(), pISocket->type()); if (pOSocketItem && pISocketItem) connectSockets(pOSocketItem, pISocketItem); } } (m_pOSocketList->listView())->setUpdatesEnabled(true); (m_pISocketList->listView())->setUpdatesEnabled(true); (m_pOSocketList->listView())->update(); (m_pISocketList->listView())->update(); (m_pPatchbayView->PatchworkView())->update(); // Reset dirty flag. m_pPatchbayView->setDirty(false); } // External rack transfer method: copy patchbay structure into master rack model. void qjackctlPatchbay::saveRackSockets ( qjackctlSocketList *pSocketList, QList& socketlist ) { // Have QTreeWidget item order into account: qjackctlSocketListView *pListView = pSocketList->listView(); if (pListView == nullptr) return; socketlist.clear(); const int iItemCount = pListView->topLevelItemCount(); for (int iItem = 0; iItem < iItemCount; ++iItem) { QTreeWidgetItem *pItem = pListView->topLevelItem(iItem); if (pItem->type() != QJACKCTL_SOCKETITEM) continue; qjackctlSocketItem *pSocketItem = static_cast (pItem); if (pSocketItem == nullptr) continue; qjackctlPatchbaySocket *pSocket = new qjackctlPatchbaySocket(pSocketItem->socketName(), pSocketItem->clientName(), pSocketItem->socketType()); if (pSocket) { pSocket->setExclusive(pSocketItem->isExclusive()); pSocket->setForward(pSocketItem->forward()); QListIterator iter(pSocketItem->plugs()); while (iter.hasNext()) pSocket->pluglist().append((iter.next())->plugName()); socketlist.append(pSocket); } } } void qjackctlPatchbay::saveRack ( qjackctlPatchbayRack *pPatchbayRack ) { // Save ouput sockets. saveRackSockets(m_pOSocketList, pPatchbayRack->osocketlist()); // Save input sockets. saveRackSockets(m_pISocketList, pPatchbayRack->isocketlist()); // Now ready to save into cable model. pPatchbayRack->cablelist().clear(); // Start from output sockets... QListIterator osocket(m_pOSocketList->sockets()); while (osocket.hasNext()) { qjackctlSocketItem *pOSocketItem = osocket.next(); // Then to input sockets... QListIterator isocket(pOSocketItem->connects()); while (isocket.hasNext()) { qjackctlSocketItem *pISocketItem = isocket.next(); // Now find proper racked sockets... qjackctlPatchbaySocket *pOSocket = pPatchbayRack->findSocket( pPatchbayRack->osocketlist(), pOSocketItem->socketName()); qjackctlPatchbaySocket *pISocket = pPatchbayRack->findSocket( pPatchbayRack->isocketlist(), pISocketItem->socketName()); if (pOSocket && pISocket) { pPatchbayRack->addCable( new qjackctlPatchbayCable(pOSocket, pISocket)); } } } // Reset dirty flag. m_pPatchbayView->setDirty(false); } // Connections snapshot. void qjackctlPatchbay::connectionsSnapshot (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; qjackctlPatchbayRack rack; rack.connectJackSnapshot(pMainForm->jackClient()); rack.connectAlsaSnapshot(pMainForm->alsaSeq()); loadRack(&rack); // Set dirty flag. m_pPatchbayView->setDirty(true); } // end of qjackctlPatchbay.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlConnectionsForm.h0000644000000000000000000000013214771215054020157 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323773797 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/qjackctlConnectionsForm.h0000644000175000001440000000717614771215054020162 0ustar00rncbcusers// qjackctlConnectionsForm.h // /**************************************************************************** Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlConnectionsForm_h #define __qjackctlConnectionsForm_h #include "ui_qjackctlConnectionsForm.h" #include "qjackctlJackConnect.h" #include "qjackctlAlsaConnect.h" // Forward declarations. class qjackctlSetup; //---------------------------------------------------------------------------- // qjackctlConnectionsForm -- UI wrapper form. class qjackctlConnectionsForm : public QWidget { Q_OBJECT public: // Constructor. qjackctlConnectionsForm(QWidget *pParent = nullptr, Qt::WindowFlags wflags = Qt::WindowFlags()); // Destructor. ~qjackctlConnectionsForm(); void setup(qjackctlSetup *pSetup); qjackctlConnectView *audioConnectView() const; qjackctlConnectView *midiConnectView() const; qjackctlConnectView *alsaConnectView() const; enum TabPage { AudioTab = 0, MidiTab = 1, AlsaTab = 2 }; void setTabPage(int iTabPage); int tabPage() const; QFont connectionsFont() const; void setConnectionsFont(const QFont& font); void setConnectionsIconSize(int iIconSize); bool isAudioConnected() const; bool isMidiConnected() const; bool isAlsaConnected() const; void refreshAudio(bool bEnabled, bool bClear = false); void refreshMidi(bool bEnabled, bool bClear = false); void refreshAlsa(bool bEnabled, bool bClear = false); void stabilizeAudio(bool bEnabled, bool bClear = false); void stabilizeMidi(bool bEnabled, bool bClear = false); void stabilizeAlsa(bool bEnabled, bool bClear = false); void updateAliases(); public slots: void audioConnectSelected(); void audioDisconnectSelected(); void audioDisconnectAll(); void audioExpandAll(); void audioAliasesChanged(); void audioRefresh(); void audioStabilize(); void midiConnectSelected(); void midiDisconnectSelected(); void midiDisconnectAll(); void midiExpandAll(); void midiAliasesChanged(); void midiRefresh(); void midiStabilize(); void alsaConnectSelected(); void alsaDisconnectSelected(); void alsaDisconnectAll(); void alsaExpandAll(); void alsaAliasesChanged(); void alsaRefresh(); void alsaStabilize(); protected slots: void audioDisconnecting(qjackctlPortItem *, qjackctlPortItem *); void midiDisconnecting(qjackctlPortItem *, qjackctlPortItem *); void alsaDisconnecting(qjackctlPortItem *, qjackctlPortItem *); protected: void showEvent(QShowEvent *); void hideEvent(QHideEvent *); void closeEvent(QCloseEvent *); void keyPressEvent(QKeyEvent *); private: // The Qt-designer UI struct... Ui::qjackctlConnectionsForm m_ui; // Instance variables. qjackctlJackConnect *m_pAudioConnect; qjackctlJackConnect *m_pMidiConnect; qjackctlAlsaConnect *m_pAlsaConnect; qjackctlSetup *m_pSetup; }; #endif // __qjackctlConnectionsForm_h // end of qjackctlConnectionsForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlMessagesStatusForm.cpp0000644000000000000000000000013214771215054021203 xustar0030 mtime=1743067692.326636579 30 atime=1743067692.326636579 30 ctime=1743067692.326636579 qjackctl-1.0.4/src/qjackctlMessagesStatusForm.cpp0000644000175000001440000002353614771215054021204 0ustar00rncbcusers// qjackctlMessagesStatusForm.cpp // /**************************************************************************** Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlMessagesStatusForm.h" #include "qjackctlStatus.h" #include "qjackctlMainForm.h" #include #include #include #include #include #include #include #include // The maximum number of message lines. #define QJACKCTL_MESSAGES_MAXLINES 1000 // Deprecated QTextStreamFunctions/Qt namespaces workaround. #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) #define endl Qt::endl #endif //---------------------------------------------------------------------------- // qjackctlMessagesStatusForm -- UI wrapper form. // Constructor. qjackctlMessagesStatusForm::qjackctlMessagesStatusForm ( QWidget *pParent, Qt::WindowFlags wflags ) : QWidget(pParent, wflags) { // Setup UI struct... m_ui.setupUi(this); // m_ui.MessagesTextView->setTextFormat(Qt::LogText); // Initialize default message limit. m_iMessagesLines = 0; setMessagesLimit(QJACKCTL_MESSAGES_MAXLINES); m_pMessagesLog = nullptr; // Create the list view items 'a priori'... const QString s = " "; const QString c = ":" + s; const QString n = "--"; QTreeWidgetItem *pViewItem; // Status list view... QHeaderView *pHeader = m_ui.StatsListView->header(); pHeader->setDefaultAlignment(Qt::AlignLeft); // pHeader->setDefaultSectionSize(320); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) // pHeader->setSectionResizeMode(QHeaderView::Custom); pHeader->setSectionsMovable(false); #else // pHeader->setResizeMode(QHeaderView::Custom); pHeader->setMovable(false); #endif pHeader->setStretchLastSection(true); m_apStatus[STATUS_SERVER_NAME] = new QTreeWidgetItem(m_ui.StatsListView, QStringList() << s + tr("Server name") + c << n); m_apStatus[STATUS_SERVER_STATE] = new QTreeWidgetItem(m_ui.StatsListView, QStringList() << s + tr("Server state") + c << n); m_apStatus[STATUS_DSP_LOAD] = new QTreeWidgetItem(m_ui.StatsListView, QStringList() << s + tr("DSP Load") + c << n); m_apStatus[STATUS_SAMPLE_RATE] = new QTreeWidgetItem(m_ui.StatsListView, QStringList() << s + tr("Sample Rate") + c << n); m_apStatus[STATUS_BUFFER_SIZE] = new QTreeWidgetItem(m_ui.StatsListView, QStringList() << s + tr("Buffer Size") + c << n); m_apStatus[STATUS_REALTIME] = new QTreeWidgetItem(m_ui.StatsListView, QStringList() << s + tr("Realtime Mode") + c << n); pViewItem = new QTreeWidgetItem(m_ui.StatsListView, QStringList() << s + tr("Transport state") + c << n); m_apStatus[STATUS_TRANSPORT_STATE] = pViewItem; m_apStatus[STATUS_TRANSPORT_TIME] = new QTreeWidgetItem(pViewItem, QStringList() << s + tr("Transport Timecode") + c << n); m_apStatus[STATUS_TRANSPORT_BBT] = new QTreeWidgetItem(pViewItem, QStringList() << s + tr("Transport BBT") + c << n); m_apStatus[STATUS_TRANSPORT_BPM] = new QTreeWidgetItem(pViewItem, QStringList() << s + tr("Transport BPM") + c << n); pViewItem = new QTreeWidgetItem(m_ui.StatsListView, QStringList() << s + tr("XRUN count since last server startup") + c << n); m_apStatus[STATUS_XRUN_COUNT] = pViewItem; m_apStatus[STATUS_XRUN_TIME] = new QTreeWidgetItem(pViewItem, QStringList() << s + tr("XRUN last time detected") + c << n); m_apStatus[STATUS_XRUN_LAST] = new QTreeWidgetItem(pViewItem, QStringList() << s + tr("XRUN last") + c << n); m_apStatus[STATUS_XRUN_MAX] = new QTreeWidgetItem(pViewItem, QStringList() << s + tr("XRUN maximum") + c << n); m_apStatus[STATUS_XRUN_MIN] = new QTreeWidgetItem(pViewItem, QStringList() << s + tr("XRUN minimum") + c << n); m_apStatus[STATUS_XRUN_AVG] = new QTreeWidgetItem(pViewItem, QStringList() << s + tr("XRUN average") + c << n); m_apStatus[STATUS_XRUN_TOTAL] = new QTreeWidgetItem(pViewItem, QStringList() << s + tr("XRUN total") + c << n); #ifdef CONFIG_JACK_MAX_DELAY m_apStatus[STATUS_MAX_DELAY] = new QTreeWidgetItem(m_ui.StatsListView, QStringList() << s + tr("Maximum scheduling delay") + c << n); #endif m_apStatus[STATUS_RESET_TIME] = new QTreeWidgetItem(m_ui.StatsListView, QStringList() << s + tr("Time of last reset") + c << n); m_ui.StatsListView->resizeColumnToContents(0); // Description. m_ui.StatsListView->resizeColumnToContents(1); // Value. // UI connections... QObject::connect(m_ui.ResetPushButton, SIGNAL(clicked()), SLOT(resetXrunStats())); QObject::connect(m_ui.RefreshPushButton, SIGNAL(clicked()), SLOT(refreshXrunStats())); } // Destructor. qjackctlMessagesStatusForm::~qjackctlMessagesStatusForm (void) { setLogging(false); } // Notify our parent that we're emerging. void qjackctlMessagesStatusForm::showEvent ( QShowEvent *pShowEvent ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); QWidget::showEvent(pShowEvent); } // Notify our parent that we're closing. void qjackctlMessagesStatusForm::hideEvent ( QHideEvent *pHideEvent ) { QWidget::hideEvent(pHideEvent); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); } // Tab page accessors. void qjackctlMessagesStatusForm::setTabPage ( int iTabPage ) { m_ui.MessagesStatusTabWidget->setCurrentIndex(iTabPage); } int qjackctlMessagesStatusForm::tabPage (void) const { return m_ui.MessagesStatusTabWidget->currentIndex(); } // Messages view font accessors. QFont qjackctlMessagesStatusForm::messagesFont (void) const { return m_ui.MessagesTextView->font(); } void qjackctlMessagesStatusForm::setMessagesFont ( const QFont& font ) { m_ui.MessagesTextView->setFont(font); } // Messages line limit accessors. int qjackctlMessagesStatusForm::messagesLimit (void) const { return m_iMessagesLimit; } void qjackctlMessagesStatusForm::setMessagesLimit ( int iMessagesLimit ) { m_iMessagesLimit = iMessagesLimit; m_iMessagesHigh = iMessagesLimit + (iMessagesLimit / 3); // m_ui.MessagesTextView->setMaxLogLines(iMessagesLimit); } // Messages logging stuff. bool qjackctlMessagesStatusForm::isLogging (void) const { return (m_pMessagesLog != nullptr); } void qjackctlMessagesStatusForm::setLogging ( bool bEnabled, const QString& sFilename ) { if (m_pMessagesLog) { appendMessages(tr("Logging stopped --- %1 ---") .arg(QDateTime::currentDateTime().toString())); m_pMessagesLog->close(); delete m_pMessagesLog; m_pMessagesLog = nullptr; } if (bEnabled) { m_pMessagesLog = new QFile(sFilename); if (m_pMessagesLog->open(QIODevice::Text | QIODevice::Append)) { appendMessages(tr("Logging started --- %1 ---") .arg(QDateTime::currentDateTime().toString())); } else { delete m_pMessagesLog; m_pMessagesLog = nullptr; } } } // Messages log output method. void qjackctlMessagesStatusForm::appendMessagesLog ( const QString& s ) { if (m_pMessagesLog) { QTextStream(m_pMessagesLog) << s << endl; m_pMessagesLog->flush(); } } // Messages widget output method. void qjackctlMessagesStatusForm::appendMessagesLine ( const QString& s ) { // Check for message line limit... if (m_iMessagesLines > m_iMessagesHigh) { m_ui.MessagesTextView->setUpdatesEnabled(false); QTextCursor textCursor(m_ui.MessagesTextView->document()->begin()); while (m_iMessagesLines > m_iMessagesLimit) { // Move cursor extending selection // from start to next line-block... textCursor.movePosition( QTextCursor::NextBlock, QTextCursor::KeepAnchor); m_iMessagesLines--; } // Remove the excessive line-blocks... textCursor.removeSelectedText(); m_ui.MessagesTextView->setUpdatesEnabled(true); } m_ui.MessagesTextView->append(s); m_iMessagesLines++; } void qjackctlMessagesStatusForm::appendMessages ( const QString& s ) { appendMessagesColor(s, Qt::gray); } void qjackctlMessagesStatusForm::appendMessagesColor ( const QString& s, const QColor& rgb ) { const QString& sText = QTime::currentTime().toString("hh:mm:ss.zzz") + ' ' + s; appendMessagesLine("" + sText + ""); appendMessagesLog(sText); } void qjackctlMessagesStatusForm::appendMessagesText ( const QString& s ) { appendMessagesLine(s); appendMessagesLog(s); } // Ask our parent to reset status. void qjackctlMessagesStatusForm::resetXrunStats (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->resetXrunStats(); } // Ask our parent to refresh our status. void qjackctlMessagesStatusForm::refreshXrunStats (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->refreshXrunStats(); } // Update one status item value. void qjackctlMessagesStatusForm::updateStatusItem ( int iStatusItem, const QString& sText ) { m_apStatus[iStatusItem]->setText(1, sText); } // Keyboard event handler. void qjackctlMessagesStatusForm::keyPressEvent ( QKeyEvent *pKeyEvent ) { #ifdef CONFIG_DEBUG_0 qDebug("qjackctlMessagesStatusForm::keyPressEvent(%d)", pKeyEvent->key()); #endif int iKey = pKeyEvent->key(); switch (iKey) { case Qt::Key_Escape: close(); break; default: QWidget::keyPressEvent(pKeyEvent); break; } } // end of qjackctlMessagesStatusForm.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlMessagesStatusForm.h0000644000000000000000000000013214771215054020650 xustar0030 mtime=1743067692.326636579 30 atime=1743067692.326636579 30 ctime=1743067692.326636579 qjackctl-1.0.4/src/qjackctlMessagesStatusForm.h0000644000175000001440000000523414771215054020644 0ustar00rncbcusers// qjackctlMessagesStatusForm.h // /**************************************************************************** Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlMessagesStatusForm_h #define __qjackctlMessagesStatusForm_h #include "ui_qjackctlMessagesStatusForm.h" // Forward declarations. class QTreeWidgetItem; class QFile; //---------------------------------------------------------------------------- // qjackctlMessagesStatusForm -- UI wrapper form. class qjackctlMessagesStatusForm : public QWidget { Q_OBJECT public: // Constructor. qjackctlMessagesStatusForm(QWidget *pParent = nullptr, Qt::WindowFlags wflags = Qt::WindowFlags()); // Destructor. ~qjackctlMessagesStatusForm(); enum TabPage { MessagesTab = 0, StatusTab = 1 }; void setTabPage(int iTabPage); int tabPage() const; QFont messagesFont() const; void setMessagesFont(const QFont& font); int messagesLimit() const; void setMessagesLimit(int iLimit); bool isLogging() const; void setLogging(bool bEnabled, const QString& sFilename = QString()); void appendMessages(const QString& s); void appendMessagesColor(const QString& s, const QColor& rgb); void appendMessagesText(const QString& s); void updateStatusItem(int iStatusItem, const QString& sText); public slots: void resetXrunStats(); void refreshXrunStats(); protected: void appendMessagesLine(const QString& s); void appendMessagesLog(const QString& s); void showEvent(QShowEvent *); void hideEvent(QHideEvent *); void keyPressEvent(QKeyEvent *); private: // The Qt-designer UI struct... Ui::qjackctlMessagesStatusForm m_ui; // Instance variables. int m_iMessagesLines; int m_iMessagesLimit; int m_iMessagesHigh; // Logging stuff. QFile *m_pMessagesLog; // Status stuff. QTreeWidgetItem *m_apStatus[19]; }; #endif // __qjackctlMessagesStatusForm_h // end of qjackctlMessagesStatusForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlGraphForm.ui0000644000000000000000000000013214771215054017124 xustar0030 mtime=1743067692.325636584 30 atime=1743067692.325636584 30 ctime=1743067692.325636584 qjackctl-1.0.4/src/qjackctlGraphForm.ui0000644000175000001440000006256714771215054017134 0ustar00rncbcusers rncbc aka Rui Nuno Capela JACK Audio Connection Kit - Qt GUI Interface. Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlGraphForm 0 0 800 600 Graph :/images/graph1.png 0 0 0 0 800 20 &Graph &Edit &View T&humbview :/images/graphThumbview.png &Zoom :/images/graphZoomTool.png Co&lors :/images/graphColors.png S&ort &Help Qt::AllToolBarAreas Qt::Horizontal Qt::ToolButtonTextBesideIcon true TopToolBarArea false :/images/graphConnect.png &Connect Connect Connect Connect selected ports Ctrl+C :/images/graphDisconnect.png &Disconnect Disconnect Disconnect Disconnect selected ports Ctrl+D Cl&ose Close Close Close this application window Select &All Select All Select All Select All Ctrl+A Select &None Select None Select None Select None Ctrl+Shift+A Select &Invert Select Invert Select Invert Select Invert Ctrl+I :/images/graphRename.png &Rename... Rename item Rename Item Rename Item F2 :/images/graphFind.png &Find... Find Find nodes Find nodes Ctrl+F true &Menubar Menubar Menubar Show/hide the main program window menubar Ctrl+M true &Toolbar Toolbar Toolbar Show/hide main program window file toolbar true &Statusbar Statusbar Statusbar Show/hide the main program window statusbar true &Top Left Top left Top left Show the thumbnail overview on the top-left true Top &Right Top right Top right Show the thumbnail overview on the top-right true Bottom &Left Bottom Left Bottom left Show the thumbnail overview on the bottom-left true &Bottom Right Bottom right Bottom right Show the thumbnail overview on the bottom-right true &None None Hide thumbview Hide the thumbnail overview true Text Beside &Icons Text beside icons Text beside icons Show/hide text beside icons :/images/graphCenter.png &Center Center Center Center view &Refresh Refresh Refresh Refresh view F5 :/images/graphZoomIn.png Zoom &In Zoom In Zoom In Zoom In Ctrl++ :/images/graphZoomOut.png Zoom &Out Zoom Out Zoom Out Zoom Out Ctrl+- :/images/graphZoomFit.png Zoom &Fit Zoom Fit Zoom Fit Zoom Fit Ctrl+0 :/images/graphZoomReset.png Zoom &Reset Zoom Reset Zoom Reset Zoom Reset Ctrl+1 true :/images/graphZoomRange.png &Zoom Range Zoom Range Zoom Range Zoom Range JACK &Audio... JACK Audio color JACK Audio color JACK Audio color JACK &MIDI... JACK MIDI JACK MIDI color JACK MIDI color ALSA M&IDI... ALSA MIDI ALSA MIDI color ALSA MIDI color JACK &CV... JACK CV color JACK CV color JACK CV color JACK &OSC... JACK OSC JACK OSC color JACK OSC color &Reset Reset colors Reset colors Reset colors true Port &Name Port name Sort by port name true Port &Title Port title Sort by port title true Port &Index Port index Sort by port index true &Ascending Ascending Ascending sort order true &Descending Descending Descending sort order true Repel O&verlapping Nodes Repel nodes Repel overlapping nodes Repel overlapping nodes true Connect Thro&ugh Nodes Connect Through Nodes Connect through nodes Whether to draw connectors through or around nodes &About... About... About Show information about this application program About &Qt... About Qt... About Qt Show information about the Qt toolkit qjackctlGraphCanvas QGraphicsView
qjackctlGraph.h
qjackctl-1.0.4/src/PaxHeaders/qjackctlSocketForm.ui0000644000000000000000000000012714771215054017317 xustar0029 mtime=1743067692.33063656 29 atime=1743067692.33063656 29 ctime=1743067692.33063656 qjackctl-1.0.4/src/qjackctlSocketForm.ui0000644000175000001440000002754714771215054017322 0ustar00rncbcusers rncbc aka Rui Nuno Capela JACK Audio Connection Kit - Qt GUI Interface. Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlSocketForm 0 0 400 300 Socket :/images/patchbay1.png 9 6 QTabWidget::Rounded &Socket 8 4 &Name (alias): Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false SocketNameLineEdit Socket name (an alias for client name) Client name (regular expression) true Add plug to socket plug list Add P&lug :/images/add1.png &Plug: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false PlugNameComboBox Port name (regular expression) true Qt::CustomContextMenu Socket plug list false true false true Socket Plugs / Ports Edit currently selected plug &Edit :/images/edit1.png Remove currently selected plug from socket plug list &Remove :/images/remove1.png &Client: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false ClientNameComboBox Move down currently selected plug in socket plug list &Down :/images/down1.png Move up current selected plug in socket plug list &Up :/images/up1.png Qt::Vertical QSizePolicy::Expanding 8 8 Enforce only one exclusive cable connection E&xclusive &Forward: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false SocketForwardComboBox Forward (clone) all connections from this socket false Type 8 4 Audio socket type (JACK) &Audio MIDI socket type (JACK) &MIDI MIDI socket type (ALSA) AL&SA Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok SocketTabWidget SocketNameLineEdit AudioRadioButton MidiRadioButton AlsaRadioButton ClientNameComboBox PlugNameComboBox PlugAddPushButton PlugListView PlugEditPushButton PlugRemovePushButton PlugUpPushButton PlugDownPushButton ExclusiveCheckBox SocketForwardComboBox DialogButtonBox qjackctl-1.0.4/src/PaxHeaders/qjackctlInterfaceComboBox.h0000644000000000000000000000013214771215054020402 xustar0030 mtime=1743067692.325636584 30 atime=1743067692.325636584 30 ctime=1743067692.325636584 qjackctl-1.0.4/src/qjackctlInterfaceComboBox.h0000644000175000001440000000364014771215054020375 0ustar00rncbcusers// qjackctlInterfaceComboBox.h // /**************************************************************************** Copyright (C) 2003-2021, rncbc aka Rui Nuno Capela. All rights reserved. Copyright (C) 2015, Kjetil Matheussen. (portaudio_probe_thread) Copyright (C) 2013, Arnout Engelen. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlInterfaceComboBox_h #define __qjackctlInterfaceComboBox_h #include // Forward decls. class qjackctlSetup; class QStandardItemModel; //---------------------------------------------------------------------------- // Combobox for device interfaces class qjackctlInterfaceComboBox : public QComboBox { public: // Constructor. qjackctlInterfaceComboBox(QWidget *pPrent = 0); void setup(QComboBox *pDriverComboBox, int iAudio, const QString& sDefName); protected: void clearCards(); void addCard(const QString& sName, const QString& sDescription); void populateModel(); void showPopup(); QStandardItemModel *model() const; private: QComboBox *m_pDriverComboBox; int m_iAudio; QString m_sDefName; }; #endif // __qjackctlInterfaceComboBox_h // end of qjackctlInterfaceComboBox.h qjackctl-1.0.4/src/PaxHeaders/qjackctlSetupForm.ui0000644000000000000000000000012714771215054017167 xustar0029 mtime=1743067692.33063656 29 atime=1743067692.33063656 29 ctime=1743067692.33063656 qjackctl-1.0.4/src/qjackctlSetupForm.ui0000644000175000001440000043562414771215054017171 0ustar00rncbcusers rncbc aka Rui Nuno Capela JACK Audio Connection Kit - Qt GUI Interface. Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. S1ee the GNU General Public License for more details. with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlSetupForm 0 0 640 520 Setup :/images/setup1.png true false 0 Settings 4 4 Preset &Name: false PresetComboBox 0 0 Settings preset name true (default) Clear settings of current preset name Clea&r :/images/clear1.png false Save settings as current preset name &Save :/images/save1.png false Delete current settings preset &Delete :/images/remove1.png false 0 Parameters 50 false Driv&er: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false DriverComboBox 50 false The audio backend driver interface to use false dummy sun oss alsa portaudio coreaudio firewire net netone Qt::Horizontal 8 20 50 false &Interface: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false InterfaceComboBox 140 0 50 false The PCM device name to use true (default) hw:0 plughw:0 /dev/audio /dev/dsp Qt::Horizontal 8 20 50 false MIDI Driv&er: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false MidiDriverComboBox 80 0 50 false The ALSA MIDI backend driver to use false none raw seq 50 false Use realtime scheduling &Realtime 50 false Sample &Rate: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false SampleRateComboBox 50 false Sample rate in frames per second true 22050 32000 44100 48000 88200 96000 192000 Qt::Horizontal 8 20 50 false &Frames/Period: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false FramesComboBox 50 false Frames per period between process() calls true 16 32 64 128 256 512 1024 2048 4096 50 false Periods/&Buffer: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false PeriodsSpinBox 50 false Number of periods in the hardware buffer 1 999 1 Qt::Vertical 20 4 50 false Whether to use server synchronous mode &Use server synchronous mode Qt::Horizontal 20 8 50 false Whether to give verbose output on messages &Verbose messages Qt::Horizontal 8 20 50 false Latency: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 72 0 50 false Output latency in milliseconds, calculated based on the period, rate and buffer settings QFrame::StyledPanel QFrame::Sunken 0 msecs Qt::AlignCenter false Advanced 8 16 16 Please do not touch these settings unless you know what you are doing. Qt::Horizontal 20 8 50 false Server &Prefix: false ServerPrefixComboBox 0 0 50 false Server path (command line prefix) true jackd jackdmp jackstart 50 false &Name: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false ServerNameComboBox 120 0 50 false The JACK Audio Connection Kit sound server name true (default) Qt::Vertical 20 4 50 false Do not attempt to lock memory, even if in realtime mode No Memory Loc&k 50 false Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) &Unlock Memory 50 false Enable hardware metering on cards that support it H/&W Meter 50 false Provide output monitor ports &Monitor 50 false Ignore xruns reported by the backend driver So&ft Mode 50 false Force 16bit mode instead of failing over 32bit (default) Force &16bit 50 false Ignore hardware period/buffer size &Ignore H/W Qt::Horizontal 8 20 50 false Priorit&y: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false PrioritySpinBox 50 false Scheduler priority when running realtime 1 5 95 50 false &Word Length: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false WordLengthComboBox 50 false Word length true 16 32 64 50 false &Wait (usec): Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false WaitComboBox Sans Serif 50 false Number of microseconds to wait between engine processes (dummy) true 21333 50 false &Channels: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 0 ChanSpinBox 50 false Maximum number of audio channels to allocate 999 50 false Port Ma&ximum: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false PortMaxComboBox 60 0 50 false Maximum number of ports the JACK server can manage true 0 128 256 512 1024 50 false false &Timeout (msec): Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false TimeoutComboBox 50 false Set client timeout limit in milliseconds true 0 200 500 1000 2000 5000 50 false Cloc&k source: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false ClockSourceComboBox 50 false Clock source false 0 Qt::Horizontal 8 20 50 false &Audio: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false AudioComboBox 0 0 50 false Provide either audio capture, playback or both Duplex Capture Only Playback Only 50 false Dit&her: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false DitherComboBox 0 0 50 false Set dither mode None Rectangular Shaped Triangular 50 false &Output Device: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false OutDeviceComboBox 50 false Alternate output device for playback true (default) hw:0 plughw:0 /dev/audio /dev/dsp 50 false &Input Device: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false InDeviceComboBox 50 false Alternate input device for capture true (default) hw:0 plughw:0 /dev/audio /dev/dsp 50 false &Channels I/O: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false InChannelsSpinBox 0 0 80 0 50 false Maximum input audio hardware channels to allocate 999 0 0 80 0 50 false Maximum output audio hardware channels to allocate 999 50 false &Latency I/O: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false InLatencySpinBox 0 0 80 0 50 false External input latency (frames) 9999999 0 0 80 0 50 false External output latency (frames) 9999999 Qt::Vertical 20 4 Qt::Vertical 20 4 Qt::Horizontal 20 8 50 false S&elf connect mode: SelfConnectModeComboBox 50 false Whether to restrict client self-connections false 0 Qt::Horizontal 20 8 Qt::Vertical 20 4 50 false Server Suffi&x: false ServerSuffixComboBox 0 0 50 false Extra driver options (command line suffix) true 50 false Start De&lay: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false StartDelaySpinBox 50 false Time in seconds that client is delayed after server startup secs 0 999 Options 75 true Scripting true 8 4 50 false Whether to execute a custom shell script before starting up the JACK audio server. Execute script on Start&up: 50 false Whether to execute a custom shell script after starting up the JACK audio server. Execute script after &Startup: 50 false Whether to execute a custom shell script before shuting down the JACK audio server. Execute script on Shut&down: 0 0 50 false Command line to be executed before starting up the JACK audio server true 22 22 24 24 50 false Qt::TabFocus Scripting argument meta-symbols > 22 22 24 24 50 false Qt::TabFocus Browse for script to be executed before starting up the JACK audio server ... 0 0 50 false Command line to be executed after starting up the JACK audio server true 22 22 24 24 50 false Qt::TabFocus Scripting argument meta-symbols > 22 22 24 24 50 false Qt::TabFocus Browse for script to be executed after starting up the JACK audio server ... 22 22 24 24 50 false Qt::TabFocus Scripting argument meta-symbols > 22 22 24 24 50 false Qt::TabFocus Browse for script to be executed before shutting down the JACK audio server ... 0 0 50 false Command line to be executed before shutting down the JACK audio server true 50 false Whether to execute a custom shell script after shuting down the JACK audio server. Execute script after Shu&tdown: 22 22 24 24 50 false Qt::TabFocus Scripting argument meta-symbols > 22 22 24 24 50 false Qt::TabFocus Browse for script to be executed after shutting down the JACK audio server ... 0 0 50 false Command line to be executed after shutting down the JACK audio server true 75 true Statistics true 8 4 50 false Whether to capture standard output (stdout/stderr) into messages window &Capture standard output 50 false &XRUN detection regex: false XrunRegexComboBox 0 0 50 false Regular expression used to detect XRUNs on server output messages true xrun of at least ([0-9|\.]+) msecs 75 true Connections true 50 false Whether to activate a patchbay definition for connection persistence profile. Activate &Patchbay persistence: 0 0 50 false Patchbay definition file to be activated as connection persistence profile true 22 22 24 24 50 false Qt::TabFocus Browse for a patchbay definition file to be activated ... 50 false Whether to reset all connections when a patchbay definition is activated. &Reset all connections on patchbay activation 50 false Whether to issue a warning on active patchbay port disconnections. &Warn on active patchbay disconnections Qt::Vertical 20 4 75 true Logging true 50 false Whether to activate a messages logging to file. &Messages log file: 0 0 50 false Messages log file true 22 22 24 24 50 false Qt::TabFocus Browse for the messages log file location ... Display 75 true Time Display true 4 4 50 false Transport &Time Code 50 false Transport &BBT (bar:beat.ticks) 50 false Elapsed time since last &Reset 50 false Elapsed time since last &XRUN Qt::Horizontal 8 20 4 4 180 0 260 32767 50 false Sample front panel normal display font true QFrame::StyledPanel QFrame::Sunken Qt::AlignCenter false 180 0 260 32767 50 false Sample big time display font true QFrame::StyledPanel QFrame::Sunken Qt::AlignCenter false 50 false Big Time display: false 50 false Select font for front panel normal display &Font... false 50 false Select font for big time display &Font... false 50 false Normal display: false 50 false Whether to enable blinking (flashing) of the server mode (RT) indicator Blin&k server mode indicator 75 true Custom true 8 4 50 false &Color palette theme: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter CustomColorThemeComboBox 50 false Custom color palette theme false (default) Wonton Soup KXStudio 22 22 24 24 50 false Qt::TabFocus Manage custom color palette themes ... Qt::Horizontal 20 20 50 false &Widget style theme: CustomStyleThemeComboBox 50 false Custom widget style theme false (default) Qt::Vertical 20 4 75 true Messages Window true 4 8 180 0 260 16777215 50 false Sample messages text font display true QFrame::StyledPanel QFrame::Sunken Qt::AlignCenter false 50 false Select font for the messages text display &Font... false Qt::Horizontal 8 20 50 false Whether to keep a maximum number of lines in the messages window &Messages limit: 50 false The maximum number of message lines to keep in view true 3 100 250 500 1000 2500 5000 Qt::Vertical 20 4 75 true Connections Window true 180 0 260 16777215 50 false Sample connections view font true QFrame::StyledPanel QFrame::Sunken Qt::AlignCenter false 50 false Select font for the connections view &Font... false Qt::Horizontal 8 20 50 false &Icon size: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false ConnectionsIconSizeComboBox 50 false The icon size for each item of the connections view false 0 16 x 16 32 x 32 64 x 64 Qt::Vertical 20 4 50 false Whether to enable client/port name aliases on the connections window E&nable client/port aliases 50 false &JACK client/port aliases: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false JackClientPortAliasComboBox 50 false JACK client/port aliases display mode false 0 Default First Second 50 false Whether to enable in-place client/port name editing (rename) Ena&ble client/port aliases editing (rename) 50 false JACK client/port pretty-name (metadata) display mode Enable JA&CK client/port pretty-names (metadata) Misc 4 4 75 true Other true 4 4 4 0 50 false Whether to start JACK audio server immediately on application startup &Start JACK audio server on application startup 50 false Whether to ask for confirmation on application exit &Confirm application close 50 false Whether to ask for confirmation on JACK audio server shutdown and/or restart Confirm server sh&utdown and/or restart 50 false false Whether to keep all child windows on top of the main window &Keep child windows always on top 50 false Whether to enable the system tray icon &Enable system tray icon 50 false Whether to show system tray message on main window close Sho&w system tray message on close 50 false Whether to start minimized to system tray Start minimi&zed to system tray 4 0 50 false Whether to save the JACK server command-line configuration into a local file (auto-start) S&ave JACK audio server configuration to: 50 false The server configuration local file name (auto-start) true .jackdrc 50 false Whether to enable ALSA Sequencer (MIDI) support on startup E&nable ALSA Sequencer support 50 false Whether to enable D-Bus interface &Enable D-Bus interface 50 false Whether to enable JACK D-Bus interface &Enable JACK D-Bus interface 50 false Whether to stop JACK audio server on application exit S&top JACK audio server on application exit 50 false Whether to restrict to one single application instance (X11) Single application &instance Qt::Vertical 20 4 75 true Buttons true 4 0 50 false Whether to hide the left button group on the main window Hide main window &Left buttons 50 false Whether to hide the right button group on the main window Hide main window &Right buttons 50 false Whether to hide the transport button group on the main window Hide main window &Transport buttons 50 false Whether to hide the text labels on the main window buttons Hide main window &button text labels Qt::Vertical 20 4 50 false Whether to replace Connections with Graph button on the main window Replace Connections with &Graph button 75 true Defaults true 4 4 Qt::Vertical 20 4 50 false &Base font size: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter BaseFontSizeComboBox 50 false Base application font size (pt.) true (default) 6 7 8 9 10 11 12 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Apply|QDialogButtonBox::Ok qjackctlInterfaceComboBox QComboBox
qjackctlInterfaceComboBox.h
SetupTabWidget PresetComboBox PresetClearPushButton PresetSavePushButton PresetDeletePushButton SettingsTabWidget DriverComboBox RealtimeCheckBox InterfaceComboBox SampleRateComboBox FramesComboBox PeriodsSpinBox MidiDriverComboBox SyncCheckBox VerboseCheckBox ServerPrefixComboBox ServerNameComboBox NoMemLockCheckBox UnlockMemCheckBox HWMeterCheckBox MonitorCheckBox SoftModeCheckBox ShortsCheckBox IgnoreHWCheckBox PrioritySpinBox WordLengthComboBox WaitComboBox ChanSpinBox PortMaxComboBox TimeoutComboBox AudioComboBox ClockSourceComboBox DitherComboBox OutDeviceComboBox InDeviceComboBox InChannelsSpinBox OutChannelsSpinBox InLatencySpinBox OutLatencySpinBox SelfConnectModeComboBox ServerSuffixComboBox StartDelaySpinBox StartupScriptCheckBox StartupScriptShellComboBox StartupScriptSymbolToolButton StartupScriptBrowseToolButton PostStartupScriptCheckBox PostStartupScriptShellComboBox PostStartupScriptSymbolToolButton PostStartupScriptBrowseToolButton ShutdownScriptCheckBox ShutdownScriptShellComboBox ShutdownScriptSymbolToolButton ShutdownScriptBrowseToolButton PostShutdownScriptCheckBox PostShutdownScriptShellComboBox PostShutdownScriptSymbolToolButton PostShutdownScriptBrowseToolButton StdoutCaptureCheckBox XrunRegexComboBox ActivePatchbayCheckBox ActivePatchbayPathComboBox ActivePatchbayPathToolButton ActivePatchbayResetCheckBox QueryDisconnectCheckBox MessagesLogCheckBox MessagesLogPathComboBox MessagesLogPathToolButton TransportTimeRadioButton TransportBBTRadioButton ElapsedResetRadioButton ElapsedXrunRadioButton DisplayFont1PushButton DisplayFont2PushButton DisplayBlinkCheckBox CustomColorThemeComboBox CustomColorThemeToolButton CustomStyleThemeComboBox MessagesFontPushButton MessagesLimitCheckBox MessagesLimitLinesComboBox ConnectionsFontPushButton ConnectionsIconSizeComboBox AliasesEnabledCheckBox AliasesEditingCheckBox JackClientPortAliasComboBox JackClientPortMetadataCheckBox StartJackCheckBox QueryCloseCheckBox QueryShutdownCheckBox KeepOnTopCheckBox SystemTrayCheckBox SystemTrayQueryCloseCheckBox StartMinimizedCheckBox ServerConfigCheckBox ServerConfigNameComboBox AlsaSeqEnabledCheckBox DBusEnabledCheckBox JackDBusEnabledCheckBox StopJackCheckBox SingletonCheckBox LeftButtonsCheckBox RightButtonsCheckBox TransportButtonsCheckBox TextLabelsCheckBox BaseFontSizeComboBox DialogButtonBox
qjackctl-1.0.4/src/PaxHeaders/qjackctlPatchbayForm.h0000644000000000000000000000012714771215054017434 xustar0029 mtime=1743067692.32863657 29 atime=1743067692.32863657 29 ctime=1743067692.32863657 qjackctl-1.0.4/src/qjackctlPatchbayForm.h0000644000175000001440000000603614771215054017425 0ustar00rncbcusers// qjackctlPatchbayForm.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlPatchbayForm_h #define __qjackctlPatchbayForm_h #include "ui_qjackctlPatchbayForm.h" // Forward declarations. class qjackctlPatchbay; class qjackctlSetup; //---------------------------------------------------------------------------- // qjackctlPatchbayForm -- UI wrapper form. class qjackctlPatchbayForm : public QWidget { Q_OBJECT public: // Constructor. qjackctlPatchbayForm(QWidget *pParent = nullptr, Qt::WindowFlags wflags = Qt::WindowFlags()); // Destructor. ~qjackctlPatchbayForm(); void setup(qjackctlSetup *pSetup); qjackctlPatchbayView *patchbayView() const; bool queryClose(); const QString& patchbayPath() const; void newPatchbayFile(bool bSnapshot); bool loadPatchbayFile(const QString& sFileName); bool savePatchbayFile(const QString& sFileName); void loadPatchbayRack(qjackctlPatchbayRack *pRack); void setRecentPatchbays(const QStringList& patchbays); void updateRecentPatchbays(); public slots: void newPatchbay(); void loadPatchbay(); void savePatchbay(); void selectPatchbay(int iPatchbay); void toggleActivePatchbay(); void addOSocket(); void removeOSocket(); void editOSocket(); void copyOSocket(); void moveUpOSocket(); void moveDownOSocket(); void addISocket(); void removeISocket(); void editISocket(); void copyISocket(); void moveUpISocket(); void moveDownISocket(); void connectSelected(); void disconnectSelected(); void disconnectAll(); void expandAll(); void contentsChanged(); void refreshForm(); void stabilizeForm(); protected: void showEvent(QShowEvent *); void hideEvent(QHideEvent *); void closeEvent(QCloseEvent *); void keyPressEvent(QKeyEvent *); private: // The Qt-designer UI struct... Ui::qjackctlPatchbayForm m_ui; // Instance variables. qjackctlSetup *m_pSetup; int m_iUntitled; qjackctlPatchbay *m_pPatchbay; QString m_sPatchbayPath; QString m_sPatchbayName; QStringList m_recentPatchbays; bool m_bActivePatchbay; int m_iUpdate; }; #endif // __qjackctlPatchbayForm_h // end of qjackctlPatchbayForm.h qjackctl-1.0.4/src/PaxHeaders/qjackctlSessionForm.ui0000644000000000000000000000013214771215054017506 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSessionForm.ui0000644000175000001440000001737514771215054017513 0ustar00rncbcusers rncbc aka Rui Nuno Capela JACK Audio Connection Kit - Qt GUI Interface. Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlSessionForm 0 0 480 320 Session :/images/session1.png Load session &Load... :/images/open1.png Recent session &Recent Qt::Horizontal 20 20 Save session &Save :/images/save1.png Qt::Horizontal 220 20 Update session Re&fresh :/images/refresh1.png Qt::Vertical Session clients / connections false true false true Client / Ports UUID Command Infra-clients / commands false true false true Infra-client Infra-command Add infra-client &Add :/images/add1.png Edit infra-client &Edit :/images/edit1.png Remove infra-client Re&move :/images/remove1.png Qt::Vertical 20 8 LoadSessionPushButton RecentSessionPushButton SaveSessionPushButton UpdateSessionPushButton SessionTreeView InfraClientListView AddInfraClientPushButton EditInfraClientPushButton RemoveInfraClientPushButton qjackctl-1.0.4/src/PaxHeaders/man10000644000000000000000000000013214771215054013742 xustar0030 mtime=1743067692.323701235 30 atime=1743067692.322636598 30 ctime=1743067692.323701235 qjackctl-1.0.4/src/man1/0000755000175000001440000000000014771215054014007 5ustar00rncbcusersqjackctl-1.0.4/src/man1/PaxHeaders/qjackctl.10000644000000000000000000000013214771215054015675 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/man1/qjackctl.10000644000175000001440000000561014771215054015667 0ustar00rncbcusers.TH QJACKCTL 1 "June 17, 2014" .SH NAME qjackctl \- User interface for controlling JACK (Jack Audio Connection Kit) .SH SYNOPSIS .B qjackctl [\fIoptions\fR] .SH DESCRIPTION This manual page documents briefly the .B qjackctl command. .PP .PP \fBQjackCtl\fP is used for controlling the Jack Audio Connection Kit (JACK) and as a patchbay for ALSA MIDI and JACK MIDI devices. \fBQjackCtl\fP also has support for the JACK transport control protocol, so you can use it to start and stop the JACK transport. Once you start qjackctl, you get presented with a single GUI window, the buttons are self-explanatory and have tooltips. .SH OPTIONS .HP \fB\-s\fR, \fB\-\-start\fR .IP Start JACK audio server immediately .HP \fB\-p\fR, \fB\-\-preset\fR=[\fIlabel\fR] .IP Set default settings preset name .HP \fB\-a\fR, \fB\-\-active\-patchbay\fR=[\fIpath\fR] .IP Set active patchbay definition file .HP \fB\-n\fR, \fB\-\-server\-name\fR=[\fIlabel\fR] .IP Set default JACK audio server name .HP \fB\-h\fR, \fB\-\-help\fR .IP Show help about command line options .HP \fB\-v\fR, \fB\-\-version\fR .IP Show version information. .SH D-Bus insterface Enable `Setup > Misc > Other > Enable D-Bus interface` to use the D-Bus interface commands as shown below. .PP \fB\dbus\-send \-\-system / org.rncbc.qjackctl.start\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.stop\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.reset\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.main\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.messages\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.status\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.session\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.connections\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.patchbay\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.graph\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.rewind\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.backward\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.play\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.pause\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.forward\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.setup\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.about\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.quit\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.preset string\fR:[\fIlabel\fR] \fB\dbus\-send \-\-system / org.rncbc.qjackctl.active-patchbay string\fR:[\fIpath\fR] \fB\dbus\-send \-\-system / org.rncbc.qjackctl.load\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.save\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.savequit\fR \fB\dbus\-send \-\-system / org.rncbc.qjackctl.savetemplate\fR .PP .SH SEE ALSO .BR jackd (1) .SH FILES Configuration settings are stored in ~/.config/rncbc.org/QjackCtl.conf .SH AUTHOR QjackCtl was written by Rui Nuno Capela. .PP This manual page was written by Guenter Geiger , for the Debian project (but may be used by others). qjackctl-1.0.4/src/man1/PaxHeaders/qjackctl.fr.10000644000000000000000000000013214771215054016303 xustar0030 mtime=1743067692.323701235 30 atime=1743067692.322636598 30 ctime=1743067692.323701235 qjackctl-1.0.4/src/man1/qjackctl.fr.10000644000175000001440000000347414771215054016303 0ustar00rncbcusers.TH QJACKCTL 1 "Juin 17, 2014" .SH NOM qjackctl \- interface utilisateur pour contrôler JACK (Jack Audio Connection Kit) .SH SYNOPSIS .B qjackctl [\fIoptions\fR] .SH DESCRIPTION Ce manuel décrit rapidement la commande .B qjackctl . .PP .PP \fBQjackCtl\fP est utilisé pour contrôler le kit de connexion audio Jack (JACK) ainsi qu'en tant que baie de brassage pour les périphériques ALSA MIDI et JACK MIDI. \fBQjackCtl\fP possède également un support pour le protocole de transport JACK, et vous pouvez donc l'utiliser pour démarrer et arrêter le transport JACK. Lorsque vous démarrez qjackctl, une fenêtre d'interface graphique unique vous est présentée, dont les boutons sont simples à comprendre et possèdent des info-bulles. .SH OPTIONS .HP \fB\-s\fR, \fB\-\-start\fR .IP Démarre le serveur audio JACK immédiatement .HP \fB\-p\fR, \fB\-\-preset\fR=[\fIétiquette\fR] .IP Paramètre le nom du pré-réglage de paramètres par défaut .HP \fB\-a\fR, \fB\-\-active\-patchbay\fR=[\fIchemin\fR] .IP Paramètre le fichier de définition de la baie de brassage active .HP \fB\-n\fR, \fB\-\-server\-name\fR=[\fIétiquette\fR] .IP Paramètre le nom du serveur audio JACK par défaut .HP \fB\-h\fR, \fB\-\-help\fR .IP Affiche de l'aide à propos des options de ligne de commande .HP \fB\-v\fR, \fB\-\-version\fR .IP Affiche des informations de version. .SH VOIR ÉGALEMENT .BR jackd (1) .SH FICHIER Les paramètres de configuration sont stockés dans ~/.config/rncbc.org/QjackCtl.conf .SH AUTEUR QjackCtl a été écrit par Rui Nuno Capela. .PP Cette page de manuel a été écrite par Guenter Geiger , pour le projet Debian (mais peut être utilisée par d'autres). .PP La version française a été traduite par Olivier Humbert , pour le projet LibraZiK (mais peut être utilisée par d'autres). qjackctl-1.0.4/src/PaxHeaders/qjackctlSetup.h0000644000000000000000000000013214771215054016151 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSetup.h0000644000175000001440000001364214771215054016147 0ustar00rncbcusers// qjackctlSetup.h // /**************************************************************************** Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlSetup_h #define __qjackctlSetup_h #include "qjackctlAbout.h" #include "qjackctlAliases.h" #include // Forward declarations. class QWidget; class QComboBox; class QSplitter; // Audio mode combobox item indexes. #define QJACKCTL_DUPLEX 0 #define QJACKCTL_CAPTURE 1 #define QJACKCTL_PLAYBACK 2 // Icon size combobox item indexes. #define QJACKCTL_ICON_16X16 0 #define QJACKCTL_ICON_32X32 1 #define QJACKCTL_ICON_64X64 2 // Server settings preset struct. struct qjackctlPreset { qjackctlPreset() { clear(); } void clear(); void load(QSettings& settings, const QString& sSuffix); void save(QSettings& settings, const QString& sSuffix); void fixup(); QString sServerPrefix; QString sServerName; bool bRealtime; bool bSoftMode; bool bMonitor; bool bShorts; bool bNoMemLock; bool bUnlockMem; bool bHWMeter; bool bIgnoreHW; int iPriority; int iFrames; int iSampleRate; int iPeriods; int iWordLength; int iWait; int iChan; QString sDriver; QString sInterface; int iAudio; int iDither; int iTimeout; QString sInDevice; QString sOutDevice; int iInChannels; int iOutChannels; int iInLatency; int iOutLatency; int iStartDelay; bool bSync; bool bVerbose; int iPortMax; QString sMidiDriver; QString sServerSuffix; uchar ucClockSource; uchar ucSelfConnectMode; }; // Common settings profile class. class qjackctlSetup { public: // Constructor. qjackctlSetup(); // Destructor; ~qjackctlSetup(); // The settings object accessor. QSettings& settings(); // Explicit I/O methods. void loadSetup(); void saveSetup(); // Command line arguments parser. bool parse_args(const QStringList& args); #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) void show_error(const QString& msg); #else // Command line usage helper. void print_usage(const QString& arg0); #endif // Default (translated) preset name. static const QString& defName(); // Immediate server start options. bool bStartJack; bool bStartJackCmd; // Server stop options. bool bStopJack; // User supplied command line. QStringList cmdLine; // Current/previous (default) preset name. QString sDefPreset; QString sOldPreset; // Available presets list. QStringList presets; // Options... bool bSingleton; QString sServerName; bool bStartupScript; QString sStartupScriptShell; bool bPostStartupScript; QString sPostStartupScriptShell; bool bShutdownScript; QString sShutdownScriptShell; bool bPostShutdownScript; QString sPostShutdownScriptShell; bool bStdoutCapture; QString sXrunRegex; bool bActivePatchbay; QString sActivePatchbayPath; bool bActivePatchbayReset; bool bQueryDisconnect; bool bMessagesLog; QString sMessagesLogPath; int iTimeDisplay; QString sMessagesFont; bool bMessagesLimit; int iMessagesLimitLines; QString sDisplayFont1; QString sDisplayFont2; bool bDisplayEffect; bool bDisplayBlink; QString sCustomColorTheme; QString sCustomStyleTheme; int iJackClientPortAlias; bool bJackClientPortMetadata; int iConnectionsIconSize; QString sConnectionsFont; bool bQueryClose; bool bQueryShutdown; bool bQueryRestart; bool bKeepOnTop; bool bSystemTray; bool bSystemTrayQueryClose; bool bStartMinimized; bool bServerConfig; QString sServerConfigName; bool bAlsaSeqEnabled; bool bDBusEnabled; bool bJackDBusEnabled; bool bAliasesEnabled; bool bAliasesEditing; bool bLeftButtons; bool bRightButtons; bool bTransportButtons; bool bTextLabels; bool bGraphButton; int iBaseFontSize; // Defaults... QString sPatchbayPath; // Recent patchbay listing. QStringList patchbays; // Recent session directories. QStringList sessionDirs; // Last open tab page... int iMessagesStatusTabPage; int iConnectionsTabPage; // Last session save type... bool bSessionSaveVersion; // Aliases containers. qjackctlAliases aliases; // Aliases preset management methods. bool loadAliases(); bool saveAliases(); // Preset management methods. bool loadPreset(qjackctlPreset& preset, const QString& sPreset); bool savePreset(qjackctlPreset& preset, const QString& sPreset); bool deletePreset(const QString& sPreset); // Combo box history persistence helper prototypes. void loadComboBoxHistory(QComboBox *pComboBox, int iLimit = 8); void saveComboBoxHistory(QComboBox *pComboBox, int iLimit = 8); // Splitter widget sizes persistence helper methods. void loadSplitterSizes(QSplitter *pSplitter, QList& sizes); void saveSplitterSizes(QSplitter *pSplitter); // Widget geometry persistence helper prototypes. void saveWidgetGeometry(QWidget *pWidget, bool bVisible = false); void loadWidgetGeometry(QWidget *pWidget, bool bVisible = false); private: // Our proper settings profile. QSettings m_settings; // Default (translated) preset name. static QString g_sDefName; }; #endif // __qjackctlSetup_h // end of qjackctlSetup.h qjackctl-1.0.4/src/PaxHeaders/qjackctlSystemTray.h0000644000000000000000000000012714771215054017201 xustar0029 mtime=1743067692.33063656 29 atime=1743067692.33063656 29 ctime=1743067692.33063656 qjackctl-1.0.4/src/qjackctlSystemTray.h0000644000175000001440000000423314771215054017167 0ustar00rncbcusers// qjackctlSystemTray.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlSystemTray_h #define __qjackctlSystemTray_h #include #include //---------------------------------------------------------------------------- // qjackctlSystemTray -- Custom system tray widget. class qjackctlSystemTray : public QSystemTrayIcon { Q_OBJECT public: // Constructor. qjackctlSystemTray(QWidget *pParent = 0); // Default destructor. ~qjackctlSystemTray(); // Background mask methods. void setBackground(const QColor& background); const QColor& background() const; // Set system tray icon overlay. void setPixmapOverlay(const QPixmap& pmOverlay); const QPixmap& pixmapOverlay() const; // System tray icon/pixmaps update method. void updatePixmap(); // Redirect to hide. void close(); signals: // Clicked signal. void clicked(); // Toggle Start/Stop server. void doubleClicked(); // Xrun reset signal. void middleClicked(); protected slots: // Handle systeam tray activity. void activated(QSystemTrayIcon::ActivationReason); private: // Instance pixmap and background color. QIcon m_icon; QPixmap m_pixmap; QPixmap m_pixmapOverlay; QColor m_background; }; #endif // __qjackctlSystemTray_h // end of qjackctlSystemTray.h qjackctl-1.0.4/src/PaxHeaders/images0000644000000000000000000000013214771215054014353 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.318540145 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/0000755000175000001440000000000014771215054014420 5ustar00rncbcusersqjackctl-1.0.4/src/images/PaxHeaders/xstarting1.png0000644000000000000000000000013214771215054017242 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/xstarting1.png0000644000175000001440000000046214771215054017234 0ustar00rncbcusersPNG  IHDRĴl;IDATx퓡0 )d԰R_d>fR>C%C 4X%jժGXjkss.KDJ"fֆ>g XjRJ)!b[jwǺvPPf:n du$W4s04ŀXKY2'ȀXb/&ˀ[ A-* [,)֑ f4l֘% qMOe dy] iҫyV !3a #٩w 03" 8 ӭ ֧#ڠ'ߚ-P3}@k/(p#&B[Ɯ :47M1`NPuZj#dauJIca fMs<Oe9\ ct!I3so'+IFqK)ISl'M 6n$"p Mm$ ӷ} Vn)[㶀 _@BUy lxrTfO XgJ q(a c '3} 8 Ӭ ֦#ڡ'ޚ-P2}@k/(p#&B[Ɯ :47M1_NPuZj#d`tJHb^ eH q.Nb7pb$ `rCk 2u/ L ;+ L !;- M <9- N`. >;- KV^P6 "?<- $A`kP6 'A8"CZ\g3 ,2;/!*D| #NN>*S 9ZX/ Za DQ>#  <>4= 8 ѫզ#٠'ޙ-ߑP3ߑ}@k/(p#&B[Ɯ :37M1_NOtZj#dl8mk B;d?!;/BW7o/KnWN` h p^y"+@;7SQ;oT]it325T '*Gf #) "Hӽd! 6[ȑ;6R%!/P([nN)3ڹܐ"$ ra`b3Zᵝk nf[RQ7OzؓtŁ$gLZg`B$")ʊ^mc3 UERTpt0$(;JԎY֡f8;'?CLfVk`3 [eV}R٦'4L_rRw91')KyZu$ @az~Aw,% );E`]ӛe4( 7]hxe_?C&0#?]p, "]j_By5" !)FWs~pH ShXq]eSS+3?|۩p0 1alKNgS)&F\P+OA|;o79@( OUl,$,|ceifB}^-#$ "*-tB$YrD~=O-)/"!1X^, 9iHVf:$%!$.Z`+  LLNx\{H! # 'D]+ ,DiqYPxc;D0! #+b[-!-M{BudJ-#&Orpq^, ,zFO{IybL4-NK8Id+!bGyzv~nd;&0#$.Ezf." *ElF\$(+$"$+@o^," 8N[3$PP3#!#*D`-"5xhe"BsfH1#!#.Hc.!Tu52o^F/"!$/H`/" 8lr#f}ddM.!"$.Dvc0"ZI(vpeN-!!$,Csj/! 2$U}u^F.""$,Ed2" }|${i]E.#!$0Na,# [c-}daL,! #+Qb1" ,R1xofN, !$/N}gU#  +/}vhE*"!$/H ؼl'.w~oaA+!!$/Jx ϼm(. J||pV>(!!&/G{ǰq-/&NznVA'!"%1M{õk//&Th^?' !&0Pvn,/'Vr]G*!!&3TҺa`0/)^peF'!!%V{ƴr4/,_jeI(#|}ucM_r~y}~ t2$#B}slfdyzy n,  %Fytfm~w'  &Hzbõujq}wa  (CX|̻ymsX5  )6kؽȵygx/5^śJ)8:}̸xm9!&:\k ( @C˽̺l@$ !'5^w0 '!GOΧkQ9& &7b궫lS#%&L]͒{iV5#!(7:QUrkc@ $*Qlܲ~lR3! !"%!$@tg^-(-9rЭyeT3  #tQ  3G}跫vlO &׈  AFƳ~I$.tD II׷sd!]< LJĻa *)6? &OJO);9'.@ &VSֹ?=A@6>!,A &",E~U->DBxn0@ &#&Iy($1Dil 0@ &'J٫/&%$Bm 1@  &SyN'&&#Sf 3@  &5-|ׄ)'%"Je 0A ';$"Nɀ_3B*@! U\2F  ZY4E `̀S 2E    bS  4H  iL 5I jM7J  rH 8LyI 6M#~ӾG 9P"A 7P%ҺB <P&з= 9W& з= ;Y*ϱ9!;\( β7 :Y.ͫ6 =] -̬1: 2˦4!>:&  7ʥ, =3AZ  ;ȟ/ ' ,Qm  BǛ+ 5l BƘs JuBu Ix  C|! Tw&t* G!2-%!G  /½'!Hh{#!GD# lx$ IU@8$ "um" LJ:AA?y "tk",:E!!xd" 1!#zL s!{tT  ${n  ]W %vX &  i1'%  FtC "||c Yxnb9 Q2 ^tle]P-/GMM  )^e`ZPCLfVj_.ZdU|R٦&4L^rQu8/$'KyZu$ ?ay}>u*! &9E^]ӛe3' 7]gwd[?@#-">]p+ "]i^@x1  &FUs~b? ShWn\bSR'2=|˜`( 1`kILgO)#DZܖD$O@y:m76@&KS ҹ[$$,|bbicB|\-!!&(qΞb7$YqC~:L-).(JpO$9hFUe7#!%LȽQ#  LJMw\zG  8lܝO# +DhqWNwa99(#Sp~ݜL% -K{@iU>$C`__O$+xENzCnfR@+%A?/>rU# aExyerk]U1'&:gV& *BjAruqmM!##5^ڛP$ 7MRvsxv+CC*"9nۘQ%4wZvw|U7bV<(%=wT&Sdu{x,)mm^O;''f ü{]!  >i}%xi^H4 '}na *)6? &B=qO);9'.@ &HFn|ո?=A@6>!,A &#:kU->DBxn0@ &=qzx($1Dil 0@ &>rث/&%$Bm 1@ FugM'&&#Se 3@ ,&|ք('%"Jd 0A ';$"M_ 3B *?!Uǀ\2F   ZY4E `S 2E    bS  4H  iЀL 5I jM7J  rH 8LyI 6M#~ҽG 9P"ѿA 7P%ѹB <P&з= 9W&з= ;Y*ϰ9!;\(α7 :Y.ͫ5 =] -̬1: 2˥4!>:&  7ʥ, =3AZ  ;ȟ/ & ,Qm  Bƚ+ 5l CŘs JuBu Ix  C|! Tw&s* G!2-%!G  /½'!Hh{#!GD# lw$ IU@8$ "tm! LJ:AA?y "tk",:E!!xd" 1!#zL s!{sT  ${m  ]W %vX &  i1'%  FtC "||c Yxnb9 Q2 ^tkd]P-.GMM  )^e`ZPBLeUh^%UbU{Q٦&3K]pOo6)#KxYu$ ?_x{8t#5D\]Қe2& 6\ftcT>:%!=]p+ "\i]e310/-  &;PWgwwdD ( 5J81021  .L]ho|~dB 2u.024"("  2M\ju hC! )P,142 --%  /?R\s~{kG ) 5%15'"52+!!  ):HVh|whJ! *"15 4652)&"  (BJYhyvfG$ 0377652,(  .IW^mzwdG! *+++877662-#  4M]dn{|`G ! 287763,!   3P\jq| {eF!  58763*&"  2G[gt} xdE(" 369#8863+(#  0ATdr}mNF@:6% - )389:9:9874,&   *DOdr}q]WSNFA;4% +58:#872+&  +8Q^r|v`_^ZWSMJA<3' ,59;%::982*%  +>IanaWY]_^[UQLIC;3$ /.6:;<;::982,#  )@QPSVXZ]__[VRLHD=5% //8:<<;<::83-'  3;DNTWY[]__[UQOTF. / 07;=<<;;:84.&"*1;EMTWXZ^_^ZeufKC>8'/ 28<==<;;:84/#! "(,0;DNUWY[^e|uZROID=8+ !2:=&<<;:83+& %),1;EOTXYpzg^[WTPHD=7+/ #4;<>==<<:84+"  $(*1=$<;93)"%+,1%=<;7%()+-BEPTX[[^`_\VSPICXJ/'6>=<-%&!!2;DPUXZ[^`_[XVjvS.'7:$"$$!"'*1;HPUYX[__^swgP-1(8=?@>.)+,+)(#**),1?:)-14322.(!',*,,/;EPUYf |iP( 1-9>1+18;<;973'$"").-*+/<93*!  #tQ +@PTTXWB?>=:0)% &׈ /COUTHA@?><91, .tD4FNPCBB@?><9/8]!]< 4HDCCBAA?>86_ *)6? %6:@CCBB@<,O):9'.@ &.9ABCBA4mԷ?=A?6> ,A & ,;ABB;GU-=CBwn 0@ &/:&  7ɤ, =3AZ  ;Ǟ/ % ,Qm  Bƚ+ 5l CĘs JuBu Iw  C|! Tw&s* G!2-%!F  /'!Hh{#!GD# lw$ IU@8$ "tm! LJ:AA?y "tk",:E!!xc" 1!#zL s!{sT  ${m  ]W %uX &  i1'%  FtC "||c Ywmb9 Q2 ^tkd\P-.GMM  )^e`YP  *ךJ xߝP  BY b>ikr#{," 4) =3 Dǒ;  N˖C YҗI !a֛V #pݛS %{I )? /$  6h >ݛ)  G_ O ])!h2$u4'W/+J$  2^; 9M) Bh;  Kޚ3Vہ  cx"q~%|݅ *܋& 2ߐ,  ;ޒ1  D6  I= PB VH !TM !JyjS !9sըhVHMZ -Bu{XH4&%C^  !0@MROF8'Fa (,*# Nf  Vg!ai#km%tn'r,r 0v 5z 9z =| C HMT! Z&!aË."hΑ4#nё5 %vҒ0 '|ʊ$)Ё ,L 0  4& 9S$ f|{MUc%~6 ߂"Բ~d,6KQD\QLm#Aq&@*eLW4?^Ci_~2Ph9>6AguWGB{35clX-)BIxBJdpg3wȃQW.+P '/?#ʱʺȒ,C2 ~2Ph9>6AUNw8MA&8ȇ! "N(=ZSG ab›paL hX$m23ꑘ9wȃi> `gp:X=;9Z_}ȋ-%~s!Xg~/Pvz=/C56rzGSե{U:7 b׌G~% P "cڇ6z6s%&rJ v糶܀RG&C|]oϮgfȐ*b?~S7HmHaIar~%DAvIO? !w+8@c2+LSMLP~Az]yT1 OFXFA7!`j_z'fs{|Z856y5@\riLǘxk1-\Ź/~s}%Z8kvVEz< #M'kg&%ZڣI^]xNf=42Qx>׍<6 o0tjpQgvEܶK> ץ/Pͼz$Xo}k[G]*1VU;VJ}S7Ùhߋp\ :ĮQ!F"\~>DNϦh.xc"qI 4/+gu{.m&9D ekFh*1vİSsoi*~ Y->mÚ'+0p&hT=E -s AB]ÊF:21QkE6F[:[~s|87&)اo+ЊSlLнaj0yaįǘ{&fF)iw'͊wzy3y̚I叕s%!oW!GƝȑGKE4Yy ץ/JX\g &x.l8ɵg ;jyg VRC8ZPDA( @|7 ^TnجVZ,ȃ; qgP_"qI 4/RށYE0mV–rr즸\wIb:'aJ+f0#nTRC-xLC)`S$):@|ڗ[[)~ Sx87&)اo+Џ$aO0RI;ɼ1; d. 6'b.g $)wMt Yٗ ש!qX kIRs%\9uꁷV`{,agϱ,{-EIIcLuH1)bm)) 0~?C(s+u7uqc7_c֘uqŮPut=QXs+b-3,ĉPnU|-psy4BevYP? =*sY|vR ?u6`s;B(gn| d  4"r8a\^`0}Og> a-?K$yngT+/^E*ƅM h?=fs.^ d5~s<Qe*V۫va2qa_3(_uG#3?npgHRP&(1'Grģlsհgsʆ.cEU6 *?!tTBOs{t!`幊GUgn;A HL^H,ChS`6ZOQgQjyч#Yd̟;An~MӉe- vji^NĹbW@ :ݺj>q;yXKGjnNNq=&=nEol`.iZ_3fkee'oH19ė$U hlTk w{޺#a? ,odmX/FmFZX!+u<_Cʹ"m\@tK`'_ EGO6ԥo -}Yd].۪jHM3 |w[idg4B~ICC;TY?$z |KjI_1tq2:y%Ict>m9jA?kM|棏,[4I= sΓԒ E˩~T,ꊈj!hP,rxۚO͞7#YW| UjDW EҊz*2@LԜ t #'fGIue"3ILѥp)vvD:6NTw =0V lP#l81,iQ3"N QJ7?9 dW,Ӑ[aI`8]Rz؎*LؘX.,jIT]pa=dӔ!KJ$h4!@p.pHʪo񤉵"#.G\O/!ӂ_$]BH܍Lw9TC߰Zt*Kvdx ͂Bg5?r@2A迾&ON)gi$s:Ía9Μ C5IF%qm&` ,(97O5c]N+$aѸMPC˜9ŜYR$JVRtn :;⫖CsC@ c DAgᠱhP[Y،yl}[5̕"/{MG8ÒIvX=diDtHz,sn;U}|22D4wk xBf'@koPoE/iu9Jwi&)rb;]˽RGef歞Cfxqj\:veX4yͼN/XrnC}vȶ+yw ut, u뾕n^+q43Ͱ-N i[.w&_ӕ(뾸) oeyf8D8|$w*c:̂M۰ҬUrxQ\q6B#`.]uaïE",; 3׼tFѕAˊʡj'![J@RBkmZ3ȼqkSP.f40gdYMy=ud=ѕ^,~.g.h UĆer#7A)Jxw =QϏ^͊1.ԣPb7\W 3WN&g" ?#Ɲf9&>#!WV%,[w"P8W5L'% 9qɘ _tCSqTV^qQsM;K}HJi5 aU9mزD5d͑}EKWHyd.mߎa=c-kHćǚ`P(ľ/;_Hs1 XUGp`p/i&Ͼdf$~ql / @CS[Awwro؇"U-b$= #Vta_ysY﮳2%]vFa\;b+v{:/1Lf/qYUc%',QB$b"~ &DB` vмɵ`:*-A۠±쎯?$cn@qe25#kLo~` V'#Y|H}$%퉋#K$H H!G_Ɨ3z@kbխt.)gQ.q(>1䟆CzڠN.Y#hr4u^) ݣHA:Q% Tw d]TTV~@,Mܧ}#MNu@)^p(Fh҉4NuVTOsQYmVTwxq*wּe}iI+8EL6a*ؓt2{mif(c%ݶXE1MfH ]OS%FH;djޥA]KwC2eߎïvNAM/[:U^}L e }%Dnu@VNߞX~0$~PC++qO",'GR;  3׼uvƻE5c-oC T|E 8 ƅmV0g6 Kr⫢`7AFm(O/=@-g9ԗ!o+ j;2 )JT("yVx%.4ʪ $!ijb#cN`Dɹ̮D~6iȠM38 J=0 ;KpE!.;&9PM׉MZKY57w>ӧZTkq _ESVe*(3 )GES{H Iݥ.ERO2VbyHT}$KV僼W%/1@ Qnl<-ǠMYuh9pSu )h9RYy3&%K+ "ݝA&Sn(D.Ģg9AqgIgKV/c9 repC%d=Ipg{qVԋz<80b$Ly-E˯x{J. %IXNjTAi RRKVi̲:oH#yǶYBڦ{m-j"*%t :\]fI+ N1qìUE) نFE>\:h}g*חμ)m|/@p-3e>FSR%5N[Qq!ThS? lקƛ7^q&[Avȝ!Ŧ2fpY(;ڳLYЏ._̘7/ݠ=XN!zl/-iҷ 2q%AY >4aTMi7oXrI3kWwZ f(rA/ Έ ({V#it7dKt3~0H#jI肜~ʒEG+=`'#_2e|^jSE! 53' :1ԪooDPHp^Y ٱWE1uO _T&#S(vp-̵V#5s-ٺfzÏ{ 6i؄R"+$7=TH!b0Wz{$?πVf1~y.tMC1hhCS5n|~8NS_^ΊJ ùϸk7D NѮzֽyN=؏ŐÁv-ԷX5zyE nVSjձ?, BꙭN/%Q6xWC`M)ǂyoqa"N59CQ؆],26ZrS/$s^@:l{1 hp;O&2茗9Dc~!lw)!khOi)&SkgZN 5(,#MLa}tE'2(Tߩ<!Rd1LÅp:ϢHnQ 8WE RS#>bRn]pH1٘i tQVoo^"롈+ok{ gSP`B?BûYS#Liώy+Lec ¥}Z3m/3f+M0/f33#oYxp:6uݴ)bLVyr$a 唬Ͼ(%Bj 2vyp243[b@+^G2D;?m?֝ eS |+A*Oפ3f}9 eq4STY9܏;KPy1v %^~C7>bg7C4U֞ ʀld {US^M>271orKD[(ZYE lDt&~ Ba<\ֹ>)$p6D2oFY;vü 3׼uv·~YADo/޹.([o[,7w8%雒}#)dKh58ŔJ 2ڂ:i-fgLbdF֑<߫́?1]gˇya!U|@R)ֱ 5H/:f!s]K&OaiZ5_rR/Bb4kkG{@FZ7!ŗCK Kli7П`)kOo=t$7ht]=}`}+d֦Eږf8gi*,%20q';HL9B] 5X'>2')J܄-T>C^|*ba,L"0zR뉷$h[I!ȶ)3uesNxVah$RsbVo4%h,qA~)y鄡NP S*2~ s;)޳>^/-%L0ba$; +ފ|c6e0sW Nw !"JJ_ \ d_ @JnLwhVL"fFq Ͱ1 ]m=&\TTtBUZLʛ\20)>$ ȤrD@ք2J=@tR)Tq=#LsNV׭ʸ߁r9))wIQUc´ A;?8*yZ,"OcI x`#^բE Je>XX3!9zaGAh0½Ny!y!h>AO^և$zy^ΉFxtsiCщtv륻ku2ehXxU<&ze@/=Xs3롋̿P2E#2^]Wm4.LU5.[n@0owh7|m*iK2\?-kKD삓Fsӱ(p/kH]?Q6)X`FAI"뗥g;jdo'Oŭ# 2ؓ!,v,crM4-0߃[`\*W-z&$ oø |u4"&{*$m5> ^8~pIY=C(RnJfAnOG$`KF͆BEԑ05=K,︒DI%"NVo.\*aDCBWhn*_.TQG߉ C4ߦv]@vw  L|ŬiEH튋%ɳ~ؙ ~DbK>?IdX\s_|d1j!WW*(ydbp-3vtU}⌹u:v鄶੿m@*t:tHtL`l&!ݻdۛ$Uw{ͤ7: r3ڨ?MT[:E=;_.? =M1mXoH5/&wz7!Tq7Wxhj#~ 43 ]!ڞqg/V*5+J=^l{^kxa!]" tG%EE&pnRŅiJb>Ԣਥ ;lõ_QaX'tзCsn/UK]cM8N N={r3R -,K>XX IxxzE.SOOۗ'PfզpaV`/8,vO0O`Wd+W@G !q1Qb:_"o!S@ws aG rgq,l YyǹIzW+ne]^/CcXqݮyBv\y!Y8U+@A;<;״1ųz{*7h^]:S#g DV엱[6P|U0Qr^6aLQSI8(aly5As8pLddVJEǞutoJ,}kwC]};ath'A).,|c[4 Ɛkv&lʍsnhd@UAKpQXK>+ /ؖG(M̓9) ?CIԴڷA&tY1@=tZu);S*byT!-u t{$9]E[7ZQڕuȟP"$Nk@qpy8KWl}&htդ b-)X;ρ _UiV{U L9ÿ( /dg ȍ"GCLtBnͪ}ړCnj,6n9Aޕ؈wG/m/5 WԚI @/9U(^;*$-YhJ2 ;T4[@7lKq^2 zbe[=-PHݻRtsA롑/IHn›VMsXՅle5*tǽ(.} iOcLLD Y :Plf( E$ & dF`)BlLܔC+J# }aРoY%OTl#lH `2l EnT^ahLȟ-Ē9a~ݑ`*eDO` wRpP_+< z磫G }^ӓ:ݍ1 \x~ o$xym]PW0<&'X`)a742Y~x]|j`.Ҥ,=E9㷫Wq?)84|!6&#y )c. !(i1բq`^$g~’l2srۗF< JR|*I#oً4-Xmp-6~^ * i ~|O2>S%P sS㸖tbJo`s_;f6S@DFNU&Gll6C3laT.j!m_Q1 p,.h^)4q D]%__ y*-8+`c,8 rh^\rXzT\2|/-xn &2+KL xz^ۼӚcAt-Yr8X+]OĹfٱ>q2;!yGm4G#O|E2UB k&nD?Z>M(C-T;?REkAG_\\8KJC+Oܸ@_We91L|[fA=+晿w ˢ9U™לx+FIfɢpi&fY)ba)[u`!n'f]Q\,3pzrqWcmmpyQ8VF<1nё>tt"56&/F@FhaYƌ&)g#B`8c9t4 $8lm=c2]"h&5*]FY블.;8U,ѽgT\+vx/#{1SDŽ)A#T 3"%D2"B iH Z(UJb94ʨ~bBmOeqat*#VoF 'Ȯ iÑ^M(rM6 a\̄e{>}$S"T 6 nvb0d!uE󽱚5X*:,~ &T*bSs";"?wwI#[Ɣޢ)aW?3H !7$7xnsʳ+CD}Zb+wR>Z4fcB@B_z rŨ7H>Hdy/[΍72`'wadd: %L\Vង**L좒$gOmHeM02/IܡSUݣ̊:O\3u@4:Poց$۞ i+:yuv!^;H 4FCJ_ usoЋu)C2Z$od` 3hzrsf|iVoJN1*M5U+z9 )3mE0`WXi6 y^6khٽ'[}R2 :xH (p9K~/kKF]=k:e8u4SBYPy'#j^b:7d2x󱂺VpxKh6:B9BiVTٯdͯ-)\V+V R鿆i~zH cϵsG`&MDp)ѻgH]Xq/D;i@Oc*xP3  =~3YW`1Ҍȧ4>ʟB[9;iqC4ewe:g2;(jmC8%,qt6i`R{}Ɠ[zVO5os6=|TC>)݌[ o7!9rTcQ!bR㙈MLfY=tL'J;.l ?GwW\`FH͠=)͆0w& jɶ;,itj"Eq_@/~bQ/Pj(B:%(~6&wpO pS0>Aʬ*:0.rISuw {4m<^ rSv, l"4ƈM Fbu-!0̤m9%&Apv[T˺_S4̘rA1f?֘l(f dLnH{BI[ /> F4F/ <Ӷz`IɦTֳPO@o>w8T9MV?\f5#{bN=8q,pG}p S6ā{YpDwj«n,-Gf |ٴ}5c>ld$r 9gPKnK]ʖW[>pErlz)Ce "Q }t&j怖y5T<Lp`%dsz86p|ɨ)M2]]ue*¿89VE6v8'=r|0I9Ý@]rfBZw6ݕy-;P& "(D|Oe`7v}]@|A#8P]4-C}eOd,xXȐ+ۜ׼{:]x3mH0yL:?64q~[,T&n2Dd{v-}(sw c trBJj\sL|JX\lks'#~U}ɉoj4iPiV)=ˏEe⼇>Bn:<~O_^!Ld%[pe?){ hkEd̢gnt§֫8aS8>:䫪GcM{ sҾ\;^86qHp9FI=rv6\W83V%1Eg 5J26n872W߉T4"RF[ucb۬3ٴ5VxZWuAKژ{*-AJch4&qKx$csA/;qc8bK섌wvh3 .ʳgv$7kg9|v@)lIS>] X$xCC촎f+p#Pv^B4Q= Zl;nGTw1QKEB^&WyOtCpd$ǨWzCVsf-uav$ MJ&>0]œݺL F,E\Z z4(Ǖw[fNRS'HP|N!@8 :XP E> a7k&֣@\}4ƿz 2s 44b$1ވ(ϻƒ_CLıMߎ3PG \Q5dX@y (Ҹ&pqT-r*v~m/4Ppr)ZG :/T}~\ h E ~_E+5=`%Gׇ(ZubI+G~7"ep4BѠ37 NBGt|fN lmKdM IAmhw!Yߒ;M-wɓ*l׹xϠW<|u|H'H_5O. g&lxCTFN P]5 p~Xظ^جT(n?3mlrVb ;sTbp{vB8a< HiLP<,8iSi[N%6qI֌G,U^+xB[ܵA">8L }F2rjr C#8Ķ+Tw~@7> _!1g~+U_!=_ɿ4\o>)JwcD+Xyyׄu']5jy~#U =N 0g+rvwc5 W8 Ʋ43.| Mi<Ӑuӿ ?ilţS tDgSuww2]ICG:8|l R"EB| !Y%Z%3MDVxF>߹ fO$ Y;g }}G<qoӝ<V1OFsͣ1U #DdZ'S{+*vftS`@;j⯤01n /BD ViJMhv oَh#QjH)UcLsc l|SX9'muXI(ƺٮm `Կ/X!d|v!̐z" 8Z|}<cHV:r_/Y1vs{Ed; KTO~6BMZ<E?8V(k{̥"r}ےT#F4f$Vܿ Lyf.@CgEtޟ/e;S6}$zuկS͆iɣrdZ{:haszm›ѝi dx]&(ތu >fX+2yJcS‘i-[#Ac<@4t9:9yfOF#}G%I[Z6I d+`[m2$Ir1wpcd;:rF6AbI&zqnU~ʙ|3@DK1 X&Lj'Wc OFFV/|;@geNFS9㢧bWGAZ %}VDzS-(T H YS evgėwnտl2P͝8@cp0]GցgjZC q|<*pYDOz(@A~`hЊ3ȡfUk~al7"aщ)ibx3VR~칠;OX'_ )U5+g l?Ѭ. q$) F'DS-_j @TJ`몁Tj x wJ6X|iȬK/@°j "}pF8MWC@i"Ljm~bYJ,Rm\[Zuf%0NiГ;ƌ ݻK_F.gD~qcE-7LDpZT3S=:-k;tƞ1dM| Y9S1,6ۯMCl:2I&aaodûNFVSlcc &СFvDz\-́pR5ƂXؗ_D?e1qrQfχjݕ'pxJ; 9/ ltG!jsLٲR.Y |jU|T: U1YuM.~ؽ -//-<7" `ò߹˞:h)aXXExMAyѽ6~}ßwzrnNֵ!Dl䀪2EV,͗,Yoe?l鏱&<~䇊W>kd m:Yя]q7f)3acO\..0+ag6 Lŕ)-7&OA3T[KYYvѮNi 3Jqd Oq>w>Z<,'N" \tp2Ъk35W [^*Wq*\ߦ&P5|ɴl2>Gñ(u/Y E[;C>%*nkncԠ)9A:Q╨KX 6B]!v8?((u0|AՕ"Wtŕ  ژ.$pd : =S01m᭮ᐉ.eE4lYm/G@FRZ?8)Sg6%yͱ( !RDupkP`zSvj)LM jc%: w4W^1{( _)aI* E52MjS\V?Io$uS-k'QfȄ!xCD<;G8S4-QN5OЪW<vAB|`l6vw9wl Ec0x 껯~pR`KAx|6W!}"5hg#m C᥇  ]S0 @CӪ"gԳl.[vo,ĥz,}4;Zn09L9|k\:}> gG-ND0]22_Tcwn d]um;*K!3TUdO+kvkd47N2ew $oEXU l" #nj09t۞*)ZxJiZ} ăJN~VYYZgSd@z*fhyOj{o _ŴВj*8Kk,7%IJ3њP0fI!_"gzRJj-aXXz]R_ΰ3IS62LO2@78ne?O(r k)~vwN;"(_3gAe[T'nxBH8n-(F^%W.*Z`3ukv ^g%0NFHTӊg'2qRO (iaD[]:MV7Eup`XQ\p%7i"qɬd@ѧ2CE^Mz0 ݕTcu4'lyZz;7RLPxF(D`Mݒ3K&2 TXlNpWq6.󋄦}|($׷?:A18s{jQ:?^嵃[#ŵ+;r3=R5Gd@bizI%!h{L "LOIAưY(J>|U,/{qRKq Qn礪Y(|drp=ۻ-v%Y0l\]ۈ 3(#,:Z{˯s jUJc8# ~q"HFsīyUhurӂ|9W?9{׵8kJ2eE*t83% ݴ7+(iK G4T[9Y+ Z#F3O!kc]^ nP.`rB%?sx]@=hWDcᤌ@oGچah;+ 5joRъT,&@P8qX'f3Vseb#2D;w3:.9Hgw/ry(\ϛUCt>+: ZY@ FHd*BZ&V@I2߂Q<FGvmU$h%6a_i<-h LW%$\MƹP-y0W웭7upPXW|.} vcF 01 ܞ4G Mi[BeZ6dnv/QD<'uAlHKJ )*yF:3k-%l,{$/pOC *>d&>qˆmQʶԺ%MI|FG?JrsIJo#^!(ag]BG9N^|"]-H8$Jqb0CY=7*A wl#db[V҄6,㻯,9|D`JKFϡqqi'FָB8d~6)@mc;ËЅ:=Irq 2>nfURWU'?ԡ /s0}(wE;ڙy CwghEZӾyɆ2 9oFLCct0i!tY%CSӏ%G;Wz}.ȗbJ1#7;mfSE-0# KpT/[ϔSL.krn:å(b;hNT*ZMjUexj/ZeJ0Ս9#_ʹk& V]x"zCfMn|`dIS2 dj=/ ˙ e@R&-~0ªֵ MN3(VQu :)-L;+6+O(Ay +5)Bdd5@ǣ;@L.M֒ա ŊsD8+e.6jR'R8b Im{ Q;]Z8 v|S0rК`^A[]Bp5Np͈,Ux^$w8&&̿O~m%oB׏]s^gYOQPd2u}GlxVLj;??QF&7Nl)Xu D[WA#r5ns`>?DhC3c+\q` 2lc^G:f'z[{GZ[E^7Lt\ߗM:OJ6w1Wڡ+Ymǎ܀m>)͆0w& jɶ;,in] N K3n''مh\{ֺʆ#0JDrac*6&ṽ^Nayg4${nه0G֧ (5qAh2Gp%-( eյpsIdRchyС 3qy]_m,0{os#'4ف. gA:!;B;QКkkP61 erpBfWrCbY" =  s޾F4}Wlb>(`̑3A{5$M|xD,NR-fʵY|bjٌǰȳԟmcpR{G):V[ס4=ʜj;ɳX7)Kw7*վ;6R7pG"tY@LO͝B8/d-> zSXZf)GnG X`"*=.=ntB2D~{8x7yU)%̛8bNݑhW/[ 1YFPe뜠 mf8cdA&Ф0Ȥ~e _C v\Cs cK :ʑu_+q2 8ê@< nc/ÊIjV>(`6pEɘ4k9_%5d]EH "s{a]tYhva.uxC7Տؓ{'jlը٢[^m 4j qc ر2̣0Uy˗Q;I.[[(-fFk=j*˿}/ܮ@x3&e,wIC6w&BDG9N1:f[C4e[LՊa3!BR/Ӕ NdLfxǠ+YWU3?t ]1ތ0zH6a) "/>>OS9npF7i.W7 =1Iб]ڃME3P(6c0KkA_kD(x(%֙Bx HenVP?&<9\!r%r3oip /51wa\j:Њloٔ5ґ #nvhK'ns"/5Ό_ifAu 6E)`܈W$'vVap'9E4<43\L/}ň>}#o-EL<C B{xO0azcmrO&یv ;Aϧ $.){@j{w-.s H7A4wű-Eb#ld@oU͝D3N8=D=GsuOw(=t$/=e!2iHH RSH12P?˩taFY в7xgLڸ1x.Z$>VT&3B˞hѩ9h20eju Y}}88a7;#* eErPՅܓU+w=6z%xgʼ6aU|!Cy5p5 3J"^ XӍ( j j/ҖS6i!B@!{SDo#G*Oָxප~;NoK `Z\+ #a) ޓbI]4J#H|K7pglyeY1i[V١I#ѥ$&)$R~SMߡe*dI4TIn 5@÷mQsY~/ꀈ;u|QEԫ,?@$[ pw0RYe4bfJ|CF%)>@I!RWb@#mSx d şD&Qǔ ~-lWjú[G}ދ uR=b e>5%Y[Rg $XO|w϶>-Ҍ~Q=2ɠ\Wmțs} Q+ ^/|?A|=QMR Th"[hXAmRkgb]y;[ m彈5ߺ\W]^{iq1Zǽ#aePIbBs:ᬵ{1J=9ܨ!?9gRe5r) ו4_YdTz5¢<†|&0=5o( oK'z^)gH?H|k5$CNΥ6H05ݸnJi*J%"iX=PrszXQ/}S7q4Cz^fɶGLIVU/|@jVg&1ᄒW"Zg5St~]شļZՂn4vBϘNZdٌ-?* [fLBǟbҥ;ǂPۢ.?.0Ml:"hWJkڻ\vQ΅@piS\Z?zT_iס<7 e)eLЮW(CeQlߔڒ9p.-VYM40uKj+Ug(13`Q#7uC}gW˂08PFb<ZNiɡ pJ|*דY机0%<ʽW/sa Ȝ7IV 1? D5ߺ}<3忓/M!aK8K^N⅋Q:!7ZPH ƂsEVIWx2"Gy:R3^ 9֙1Ȼ]ŭ]CC~{؋cW*Zezh\pL=bڝ{8 8?i}Q ?j!*t!CcRizTyHяX;W>7ݥΩ+Kʷs,eMjHG[qOGh덋 Y |UoCݶA/rhVGnPׇ%3ݾ$XWt _aVRT8JDꋤ;ܐL?[N]S]U(^D&8P9<.ʾY2X15Ȟbiⷳ>[91JKYob[U"2"Y96WqLbN/%}ExF`TGPdU#B eZ6.uW|6[a4)Et >9";MCQߪt(.RdDžy#&>n7 rG©}~UzyG|2Sڐ02<=~@@yGdJَ3mPtfj:kMv4"n_ ~EP+R P=6e<"}fŗ|}DE'3~dIq䏡%ǟضj>*NktWZR@שv,/,'P@{|{,G"|Nmey"8Y' O/qeAϫrrua'lrwFߊP7Zs*jЂ!FWq>(Ga-gDY;أ }i;߁ |W6>&#W)BPxVʔoN@ُ(&|kZ4|\T+VI :NDH˚K+]vDm|ڕ äʅu jfy:CKAal"ecͤ@/M> P bҠ݈u O>r/:&W)k ,- &StAix,_:BL28j.,ؐ,^P K;ϤyɅbvP֔©lTz$9CDxس+ T l ԍSӢT:in@|1}B>y.IC/\&Rׇ#wݏs5Qz.A?NJ҄+x6!]]z7Y:@l xX1  횩Gx;hAJـ*HbY'F.=E ?⌣ ]22 mYjRiOdeRX_G@>oSC I?'YJ}m^(0o;Ji4=jL4Zg"ڎXKd E%؍MO{-I^Sr8~N~]K:ν%tw$g "3]/C|D $j ?~_r}U՗߮:?XtX!/HRRDz-tJc76AY8}l~ V_ET!. &ڝ`n}ψX2OMOQ\>!2Hx{W_v3zlW?*ڹ MN'ur>a T!@1q*MG3|t%L#3Dt4Pe6KTkYh+8EyAwI,ٗlUgli7gd[eYPyos M;^UERk% {-W|dAPb% jL^|²GQADԑQ [Q\& R~$sMb`Sͥ*b1E@<ןu'-5? ꛵Op@)%wdbc|GquVTD=w/tuS˘&HN M4<(.WuYkj ~ҴJѶ! FDc3R>X[=UJS95Ǭ2jS`żYk{xqߥ5Jp&=tmqqߐRI#֦Ap@Zcz _`1q Am49@K|.S_0W?V~DcRΨyG[kri5SD [Q=_Cj )o2Un:6sVW47Q ^'f"4ۗGmc˗Hci$@.. ϡ誫E`6P|z$5W-7nM;R,jE/PdtrRHr$w+d`U95B^)<|f6H"1rZױ'|-Owj 0 !٣#:tUFUO-NRkX j,ВX`(jUܳKi7hw`Sk:ke҂k]]?5 X׌B]Ԙխ֖L@i3NT # 'C6#څX[^^ʃTsp🨣>ztpr<*ȃ*y><ۂV uv=0EĎ Zd49@c|1Ys}CB:yg>ܰpS '{=Fʶbe$]':' e7qAك3<[{}#?,Uu m +c̠Ha|5]l  ^I/!'cHBԱ9r? blNù6=^ Xb]e \t- a2|֏y#fg7 oHH쫼dofDg`ET'b)釘ھ'G:f'z[{GZ[EDH&fûX|}Ct̐|b\o %bCZld SЦ@DKZrA؃u,,Θ>nN5Fv$qn ?NR:u]y }_zn||ldqDRcZm4Yi)x׀Z"-$#DWaMMɞB SkJ5ٰ@HFT!ij|+_V 4kAw4ee4n EcҟRhOJ5wׂDghm#8r÷Ď&2 ?KǕ aa}3'H͊Rdsg##Ñ|/7PPdG=5sӿ,pd763ңrB:L=v>L|(!-h!һP OJE%W=HQ 0b:=5IO! "Cnj\M%a ]]ЇE"}<$wzXvnCT#a9B=f %CdyTݫ%nmE Mܮy#-h|?V֙c}cx[{s܇qҹ'2.+x SqM7l91eF3$%_uqm^GQ/[a/q>ND?-gǴUh^Gݔ nGvˆIDcW(M8"Ct>m@BjG7-S:< @[69 @}dZz3ޟ8l`qm7|o 4D-ռPS@v5h\ ٔ&6Tp۵K.r,X@ C W%|y$cX/=;in\(Џ5㩬٠/cpj<\ʚ$q:25{ ~mL SH)grf+qj[nT$Lhˌ[icM>yjiU;DHUXW&iS_X?v7#-О.rF E Єx)!8ܦoBDv36ԎjF\&#';崇}:Ը>Y4fv޸.sdU%FVBcq| $}͘|pٌ4SL /0#JbNAWAoi!yÀ'te#Zd%ҍez\A aÈ<`%8r// Cy?!Hpuhv7UH-mN5vq:oO=12|ȸ1@.q+\^8K{򜮎2 R{aX5B=wLGaʮ!@wcw%' {XU#ߥcX[H dU 6{^?q4AO}.kV!I'.s[X>&Ym/SFւ^݃0l-gU!'f4@l}krY`MD""k"I j}Rd<Ӑ&q2KӅzB ѺFʗ~ 'D@ <أ-ZĹhPq"G Gt vo\.Vª=f%T>qѕGMf|_52 pǼ8 ^ <oCWjIAfwOJ(Rzv|R(؈phGf0NgkM@DwqؗfH&Udv.S8+/E&MɛqJ-dj[syI#UIͱ`]^Hױb` N;.:vY61?8oI->0ُ^bZr.=ôb0ʞ;><S˿=/V$S͔u]i$Ѡ??JphL<L nJ]GA$5-֠Pu.vH5j1%4%q,>#e?B2 h|%5zf# 񡹨tUb n Va@8W }dC@6+گwg+XS6V!_ip4{޹P(H+R%)YyQC+oAHJȍNaN(9Sy{>Aנ9/ñj x,|* rJY7W/sTh[M G;jgĔ'[ Q"};Rʹ<QIQb* }m9{҃ ЈIPiSDc! l[vwjS <# y+9$e큳OΔ4 nޏ4ˇ<îGA`/9d^PZܾ}ݶ]Izv5]arm%,GZ*TBL;V=!fr1t160c(%`:n~z_.9NU"ʧ! с/L\ys.f *4LnyF~%VkC]I2?k\q7nt?'g$xS07oX^ʈ^^4}Xv9_.Wg%}shzKh@"uӏ^D Ң|YHY1[^afҘNZV.[ToSJ _iCDo*M$$Jݣ69`]}EnSʥ22Ss$D!8OXgulML@PL ($.a@堸#̈Rm3 ՕXidO,^WZXB1T){4^sݍ\M&Acb(E}4ɫ2 :IY,`FpM!'CDĻ^~h)c ^"MUЂA3ML;Hʨ4k J"ͱb=!JʛON \lm+gnQam߲Mc:4MPEǛ۝-sƟ3:˻1 U`nĿG`Lֈ!!5/v-n(@P >Ej'B{Y8 N\uȐ>\..GHʮ8+_Xب/Λ,xO7x^趘nK ef]=2~XM՝4p%i%N՛C\LF2$B<OLћʪ 'CDq-JFrCl\xmC}@\;Ҙ]˗49$7Iz\ԤkHH  [(M"xxbx%#uG)З3 HhnQP[2jɭ- 3+}, ߪgDDw912bOZB{+l``;p8łYXN*Hαwa;DOx?rHi֠`\g8'gCۦE\ T~E1Q׼S#Ig2/ƻo_!Ѐ`z&+Czgܭ~,w/b_瘪r豂bMm2P!d ߥ 5;T{d5nTt}dǁԭ e5޻d3chx\}?ZpM.ZHV뛋vYYPsjzھn ^_ 鮋ߎ'ʁ_VA_5F@8[ 5qX ЇS87\[v$Cw7O'8j!vMz kT:?BҊ1Y/6vZeҊ#-xgVSt@E|qV 4&@ѧIAJY Scj ԭ.ܷqPƯİ ӼEOvjvEz*+^v8xA T |HY:\MD %wd`I4=SG(d! kĥz*`K dtQ, x38aC*ƦW[|HgzyI!ZD P){381)x-({ZLRiireBѯU&!=B͞Et[Z.fʪZIgEk!2uM"w㾒 9$B'^@„"X/e#U, _kQvf+ XT %u4=l.Gaij;eDcEF.eW/*ITU;)[717Nwmk<M|ʲ  FAmNɼ̾M;cύqM6-[Mz[B|@1-WNXNd75tHzߠGb},8J364fGtSiϻ`-?k7RM$m$f) c&̆=aD:2X\~rZ3K18`v2ӐcݻT꺼jVT't4/ !cúkH7PX5}fJ-LzԻ HFY$>5vѳm6& AP&45sc{&ȗIUP:$(Ua| 'ZBhׯ11I-qB}&&$'7%"fhrz'st}gKtD-Y@9OC nv;w:+x2jdVR">'zJŒk.׆^o${1(}L -D_oOQ1A;e]k:㨑<48a|l}6sMjBdNh+S'߯U`ñEk0"-֮?Y svh*xlwL,5)̒A'g)^l\X4靘~\j![+gk4{|;h>F*^| exQy'ӕ&~W@,0_V/FH LVup^\pu]-pw+it?NN,tQ"{.t{LomǭNFY4lQ2Ѷ&iߥUR^GOϜR=S# oSR0egk.ԑk-m i8D+i@+ZYK2r5R5t jOUyKx huɴ"9b-qu!zQcήx7'Fݾ?8`\KS%%Ħd4/e_XTdIۈ^rpH}gM?mOKQVCh! g*$L 4㒍mȳmO$^Պ,UܤM[))Ȋ [6 .B ȃ44M V6 gBl qw2i^58tB快Zo֨ .󼏊 QJUdڙ3ːC6kpuFvg'i:pN~<hi ᡌxUֹ՜lj^Aƪ wWm.Yz%~ |PIݡpę ,m}:?. hTC*dB?rڍWbFS xN-{)yQ]f/_mZ%#⾜ֲ1/1^\ \O,&ބh}QbV/@`l:42:m['LGן-2Op xi2EɅķq cB! n V,[+EF XPkmfyE?25O=ZRE%):kR ԅhoױ(f 7B1RSH16{Pۣ[Q.?6nKu2=O>ڢz=xۈdk9Q_ZA_9\+!J7YVC^aXA$Wru%0grUw-TaY'1ځ 6 iԯ/eKGǭyb;Wfzmӯ |tIm?0"`8KPyl)owMiZDRvRETRMLRJ>;%a2P'8Dy Ղ>}!h,^K]&9d ۍa3?'9\# Q#@Z4~ߝo=od`:"y8Nf~?cl{?EYp05%m_oc@ouN !!m &l":4̥AcA(8E%-8^6gZI(]ԃI`8*soMac. މڝ1XTDs@i/ "_!"J+,u{_vkF2 Y~NP=֕iZ\aqDQa;Ѭ#ߵIXs>PUKcA*K\msF8#Ŷw3*6U${l+@|^H?*x_XFTbTF%ܞ{tC^ 4.a,h7ܝ4]Q I緬HΛ :9_BǘjLl4|^If ;qNRΩOFq\))^vQ>F$FWs ]kNU !Gـt%/L4';u^Uv ASuwgoN¹@@] nLM_Vcb,#M:9J2UMvmn)Tw1K}d^a$- o$v+UfNXg:7uz]cო$ Ҿ]׬dӏ`;MǍr?oFo"A{1KCK3om[1mz?.##^y|^6ZSiM{8p%M# ʗw6<Ӄj(+Kx5#u/['T}1z c  ʦp'6yBo : H[dR0ðC`1M"qiCwt߮< =s)#g`_ 36X>IQ`+7( LLѻwD(JK#X9"dq~yv&IzNCd"+aU c5J7/;51l%kgV`|o'U< ~Tᎎ ]pr kOJIXb㲎0:ik"bm-vRLtkZǢ4NL*zRYW<XۯeWjwtWau@&|>@6SAh࿺['ho=R9c>P9 Rq`eK(_P\dDSq0\j(%T.^j=,${O&+܂V_K`|ܝkL6]wĭʿ,#,^sWtP?M]P kHaVK3CLȝ3PvlTׅ1dWeZ٫TmrA4ķpwr `䐶< ,Ċ@&LK=I?ic09^ jP ftypjp2 jp2 Ojp2hihdrcolr"cdef]jp2cOQ2R \@@HHPHHPHHPHHPHHPd%Created by OpenJPEG version 2.3.1 ] ߅|镼Sbk8쎓ogL/8 d:z f͐,]e&iuz[X~ٿkFc;KO5/+QfU 3Ub}f q .[B kEcR fݭ,mTSuXpٞ.E,v>߅|D#ڨtbSƴtC dJ H.$J B^~T.mH$-;`ilJGqǫO@I s>Ub|#,<ue̻Yh?!Z5ב3 Dhem?!7C/k :mt2߅~|B>+ku7'e~哈@6?!JM"').7ji0i&3U ,1z,zfI?tsJ=~75 As܇?~bB* M WJ@$)d$̏Q:1mv+|I*dXMuqouAQӬe1ob]-UCV_H^^oyyQU%g?{vE6fS&~l&GAϖ6<0^,ڌL6&'i5+-SIh8@x>O4) m2;GwڵxOeBS8JsK2 "i)"z5)!|m3ѷ[QQ4qwqyUd>NR+wHW̩J1 oF|~}bB* M WJ G` >K$Ed^ML^exKRV| =IGo}leTn!wY#taS&7r &I_O3%g?{vE6fS&~xBpEA*{6+бt_퉮OGPҪ%bQ)a1fmDOq3)#ocÃ$5ˑ#y\"i}E)Ҭjd Lr'xD%%OGa1tiN="js$^C4ʵ-{v &1σAkz$rb柲 =${~3vbB* M WJ;q[5/_EHuG31*1;=[`z$\TX K { Ң)-aHY.dp;'݌9ʂR$n&QF̕}E&\S>"Tly^&86̐.jVEj@X-Z1WW~ݧ 7_@hZ7@/"i}E)-dUw/Lh. 0PTC_h * /}3 Y-[8Sߎh7C͓heHan~];;"xjB}S*g€C<i'CGa^=4~v _*8%RRn\> ~6]xyjGIqPRԖe(_V|$}=հU7ab+# _ 1 KxV7!ιhy16ZgtR7`Ode'xt4$*At R%lWrdcU_:g!NNWlu-|B!Ъ܄"Pm7rm3b]=PLrXv 6`!v,*0 IoD=j*PH_2QdHO^_~IyQ˲_X᫱klR8x`TJ |t\{!)-p&Nlz!9:4(aw\xd]е$Lydl"L: ڔErA`H9;-|cei-n! ȗE)+M 4aԼ W!'2,MZ#7oC@XMsSj5yL4{ТWe|~VΣ;ϣD>7z6xB-9ƻ2ybJqR ߮]'eCQE#BO8,ylR)!< XinBT61QQQ>ܣLAT@锵|•8ˇUqN9TizԶ[!d_s7|D [< yr' 24֘DdW־% x7#\NNJ Q\DtӪrD&G։a4]*]{c{S_ `?@`Dn! LTx҄}~~QslHEPi=JD(tX3BS[T! wY.*`SRx@s5l̽*Y:("WQtSi@uM~aFJPJ^x2edOQQ)rdFS֣keA7S yᵬz&\br3ʄpf-42 I9Nr=ڥrdZƝxj 5Nf`;QVg9%ה-?/#&DSG6hNTJ Iy"XeBcqWgk핋ܣLAT@jӈvXn1Q2T+ͭe=0xrh?0 %;Z ;Q#xR81(ʨA"ne@ .jY8& }93Z\݉<>zuGo^&2I_:#-AaLkRITG#΄u4ewo`h(ƫ Ƣk0bf݁IL4rU6I87{-v-YΫ$H Pֳas;_0rlV!0M ?$8🂐p}'݅Aϰe1fX zL 8ڼMlMQZ`XfruЕo (#tDfdlW9ZO(%mLSsaiμ,Oc(xiI(_Tc3Hl '-6n8~9[}PUߞC*^\3Lr3B1C{h2ՇIQW#p!S擯/u{Z׿1%L] >lLޅX$мҾ:7 ƺk=>/ IF#u-! pr~hr0-GPjlR8x`ΦEOG`>ǫ\hfyy6 <;H-Y"Ͽ\M:cӖ%+Қs,}c^OCMb3bZHnAFOQEa%/NYpW;4(K1I[uT?zMz t(g70JO Wn`ǴMs oZiZ>c\&| R6| iAh :s@/Úu _>hd/tt*vfڇ?z*~ƞR)/gl" iDv/ a`!D^lJ D hD7͒&ĝZ+e,x( Ϙy{w;桍<?>Ĭ].x$뮖-Gr@(-)4IR=V֟gui6x}4AkW6y 2;^-ae|Cv5uЕӴE0:B_6\0dy={zXMaf_Ҙ;㬖ㅥDykDU 9C4385DAŒ~Pr2JJڭ񢸻jV#poM1"U*@:Jr#.BTÛ;tD"_SwSV)˙Фh.۾ 5D'CgSC2@gW(Yc2Vց+AR#_"n  $Niio.Oz1Ш5Aܔht( ж 7UR-|"eKA.`gsBUG8,nx*Lxu,w Ֆ52y}x?3*{ Z12~ZOV7M BոP]I~=LBUpGƱUSK:2%0blØjr fOR2v6i7:R hεI8vKӯhWbs"CD|#\3M>U:'%̗PM#oS;CImC^\2s_3M3de`ڑu:/m{u(`f -;Z9zp$s^ȈN_*,&½9lV2 QBG>n>"vٱR:aryk&!;:u.'̓"@80~R&]̷]-ړDh(IyŵsxGG asו ESh7NGVj̰[ТgͯJvxh,h;4nA(P@b;] u>ǼmP:d_;n&Ńz1=5p1{iEK֊A7%Ftؒ;c_\/uNCԜoGwHc}0 ~*v!1KNhn+ _eP1>HD㿓Ԗ˼nX<0*{GUWr_tK,5|K""@-9 Pw|$ucۍ| f{)z#J4TvP)<]m]X4cQ_欀nrq~@fU.wT`ݵ{F'UYL'ˌǗ٢ʽ]G%h0'p7>ٟm;E: Źwۣ+IwFp&!`;N*2ƫ:mu2o,hNԋףҥi ;-AJUff!GrIV+qБtӂ쾫*5 Kjn$AǠz{ )8"V!Mמ#X^CAm8 "~DAF1"Qd)sZrA M40I.ꪞ3S5źw^ϛM bܵ!0Wh.-/ȓT%ņ(#vB'ᷳtr!>S .)N[Kin$NQȶ(3?ҬKuMw߲aL ]>u N^X1׳#Z^ZJ;󮙬RLR'+mU i>3NgܝI *D4kiYR'Z,3'w*;ڻXiG=e\:Ų/|ð<ufwܠ k$d+YI:3Dxs-3Ԡr+0q^ F1u)R|>uH ~\=QP$?$ʚ,hzH?V. Tے&NTJz91Y(vci- N$>i`۽KKF> yto$յek8u2O)"΢YYt2'm!vcn9ED~^c[:L 0C2zTȑO¤|ZcR] :(DN,l㑷z>'bU1fkŗ8q$<.X;@-:LFVFjZv3GHtY˅ "볃\mc?`NGƓ dEvʖwvj@Ɵ1_^qGN\Z #uo[@M` *1DH6rtcyPrӝ㗊@ib|wT_htxe|/,q%6~EX( 'S-9s0U =㷄ۈP"-8.ǖa4.nydRtУL!UTk}IeX ާ׬x)#H=%6V*;z>h.⟤q^cΉAvl,T>JXV&mvkKe93Cq$Uߡ~by'aGԻE 1ms3nrF4R5хaZi9#9= M:!3e+spS#T5n5THF_,Bx6zfh)a6b5\c-liIIA`9?,"zLob+ƀc6oX#|Տ4>a\4<KPW<+,{h+ȏ)JWDGWDόU/ϻ,ΰk:ul`=RJ )Ld.0ƒC4<%ߔNVcA ˊq4Wx'dU6mvVpbbX"APynj-Չ jy'>(,.i˶Lc+n'(a͝upбf3Ԭxc A-}U nJE!\c;,jw, Z*A¾{I(E>! dtc|rH͆S'NiPK_Rqbqvy u diiJN+ 2۶> P6XW2gDSznp]`Q(,kPlCr ٨n8XG7# %+nԛqYKA xAWbw]@9 AGΌ"w/UH*ƅ6=4|aǥLZEqR~gǑ3bK.G[萝D1Wi_p_׌NZTg93eJ`B#t"lAљ63 H*Ψ{e 5ar7 T s3Z'DĠC@3dn8y,2{QEf}/ vl ~Z bҮJQ _>hwZ鄇dxRCGaېO-v{̜_3d9 XaxS_Fc,Mk! :<;$ 3vLI[Qr3I0&giF!oWYH7xㄱ-Rڼ%иȤbɆ7<}J2yHV؅J>! g-{ޖY@zFwv0{0/ߌT{:,F*ɲA34ԨQ{t}:OmL z2 ~|GYE4B |tiՇ{6}BpťMj Jp?w7Nl!v`g. 'L5*BII%eLfOcU3dVAy˅rkYE+V&cu?D:j%m[i1hpy#Z%պyǣV!qr='}8XU(.,u`LVťԓ{h}s!Q˒5o򙂆:ҟbW@qrza #?hcmWgB k1gH^-dUqK<,]/S WI){# .nk[cc0JJVNwvQ"lն?FUΥ1M@{HxՁxɁ0Hz5 wVnP 4}jp~͕:~8kޱn1٬ sSz&$V\a&3nrF4R5хaZi9!91$svIcW!^6K*5, xʼnI \LdVVlpΘY i~,N+,쌏pVZp.7~N0]:~L+tZGx~3@Y_z+1ngJH166DM+1Q!;7 %UJ9lz`z.YTd]/ ,`Hv1w!ä φ{Pd&A1Xmbߋ[X%Kd&oH0nmr}W_M_W͜5.nejs'As:xrժl#bMvvTFF]2T? iΛ@Us\"#!F~Vs /p?﷩$80U2i냂Z?eѝ!5|U;շ5,|TTI^uJ;ϳOo2QB~~&$1 I;ƼZ`U5mGJ0减r}*^hjN<7M>Ӥ0[[x]1C5(4梇Aއwf,kșUXN#].o[K-khS-:f}aam GOpetWUb9obz1}:xuMC)Ѿ-Ln-\hT ='rS(~!J}*&<ًՆ,QRaxhM!fq+D eU$kNh1y\`ջ0ۂ4B-VmiH3 G%f]k{_pih$"8x/^a \27sL{;J)5-_!q(Z>[b_%B5%@'eL0`u5:ϻ+~UAGB.&SSXjrh~$ ܢG֬*lVub#:#7^ɕ#"Jb{/ht ʖ=p:](Kt2V% qSidMB^2zr!7p?cF@Tx`pE(i*n3# ځyNB'/4{~߲x:ýR~~@ͯJvxh)> QljD K":?ב8ދqbR4>ObKeUtU˽7~]H>ݚ̗lLd<\Seo5q? [ +9o2E._ _89B.mX';Ȁk`Ná/ĭ( K%ͩ#* %XoiRbyMxA+.ւ/6މ/46F5Yѽv" Gˢܶ:79y]Z]/*,/CX_hH,|hD )*r< r*œ-w]2N5sz`}щt} :ʨery)]Fpe: rånq I 9%DM01TZ8f4(Yu?7*mv'xO 7Et:oE;g݃2$ k`H'x?#/'c{q@bݭ.܋鸮-"RX˩oPQĿl!P7>JN7E`RFqA<2 @lC\jXlZz{ ?@Rv&K=o1ïD!  J : G3³x dr-wGfvjG,`0^*,+o1 @5>h%V"E]zSx Do3St zb!F_#N(1#rʥw#i~`cl`RLe~ OC0TY%/"3!_YD+8 즉upn=)Vbc+qS%dw.VK٫j9\ᆉ5֏@4/T`G |BLĉB2K<%Jh:ÊQ] v:8q _DK=3%!Qn4$̖.HX';:Od+7y|]0%k"=\$ݬz;))Cb!YJQb52=kDh'~Z4ԉKPzQ^2{̲l% nCϑAغ?e'npn$>{jMPaǨ#44&^Ҕr1r򣵍&B5SK\r9tr9 _3su.+iS* gOK#9:I懇.Jŗ#c֫A?+x]5#y14wjEꂂߐ)1=-n-u0,ws;n`RRI_?͹7S ^l#6'|^n4TVw36 .=6mӡxm hWi7#/>V`axv|`Do֮WБZK-ebf6WfW`3nrF4R5хaZiॅGwB^d?-֤ u P[8LBuÃJ9!:}`r:,9H`ߟ /_^1ho# /dXr}ĿбȆ (=;XijX<}z:V\:Xu p$* Jc P`n ]4ӺFTvy ^ r@ZS"^GJYh`dMl '1:q0S]M+9ִ @rh)v*L"|g.l r"S,_@i }'_a-n|u[^5;ַdV[rh>kj&QPmch]ÕGXl=s3 VH )Nñ?^v2BHD6P ˅83Cֹ=>Ila ?]z[/P0h+؋}N3ro KQ(l5̢fqhs&!C3pQ1hqi0E)r0! jsiI_<@kpqBXU1>R͖d˦}*HTV)6X0Ŕk ȡ(Io' ~z!kO,S44?M;9v? bԊ>d`⽕QeW~I}vOe5^eӾ*VOh]8XFlojk3`SN&P}guRL*?Od/f': EooSU!B;v> :TB'#89O$`fVK^Cx&nݧ*c 7IVJFtXՀR%ڭS81+ 7!6E6 iӆ n&(na#"DQX}04ډdæ~}9a8|kՑ7oUI'P5v|:C"vPnҕfO9]qݏ.h>9d[J"`E9:TL\ ٝÊ7~q:}XYJ;k06Exza $`_rCn*j"$UON'IK Y 2ˎ:D;xM7ҹ5a8dgpahCWuY}YDDULv]ߍ~PfoWj;l'y {\v{}K>Aq+[ь66LL`3TliޱP ! "6n2\@k cw=8ʋĢϠkB_cpSoܗsƸU<5r!nwR[a-7S3p mS}5 V*~ OPlj%G] 2`HYIwlC(a:+ޣ}/ j3ZǍiQ?c{VckNE)hME,[uD 4@ j?*`O<,@_MS&hCc8SX][n 6l]< ɻ$)+ Rk6|:rCOy>7ZoԿq`i?kεW zxBˮJu}7WJ 6Q1-%j |o_HGLwx?,9NÉ'N/V,mZ Y ] N4aT!Z1FPɊZo,>aE$F?3ؓ* x CQUG-ҩ>m8@uf⪞ԺS\=hnߧ.rsQgcasB@Vl{ث}z5V1I5d*gSm|[/-TH+lB7< 9 vjH g2MJ+RxM h&x?~f+G 8*Z *<Bu4wi4I^#T<{AiGujN%y9PeW r+}sL~vi=bK4U\@4+a<2}hzu(%'cxMQgD_ Qɞ)Rñc,d륨+$G^Sپ|AmCQ^9Fpd$4Գ&*V?QCr Q(b_/©-,OD qf0*>,<ඖM1C\r,n&m)ao$ @j2꯺v}81,QѕX,YjB-\GZ^݂P7xEXp׬*R9G7<)ѷM]D[Uѳї/֜SdXOgZݯ9>#;ymJT?=%ʩ4ϭ5Flrme_f/{G\QC)MfGC'`-h&YșҝjԴ=ptLAB= TW t^ mf\?&Jޜn>Pv`d_^eąIKĀ_޵N~α%-nݡh[} |zK?)qqc ZO1=s|<?/w45c6d;5}4[$zZ8O-QW5]`zXsRhH )v2Nۡ卂t`AEX/*jZy% ;$]kޅ*Cn ԅ%l6hsGҽ:7_Y0c.Ծ-pJ0.*0pT1tk zB>Ps9ʊN''r3cbBw]a'jNw"+OKSUmj;!VT:P< D~-%!N˱?*f"\z=6flzo/K[yDBS,Av=s΅9] EUS1XR`^&P$RDDC˨6Piz5}2 G Yh] K] 3dviTǺ!Kt 'ZdPj,V7wtGVaKU>SԟZzDuv4MJt_* %&u6pv.z16B,)!^ .|]\B"3\$k;+ѺeK'q,'"@ʤ4ssgp-;!Ѓ6c_{XˬЂl"ewHbZ3P1{342V Ƨ M]0~&Ə Ee&p Wa)szIo:<\u%x4iAZ)X?^jۢ3tצ\)u]2'hM`=q#%cO@ЎE&`w]6,\H,3Mt;|n=PzqfBS0'_7F ͩ:tjlG RNy7K4t 16Eprո Nb%j+<{D/C)-2qOH`Ue8WW+t,P_y2s#4'+z(a". K` i<Ȉ5gl鳔\Y-W) lgfdPò2]l~]`GJ$ydプzZ89]]58nد ol- 10@%ps)5,M;?g^j 8 rd~<-xu%4 9j&n]Gk)gbd_vfc￸ߨR+ t !1ņ_4J5- %{m.fLcEn4Όa`} v]J}4%ڊ~m7j&ORbYKlL˽rOyaX /j:I ]ԁJ9A [,d@VA] Q 1y~mS7wws{F`ցSMX_r;7~lOl;z=fjUUfUMO;WE+ŊQ'R(%e:_o]JUk&*4.3ȵ~{I9V%Jb큨NBՒpQ:Wx~ڤ`bazgI*W|a~&*}ǴKrKҵ̊t%n7=b >8o}fUAkq:Օr8/𙔒"دT3OĄ=J?%qmEKxN4E}$;ȳkXh9/=#)vP*Rۗv0!$|Mӱ?D9Cpmdh.߼ "Y;y6J'Pq%4Nmg_h}u{zЊX"."NUC[|}m Wzʌr`xo %"tbnhL|ͤgqU$C8'Xa0Ğ2v',S =%QrJ.9#9AŜfSRLzF\h6CƮ݋^iT- KxS ~eoW/hLFq~gWD$Uӻ'_mn΍-5GG~Z=t -"v$F-%]íi h=o`“%ҡ=v{6=6PǛ5c)5 o}X;`,`\5T\j.y`/ N| cmzo/^_-ߙZ} #DSF#paWl$֗ږ.q~u"[e&e݀YS40ַ?zH]0H˒C (FK <{Ck7|K["?`.o4H@u'鏓PzP'(ҙ8Bf\:#v֩FPT c ǷA3FMyRԛq2zՓ-4V|ٽ7q(^Z.YɁqx IwMX~PN[Jzx# 9.dB;5Pl{!P:.ykaʞ=QQ~B4`IHbG'd ~Rd؈QA"tE^$Bd?r]a!>،+y䣿`M@0V#P(Q.9x8ŬXƭ:T|–H$N B=ƺCd /4b>)@]PAÐ !ԙd1h0G8lgyTH35jvlxYOzZ܁D n rB_4S{e(U0KIE$x8Ŭڮnm(sK# mwZ|3M[Zf,s6KxʉW8]"oj}(ǜQ =T-d#^=`D8=&`J-yż h Bh#'*␇2XfWWh?O–zcKpΒJKy+m-n$.A}G4N|N#HHqf<K݊%3K=KhyN~J{'GLPt?DƿО9CQ}?ݦKr`TWd+t#HoE=5Cl J8 Cs|uܾQZ2%kYx)yUォBʹYv|H1҇HXwRd 7)-ϝ*oG)oU9 8Pռ,׿+\`Sم^J#[[4}I4L-n<-[qo_1զ8?Ncj}̪>#'sIo\J%a^H6w9Zho $#DT9 .V>N1ɒy0mלxnxtzhz;rIH/U_x=1H;wӉU1Rٗ=n&K]z^;8Z):0F3) ȈGv=,Sd rm\-UqnΌ͍ڑVG 871?(U %px#==NPJ)F>+BY})]VR>;M|eg0R NQW}pg@|C\^B"אR'ĽSuUH4\eWQiܹ1PӮIƳLٲS) Cf*_rĕ X2ٜ.ce`9?3*\gv%=Ib %Ňq'n԰={fx iײDWQX9hT>B d@jCL oU9.JI(@q&thpQ ⹣MNw Г $ l+y'|yE*#u±:K>7DI9'PVd$cjDVt< -NΏKyliwi`hkXa y 2EmƢ R"믷 %+qTtsu Y.<&zl+JBӄ\8$.Su'W8+HL2ώ5x<N~wѻ"Ѐxn~sfJhve!gVo86:]G*]< \˻Cdb͞>ɷ&q0ؗqO瞍`v']>7 Ze.lk BD)! (R0>Kԩ<c,57ptffo5U>"Ǽ UA愆>OW[-~RYgfbBv?E[@jd[dg H;5N 9*ά)o<"G' :Aj?{:SoIt1* p)A{qҽs&)ltъ"nWs/'TxE>5|J};ٺ[bs.pvygu=M#<xGs;I!Xw.cV3WVpnL1M.J0]U&$=8IT#c'֛+J!Zhvs*6#18ڤPQVGʳ6hV4):}G!<~4 (z" Fiߜ6u!x-z,Y|OVkȄabgؖ|'C\(L za# pQ_XPMFnzb|D?"4]  q^U'ڏyk?,*F 5Mj31s1üfYm.$"mU2j51ne’9-:r9/vHQx[bP]7upʙi&;>J/0P8,5C5^Ӝ\]iyNcsDm+X(^">9ayCn3=.q徱Z8gQN&*:UW^?\.)bda3vyR6P_-]xqL=@Q'C}2^W d=/goR_h/ 7o!We]aj_#6jUw(ڣ|}KJ1MɆˋhP ˇŔ޽cIp.ܘjcDE>?Ǵ*.aC#p7ӜB-U')6uXUv0HW)ꁦm+n5w7\SޣOwUIـg**Ry̢Ji7BKH^T"j];qwC>ryhcn+ϙ+=SɜBk9bff>DQظڛ8`%izG+a[Z8?bŀ=6Brxmllӣ(qE|Ù47 NG@'qYR{)QZk eqE9pX]nD6/^qJ_5A bA7Y+nnTXS }HkoP#Zu#8TtjғNFk2zך)+]8H԰e=Gl{>1&HB< kw,J`%hKoVDZ=}{MPVbVk|`˩5g](3<%M?4NڑQ @_Rn\o=|/whԒ@IӖυLN G3P뎘vU^iNYlslq1RՀ5 `Vs4AJkǤbQvc.ƨ#.6Z3(oF<蛗# J I3WGZdФޑi0)5T\uH=v楲5F~5Wny7..D.hBCh iܰ@Il1.r܍j ^L2Sс}Y DOl4Uʘgyׇ-X!|<`zI2s) }ىT0I-f224!y>Lwi<>n ~gY瞒zݤ9G,%FA4 TaP}ު fU}\Vb<ôrd7W:;\^F gɛǹ@s5yYo4vSL=Ug㱩yv%y &l 3K bG3,-w~r-oNֿy Z E\0a>ۖm)VZmT9+ ęb3h" ^'L󳮕Ehsy]0ds[(m+-=Қw3:g2N7PY/h)5{`I=$~Y׎ewUQR ЋͥKExToYV#{P"bvg{T=< oqL1NYpx: $żZw64DzŮfFpp3c +KIrbRkd2OKWp' 18ٳr\0@>dvâNi3-VW*[/2>NgWSZ ʢjlG~qqcm:up^u#HjZ(FT3L4c!B%>ĒRjް(Mxkj)ۖ\3Il6;fYZF)9 K3ީ^Gz~ҧ&t z?bon[>v4F=9(%'cxMQgD_ QG#+!Sxak"jLQC|dͫQ\+T^ƷwQcACa&NxQ6X`,܆#^yOMG((QX9d46S'֘3>vEߕb8cxgn ϖ ߵaf '2Β/?ȇ42D`f?1Z შï#dXb@~)#ĽcPPV`:R-^r7*8c`\c.N~d859q0VWWEi1Y?FŊ]dA=5!=*+}~"ؔJ3lAӸ jϏ:(dok~)l\n}U-1<߲HΞJh:p i@шݤ^c(@ Ƴe{;HK %ޣLZU)2ّlnĢe"^?A =@JHxRE)>eHK{t%ynο뙮eNiG"iq]Rb(vfLf1tIi*嵔ZPLAρPWTz>1;zz`C9Kf%<%ǁ,p6N?V܁z¼wĨŎ{m  &s[qުQmRt"oH%Nׁ"p~vukxa@'&w3NBAX%*$ǾuEYKtp(`VȐ5e[(Wdm'9pKr_Fe8pפq,cZ^ϣǺA%|%ÞjZqx\ex\j%r(\ bM7I#EMPOmzoaTsbmTY^\1l6%Ir+a .6{_ *\q_ֶ'HrZ@TS7GB* ;ſG o6dzsĦf&DcPwSn}+~<]Q!TB a:^ T4-|?xk}q@kV oR'٫:dy؃v$]1ӆF%ZS繗u%Ppᄳƒ3onӹo3OnF2j)#[F=YJ׎!#`gue~(YJCvkcm~$ H#YPw.'u؅wxF*MG;fi#о2XyT1x,kuk6A+(!m[Vii l/LpptRcu)lg>7'O87J^fm#KYf o`2:&4/Q׳u=>*Y7Y[[Kb?Gt &DG1vOfJ}A *wY4 o)~ro&p@@%Fu@Ml}9 D~-c+ ? r ama4-j="Ήu[o'?"ں7?}%OIZr (?$Dvud[Ћ*:T-z3 ࡯J/Hph/Ĥ"IRˮ#%K(<ݓr >Qu?u2Z4O1y|N';7Q` , .W?Y'{-:e_J䤔rēJP*vB}avbҫ,56cBo;ǩԲ 8|mN0SWV)1v q(]txC0 v'ߕL!QN~w?E" ov;E |keV&^m?s;P3Z˓QM('Ӆ$ 8NGשʹЋ]_.&3S@]a(&ŐZŚ48u*Wqca dfPCZ?2\RTvo;Xm7vT9`dmaL9ຽ)J?i)ӡQX J$HK N\D9$G9=#)vP*Rۗv0!$|M] d08;J+Œ9ƣ(1Ticxs>_c W&ޭS2)tv@R,7@/;G`=`^f̐JwfƼT%e zJ7.3NYVmg~+bB' :L #:x[S..> !F+i]Fz XQ^!=S D3-ڋ4N|Ƭ\g">+2g%{U%=Ϳ"A6-RHXN 3r}aAEvx)Ks;a~׀WhVjN>. y%6ѪfjM1N30Q^HGE7G!Gy]yT Kl\snyk 7}}:hlC7n ~rIܼ/na¾MKirYtb;Q緣-0"! {a)wt#;6W^E[A%D˵0]?"7fd^i[A4210swO>?w='r$4Z4,Z~ֹ[J֮6 4uo2L;KVv,% l[kegy7t >29Q7O#dPكk#9 N/_?ȉe%\M\om~:vv%Z !"*^O'}mcnPzr*)m3s BL"J>!)A+g<߀J@޸Ug}۱ǺIVwnRI ~^rMHzCk&a}h? $rTLn~7}CG`.J]-AH6n&Ae㸨9>0v=N7~Tq/XkrFnX$E5W>kE~)% ZFOyhьVx6Mn"V g2Zho !"&QhT?HyT}8-%vZRp2y#=yoBХ} ,@C280{r, '{7j.Qv% gƫR7jMSM(fe뇰Lk.v&r8q?k;8ڹo6>Q%Wȍv|wKbMu;ŬMZ̀FYn|, J?{cD X(g8D>IH/U_x=1H;wӉU1Rٗ=n&K]z^;8Z):0Fh OM>N/&Cg*bъ-:s ser1i+X!YSMh>AqSHr=p Wm$CLD@4Fa,we8`S pcBvAE:X]2't6|ғT|5Pw.scPlxW/0$B[p7(|h+M1}v_&eT!E;&ǿ众IR.M26Lw_hs׈.Vaq}RYgӋaerY@w{!`U@JNk ABЎ|0- [+ 3@X[|/G-r6 zH"*Hylu3H/E YڡsG(6^-,tѤݔVobw_i 7*yCٮ^ WU 6I*[ۊwK ηjC]9+ I5O$PF!bq<N(.SLrw:s=@O&zn+gc8|җu{x@ڵtMOy/6 nK[ԁ}l7 1{K6g*alX")]yPLiif=_GOl_h9J$Ay+>h(랒ͥsrVI,}2ֲqֆGRy"{ZI˩ՐpQp-nB` v.ǽJr-:44,יCy;, l  ~t0Ns|i`8.bMv]p,!jZ Ls{+ni,fZJWniuǒhNqRb"?U?ї1g(r%M}sphI ޖLAPZ =}E}aC*!﵇P K<öm6+ o_v&h_%LwژE7(#ԦP)z_Oe53(9ҍQƗRY>/Z1'hX;$wNhd~]!t f%h-gÙ*B c'e;G5gH҃]BԮz#h ThD}}o}-PPgNWΫndr2ȔuJ4#fqO /N! S-"ۖʊrm<D%lrȈHn]ak)>X N7orUCE&nL7qt v$b\$Gt]4X"ePg<&hs@= 2)餴ddxz1RT[$Y`FjImJYic mFR5⪢7WY*NoBjm9* op`R({,[-+e+WWfWɃڝjׄZ*θh V',3D =U넣EB9ʣ[2 ?"n֓V`X[v Q}Z੩f!32LlwY$ DG\ 4!0ܳ ȹQ1 TEaO_=sN$fGLtR?CZ%@j3 ё[9 XhG 6L{YJ՗󹒗Ճcm hQd%5Ihl^6̎d\R]6o g._E}f1R/{k\ 6Et?M2wWUQ"2Q%|ggM(N/#r̅Mp4X5tXeŭ8)k0a'/p¼$1EN 9 ȂGNI· X @p}KhAUGU*q+MP2r򒖝摟vm<O\QۈC3a˃#$,\p!F0J@wsZpVu8s oP/Ho'QvE/JQ(ؘPn[ցfځ &/[Ѯlʯ~ eyDQ\49~‹+El/8 i[2Fvr͐Q"igpκ##*o32ra Ǘ .~M"ppRgWF8.t{F{|ru!`0sQn1.ęh P'~øǤ@`t'9 $bʼnx x~D4^@=ZvPSe}8uJBkiCvٗz %xZu'BgDf+wD"+ OeC<>.nnpRffs4t!x|m?5,fz4iUF BQVC:~ Ft@u ~6$w |@~MT@EdGZA:߄`?镮ӣ%tsW44ll&=L-1#>n xRJUƎpm⨿Y(%aaהf+(vO⃨ Ct(&EZ|R8>&eYa?>^`fZ6|2Z!I8*4JmJX}<0ňOԇi&l(<9hx4m|,T)TU\7=32k*G#֧Ղ\Zda>#UMg0 !Cޒp`-%v(4U|kBb[UqE+#5q4,e^+A9 ^'f"`q[J\72*&Z__pe*KW4Er' }EK9@4Q38Jh([B}Zq4B6_L:JiH'2 OF)tsVrj B84ս2zՐ)/Ñc>֨kcf[-n_׆lmCӠ(%'cAeRNy#2yAL*Y@ke@C`+ަL2a J%`vZ97sʼA Rs3F@6D>8NM<pQ?;h uӜq< jWwzɮ`e5 ӝ„j}9l5W?ӎ`eFMzh6Q"+֙ax?/qhKńpiˆv I紾MqsDG=UT&]0%[($`ZGl6pEܕr‹Z K5\,6Ut{#k= ` r ]Ԛn,俧==-&#Nom @8YAJh ^^x2"Ip>2P5bo&sqVr̉+e䦋e% Ƥ mw# ojUZY'(Dt>䅶1J vﷴFKZ 2.QSՔeW6+gCLJPC{دkY|Mckq{ZHĶٝL9ҥCR߂D8kl5[T=j9&L@J9TLWP~~ܸr/Ð|+bV%p"hl­S0rBH˗HM*=,,u0?ݑ5AμazN$@^rb'!SG.b3}\*]qd9ߌ+K'SfFϣX(B"E((Ұ: O-G*<=f߳1兲şPz< qb˝B.Wp.xa \E}Rodٝ8&r7o*J16WלD6sbb8PLtEHyو1>eo`(/G3Pߤ0E58+G^''$OE*Fs *w?\j8Fm R z^LS"أ Tø(-y 0\kx|"'UO6L<5%ɗAAKj;FwH?SEtolSgaSq!jHu.{bu'/69 q;i$5k, Ѱ^Rҙa0! Es{꼟3i8A!fq{<to6JE_A,y%StS'ACk3-M!'JMUZ<.-4=xt?I q*=W /m Qsx֤|{' Ш |C#m@tW`65rY M~QmBC`S"A{擟+P^tLC&?Qz F I\%_dc);/)(v_MA_;Lv&ԍAJsH򠏤W.tJw'fghi"sdE /ϋ_}'g9iA8OU/Ү{D5hOsx^jE^jh:_0A*'b^ᨻax՟΄tUH+|2C7kp!o<ƄC&"9X)FI SOcO9HSެLmXF$(i8?=#)vP*Rۗv0!$pk YķU<<rσ;aen]nN]uyY`53{- AeFfoMDl&^WOOpT}#JbY1}֏L" Cف~Mz3lY+1ibfĖi}~ްATx35?OW;Zb,9 #N S!+O%@ӧT6e۩e/w|֖j̸l)v pm9,(v:CWb_9uE俏7iFezy}>I8( 堩I wɮj{#n (5y5кZv1bQKeY$`$]{_dĮ?Ĵ5mZ}M>ϝ, RQΤz! 4Qy] _k,ڽlS7A6#7a|9-Np9+VM˒kDYgl/:⶗s{6Z\!2 ڱf׸ C+(,ye˸0:;#=add"]셿 !v qw9ע_EL&A FY˕8)g/:9Ȭ_kݦ͍E$%3 %d,mV#P$0ٽ!de_W;Ɇy:_+~j0)dZ<CMl`sx<heEDe`XNop'aջ|L˰)E"5Z93"_/);8f>Ŭ [%eD'h I[uAZbg|p=955[]oh-^͇_}^q\SMb5XϭM,Ky FV*r\I[B/!_%-Lq4z-?ܾBd- ->^bԦ!7K\y ,J5M.Gnl)#_G).0 5$*4x`(F5\ʷWֵE?pr'dRXw"<OT ʨaoRpi`]R#Sgg3I{C3sG.tULA;U '2|`$%e(њPY0-u3I@?p.y!\1:@.B+חiuek0n<6Eʳ}:˃  jVI~pXpQf l$ O$k;(źt!ܿ?{cD X(g8D>IH/U_x=1H;wӉU1Rٗ=n&K]z^;8Z):0Fh Vg{_&0 &\Z;I CD ɤnI=J lBn&+i:Cpg,AZw&Sܭ[frݹO,e/CeU?v5Ϭ\/zܓ+bϬzʡb 촽;Pj 5/DgOXӴ&PX NdNݢB 6YO,2J\AjgcVJp휢#LeT|a_ 1`HlBagi- 䅣LJ`JAYJN14r$\E$ueR9(Wvܚqբm0m|A[M`)ꄎByMאG,1# Vf#!?Pa"2c!$@|j1dyIb,q!3U‹W1:H*vۯ37$^oCN^#o6d1U=>q;JeUS j(I!S]8-`@!d!URɹLdz1%2;S;RPܼYReBepnr &W͕;pj˗SEb'rRH#gH^Sv֋YxT SA wA..* [;sKb.BʞNl"L*}KǯW]RQm`E9,{YEpM<*碂:r3{}U:3_R~S?ء(֤'hS%K,1U+z5xH KHIW]Z!UrgSYұ۳ 3}s jүwa  C5 E GQ#5w EC+@X:7uA ~cͦU |{9]OWU:uv/8UѮY,5q½?/z^@$z1oS~u6>+#XBވ}{ $l,qhb )rrJJ"1nUzHS /3buG@"86-{""oU JTN9J][^<>YK_'-y8s'f_ܗίl.Big[{17\ ,D͒sABy3#(};Ů8$m6êGĀV䤣όヅ䄬*qc̹N>@C΀! Dq)2'We :^{pf|N7K{m${\.&YGX r%Rry1pLTXSnkS0E;fgv--/QW8F`pD_CW衰ClȯijvTϏ/ݼY>O,QdžnؓMZNO:mN[vg(~Ϭ}'eavQx1G5'6:O/T}Hn4Fyk=7 Sk)s{ ddۇzt[4uCH. o?@$Duc\6B(^rg݊rd~W'.p%X~k+4򝿵*RlCHZ,^T-E"M3lc5x{&$_Uո.h n'̏:XA.P|B eyDQ\49~‹+El/8 i[2Fvr͐Q"igpκ##*o32ra-J;uS]C]Q@Wr Xpdf 5M[1f"3VB V}wS9,rg bΑHY?˃ˆ!D+oq%TXNߌ_rMV HD#s!ܢRE7jÁG%E\-:ŬllW[: v> R&YC4Ɋ6Q=fА]|ѱ;Ԋ'#%_UtjО!,mqf~hߔck ӈM ፕ:6:$yͮ#`ACdS_<%w9ɧ}+3N)T`ʓY_\{ݙ%` %mʊK}L~QE3HNC`$DƗ|'34LM+av66X4FXݲK1H:Lyv'P5zf/ny,c&ىio|ɗ3_k_܍~/OOu3~ ~~— yPm3MX&5q33$bX)T- &5Xnp@}->\7K2eV|¤u“δ4GʌZ@ έR%c< pܫ3Wf.aPu>5~M:H`u/૓? #{+ #;f2h# 8ѝUa0D~="k9«=.zBi0\CY(cc$_e>~CE%lS۸ilfZ] ܊0p"ZI,A:b<#tG͈"zFq_Q]#̨-DإnY$F ^ڷvgI58Qwyr/<+oc]ɭ2$g%4ӭ@y17cOj %<Q(bn夾@u*!=VcL5_BTBCS?Z<:hlՁ67NTPErDBܒaHmX גu& htk-[~EStΣ,vF1P x"]6!7ԈqD^J+UNEi0 -| tJ6~y8(Q2άkpɶh7[vXU7zƼ0RrM*òNth"!3whdC)'Ə&GK9lxۂΡN#WS LK`=ئvdO"v+!^Vj8PBdug8'../N[HnIFut3.z$W^Aã:?P%\p+ܯ\Ł,o9y ^/vf9uR|Gn0)cx%)+<Uޑkh~/Q$jk4HYp *1W$+vMc? /=gcNPhtQwt;x }_YE2 q`/m 2ȹ׍r:@u׮Ȫ9v؎t 5p}qZ"7-u"rǷc{ory6G2Pp:qo _!฀A%wS)VYfH$F9 *[7Xʪ"[F px?"uOB$찬ӆAܕ*k$ dtDQ%. h7ӻXS ̆b8S .E]nlHhWŠ]^:ہ 0,DD$1.MnuYF].^FY#2k}I񄐓Luv=DEP#$D,D-?'zBTmg"H|E>< X+iyƺ:\-0r*Csږ?xFO?s1OJAYS%R: q3:D1u*S]/WЯv֗o=F^q+c#'#@r_;W7]E_, 0ENhOob&5s^sm34f< S#.JOzk|^ä˸WG s8@x*kyl^fdF5}i'xDU13*}~sWy$ v"/|!Z ?1 ~+ %GMls=zw^5yOXhK!}y-&1ٽu؛NPIrYxN2Y05qOE!숺CEsMm/)1q: V8*$,{dQ!G<1R[M/ ]} @4dc~oܪ0~GmϘ=τJH7*8,uȭm f)p(69'N:_: VFm;. S3ĖL7)A7Rqڟ^ԇ_wq#]CK8Q};[ .ءy ۲m( \aweQkI^k ·N%ު.Ю|ϗl{5If,+\Cb %(w}%6^^@ 8CdmC$z !Ww12}Psʍe{o?JՍגq8~kKjd1jۃ=9̟NdO `#k,kP-AÏ@T긁,v7>6bSj z` '1rAآ/C`3b&o%O&g Y(g ߆SٰlA/=!aĹSR\/eI&Hre7mY`YIKqyCǩ/ZRc*.Od/j@ Iq[Lniîf ,!D7 7D _?jTK,քP*"#ck[Rڏٞ("%_V'mzϾLdԸoCY t4D*vQ ݅ߝj\/=1a~q[J+X?\K2wtL .ۈ(v 7|BVWz<159B8%y+Dig+RvѢ|"t@21uy!vf[T9Z@b.6O[OKuR)$&1O lƆ!1Z.tHs{ _!>8Y:ӃU蟭<6"bE />UDeKCb+說DfIP7Ai(L{_NЧ^Wj1@}/DȓeqktR6I=%WQne(67$<*BTb G3r-Ĝ/N4[O{R=H$4l%d[ƸɐY64I?~N3C^ԩU)I<1 5dGz:]GwAyk >tZz5#^2; -?u,xv^&w@X&A~B5c nY {uoO(58FuČYGOuHš׍Iŭ3f+ZePz}BTG8[ye'ahJefZ#J ٶb1neJo{lx LRl-󖽴mMAFVi 6?y.} ;i3CD\5Be:E&s(Ȭyň\+-lY_%Vqqߏ?d>]/[J{쀺`n3apR9%Rܻ%:En7 ae-i㨽r_Do iմIo8rs^f)X#9=]~UL?IJ^TexE=pۘJF PlPr(4y_n/ t͡ޘslmgo-RlF$vrmžݠ2%gA6P+sODa!vWQ X*WzgTg\FݬmMJU·_{k~}~\'s`!a!^Gąz6vu @>&9>gDDϻ!EeJf)`_SjRN)ʁYzW+ +!W=|ˀvmI|^{qevt NCr}բ:Lzh9D+5RYp.~v2J"GyF>>Awj -]$}up?Jsp>6nNPŢ,>Dx toR {fz*hj=Lh798_Sn.6.|=NՏ~3{{s6Wěndb}^U\%̅c  ^ث:´O- ~aC&/U:Xe?+]{sٻsXgE`4lp\<ɗQ+q|3"M(b6MDHqͮw3F߾~b=8SHgKCLoY@s%b&PxZ _B1@,WT_G 1Eh߭A|=jC^%fPHL:Y9FYE}tJEQ &LֲmՓ;od@x;t>-ׯ>i1 ;uCi?Ss+Q"YZɅ`Oi$*BztĥYÁ];)50\UzWz5x},|jYDúẐv.j.Mweg΅%U~LsvG*'{x NZ< cs7 rgI/ |쨳^b1;Ҹ⌟e`BxcU`*#qiGyv'i^O΅%4@߃EPyOV?Evm7 f/O1Qg6O ԊU-+V*D%V7,'cvM41eL:7ۥvx2?A̛yt* VDכPlսIgqvOw Ū9@:;wy]Cߤ#Hмb0XK'FQ,pWHefr8XWÃ3EY܂Y]F&YL 9w.D=vM:JRĔ\A^v}hk|1Jw5>[Wv#SF/PQ-Zj&_19=G![<@<[ C%q4%^;)s)8xGⱆF/1(3R5Γs!M |Z4-ѽۗ64FW?^Mri$w»&;j=Zy k-̭O%nG;cSoG69NW,_KjZnͽl )1e6--[s"N0ysu6`Iky;i+w>h9`F[8qm  m}O*"Q,3!BZ$+lˇ]z& [ӒhAp #dӮЈǒ\"#Izon-(Q)}KoO3ANc)ZiI2WҌiIbߩ.E7YZM!EqӠ[ypR0Bv۞UBEĬXDh8 /=Y3Z5Re޿C%d+HLpbzu.KA  wC!qHF:\)g|%Ak ipL]edz~U?l$9/$5J]|UZR6ű^vaHr7|XJ3?NDm0K(&ƉRbjdn2M4L ]֧Kv~6w]9 IpSr0 ZlEPȊV )Bk}34bq"PHSX]dCCCXy0(i\{8m`8;U] 2 s(vv%tZJnR`:m<Ǟ$ "C_ܘyNZ+<5RʹT3:2%yM4W\#D=jejӭ=L9Z31`AҾ^bsl7$'Ҟ[|. BűxK}`?W6[0oE^lI3N sRc QA;MX<*s a[eGc*)I[un*N3P/R#jl*ל&vE" if*A{?P6Q1C)vtk$iY)?ݾCTG 3ΘJl{/[^- CG&0ZGW) T|kxܪ9j̈eGe ˈ|љ5Bκ_[?5%붿!5If\XkO",̱]M++pzke%U)e`vvSL UyK< /qGXg=2禆#G (NNP ~50ʣavcAժe 5p@c"׃kF`Gq% 4GV&Ew4ظ;v)U'Dk݈/4f%AFA ome!Ѡ8H ^[<kTca gOe;a ~o?L~$~H{mxv1:OKuD|[S=;Jm|NbuJӘU`bNǯa~S2 DoC}BӫBI@]|E,$31mDF]"BΥS#;wCh_QgJ*1/b Qf>R f CW@LLI:g56duEx!f DM5m/6:+Xħ{s]3X8MaSpg^:fkɥ҅<5ˁROWjRtKt,qgUyI + 13IuFBa[:rT q;>*+;/YeNpdf$}8.|$])Ggsmܐ[zqW % UօO勚:r%@&Fm:)JaZiX.~ʟ(۝y<_c*d$,Vޯ˕4WVKz_N,#VFa/J<R42Ifi͍:1(x9?o+LC-LYw7l7q]beR:")ͷ|3ys<_,\k{m0Vy'Hl6߱V'o^p02bPyyK0g8 ?ҔR(c#7@TX]Zck,!dQr[z1޸'r'Y{2 2 I@r ˘3 ?\wo/iOjuw sDv!S#r6 RNLQEuJ %˄A.$Pj3lGSo 4['@);Q0| (]'μx!D%SLA7e=@*[),Ԝ^'&O.whvH&DbU> :md_yAu}'\gkJAfYc"hw+T5k33|SOae耢@n ܿOf5[~cJqR#*?>5wZI\EFȁvj `[l 18HRh2c\_F)0XbxBNews#`y'+MN$YaBYo*N+k{ s̖ovt8|]@kЛƂ/MmV!ɐiCDԏLYV2Vj ޻$=gkM/]}3%G݁t _H|,M?kbpDYmX Pe>d"j/J4M +1T u9W e5X)E ;.z.Qq 7SD9ʓmxha2k2rD2o׋Y;Tt(L;y*MT _#rjyǪ|M]&1>T% &d45ZakO'o6hGQJW5Q.zN^wu2m&{5'7'`ʦ Qdr͝&?>N6^@$laXli H08Ecf tҋB-FhGDaINL!%A"9hV25h_Hh CJ+Yz'WjRl 9:N _4u8I8\=h+_b{}F/佥hC?%-g=~5_%4C(AZ\|*GU&'UӍ37v;*9 P8}M2=˒ KK5wTGR EZzNlQv%F!ʘsT p}}þ! wK>M&Kkly`UPo .z"-2}HMkSvX)w qq.:Sy @coC\)[٨:hɢÖ]&kۉhmU>RO~i=M4fѻm*GƸ4}xuFB)h[jݏT{咹iיJe V}m4g.& {24J= 8𞔌u)7/VbmfQ!+lrۿJMkn XP˥~kQ0:mW*zh a^WěBn7 ͞20/wTACKl`_;"Y>RuNo)fJ4ND+ֻ{wƓ[k*΋3,HRX?5+}T\:H+,=BWE_4]I"uZsZTbۖ]w/F۱3h0i [Ҧ)F|e< a1*C -eyf$9Wt׺+rczʵ$wdiYOY\d􅖣'=ߗP2S҂!m㡜DɲTEQO)>|HK\}ǖh ( .訅r+5&v5ͯk(CڠbtxVV: p1$J\Xb*QD:>dyk \\ myq&Ji:4¾K5ҧ'5[9rda6Kz(+#>F_bҭo2#dcg_7܉T8uEFD |7~]OG>~!ϋoK5'y+Iݧi'gzQ]AUfcX1l|2jq} \o^CJBLۮ†l02"&_yd&"1h~Ԅ(oH )v]Tm9&G{M<vkͩyb=w#$r=)T5~RΛ)1qrMO XP `ӛp'*fa`?2ԃg8P]gv46/xrs„ƾPN+ZNI( P>\h~F K7dE| Xp0}1j!0ᘭgڿPє0ұ(DعnwnJmzw`0ڄUWLxG9́TXAT69i`9ؐ-"Ԑy'g"U~oC_Z"j]u%y|>|eΡ t B6`&DHiD*/pÚ de+\/>Z*:-l%q܏n߽=%̵); /Bt[M7~ţUҷm}=Q] (i^Mq`3Ėr[¡N< b_xK <J$&XOțHڼJ(-`o1]=!*rÃDGCKV2u=/tڔpY I'߀j`Xs3f6F<[UV T` OsLݍ91% _) V.S]Wv)*G:>OYuß}"̓tG扜NvmQ0%R$*1Ѐnc"%{AxcÓret:]0Ebxܞw 'RaZX#܏@t-lR]:1I (u~][o=br^y.xw4n&GJXFDSm^7 RFXmw1[Utn)TVLŲV;'Lc0'iv?MQ!Ÿ\m뵛{OZ>ۜHpٶ6 aVdny ,y*L7C~8]5`ow4_ :3ubU:^ظ>.hd>q3n8J7+ 'AwOCOôHycKAbWo/:-3)^}~%xtz*_Gse2lD:KDnYP3cZ5e3@W]؉7M0a!b/f_OcXq hza钴(&FکU$ʄ+Sq *Q؇ǘ̺[5h&F:#K-BtֿPt>FisI"qnryMĘ_eVE፝#g,}#GUs!cͲ'FGfX[hPԑm3@qC^Gl8Q!=XDwE+.5bt|q)>&(3>]ߢDR1\N);c0|! ]0^ lfDaF0gNw xVjt[4JΉ}3>x5}cM ʛD$En7wow0vo4u\^O+m$}spe,)YG”_[pE]m~#^L ф8j1}Jv'r?Օ!ReC9t.t' ;akQbDuPӢ3.tf糔4 QH;xµp~3vT+#"VF7LFLZ !45j5dE^4k3r{~b#°MB.:_5 5;H=gzhؓ+=ZZy'>M^:3c|\.Jg)+v/IGC{.1/%Y~ik8[ #Iv\E >P@1U0J&O+&vθmwj6nv{hsy}F>1o%n#fj,iKo1:J635oAZ }SLt( Η1/@X?zSuMD);hd7#Yg43ra'UK| ]b?*waqsJ_o-miZ W,AU':Ӝ(#%3'㳈T wda,JAE3BrqMjެ(r`T}kCwvM$C8V:Jy/7 & )äصV>oϑ{轎g:ńY30:\S0`g̟|jXu5IR]I(ѮДW2w/`U`V*t-.,*`KTlԜvT?Up7nxq"Et,ɰo16Vm ҰhR=dP-H>z Jmz""o+KbWyLU2;ۯ*qizA~yj\}gtq-k)RA u&My'`!{]mՕj(GV=.'cIտ7G#4lr8iP&Bmw,DfH?Йbb66}NC~m*9M׈;xQО΀TzN*E**Ӹ?mr.OogψXO?P)m1tA=zOc=-r'_mm<%F~VF][=1yx: ;Z)`v]|xԬ ش#VLjG'A*I'>_j7F~p߹}<ިۖ16@bz<őӘMǸNl ar[oe^iW+:5ޛ4  fĦC(ڿ(|Wߝ~UTMvk`;@vo^ip` m0;ЀU-uǔ1Z\]T|%eNb{wVÙ! `9`t *uqTy(~Z4X|.LHM IWvIJ`} 2h" !a$R:.XZJ 2|)z)#c }tedi3ya`UEtqܿ'TO-gֈDTQՊ̰oۅolQZ7شUhF~UFM-dLZm@jө?$#zpMggo~mFHc!`^Tծ`aac%SsTB0-|=ؤwDP<"ZG̽'{9We*H 7i8 d}\7/vk_NfPU9oOq##4TOq+D3v^H RP1pW% J~֑xsG6v%Wl->3HVhtn/{~HF |l<:)bͽ+Kbo4[UOu]ׯ*.e.!-yƆv˖ؕ#mQ\׎+T!iJTcZ=4}LCe5n1V0#t1[06_ʖ$¹A!\1&iHZY_FJ˯V((+0[g Qp;v2#o,&V'>Qԇy$OEAWث.^4-:P9ĶonieLo'Z/ r:kJ_|`)^ [#~q ]SޟvRbKVwxԯ+"tFMYkK"_մ6!\i'+'eSС go(rO.ZETvn5uپt"C*k8B.vɼʛNynҵk^l55Um_v◽ŷ{[Wfcǃo:xeBy0h] #HX4>6LQF˵ڹ+uTks<;+Fi=:R0ejNUr:9R׃9 V7lۗo$k`>*#Dcs^1݆TEgMڊSEӒk_aLm\)tXqP ,N qU"8Bm&%*/D-y-ࢄ Sqç .gFpZyuֶ;>%bu.|gG "bg.?6v[y48dxjSVr '<_=~2)bW\a,ysyjw'GXϔ&3ߥjUȇ&* pHS\U EK4rDs{-.*k͗n-}`ʆ3 `W&is'9 Wϸ[nIoB6 8jUok0e}puTffV(.|FH>[OV)0:o/7W|@,!u۹$A oҖ;2up lwV&97r ڲJMV1w#e꿓T|uvzpftWy191GJ֪vxqtIyΉ晃r0Qo@ } Y|*"B YX # a GM×? Qݍ܉M\8(Gĉ_4:pO@VB``?vK \NҊ[3Vc/[t8K, O\9״$?8#xqKc> ۔WgG{˗y)EoSѳ $edb#&M9C @v蜲- x $e]A30wo%dxDdLn*S]Ae<9+ m +Cz#3nMXvpIKO"w# }-`P4: H:Mtp-02Ҳ(Moaaz恞R4}D?~;4VAޢ&z %)z ]G- 9LJ!n2O KipQ[܍‡D5g'qjE*K^ jr@ك݈4\DfiPBRb T^?l9'E%sBbmb2뼦Sq!lLϧ^gO#4UY* /<6bo|"7=aY8E;ѓX 'k}td_Y+ϕm keAivW=7cX'V&\" .#5&DJu2<sjx}Sw 753Y)hS:AA_Z.lj}۾ A3Vv?BN S>MbrDnJ;p96V.yV2[]Aʩl}}ȁ& Y fĪfc3nEZ|\?G Hw{5 yD$WKE(Z\Gn@}'aM T"sCi3$zwF{GȺM&+^'c9V"$b>kT8[=[EHfh]a}f e4VUtx->D˺ TK&ӾA +BEe6+Qr[bg^8 Aԓ,<Np2G+_# m3:Ę+<ѵJUP] öN1L&lVWAW"ML}2R+-^ rW#znTLBHpnԖE vW4&50Γ)m`ܛrຜǷ m /VPg'ö7l{rqJhOH]5C1NVV][F Ӟ5 iwߙfҙk>?Kw7KKR_gMz9y~5'5y1WvLs} ,HT+plC'# um5^,pC߼ ϳԦv"IsC͙OŽaw#E7x2*(+ʢZcDJ mcE FZ!YҎ/: DY5cU:hvB@pѮ(ѷ-[ڎya%2s5 &^?vӵvdmJ+M֫]5]m-ظMoI. .NFy6h/R'ڰ#o+_u =Z~vY5k w"B |kh܎9f]ނ+?s2vye:'fM0=0EV8f1ȈQ1!R7-c&xG͟PZ ?Fؾ"_x5zYYqrڲ.R$ Qi>SRhF6Sl+.2@I vHt. ^=d4@DUt)"{o` ə5l_ޛz^vm=Yl.|SI V9ÿ(ZK~#GTWP`u- 8jA#c"q]mnAq^lW=Л1i R8fI롐^a: Y/|b-lꍟAYFvˎ2/M6p"Or +;fUDj;)L&tDC4kR4tᬝ{ ޣ-;m")]b1`0 G8a~ᾝ=ZIj Q 5[k}GSCCѬquƴ|i;ImJRrC1A2wh,fmg#!qslM;jƲ4'ox$t5RiyEsJ` ;w/]wA- =F&Jk[g(hV6Еmq1;XFYb[Lwl38LyggYTŘq+tl&M2S؞2vp}e*Rә/-[筝^0Q}=-*g}]JڠW_o'zMd_KL.LK.jq)5ɍBxq˒yFLF40FS:SNdz$.y.Zae>u0EYF32 ik7XixK Rwy%#k?dl!\|vd>z]F^QASRW0$ "bx@4G;]S{o%!d|?_5у=;ǿV87˷2FI55lҶjdwRƵ+&VPS kk)oX_ 6Cd9ź{bJBd!be?-ZtƊ܈zC%>I8*lI c곹.Dٟ)/DX/+`9u櫵OX gߢ4)"i2?)u' CFM\ *4 yYgFQǾ S31kO߄VD6R N5TN2j* >c;}ASNGro|ǨF 0=hbfy EWVj.5W 9fUvDža;#LiwL(,|E|עzҹ8mIJS5n->'@67%fgCKD%Ufĭ3,*8@-O +Y(&tHY & {xN_" 9e`Qu#S vl7k1To!9᳂CV hL| u&!Ǿ{ΓYT'6`WbNtכ.g IoT,44Kps q,c%%ZZA Evl02/S(8T֒pcMB+cؤ^ͮ>GVH Eg>Lk}4di-fx}&ϝA%SQD%wɇFdveBfϥpK{+!&m0, =4}D|Ҫ\c}U=R 0a >xFGY*B@,n3SfQN: +!_{ȸ,X-|Fy*ue/}5uȸsz{נo2>h1KafQr/lpmNV1beF_Owqq(KEFn{m-SfeX+>{>p̳?jy:~CRMt ,V͑ョWR?,(1,2ֆ\쏗=7 :z]Zx^G#CLǜ̵yJbk¾,LQgő4srp z gz0A(.@|&^L Kͨ8Fa )ڴK}Zϛ-)bu+vxI.CXb-*l &zbB߬Bb Ԉ:9*tMs]G"вȂ!uJ\ZGG2{/Ak'U d_VuBR+4oWF&0$Ca(~eZŋ-qh6֖[6&֥-gnnwd!3{X Y.JODLnS6jmO]Ec55F#[HW%}w)^}nSEy*cmnq3:ŕf=OOO d3~ /y%>$p9M1+c#Qޔ).wYbGi&VowaZUd鄣~fl[^4_Սm  +߈ RX/JAZBDci=T'#<)9evlU[z%g@F PsF@E~< Qt`bu<uExMP>}X= 4r5ws K^'&+*@' ŰM:OT;6_tDfEZuL-J2b}F" ;1y *)/7]䩤;Z? <4.'Q+Y#D 9mՂk)05,̣kS7;~H&sZQBe|}lFꘫϙz~i 9~xux H)2mu}\Z=VgGW*Q].(P73>@3+7hwm,vpV$rm_8w ;c?$<TJeKQ:c0j8S2E#5ץ| 1 &7Nഒ,wgzcK&AKLEJlV-\26uq YfbwQN~SV׮늠r)㇜bTP+HN o,=%TRڂJJ |U !p`DV֘&zRps 9`4D37T$/Bri8.P :1KVܻVt~^ZZH|IF; >z<~;$/qE􂇝p<$ѽtEĮB2L6XB(G?[^-;F&XIed|]@"07kⓅ6@y'՛!brd9|-8Y e-DBn\yW7Nrfo+9"Ųrkdٗ#}%Lq=FEj rP\g(&M#U_4ޔs.8޹R/M5Y_M">5n /X~޷kx#i^Æ2oe@()b09HQS: K 2<&JKuh&FStlVn43ERab^gLB0m7ٲSljT*mt J^i:1!EF\ c5K&(*ء`ORL5q, x}0]DɛuLpO ey.m$|,nŮbO}%ѭMg E"ZkJ~`bI{3K3dѭh`$}.)T7w HcwgˡhC&:w}')0mtm_]nPhZj{ʌMeRACf % o_Iߋ\d֞GI2/kg.SO@Z"(9"+ȥ-q^>yCI ̱a<=W%=jh/<Y 1ia΋DcuYR^7jyä0EyۉsKٵiNi;WhЮqu{Or;)|W; 7:oe|[kքQ伖,Nv/3^{~ Df7HM":u/Ɓ_WP{jg AqڻV%w9lzKX_"Q͈6f(jh-E}:#^Ϩb팾b ]Xt'oȝs .L}i/q$=JHŮ !;Zdq#I2tB ~ SzgZgͧ,#0>QDΉيPU/F쁒A3_ɺAd#!tz)s%-d! h>R}6qBwpCTnC\~W5鞱_wΪחѿi fQɕ0c-$];=l`_pFl^XOaU~72Y 2KL8*kMNI,[rPfR .%eDu%}>+y#1IsXWHAۏkR8Dw]}hVX3&>.9w;9g™u ~3ww2(]&{ǝ䲾 `=.-Ҫ9l0N^E X.y "&w/tJW$`1Ħ]W?3F@b'UB_.ȕԛ- ˜L }ӜGYEWoN y@ϝIOi>ǏsҥtjWLl"ilo@+fWCw":C8e;@[oYA+솷e K]ufȰB oaڀWTbY [+zRbEc S8xB'€Nb)W&}iҌeٿ{ʣQkqz]:,׾-K.H+vZfUp:J"G,dc[*q64D 6g}feG*kBnQ ҃l8$)3pdq7oWag lau ce|~J_?%d[E[Qhj6]$8  O2 K:[> cra\fW KeoO!T GԚÖwT.+ۮ֭yo-X@K}Y]oF)Ԝ2_+τTd |gc2t$' +t@Tܬ0öѼ 'Ќufl~[K=Y |SC.F$waxwH A|}qU8/<\x{|,U<1^EЂ4a e$@nQwgNjxz K]|1#n~M"Ƃ"b2I`Eb1ipfl{VHnr );@^g֐K)cxTԗNUhMpjYfb&rѬtpELWncZtb˱3z.=}5_u(exQ>غGt(Nԭ ;  {b4GL7="9A6e,H%nmq^F}\h8* LYO셝Znnz6ZdcYD_m#bݍQZˎ41ffׄ‴B5D\=|4 ooEWK#oKLRzĸDLy: av VqgYpa=5X_IӖVd?U<(vPbe +˪ syU g^ AgsްP`XZS@4o u(4" pdPʢQ~TWԃ^%P^~Ջ!ub_V4)12=uCwXzqY:hK:Xehd¥'%0_, q_&H?wy߲4dq a.xz%pЭ65(An!3ٛBCkKl}qQ[l:ӏ#05D̢ BkePܙ=3W"fָ);zv/(TiܠrR55i7qY;U,aK KT~$TܥGpPtQ͟}0 #wP0Hth:c%:x6aB.СkxB3҆ "JCɐxko{em4y_1WkQzzG_vr0X>v&d,0gHs+Or5b=c#NM {'AE'$8LXg&Mx:4ҫE/qHzۃ@ʚa?(<Ԑq`5mDW+T%Y8^k0\TP*>z!wdPa &cU ՗L F(cfEU&!)O.=:H0W Iá$&VA{9qeK |HY ޫtFv_Ť2<~5*Tr^}4!{:dB0`ZPcb,LGs l7-|ߣ߲r[,SQ Nz'[uƍ!C)^tfBrDt1+/P(1ȭ@i&ƻ5o3;~z %-@٥!aGh~\#TLZtNdVQ>>^!+!Dta(TB!._MJBEќ3փnR} Xz; xav-/C'mhe/Ѯ}d(qM1~{6ƻ<ܦ BVn/--M]eHiˋ6wu6Yғ H]ܡ7zSGU)t:` el;iYjg%Gp>^Z<K*D;zN{a?2XSA?o{͑_7f>hsbbU-=u4,RI3 O:Gk2Mj$jUK>iMXϧىuX@AUق(\h3}zOƣIEҙqUeLJGTk-m|j%==2 ٤G]Ѻ\f1]fApiVyگǾ3WBtJ'uT*`K+F sl<ÝuN؛;P!v2Qk݂nŸ,_KBx,b,*H >"qJuJg)^֡){6RN ~I;Jɑ߬Bupb7﵆L X$j utj9+(E1T1 ! |!mK4hҰV4{@pzYa1u2WĘz-zNgq Tgcy 3A@j8㠙gM4]#u$ͣ)tn-"TS͏/Xn@d|;}FZL!KF{`Im)|V-2b^G (_i2BRS\bg]wF2;BܥpRN]_)5Cstbg>(t< @pkVdcym^!ޔ%+v(S++FgPaCc.E JdT4uay\k9#c 5[|-6_y{Ƀ\a_q5+#tF&2H[FKQ6+3-߱˦K5vu7ޔMM|]wJ m;A-eBxȎdRPrq3kZ0ǟ+/BsYkh Us?ɛŹZU'1HuNx@u7:ݪ0?~;#mAN\WxچFsG_3/x+"/bP,2@9Q'Ah_ 37LșsԜ-RJ'3x|Ṏ -^HWRҢ~rbsf׭h֎i䎥&  +pX07Lz K&IPT" &A-fm:|E`l0c_ז%4#= zWWzӣ]<3$p2|Aʏ]`T¯!_5]n|Ʋ~vԮZ g$գ^iDf6L =.ܡVV@V$+/͓RbD,&Si\?҈\ZGr&4=:8ǐ=Iܺm BZ4 λa`{%զZeKa ' !?/6\< 퇻%Os[BdR: ϏŻ?iSɭnb?q5)GBqsg۲m"j;3BkRHuX7}g/=_wS@;:R {4x\*X~hlɦ]A$w`uު;w6 Jgh$ݲ"L'[ A$H*2rij׀OپP%1TFp 0&: dsEXYUm&aKbHT{gL|tIg9N"?:w/!SDܦ=e%^|h=Ea;\PK}o1#}#Kwub* ­6i´Z 36vP@Ajz> y{:ll>vW0;e,]úW b X0n +gS(3*dsG cGD&Y mCoxW]J\q/7hf F!zs,z"?g4+{n)XRAlހDl.ڛJ r8-mr imNMYgk{;bu pzq'aQƑ;xVjh>mpvkn Wgz2X6 9X(lxMKk|K8VP{vY|ߵY]5c39Tegd2y !B0PkuIRɫ \Si[m Vcǃ>㻋"- dK3} nA@TY2ɗyQdY*J5voP/%X.qCޔ'Un5U-?Վ_-oR_"қ=RGyt tjҌfy%8UƶC q+O[ZF+:6nz_ѻhkJe0:5%bQCDa #'VMyD9T'|mxk\dˠ3ŀ&BIf'#0?.U3].[ɁƸ Z1ru@&=JNcuT'rjiP917Mm$e . {8j?x H.?UOiY/:I~ Rݢ!52[a%emj$Q""kS y:rp?Etl]^˴+{3_`wfS]i( >=c !HoܙlPєtӟ bG^F3vK }}P2A?f+dx֦s4F0],^Fk8[K1Ds%SFfC0,/yn^^^(t^xvΈy IVe\Zt)V$v!`>:_)}V=sF/ʫA_L/֜ ;h !b-4VKw?C[rmO INՎ Nۃq wR#A7Ȟw:1,z+CwD5pBW*:LPA1*>rҵy$az'3y64k++ hW¢]j5blOhj7Qc$uǠeb|),6oNiS,-3 kRV@U[}GvOfIfMCކzh- ^d˂ڣ(}+>QSU3,xٸORCI\p.LT.dmw:{܀~Q~%kqՅ{yPWcHO[H9,`a',UXsX_]GL4 4Q#MC Jׁ-n X~m;NoPht3ͷPPny{v*gh_&g2>Kl Fɣn=M2LggދO"IiU'$WJQ 7ۦQ%C_ix.g¹13. DV(y@8 >ce5TkϪX6T<ߖcqxCYV 41vNq6p[4-u2q4IȢ0@$ulX^%}{v | 2{쎻e۲֑k^J|1HZyXR,g <:{ q"ǖe.}pN9Ë*3ԻҌE]2VM&K@>jFqo( .N΂;YS b6`Jnx qЖA{-4ܶ=mh6M <")*#* Vz" Oרbc^]K5NtX i ]JN=ڂu&[{0*g-<"*i)}m#tZqEZ$i%5I47-]9aO pic򇰴#*j7;$[xi_}V4YZsy*.TFO67% JNJ"i2yxn(ϋk\YKu^0"eڼ#1F C8h@U-&ְeT$咻Զ)ڭ^{J~C\S~]$&!=M /)OQלrikS k?ա/+p_Ol-e˚ݮ'+EH>.ڎjѧK!.%"ݶO)–tqzS ib/K+kOK]W-w2o]#)EH{-WH 1?Daftr~2_Fps[1V6r"?Ib:׋G\&}RLI`2gxܥnWcpXFp9AY;(\Fi?:㍝hnh97 rEASDCjLYYdY'V!S#pLA}Vb{c 4o[wlzA10!q3f [@SeAψf"$\__,9g*s*=1E.Nb#.ӹ/Q05=}VܣUe_a\GPmJeotN}F]Σ.Zo>爿.R>Pt~k2ׂ?# oraq>S4$j\x6XO9v@}?CaB[ԲBẂ۱%$`[렚40CjWa_KOؙ03aW&e)iv4ŒYeĄն%N*SX7J}r 7uqB_O^` l_=9u h푑e, tS 9n>wUs?+y#6iCY/DfcWj^ztUa7cI&M&gV 1jbJoM!5QiGluBAɍ7}g3 qēMltj16ĕ+H,qb—LÑO2\F* Cb[ ou2֜ED x?Q8 OGeNmX#lw4%\vWʟ? xV,J>f3xy$Iyv#aYF3/P7sHpFk.\h{2`T`}_-觿?L,HԘA7f e}'Lb-Ht$:hUjk+wwP C#|d voO)5;y*<:KK5JϔT;E{aCҟ!;XL z6#h'BoNj|!w42\~C:-nVڊ{K3:[sM҃MiKD#[5룭"\5i•]k0ss`^Gu"D3`AڨJ8) 1ַ8x ܜ(_VJ_̒e^8.P*a>8SOn%Ϳ4K!eۯx!u6APaKV,8*siŃ]nr]hs=ҬH%iBTZUd^je?d=vwCEcLAY9q:毋]d|V8}tU[_f EQK=p-A;vl#wV&Qm4Dp/[U g}ޖG l;p<%vt3:)b~Kq3=t| ΢/6t 2}]J_*4Ųo/UK=ԧ*~`D ^>δg[j\okxJ`#tzgM( ɘ=` t"G ؂ß z 9Tyxaa5Lm+}!ZQ ^ثJaۦz™_n: Xy׌"kѨp~~]rPfS's S81Ƃ(n!qY6L6REp*SɴtҚ j+N4a_xLvrl3̒¯7A҇hثb-2r6B9𥚯~4!A8aЛ5Pm4Ǩx*~EZ˕*z"%ن(wd+hu*ykA{Zz_\MLVsgWvX}oTwC>H/\UfI15_IL y3pRlO~ݡSx8 F:syۼRYVǻޓ_hl6b˰uT oC֟;] Jv4_n!zp0,lLI.$aW{+TҘ.?M_~mEŽJ$a[CS|)rG$yiIG8ܑrq)eۊvHbPͦ;y\ev=Ǫao=ټ[&osjDw.Iy$/4zĴXa96ۈQ*ANHL8BƦJxޯ+MuoVBG"0M %,KTxR慠֧ae*Fyܒb$'3`azxcd^5KÑ"H#&VJDAh`mas]OJ@HSN׫\SûϱWQ6Rvpy=0Б;Ÿd!eru(j ƚsq{ &e(QA:ŵt)Y:}_:?:eN&̲yMX.>g8CZ9!d7sہr8uhBL[E>ҰXE=K\=MS:T>8O=VqڿA6a(`H̓ An>+ǝM1 ]ѕ<@ة5`= ΰz.h4{WY&&?)T0|7gvSS2Pڡ"{<':o \O]GgdwC06 [WdcSwŷW d ^^(.PmY舰HWm2g i6*,na" nrBx|/?TNY~4um98[$%;b0G7Yϔ^AZ1Szr4o﫯 BuhQMhi(Ưxˣm/a>śe" M'(Nb[ ρ!r|9z@qnoVEI BVgZÇX L 4X {mZkdS!rP%Бz7$-6Dʣ\e?L:E^=<2-}d ş}-&o{N krzy2  az<1whE BW-·ͩR ܍㡍@^6F웊?`Q4T/ͿA _D_<ٵ)/X iF̷($ d9;;iArs, HJ3]ly+ߑݸdI3שwOACx-f%]tb8 [췛1{vg^ڝbb+-5#hŧ&xe)"'ƭ)g~3OL.*Zm)=3{< 5Ow1 f/4\^MVQù:\p`yn,D,[P?:%-Z)E8TmMZ _àǦEw 3/Hƪ>Ē{=Ձ4'eCY^ î`E 2;_k hEu1bɗ8 J7+/F7]~=ă0ud_V♧-ԭv0iw5+$c 脐8d!j|0x=(մN#Rڀ~TDڶ$UOǨ*w#?HBC~ҁ|ZqM+ 7z=+-r7] Ǐguŭ#N'RryWz@x"[6ħI,#>?̿Si!7"~0 /.EiIЉ1K,nRtwKcMܻ 5kg*Qw~u+۸& h bcW2^l}l {wPoh i`o(q`$p.3 ) `]BUo^k_u4^KRd#ɞ,6@%@}o-SKtԴhunAhҞǗ[ 1#(;+ЇDP}^' ⁏fjؙڕ~ e@p7ļ{]* , d2YpɰL>oS05~3+ .p ޡU.x3|3ڧ'.:36ðK}و ?`0f/17-cĿ-nM/yR\g~`uHf┡ |-?6]Z9[ ŭ]mJ!<ڹvTBlbT{k8eT=stW df[g8'N:kl0ZɐN72J̹F^cFx,`쫫tsƴ'v<.On;ec(2few7*#/p&3ŕmbE.o:|x:mF9-ܼ隌 \ }Iv LbJ2QqS^ZV[!0%o+5ק,)bgяoo|Cwev e}q iyO^fԭ]%Hr*pKg$#SȞ^6(NiG/;^p,sMF"r^I= Pڝe@L(ٙ Su+( !">fsMvzArm#Mml.\bJ70B3 J:%ׄNδhͶWRxjvЕ}VB5XP5˸iT~:|d [9 Dd 0L??R w M)đaZnwz'FDI=@( /x$)P-q8.KQ&FIq/  uT~Se_,.w#`x %/'wob9"YrPzUʺ}oSy֌I~-8'½^#MjoPae[z[0c]ެrx+Ÿ0_sJ^F5J : [ډG1Y.Ъ܏$r$VuiE9&$Z!`tr9Rflʾ)"ڡ踿:ӁD@*IO<߸δpXjS*+mv8-VGS>R@Qa/StK*0,ʚ@>l3?J; 37&KSpnAw%9r3K5+rts% v;*9 P8}LLFbg^sBf9##N&]i"yUK `6W=] [9|Hnsxb L; ZMC,zY>,4:}6B_r焗QY,:Bl/ZzFW%mVa?K_B5Ƿ@$հ2kaUWP_(~৽]᫽;ۉ mb-^ܝ5:{P?}2~ㅶs:C{241NAT1W}_˄"֭dv҈?le|O)_.90n^YLꝽVO5KdC_TfWk ]ヮwUfP4WvO_<[yLv祺y2TѐE&wIM(Kzy|i1؀m4b{Pe ci ƚHF$˿}0n6*c2ԃg8P]gv46/xrs„ƾPN+ZNI( P>\h~F K7dE| Xp0}1j!0ᘭgڿPє0ұ(D-ܬ樹Y8q}@sөL׬ݙs%,RIl *W%o#0{1l'R6Y+?O;r^8D];աDejRkY$ FK l'iϧnakR(UC1ɬ.β³GuҴhj&HcY(Ldl*RȖPu RbJf8yc'QL?pwQp.koi /yk7c_{cPQ4\ ͲQeWb\֟qdV8-fѨT? C~ Op-G*)X:@eOzi)͗NkmlZi`/)ĈEqoctIeu)%bx6gsUIZ*SL3Kk/['e6+nx)/ytmU[n{ Nˠ  R)d rtG87͑jBĚrHatxlw8Òeh2 ( tad7I iɻ# =`{8 !ΥػwC{Ty;h76X'<'&>ʥlje9 :}'P|uF{q.wӪ.a;^Q Q=Aht/^.klMf32-%Ya!.Uјؐ$͕|$ȳJF3`\`Go'8XW5 ?bu~*DdޙZp0B5ETd-&,$ʹߙIa+?~l3J[Y|.){,ߢjQHPyEd?[YgW*&Vv:sL!G"\fjd& a^7 ф8j1}Jv'r?Օ!ReC9t.t' ;akQbDuP@`XXAi}cLdAMX$0:<[[O)t)/ 9ogX rr_{o!>TEjb-OtatdŚIWf%&F$Oic&e܊_eƇCeOU=7̼~"j2yQš`J1;;L:'~ز Ixڝ",Ihqd;)EsO7*7ZEz =s9f2H>H'A8y</[#&5 kزv]>R4 ܙlD=G62\$y|@)Ocmtr ]ԢHPN@$w:0M2w`Ҁܙ6Ih~_OT{H۽=ER_bv%#̷;9x լv; EeRZq-,]y] a7f}養p/*hI bt`gЩN4ǓIaDR_,֥'3C_TUp0<8 3Ri;RmhpvT3"1m뜦|0vNyJܨ֭ nW;+k>ϘJHCs0#"k>ҿ:3 $m{\v4}i*Ie-:f!rGR|+ԏ Y2vX(/ɡ/=(7[7VCROODKYO&9FJɅ4%*(H |/><8OB[yl=HJtR8xL "gmkkxtΛ4'_ޕb/f=gH G>W֏D%#=C&>%:Gch{e CJž:}CTIAg!*F"mC_i8͔ [x`~cJ_]5iZ'܀d1Ԓ&WTuuY7ok' RĨ NLMR *=> L]iBS1yOP6VbDEߟn<b ˬ MM\Sm̛vbUKZ1ܐ IȈV6>kMk{-Q˼ᥥCp^ЈF7x3"`9xǹZUFމe4$`5_cݔ jMn*rjeité|"T}%ksǡLFgs8-}@E= -oU~,4c_GbvOV dtjcWJ&gt&EWaۚx$L^SE^W?H*f9A 0|#plXډ<\"Șh  pݶ!$Mhtێn]ɲ|"Cݗ6cvC=`NG찅x|=L*#]Tiz>P>(xIQW*pYIǸOX!GhZ0hƌ)!cԜK"`1lDP!G'E;jx^mcVΤ|Nn"4ؐXE\K IzsJpFMO]/)be2hסaoM/;V*r*&'jn bg20#aM{*!' |OGeJ aK|IʰrV.Y^6FDe=L6goUDِ1: 't;DU(:/Ow?^hvSi`Lqef3cÍc[bL(|IXs,&xБ۔ '4.OdE']GlH{ÿI< 2*#˯tݱ;fp3*GM#zQ4Uy}=F$+%@4%Q-~/+Jq&*;TMQtִjj]_Z(c6 &tiy[@9nWɿqnDA}@Ylae]'pZ87<8S/jhި(%ӎբs]IBa7k# )#C=+@*Q XmZM\-@o,31n t0U߬Е-@zWv sg)[cC --e_6Qat&Zu#阈Đx  ?,\7x [{DJhiH|&Zo}DNm?=/?wjZUiZ#?UUKE '`$&vezD- ʼnAO5s['>GbFM4֞Qc8%PBR@af%p"Ve a̩ԘY5?p!_RzOi,%׭$[.gڱr90c">Xz ~YZHniH/Y+7f7) *u& TµTR(mGf p%އw0 #HZ&_r , ~1Agj}Qj& ެ{7jj:A9zQߠu; >c۶G&u.ji,xZmȐ\Kّ_H?:X|ȼٜ8h—ZvY}J<3}3O4> a |k&u!1(Al־V'ywȊaI[W<*lm=n䚁<@dTNҖOZc4-Y;)Z+ҕ.:u#"7>qsUl(``qo/.k4AzY-QG[&`1F!ټd1Fq2vG3D8dG- t>B9BMh6sPQ::S; 'coݭlTCO2:!ϓiv"f+0NE %&Pk;DvQ+9:"T'eᔛ\nm w>5^Y$GB>zP0(y܄Yn= mُ@b) f\ܖ#`\!όfX6H%DKêBOU_^☚w]O又H(貮1ޒ Eؕ|'T|*%ȧk瀰d$eIbuԝ]V!zKg$*Qh1Z.e7!E]]\"iLO`pQcF/&?x,",lyDd"\8EEνtL^~ӏSW-{}Aב4ĎԈl5Ľ=5G1x\OTLu͡sıH=`zA凞.5':j,sK.V%$ 3 M 5;[#b3qzwF"ΫʱtE]a{XҧHi&|T5Gw#nTe2渀ح'EuIW$1(K  U5#g9آ;| y[JWu8`j%]a߆$Ԫ؂e(EU.~f}(~R|ErD}s*5UC/"( M7$Ysz snU6? (b-Yl%,6tFJFP#w~3Z|cU*n^4R#egIÇ%Y~ /|ހ1_N˦VK%( 7{cRnlsKRƛy:ʅqN?J@;xe} (yԆa,\0*5gŤrƶ{y .+\&*ı`ʯo!ݖs-Ō47نы"iާ x7ZU } ߨ4v-04Dv҃ ۦm $`)cO2~ 4ޥ*ۆN- e92Yn%wdL8zvR3L_[.lX9b*s^D"/.ϳ{@8A꤀"z2V9eVfN-@ͭFmw d9݌%Cf }~)Wv|`}jEq}q ]ߡ+^M peHhA2TWl,|JZկXsf'kXh?qÏȀ7~7ڄ˘+-9q)jy;㹱 r9஌ӡ180g$%[VSۻm*]q=<ՅY& ›' ~:S@l.OpS9;*ȈOnPmo8]`fm_>N|qphg5.zc~cK' Ñ wixZ%_1i?Aj0]5g 1*G/MrP&$ɗLPyY!o{ mc7g=5 /a^H9cX)sbw1TW-u؇a#d@b|<â^e 5:>۱!Wbo*ȴ6[ a0կٶ{Q+N BcYt=sd37)+j%neSzհ|d3ȴnjQFHǡXT툣$fQ1nU%vckV679_Y{b)#RԬy/w)HVL!ᅛN5}}L*XRW KӜv}&>.|6r֗ܰM`S}K>h<m`3 Co"7/W!U|`j<2T2;MqP- 0AVE)>1.g}[-9߿&A Nɶ 8Cy g䨽oDJ(ޔVx_`8ձf Gt YKߵgrE,qs u2v֦H uLS_6X31^Gٖl,6rkCt-͞ ջ放om> Ҕ7ʺ_?7 [MRztBM42{gsM!҆ek|"Cĺvt{>?Kk)g ]99%Muur!=95ϑ'e|FNRɛZ,BlF m[ jh+ɱDo/V+jb)Tg# E6TF4:#lA-6pF)liclPaaf (4ڱ5c (E7]f$1sSa艺oڙ =~TUo #l&nzJC%GR˹o [`9"7"Ϩ])u<|n0dC: ]߼Pغ6pX#'L5 {|sj!3؊mG."1Q+_Tz U 6%ԤVN,9 }ȀB8_Ӿ sb,@PђOl/M' Wc䋬 sjth%I_1TȞ]3,j)%b-uIw0%R\*Z (}E[_l&ODB`:=w-r8ק& @%mɵ\?k%Cg/O{>p̳?jy:~CRMt ,V͑ョWR?,(1,2ֆ\쏗=7 :z]Zx^G#CLǜ̵yJbk¾,LQgő4srp z gz0B92$H5Cc+xyY ^_l%qY(O%dRiҝ ,mnH;. =vb{q 8<ɡ#ذ}q|1s– @'#ݩvTѭc6&֥-gnnwd!3{X Y.JODLnS6jm7@!c}|zK-?$1 dĿOͿW.'tUحqL악ct~=R%$6#:Ԭ3jտfltPk~Y[UƮ5p^-j8"+_ܦ*IͱC0!QWJቻ^wU6b|>G\m ojRwA1>šzu D ZطҿV6ȦaL0q]d<ر.meͤa_3JvKģSjc >PLST2F؎_OnDdgňbv=6H~b,Iv=ѥg.ڏ ;ϕd6.ELk'5*BvօT32=zYG ҠsPXOB gImiܿ+H&v.ḯJ(Y&du?>/!%W^%3֦%M$A؜->gЈ\;can?3lGI0cl9?t6(qAs2cGyuH_ ء5~ ¬wCr#P[ЈYò&GP07@WՀ$vֵbKaY+LO+U>Obi@CGxx)9 $A8]z[U"--u`"MZ-]?B8ځ":.ltn)>{El{%EdW=j\:W-\T1 be]YǞ)~vdGxIQ(+rYYMBUtVo HYo [~Ҵߨ93<-+AI0ϕ8{Yj/F ~&s ]F} $w2a୐f*wb I_(|r/^zcE4 $lƥ Jc_?c:34UJx@}#Xgr_M؄}1 ) ǻ'PUE _NWbVKqE9kx@R}+z$&J"0l6ΔQӎ ]xM!b=q3 ?ŦdY-0a~>p}i2kVo+TܪZHd:3S[B}Uo6da燂?7H~x]s)0/> D٧!rj[cL<~-Mwm3T:=M-[>Uէ@ U+ 5o+ԨFA)~8"SBbj`n^W Tϻ@ &͘)^VYv/^ _m;ޱfXbIPc6-Y9le4x3xP,L̙-*'CH 5F ޔ1׌1iD?:y4 BTb">_ʩK@yL07/"_)ŶNS}=Ҋ!oPuMQ tMkoG1G͒W=@ HD&R{sjZuG29"-P>lYkhqw@g3wJf?cUSq 6~F)OfQ M#`R [4#дǙAYELu#ok16 Om_Bzضa3xZʎxZ{0zp[Y_˚\njL`yLr%[%&WM>?0 ##kfÍOe 'EL@&RcWz-OMZuC꿵A$?MUB리 p=sk'-qBAOɩ_^06On ,J, lȗ-8GkURnΝV%tU'0`}/̿{ZK3MhيLְ8D>j?cBC3&S5`OP,dvrqSlI| Ea[Iqת *^ܭenγ2lЇ@vL"juzrLկ (|lճ сrǀfx)O{cS)ČW)TiWpPboP-K&ҝZwMcOwzp ^M 'ݭS iA%@ [¨uIcwqE3M`LWR ZqUyo?˞5D R`Su47 ,:ש" FLbYGne:SBNۧ+:?SY=*_?TcK[W p*{WG̞,{F?ٽfu~MSIЁ{@q  _=c&Vx@qX~H˭J%TFT1@l]4ҹl%rrs)D=T,@#ʦM[)]e-7x<cDh `%=idPɪ+I@i{&q7vNJ=Ru–9w$=^XU;F*r<о8]8ɯUfA $ {˯&yuK6ȮV'z}-xʐ~G ʢj$ j(N,*>d8jǖR>5/ UO,/ɧZ*ӛ,^3tl թv,|wA q@yZ8!G4W}|>}{.q kY\'`nX(o&=wˍ213ur3=ubjkbZ0 \Dz :T7ЉMW;jsʌM F7F"o1Dʗ)m^-t 8BSP;aoYsI XeG=Vպzxv[Ya/9M\1?꣋~~r cU/}vsE@T<)w\}a5A`vP.z+/Q Fk Ǹɗ,td?FCNb4`r v:¢B|Q4l&ws .?'}9'XhVs[QZ|Yu}%crf!p* <|w?rrBq}l%X+4T-$۬.v|`N:gP w5⪈\`~#Nj0ms4/i(;)Ps* r?ɣhh-)Q @H}na/1Ph}aEkǨ=7KV:K/TEA]A7w.v(r[/,u * s$mdcVber%f,B9'ݙHG0 wѥ,Q̿$_\rdvfAB ra:K#΢;eC:-s$U4A_Puأ-DUWdk*UQ |qy2S@G;ZӟYMXRjrYɝ8k)̓ Cwpo0zPCaݗaZ6T{Ka#aKOe6qX?6‹U$WJiXj܋w0p1‹V+@ Zβzr'vZҧM6 q`O#.l;a;%Q>@Io,{SruJ+%Qac'ݶI˿u[o7G%H_UwZ]yNfN7*oa`uԖ4"MY ;]6e飊u>yoTt= sg eVaa* F8iscj3nj'Jp,bkٖIUȀL' .rL7+G"?"#r WVJ9`y#8nɵx459d]YxC>לb_s>A|Í`QmNjoH`eG{_NxG4(1HϲFՎFa<6P=,>w7رSL*߹&%k-~v1IZo6c|.*J8X|9+NmlPuhhASKEWr=M9|XzoN3c΀5Xe`"N#OlfRȄW6`̾\!:ֆ*ŏzcf͂W7 ʤҾ>W"N=8`LUwۑdi^]{ Tj95+Y?mIHUq̐ )?3bQ&&0t?DW9mXѓM^AJodYjTbLqw͈>` g\?HOd7k@Ғ3ݞÀg2a%% _1 7*\??QЧʆ{)Զ{DEni70lh1V"3Gw`?g(Hl ;ҧIdpn cqfdq"U}!wөo{)=Y)=vJZŢQ!t科*\nAUWrWC'[w+QOhՙMӬ T=NMFWq()b_UH:e#QPwL2LaV珗"vxKˍ0"MHG*PhJ&1޺_ϩM9A`r:W@Lut( 34!$wi`vɷ}և+d됽{/w {rC3YlDd[/g nFPLJ{]`*|t$QH%ƲЂ.8H>:-dXCqLs0 F=8r, 8<IWl -}vg(T< _)%lMȊIU?I#DԔRTfF|pTnߖTE7)%ϒ_%"6)8 Ed&{ ͣsS(Y6l"tb(C"]T]1e c@X w'h 5+oehkz%R4K0T&"U .~6>槄-ySrB_wf,,(Zj2qlDU!T<반l* EZlo M EǾϖpW/S:lËEoS?e KLGOa;tz{iEǼuUԓd .LW7$-3h/#WI.Ik\E=|HH핗=u$̭;Si~~kFH8/\/M-LХ':ŮScA鎂ܼ?K34+SV[yT&bahy*-ŗM>rm-QLjBa8m놬|P5|8t(H'@iw_s\+֥+q.:*"(R+e?)(*9?n :>#TrGgYXSAʹ= vhvs:8"P#z+|ĝ KmfSl/"C)+Z؍Lxsk,n4&<0ʙ!Zuk+ 撹^;iIWI+S3oqD"kȵFY.vFAAS~5h %+tWNخ̨zb(/._eΗVȞ;wOtp"+cKߚ8m$[&=*p)J?ƣYHbaE~n)rqh˺[nվTnëΝe hcֻP=z\ȧdwS hP=lw(y_>~^֞O -hFR7evS!0/hsw! ҏ/疠,lʥ l2"^Hx;s9IpE77߲VÀE8cX]㝖 lA8 ؊;` mv-.|CW; 茼;DJRE+#E_ 5.4\ Pʶ#ϖ^=Zfm'"kŶndPv,q`ۃ7AjxLOJ'wVBzܘى71BIRnYôG#~7cEyܘ70wAvXD,t2! huZyjL pY\AD! |b>3 (A塉**X>PЪz:~r~k-C#|3`VXͪ`}ޣOuρK*)eb~fmw' (c ~UIZ~c1aE4w_p+L]?ڣA3vdLd^"h %B Ig 衆Ho<euph3RUԤڏavZ}!7`K +]ޞV?Q4l%{uݕw !'@ִ3l(6%. ,6a _L +d ZJ|@(mwѠ {1ό>`^DytWQ3{b\܎[_LZ=jrO$ קb6j$Z|b^=u u YC\' -Tس GqFֈ AJk (j S?8VP{vY|ߵ&ϐ&hv[1+P2zΞ*4ڛ8j0/Y\"'_q@":#Z/6T6:_aUuPhLRVns$QSZy5#&Txx#' -ZV\h[ԷA|lqnZ#4%0Z.RA'aąu", "ʞھEt``ZBecY;p!^AA8 rOm\m[ 8> a({7G+o+,evs2;Z[czZK J L#7clm-~p[ )1P Yz-D_eD csc:Ą QLyJ!b}xYjbɤ.&j  epl;؋LpV~U"u0uaO˥X+SKebhEt,`a',UXsX_]GL4 4Q#MC Jׁ-n X~m;NoPht3ͷPPny{v*gh_&g2>Kl Fɣn=M2Lgg }'QWL';+NEsi,Q\ ޺UVa_$b `1vR-Ӿ(Hb3_z/E9#\&﵍MEs.JrÑ3o4.rp+oy`Wi8VGa'+\G0w*aw*dX jO&B8OIX26 U!Nͅ0%C.R,g <:{ q"ǖe.}pN9Ë*3ԻҌE]2VM&K@>jFqq~hl!KDMQu"~SB.F H@cIDʏ F9fo )R~T?;ow75Ƿ2o|$s|$?H-|˳Q( -MV#??>`i؝|WǏ*WVNWW;dE>$}G 1;gNOAU5L[e#`j.{՝ pdz qH3pN7|K8V1[/;Ў$T?~%BK=W4Isxsٽ%Au@m7I`v t~Ggی]$D=vXk* [Ѝ[L!mT0.ށU'Pr&NkBeӆ?NG-UYC=s*%o,qd,J6}D(<9#WB_ӿ\%9cJ'" <3Wnu5 ٪1{ ەlIvMp#)g ؑTX><wP R7HsbOViFmt'S2m_jU_U}GDdl~StӿoS]{ ?[o"}='|BJY|3OBl7 G# hBR?Ov_shr X0l<+3uFfHY|op8ԋ'.h ~W Fދpj|{ #8TP߈f`j6NYz$x6DJh1>),yu-;Z1 G5>ZC;_&쇭4dIbV6$ButSo 2uU1$u|F\0 dٱr^ >Et%g]RH h@؆pZ u7?QO}3v;x 4Vto sXh@.G|ZOw ORG0QV5Ifo3ʄd- :X~;*Rׂك6AbV}G4O҂[{]'jCbTm]\#)sR5_)}[nG`+ xB]a2&Е3':n2!nKR{yw _5$]tx^㸘.o!Q6@$4o'F\3LZgj\.Btj{,0W#9Dv^BSd4(}UmķDQdw['PMrPm!(~F Zw> F|-n͸,v1GhkQ" gأa9Y0*rY@ O k)U+h(Pێ^| vAoc"xMe /ctW/=$rT(J}bNZ6 (I]2h1dq0OiQNޒ.lbK+SkPdGJ]*=?0u!)4=ijؤOqE¶hW@49,E?a ۳YtEhbyaj3hCZwR4F=V ճNo `\N~fd:Xmnu>+lV<}Wp 9z)|e{)2Fj_''/džf(V3"Pb!7 Eщ5v͆nx Mm)1OL;ow\V$++|N[6_]-[A%dvF̒cNP"E2DBMXC"篴sc2pnQQeVeP5i[3lf_VM aUL?8w=HgO\P(?_~,HS]٪LU7:H s55#[+r܎+M" \eq}oY$?xEhF3wȳfcC=>]?TW M@2y'OvfCZWΧ]kO;!'0?ou8HpjC/R1T|)틼w9bFE{|Tbͷ e:Ғf5,efaFO,jNeȬ` < W;c"P-[MwUY9܁x?IĤy,Y"u[Vb„Z0tFe*|QBLkȷa" Ѐ۞Ul㼲 M^/g11 40im)09KS$heLv}֧8.-5iMĐU}qP8wMG~ [^=w.ߊxmzu#F A'RnЋXC䓀f-)8$B]q3,Jd z/@EX;µp@;ď4Wd:g̺rHDr &cm:X2j|,X i(^GJye~i$=t$v0h[Ҵ!>NjG)9AߟҮΒMMD*Z"PMc" }o*bᠠ>\y%c)\4JK%it<¶8L*. 3OiWVi&A^J)\rM@MDH‘Gta!ra@qF)}^3J#k2U A n"{HQ}C5.b٩b(Zw.Z*ւ>DmBUK_C`V[= 2~2$g9d:_A=9ݣVꩍL8&hISJIT2C(])dPp(־'vk~Wf"iKyL5`yj'{t"*dw7w\JiwP+Lۈe)nvf,IKOTGgAv̸c7cAd؂lϐ ^ثJaۦz™R49diWĥPUօڵ& ZU:#wl,h_;֞t49E-'e^x.Et%@^{*`2⢤۴; O͇?5dՆ#?E* EʏcX6֥eLtlY{&ZfyGp- #'1w岐t)g+*-* r6J32?㞔NY|&ⳛIs>b]wF$ʣE9T",` ig(Q>ިW(*֭,7YUHMd;GOmf5l}L[sD" +18ӋkZLuHRSwAQGBO[ 3fyȉ *% v`Bᓂv:w)`ycЎXH.OXrk-GR#Ld14us{*oP Wi.T~yZ+,è7z+~ciI 쌘V'Yt DĚHWt. +ۮ1 Cة[SP.{_n0<6UPŠ";X] iDY5^B&Oݛ1?7@LJd-;;D<54$NJ._Q2P#Bls|_6u c]sCwt W+2V0S7!| GspJ.FVQp'PO,&b ?t@fc?@H]w)1xtR4@g2QiSRS c3!l)6tPܤtZ2bN\ZqMlHPV3Vd?{8%zaJ8}y&qLOTΏ(Viv]rGk,3d| HX\M5l#_Ԕ[ǰm@ 2΍\,щߐc-L4lJ"Sm쵭J'5r2g> ŐnϹ Kdn#>Ȼhݥ2׈CYV͛yh?Y<1,<8<7UZ2=߿Ja*-h!Z/ꃥv!9IOI9o['.]sD+H2|.'w\WI:#巎+o_8HuV?٢ ?^AݓcYBG_dp Mc.id5t PZWRRcr+OaN`bc_+5[w~$1's" 'Wڥd{vwu/Gĭ,u7nZޏ5O ʫ,k|fub1Q%$n7XZ?H}\IT|ܛܙfўx:w*ub+01ϡu*\x3g/{5s~~PrL`tǕ-sKM^eGd$A5L/6鼲lͳ\B0]5'D9RQD Lmu?6IYVA-JN{zgTqsoTNf ?r)",ެ [\K  gc[Pr|` 5.YOӸ7s P?}G8h[]ݏ ޷+iA"62Ta0ZۮALgx9tս4.A&;_5?] #t_x{ ˥?߉HS ʬtoˬYm0Yv ˄zJJXr8q xeX1$h634cGu&2t$c֤c{Mr<f Qe,Ɉo5$fAL\RaYX,{U5\o8-Z*K>*(Oeקë$(^C]2[L jۤFDەdWD!ʟSAޒ7@aϠ4сW/`XRhwzedx4uԯ ZZ]Y.hOcLOJU XתM~wTeЇ Mh yu&!ćd&l3k_Py-j| I<хsQ6XAD @b##v;*9 P8}LLFbg^sB6"B{hحď>s0xHtgO,M٪mv*K[w5S^5ɸXN>uv+xGT l.kJ'2C>y&Ȧ *:Pֿ؉ LI|vV_ ٨VoNrjBOmxL̙EV0KBY#q!^ Dkz57Ɔ%0Vfx%]q0u|rG }63qK%:bss=5{Y'{ Ì $AzGt琹.ȇV İ2͹x"Oc]c#ȡl]"Nњ"=?'{//)c؜E==> ?W9I[gm0vͻfAKkd.@$1KGpX Ԉ @7)/݉g-Qi;eQC1rv3/䟹&j@D^YV M#pZ^^+J iPؤy;}20A#!]I1EfPs\NsGS9-6~tY >8l YM/Z 3[g Y%uu)t2ye_A">2!oE~GZ͔o:WdmMKӟfML fXNڼ=RP1JEspx(nvMg:ZeSsiK;aW 3?2ԃg8P]gv46/xrs„I}5,V%~"=sj MJ|=i 盟?VpwESQsI0|Cnr;Fb,SmϭձV] B)KԯI/0J,sO$!L*62 tlۿ{sl =zMn8M*jMV gʁ0LbD0[9~=v@jV%hʾ=H~f~SAQJ|\겐N vi&\?GKo\` qG]8%-eqJgzB><G?d@ E-wodm-O;'4X1=eVS[V/շN 1< N}y(s:mW-wap$_}`Y^/ȄSR~0wFL&cvJo/<=}+.V7 `s *}s e0f3'G}n ) %2s1-`>갌f* c+8×W;h/P(ކww&XNZvd^q2 ٙE\߅!1bGk5KEY@Főq40d\50 y>}1XW̸% @j3G^Xw` Q{AJY$z{˹D[;$pl$vϤ(y蘺<رq4m܎% E Pc " )4Vxl[ϫ8e[j'x +}h6rs#XY=4ߍ U;"bŁ ǻta0JJT}:7~ xn I^2,t:EDMQa՚ * l]/=Bxz-wnvIaQ1?rdXGp ;g43,6Ө. xklŻ-7iU6Z)Oa.(퇋QE$#X'7FMȷD1DI ]5Qℍp|R"}HvkνJUK/ʅ,W)xw52Pn1ڈSyhNyߣ;_YiZ~Bvt6O*V՚",viT>Q ф8j1}Jv'r?Օ!ReC9t.t'͏ppK-{4!a].-$8Dl/m&a8w+`1+hAIQ}|zw:d70C1l2uA8Q[.@JoF 3HrY&wf<;@Nbb (4 h PgF\5-6*F_Tyu=vj ;H `Y>ɦ+a{Lí /a3= #`e&"|zB)D247Ynk rUUraEl9FXg\{CԶ;JCDq'+(,/文RFn{k0|5 AgwbskwJ@x~b[-&5l`-݋1sذGQ:0;؀R"yG6_ Grc}c?i qmFtBP W:zUH:SRat 2,ڌG,_cI6}]GFD.KB!L,t|Bpbje֔MnV`0!-~oSƽE#C׵ap?~/ ]ZS_=}Hڭ# |&Vcq0*ɰ 9(Kx]y0Ar{Ui41(.EjRAc8N>I䟿jeaNgVP&nTUgxo5v#ZEE,ldZ\OޠE>LEHNse֩H^j5w!DOblwᕖ@ ~P^>w!!R{"%L/\w>uP 3drs@1ڏ$?QZDа (Jw❈)(ܺxVMC݌O8 ) :[p-gh)l7Oŷr9BK e9N^72ǩ۬#5kê^^Eqs"q,*5 .Jw@M|@u4OwJO3'wRs&Sµ@'q-!-Iio.RGݪeA:J_ ԝ)Z]£㕥$d@_ ePX j9l [0W|H]O)J뽲 ^b0Ϟ aa+9LYXW.dG fL@BgoAm $̊[ _7$P˾M,#xw.]$Q?3V+t"rO\6:ʸQכJhH= Cm/|SLAw0J = {©~RB =^Z0#p^k}XK (6҅;1/k]:}m?L^VR(v+E\NI4kHߢD=J2:q*4Kl*4"t0H;F~>rg=J.iߌ.߈ {%'< _:5B2IiJuZˊ(V]8;xR'NK0PZƽʅM7} 4ߣZB|+@W+qQpGUt-T,(;o[Lf_hs1dZk=pk*˒μC\!}30z_c8g5 ԨS' W5I "ª"u=δs:csq ^htPT$BC!hhNĔl7YC 6[~W(24̳,.>z(Y3 ":-8ҍw%w` IQݴ}@I UD*br]33O^Z7Ցj:U|iR;Y# ${ \ScjY/,2z>Y(ʵ,cExjU8 8,mSiN3|ƅ~?q,HF@:FXqx⸚r_% soȩ%PުQ/ (`3ފgn5E"%3͏W"Q[$-m=RyH $qgI6OO} + 4y2HлH'g|MM= E5cPgCJGd梘Cc8輖ϠZ/|?4+)E@G ~)8֌0|wtt.BLގpI{&kHQ KP*l6d熤KYW{K;ej+9 _k/'ʢP.:pm?Vތ8&ΰWʳ%uÔפHR1R ]p.=s8qEmu?tR)]'baAbb;@|/Tk#b%0{>[J^:|o.B&LewKyd˷+p|c`k~uSVG>!*#QMJ)+Jvx&.vNLPvس^a_a3L[ }J%1p!|访f4l9U\T 2 3@<CXnBD zK_/^LtY5Mt@e؝V%;RZ8r~/uUJ 9my?PӷV< L iB1Jf{g,Qc [jDpJ rIov :?NHDˈ. ںOJ[:d)wKP ɿaK } QrYr)?$նIVx^F+$Ldn7UIv'K[h|,N-a15fB/3uȘ3EPꛝNsLr(2$3;G%:{$ а/:"O?y_RiQ WP~c NmHH%Ji'@QV+h[T0\˨Tt'<Ϛ"+/\~cڀi՚zF"B w."[.RK zxAz"qQ+)hԅ3BsRT/ &B{8\kByh#꩑ zl8(jLjx G_nNqu\NP886eD͋7#;m9c6N%xMin7s?OGUq~ #ѻLeҨmXo?Of%F<-ZR `{>R%3\נKw%%.{X#QqǗ"v6iKel[cn[Ԯψ\i0%zU`%X#otk=mY}]zqI_сяF+JKQ@q ] F *Rsgɇ`!OUgn$yN"y+>온k8ˤbn^ʣ H6SB8k=sFfj( ` ˞Xbs0y1l dW' S\ӣ!D;Ȏ5}B/&yA1+RBEZ˴y!o> l<~7S`k p̮؉ ܵLN J:i{eG/Aj"N(!fQ,hwY&AGӣ֮w( #<ۮ Q }XZf;Rem@;XMK$bϠ27:HLHL%%?rShlJF]jAMeҜ?w9=kl5lr/qʈf:XOK#=m3ѻ4Az,n>AO_3CșmvVR./X.B(˼ɗݍ,}6I9 B~ )99أ`m>csWPk{ R6C!I)(Ζ8WxS&bM'2BϦ(hK'jє !'*Fz $0T=Cjxey~b_`s`ʽ %Ymb =ԾKڹIyn2ı]CAgՐ""> oznzO&4^! B*͏tv%Ѡ ~%lzƑY8p / f2ܭ˧Ov%zTPFaQ<­P Az/I\hG¨*ˢy11$3@?%.֦: kwuE`K U" KVkZzE5_?LM,ke+ֆaX,=KtR|lp42]ŒgH gxx|ʄ ~n;DA3D<|i{rz< eY- /nl|{P7( Ql}=v_(сG'hW?\8'OiRy^*Eڝd%N$~\j=&UX׽,ZɿΊ Sy /KhlrmDQ s,gHa%<+"$2Wy_{ety/|$Lz~Ww-6F*Z:Ms0Dpc.]Rhyq{dCge15ee6/CU*#nuA攲ȡS{BoLWg8B,B)=)EP309 BNґ3îzՄ?῅_/dZٓfB W39طWk5yT!7,> ǵ:nP"$ S)Joo{:9gRWdC߇P$M+@{fi^E Hdje/{<B-I(羅G@C`'3jx4G1S9oȠј_vX2"IDqCʯ t;!ƞZ&fA MZiǢ1mr/~Uhk ]uqx̧+:[SIeCEXunpN9$V#(%q3^Awk7Hm`Hh4uGB6z^"1(IkJjC6¢CE?ez()R{rI8}4mۿYj 0c#ⱡ#6} UQ >>= )8vuzo'En F>&$om؈KS+[/B]ZQ2ge)xo,Zp3{':"qQ} ^ frDq -N^A=k H=HǔG 'dNżtS1 s_B~Z<&1?lӿZM.иW/DtmEONucپviͻ2@µB;Gdθq([ʹ UyX+h׆%gRcO{/6V.l!Xj@0cM|%pccꋶjKb_t" 04e.WÚ2d`-*] w+3Bf/!|k&Q=U!)P9]c8>#o\L=i4&>W_4t~=Rhc=seeA838&t!Kz+P*v=TQ*&om}P8[]?W%'gJdf,4^Aߌ2Ds>ɍ|! =tLdaNٸ63Z ɨ,$-7ҥyX%ֿ˓[| M%l?boѠGUdy0r*w &G9WbPHwReFG%HKqdw"|Q^xdi&i9Aq SHܙd./bo AB3(2T!-uPKd2N >GNz+b#JCJ%x^fݒ4ӌ(vߤGlXot;Ol2oI /w΄ q8:CAY1]8Ld>E$7Qn#fuQrfPZX+>{>p̳?jy:~CRMt ,V͑ョWR?,(1,2ֆ\쏗=7 :z]Zx[jvg#CLǜ̵yJbk¾,LQgő4_IYA5Hz0A(.@|&^L Kͨ8FdX=/F]39z~I}}Xz{rZܻbD'1f^&|?LaB9!x{P{5XR4w~#"51x\6&֥-gnnwd!3{X Y.JODLnS6jm7@!c}|zK-?$1 dĿOͿW.'tUحqL악ct~=R%MnǤI"c/D#>>.kB':I$BJNCh@g csP#O%ܟk% `Fzʣ>~sL?vs3N(㹆n)~wWDL{6{O_30tQPbTx&p9i>d=8ߓcGf.7C?ԁOs.s. 4Q1 ;Wy>~͘Uk:I`d"f( < "qt+ϷI#mP]a@{tM\HBVuf JyV =^b=9;8oDTrF58 0ˀhSzc|{9N1ޠPKFt ']&lr\8&4HRχ0;K|'-&YvY Asmn|HSLX7 4 @肏PWh7W~gOGkPzZ])Y{-=z?v"yT K *BTş&<%CIY|V_qҏw E(έa|]BJU&UjѸ[MfuG%/.ȮS^ڌfwھv}R 2P]4d/@iuo`oyUY긿X+W;/o#0@nYlF"T״ $0hRMR/3,her/#ـw%<gBSV@5άԱWIvZo kN$f>- A4M$k^!zg#Kx,3|, Iu[?ʻX7xXӌ^B?J@&I!z HFM\[NaH$[Uէ@ U+:-[tqӽt6] i~)(=^k|VEVF9L>hC)drQnHIAU.iG-Mu.;@TO*Rd I>|'G>ؠ B?p{VTJN. '$+L̂?I0G>Cۛb)PM%1.ܿ|qɻ!}kG]G M2 /} QVy)CGͺ?EL>@4hFhgsNZ׌AnESoy\hܩM4KLy c|/s/*x:.bb`nt9rH)jUk>Hc;2508ԏWk܉Z tM~˺{.rF7jX~_BmalgyڰLYMA΄O ?2jAl'Y(:}t$SF鬽Cudie"W6*đYu9J<9liRCHt']<Xiz cW FFb&CL;=3;:ExՆQ͑T['_x!c̸ߥ2v"PE0vlY^3uGPGysj3 = DT~'LFsӆd<̆LByU0byXHp Jip{:v8Nʨu $1z.hQ`#iw_p%)Zfa*Wil4܊͠Li1)KPrOA$A*GAs7!9r BȆcL@+&y5A5xPA}Fj"(~8dѝ]FcGmb];{"v@^!B_y{`jr!IuG_+~R0ZFMݱŵ+tBЄX{c`dnVKo|43%FC)M ?)vJT{?3!j?.G[}z`u~!GLiX21-1$v-` 6}8FӨ~bsZ&?9|@H$NBg-AU@8TCX(8c{KdR^>ipc+ʗ)ީ<ڻC8Z uAnxc`@g$C~ێI{0v)o5r YG [|mD%}pvH&ybjۙ$_Ε&9%!ӀJD'Ġ1ZƱ+`SKk.J2#;8L|v3r'?>8 uu;ߑC^?C5$<\ $J*[AMXǔ$ƒ5GY]fRvʼJXK\*kh6M9_v hZ n.AB5&TyBVRTL.m"%!h47pj3w`'R;m&;Y7J@8}FYb7 f OLuE5NCF4:RGx8u=nfX~Y-?<4Qޭ3ʜ\ [ponݳؔggEl/,P*@sg=F@ y ޞ۾Ch0Jr%f,B9'ݙXRBʉp,fTQ{-(bիuT2R51Z1WU$3Ln'~DFl;6.}QINb?Pu5\` (h! ޙ{[\ i8a4Q=Q dD!΄&Ћڌ}fD L` RJ[o]5*e I`hOJט8vb'Kd}.P _ J^}i8Z%fCk5yXJFOu*7Q q35Ӻqf˛^qJ̓7cE *!J|tdK&tBğh}+jw$2FJ7XR;vM¬aT.;; 'rA Q'Esz aQ]7UI=֯'Z`77$O?`uP=S'Hb~gX 1[)y_ lO^>{Ho(uD)S;i'zl ֊ܴ ۆ᧓g1 >~˘2TqtkWI0]Bj|,ץMh뮋`P`z ]@gbȎE|(}adB,F ,I {쑤 6T$Ï<-ZoaT<-I 2jH}~D"j_* Ƥ!d%0:+ywWwpZ UUn]rz2JOAM[*2Gti)Pen#V/e8w"B@⇮!R9ǏYaʞ( Aw pn~Pgyj0qt3;djZ nXp "W})o*&+u;Mڸqi"_7x]dˌE[9voyM3cuXʲ"SBn#˼B_+`=]\i ;/G*[ |VHD `\D \d-=[!r,g(d a_R,^{e;]5RE El餻`NexAZWo5$QHŜ9a9@=6\Qly'[ %w,٪^k4Ogt_n GY$":]2wMӬ$d^u ᭘ g>+D;}|UwF#DD~* w&5E֡*找͓_( al߀⛩u!ޘv}UK>Nk9'$OabMSe-A):=q/`JaG,zk @O!CsO.ͽju޳\ɕl!HuAwJ82rJc|idP(xQ&,&j[A:.mj+o4:Cmf\t8n9ѹ~4US,uZ4<ؽ+L"'&Ĺ7Vgf>a9c %gDI;l% 4UI#ܙ@vtgI:S-(,{ݰ"@<Օ=3 (՚ޒđL\Qp"DrWcM1uatFsGZոgAcTяQvps# Dh22ADB߳6!4+1R䂚U׉]gd9Im}݉yyn&DϚTuMjZ''3FPtpߦ=<'OضF )@e <PR`I[&mЬ p 7(F"e3h4-xOU% j'\R'3A]:jy? )QB+zukd/xUWQZs Bޖk.J8D8pB/WNer^`4rӾxO(n#;|A; >tl 1(Z^\%zr5x~f3;TcZދC_Ea̓gD~Lf >Ʈ`qZM}&e*⏡I;(悈as:F7œki(3_S.cq,WUjM&qL(t"(!/#i9M>KrOlk V<{pGJv}1t 8uq1Ea>B3맠 3"SU71߶/;י~ԩ@nB$@eB[FWi笶 ,G\A*C :[>Mn SLbM{# }q^q>. 4o(AP?!RQO Va}g}ysfm1jޢAϒ1eIIm 5A:ɢYHH}| gB@xmb=͵ue7Ԣgyx]0'+E!~y[f[k]/D}녞ܛ'ҼKҤWK~{=ِ"_%h kq` ˦>qnG4Q+ڄng$~v30Cv\o@]0m?D)[v289}q}P^0ٱxF8~{,5@>-'AY YQKp;܈SQ'qMХ G`ΔfdI3^w("Y_+DǢ#ȢHh)rIya"J%QΰotP2| -G,}UG C8ƌ?;7jwrG[mףV0roeb:.'5uYe[,ZtA`Y7&;2c9Jy0tLG %+Yk\\~S @SWqTךn ,ej[D"J#E%+`A>Uz6 ld =6Ẇ5Gi,2v)o*T\7G=a|x K81#[D;2Rs(5JEM'Lμ%>eUtEԽV)+ȸ} Zr]!A}B<+'+ow8\3\zx '!ڈ׺y4+rzf@?l| fmt v6 '1~]EzCL*P'LO$av婓mTӵA&F# tv:ժ0RوLhJ.xi~(LDgۤ(?=e"JqC.L=sZwc#T5R(t.$B ݏ|8r4M`J.fZɔD,a NV)GE ^[)/RB )ŅOȋϰffl)LR[a7QyLii9wl]1ֆ񐭹FpYa0bHYEҟP'd{>xf!ЩlS)bTu 9t;Aʤ}`oovJ {#}vw 6fW1^Cq*C?r*>p/U\'g2-.& SIU?oc޷OxR1pe+D!ܯRYܶo)5ƥ%ZF1gcL?z/F e:Ȣq-俞@z͔ePca.ŸZuLAXެIBI{00YQĈ򜜆bO+!!dv"_K5k9KňrNhf4If5_b%Z (<68Nj+ `WKr*;}!sYX><^TL6Iʹ:_C|DŽE ȧw$\#SQHF-v"լ_Jkƌrӧ~;9+d(x/5yokRGnڍ.;B0K$ u|Ev=9#wC&Z-g$熊EgZ`7b1jUʼn D0[ٵ2VY>tRrR&>:Dzmڱ8<2QG ēS|Oo\Sۋ}I]}6Ā^ ]-u@UcIYU{Jbmu{A}(W=SK3\v ]1-Nnm)a(ǎ(0=fcZpB%rjP3F= y8VP{vY|ߵ&ϐ&h ubNld$;ϧ! 9 bى%ѴHՒD x!p(pjHp<G1~R_2(gmcY;YQVa|ywL5V}5گuy埪h_gj.=1Pq U8~װNG JWT+E>"vTyK*Ď Mޥt,vj$ș5Y#i,[h;9E.AD. U3%utg_6 D d*SkHNsU`뇙vQK/[_]~jy#vfT3 쯽4QriAM:z[)۰*cOeM2.Psҏ"l ِgg67a&(˛,(oɗ5$bDFGŠ-;/bBڃP&%+?X~sHNzvm8Z@9|5RCYOzP[}P7/CPS1sX4hF#zEO Gb96Oaȁ>ElZqFC] !/?rC2gK{r{[:bw߼MeV۳½<FrNrl'OlzG8 8IBs9(|KHD5iy' &xĿ!1dz|RcX;!MP~TN-\ `Y"Hi=kr݉2e:{d E \Dl4,<|˻ 0,ɨq[/JjaٺhSgnҎsJfYCs~I]-6>$x"mhcQe@#|t|bŒ</#ojF;*B%l}CER,g <:{ %:802p"%vx% HcUeKTF9[PC8\ʢPA"{a S/`jGñtCJIQ(Ơb^rkFgjk{. ^l7 oLZsC lvwkÙ14a̓=zg[+ÃlNO27q1_@\RGi5C(iQRJtyp3sf\/T3с*+y0g $- Z@vW⟭Iƻ]h>%fhLQR3K޾>Pl8)=k -83۴k+؎3/[E`W\XM-bġ4ٶ€ ;DD_bEHj.m& o9=&ha7 D ECLx ;Ft6T'y|@ 3$M%pC͛w4(T6]Q}\6SGgwLGRR/[94"4v~Y)t_,̀ފP_P^, #YGy(:azP0sCһ L>v8vdtAQk+Qv\p u^PB1%QלHoƘ(JP+a0NTVY'1KYD2$OvUݺL/CFIшjP`ū[CPYm]nnG5'>ˣJ][ҭ/&2J "_oT)BχHi hsK:yȯ GNz9&Ԋl^6Șԝ1i߁\!Ddc=u7yIqH"Qx #GHJᾄ?f۞r,TYRXvv&"聛8H~j~گmT7B/\_Ry~ޢmO?m9}NTJ}>}MQLMKoڿmKmUt|B-In{/KjgC2*Ԉ Y suh?Foӛ7W6]17d g˪2eɩ)@ ]~_F`Č`W -W2) :t&-;xSPu^ziݔZUa&_3E:#ŝ6Hy)3ZgMXH\/ 4 y1f9=MmȒ_kt  ?^'ՓLB%6|wzMD;r(AڳUs-ʺ'ajb{Md&+F6D#7j_E/G\a^r•*V`5҂R{17ܿ>NOOm<٘  hTYHjX l+NV]0"^ԞŒ^1Uqz3A>*ū2Z1X\257ζZ:\,6y@G\l)W$ZX/ *tyDm0ϙ8A]+a$#n~+\RvSx+!Quv?L?јp/<.gF"KtN!̌ɷ}+⫂sWc)dAr}2W: Zp3(!"\}'o8N5PjљlęGkHRNkA^ )!4. G'8eH)' #Yƣf❿껶6)%7]51r$M2_U()?8؋#ZJP J(c79yCldfFzOi*j9G&'ޢܮ|G?ZSݰTE,־˂E9C#Gm1cEYb Ƈu0Qjrdu;b )0xzf6Rʅ- !:v&p|t[ȿ-JG bW)rx:=$,~/n4C[2Y/ "J@k;|_3F>DDAlϵ;ʹoԃA>qMz)wFǜNb4㆚h1 `b[-e/)E9LloOSʀyfaG6Y+ ~c;di:6/rMhRLa-'gـt9SE{MN{QM*b-ԨsV)dJf$"2&}Rw$OFFkC-UHEo|-vD:T>8nc:M ׎?»' |Sگ%3рғK:{ҭգx" P0>!Z@UZZ0o=Wio\p\"],\eb!)R[DD1c,d:f7*1et GJqFx:ERn EėEWjۤ$>WJ.6jMِFK r.M88[:Dx0LdB9ҏO^Üni@ڝhc4[ M^O\kQf_"h7`XXT?"v g&I fJ0XzIU{"{5끦{L`Gs:]^qbOţH8UOD̍UA$=XTTLts%EkGj/b{$a\͵YIO1w0m,@YA˓o; kd-QwG!2]7b c%6ab*L|O;WԬ:&p@kĜLJ(&Uw 4YXMxC,J_NП.^ @ŭpn ]W$ BgPJWUݻ?i|vh˂gǩKi%{*~4ꕾfH^iST lX,5?Lz("̔9\Jw+6 g$wpp P;L= MQ1쯅ę~ɫ)3#α~x$y.gh$KB}-ȱh1> YێRa?[ T3hI12%~#C-_ǹz*h; dѳ-l#^6ŕi:ZAV9?5,7PzFTْy Ac)if)#U?XV~ӽtYu&XS8Z*z0CnBT&Z)ч$OťBƷ[34w@^xY^ł€XGX[L^/!T;ڤR-'i ia6@036NGglMa 4$p8}%|1iz<,S-&nNu#ꇴ_g'H^md^` Xx*tvöUS_6~̅Vǎ$۬5q/^M\Ci+Jn(/DM g\5uι{(R:I R?: ~w <1Hc59ІO' !lϲ8χ>jZണ9YúK8+5PU$ǹ^Jݕ;@Q&#QY67S0&퐍Λ"mU{>,Vdyb"蛥rpϱN1NIj~eiVd[G^@u#LsDExY`0R9?W)A/|E4ЋQ A I cէn XGq*j@vE\FU}Z?W~W5 ^ PS[d"Q;XޏPĜZ.Fe)|Ig:ێjEi=u Yڑ #P0ߐE\%0̐e/9#6pn@/es/¹F;=] })|v}-0hrPf %CvNECY EX&*t_pXd"_y\;'4Rd]jADR::;ZҞe$__&ȊAv7sRj:Op7BΰhiTevd|[e'IףبପV;XJk).jI+uy_O'=iKe6vX4"_=v"!8,t #V@xmVb|v)qKYjSm_d_6o׳;ͺU֎{ oMÎH-O8O7`.W[?K63kpH,; $g9Rvz ?Y ,给~+V]!НL-k&>up&~Go|uLMDqjbEˎm$w$qa_9~ܱ[ 5l[b?.'-&]X=Lcg֊ǚ O47ր" ]; %%`6`2{A9Cֳ#w?PqyF"5Uk?ɇA5]L_A,)M,7ЪAWBЃ6(~m"޳ zҥeDxfZPGs&ulA@*qXcs/Vuo4YWcRg;b~21t^͞ ^0=)2r'噝PgǘkJ]I+'o7b\/۷h]i-o=-c:tP0BU;՘ _kcU)9ZT 8vɋ;4l?'};79z&&(vx{sPp? ג "]xw !_gTx1#(,gP Lv#n; Efm0n˱;,8 N{Q"PRڅg!V9q~-CI1!?(lENV\IǭޤХ zBhzj>y*Q}O^an$bo5>_?CNK&hd tD3cYԷ}ޖ$,+f+-5H=.Oʞ#QWtKWRlتmW5· aDs*ARDVF0 FȎν䭳zhDt(Y=)`WC˰l8`ݵlM퀽?tI t|[!_8c5^Ø; dZqjackctl-1.0.4/src/images/PaxHeaders/aportlti.png0000644000000000000000000000013214771215054016774 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportlti.png0000644000175000001440000000031214771215054016760 0ustar00rncbcusersPNG  IHDRRPLTEpH@@)tRNS@fcIDATx-A E-Sk;8PbßV[\ya2)PpHx3;>{J6reF#se98GbIENDB`qjackctl-1.0.4/src/images/PaxHeaders/up1.png0000644000000000000000000000013214771215054015643 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/up1.png0000644000175000001440000000030714771215054015633 0ustar00rncbcusersPNG  IHDRasRGBIDAT8ݒ E kcؙLx"T⿐6-%g"k\ԃЈYШ'Ĕ$3S% s7 B3U 1ћ ϏlakGoIENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphColors.png0000644000000000000000000000013214771215054017421 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphColors.png0000644000175000001440000000256114771215054017415 0ustar00rncbcusersPNG  IHDRĴl;8IDAT8ˍKl\g;sOq&NBT4"  RJn`- "bX TX!RHӤ-A}ФMMcG<3;޹ JZHG,;g.qy1:S7Lu)v'$L'|m'|4 w*N9?x\=JƮKi2[υ%)L./S  CShK0GO#Lۓ_މ ꥎ1#ϲkNLQ vLm@ٿz*0pʈJXf͓*C7N2XBD4Õ5PUJ+Wyr.@wG]ȴo9f1eSYoxUp,ؘZww/orFjz1۶VIanܷ@iqJB]#7y BluUsE΄)5@ݧ͍>NO/mk5ZM/QbdF)H˅ۦU_nrpxHx;7f}.ȉeDhxq4/pe?)7.In9Ǥp` =S3l+"ZKdXZ^W A^)~+IENDB`qjackctl-1.0.4/src/images/PaxHeaders/asocketi.png0000644000000000000000000000013214771215054016740 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/asocketi.png0000644000175000001440000000137014771215054016731 0ustar00rncbcusersPNG  IHDR(-SPLTE #%;*+;.0;<887$=9=:>:?;@ADD=IG$JH$LNHG=IH=LK=ML=ON=]N#QP=SQ=\[UT=VU=ZX=^[=gfa_=ggb_=iieb=fc=ngmnhf=nojg=pqli=ffftmnk=us pm=uvvvso=roItq=trIws=yu={w=yvI}x:}x={wIA$}|4B$z= |=~=}I}I==H =:I==:$E==IG==&:=IT==:===Y,:A-1iI:hAhAI:j1,:-I}-.|º)|Ľ*IȾ:kºhǿI¼jI:h¾I:3I?ÉAIlj:ˈ:ABntRNS@fIDATxc`iI~N`S{'55Wj2N2),$'.]1!G-=N,ߡЧn2kGmIBzUJ}Sx_5qb`IPrNr*]YiO<tBނeE3N.Bj =v^E#ILsDX,).>'¼^^qr6nk.^TRCw,漀<%18 *ݨBBV9bu*ZU FN zū6Frཀ F+vr^IENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportlno_64x64.png0000644000000000000000000000013214771215054017647 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportlno_64x64.png0000644000175000001440000000343714771215054017646 0ustar00rncbcusersPNG  IHDR@@PLTE         !+"!/ "$"(&3"1%&'%*'/&4%()')+(.*)1,>*8)+-+A--/,F-<1231=4675796A?9:8F<;=;>@-R<J?;?A=?@=I?/`=AB@LIDD=HF*DFCGHF[IjEJHLTH4mHKMJ_P_T sMOQOdQRTQaS9]ZfWTVS``r[WvZtY%kd[]Znbg`2k\BYl_3d]W\xavd`b_k`Oo`Fjj fbdaf`egscCueEurchhigzvmkmjj/mnlpgytmolw joqnoN~wy;qsp{q0~~}3vxu}xzwSuz|yzt&}|}f{ >}?3nÃr&{5D,9>-ٿ-pwVʹu\f]JdžS_WlZ$iW7(Lʶ2?=Vt6A%{?_~ ]}-X^],Y~rG̼t \_נ oΏk"{? sꯅ?"Rʚ?nvξs1`wRk8$0]uw-{$yI q>$9ڴOQ.})ek\K/3KtJ΋e3$.XZ_MjXy\ a2Ws330" 0A=O$[d%[xfBkfmfC5ձ=7,דm5ϊzTumne.i hݍ3ȩ`[aʝKQ.m㭾|F]4tm8dm ?cLez h(#+/{.;h*gS9Xo'#A :* I nDtZ;'cpqZB!fWk8 rT~N87u7r۫YZ(b-0`,Y~Q?HDa2h8 t̀1Y0gb6M,sY6p*A^̏α yX xZ$UWHN JQ^x?Z nY('f V7 [Ev5# Lb~o0~y҅d?=cI55"<;ҡ ex(,a:C ćl &NF- 1M 4 C4n"GI]˩B=(X^]Q_"Y#[,dZEeſ+3v`o#dy>USV(2Fz- c(p %kl{I RHfX!ET $8'Q⑾}qPjNgF IDATx]],M=Sww #!x <+6 ;UTJJez7fNVUGGQW׿_4=῾ﱼ= yuYAf f~r^猼sƚ3Lso\A8xP)Ս {C{\_RJDZUn?xT:-%<[&|y{cڱWp|FJX]cM݇Su I^t sI.t$.,>|J꬗/7Lox?ןHgOXH3uE3.2̨BY8qa >}C%[JkQ^u^OƺWo9jWN.]]*"S@#IZ@~ow|uI.|コk0+N |ǧtIHiفO H,vX^Y>vlD桷!) pTk <ǡ^lnn[L^3IFWUjN=PX-$߫/&`D/K*SϗUkZ0ETP )o4k odpґ8kHQxfHghTHϮ 6Q-j)517 r0#}!d\[Tw@o @am@1up\0O)%|"|Ov4kyfgP;.Tࡊ8KS8NA j*|9y=#1a8bz_]#E؄HrUޙ%z΂MY D%YG+K6 R O.t#,~t{Q!:8v:+X8TNJn gP"W΀Ȇ=2$C{!@I%. ,]YCl}PT/vh<>bi_c.;Ό)},Bk݃Dv2+T\@4]+ rn{Ff~gCccxSY/vr,o+|!yC( D`Wu  0pa;?%uGj{̹U6#+<a1zH)n`S3xDEU7?[$R~CړW |l%xo(+2 BUasAf`7=ՍUvQ4X1SiE2b$_l^N>i%m8>;ň] r]̘9/[֠0 1@)X.FY! 9 I6$쑃%"I] P;Q-KuDDS顜N1ީ"lO3DϞ<_3&!, ^ ! MKP҉Wre TGAblР)0Ҋh8/M-b2w3|'P_CvIf,n%36|  B|߽ηE6cPzGRVf@  !c6Dy!0/شkF^vZ,(ERQT%6Id:Qg`Bz?Ii ]$-fZcr'v'y x!2T?G>a'Z  ”˚vy+ԢV\gRLUh :* ]]lᴵ #}oUvwX9i$,i A 0*:sPrb^<# 1";o/B[GPh9 Y5T BLn:HgCBum.o.aqa8>rQwO'p6gJ `["/+"#݆nsP x`ioc:^A4EIj4b+jHa PHl;*@Q`$j\s=fgXg"1-e!L+P+sMCSa_BOgr\Z -Tғi@#9oꢠ` Z3C1}*ʥo52i<`d`9ڧ7-ˊu!Šu]qӘG!vyTDbsĚ j"cM8^5]3vrTCCHqtKX:Ӵ9jv<)lu %8…+?f0N,|*&ɶtlk|A!8@i߂qNJq@&'2@NgQ\Dv>Ӱ;ɐҎ뚐MxcˆlF&3Jp(䪣YnGhKPVj˴$k^BAwG8 ҋ!.'Q,4S0$$sQDyMZwīb ':/P ;9*< j $&\P D8aC#~G:>87zEt ;Jɹa9dׄ3HbZ 2bs^k)&ҭu4m"w }m҉B Hv]g j0gvU₰k }GLXrR1Jc 0c3[S´M`^V !$Q ݆M!5ugp zNAs 3`l\soqFv} Qrp\qg(ׯ➻ɍC ڃkQ5s8zK/ 0PXr'> D޻`JC$TL|557h9`FeZ34ʭ5$v|w!─ku!ːq93@6Y1^$tt2{HM&lg R81$0ٸ%R”KT+ÝOhί,9&(JyX -cI 4s֎Do30Fd {tvZLHtȎp:zyq٦ZMŘ4+X-r+*YJD鋐(e7l3T!MjunlHSuG ^^[7h⻩O;"5BVĹk6~3t]5bj@@we7ECq{J:!Fhw)*Nt،"c8 Fk ~m :mQMv2<rJ)Jt56fF zFܨY(;9gu06ĝ=}X~bkUO\0 Ge2-FI"]S\g BXMc qPȘLd Piu>C}v$yh3Od8>rҶ k$ΠBg{M9!l;~9UyeT-HuΣR姕F"Ԋ.igzp&@  QZcp5O; c:xsy/LfvjO:H)F&J(=OXCV\g'xĠ6P8iڎ4` ȢtnZ1f)O9h }8= N"C@07ai<LH4Zlg8wf$!G N;!tfI#~VO! 2߈ZlTVUe!k`KRGZ"9f B} yr ٘]Dbz>!g)CVcfXT+ r@Iʓ+㷴3,:}3t=@_QOތ fBގ _R@8rD 䧺(Zl,kn%%(S"HdI0q b_u7O5!ߣ4L #ciC=\`k 2VjUBJIj6̺aepBW b`] yN Fv@ESF 36EkaGխl2j'(bbl^q)5dJBY`3Fnڮg؞xx'<9RL]): @*KPg9  J#dp}]n@h J.< rn]eP$ Ql@C$eeEfps \QG"PSm*pQ9peϧp4dK&hY @43YC@(ي*"[sTڢكCɝ:)Pv2@[;PeAszQ`D(uơ:ukaY9;5L_Cr)J4V\c?n@ _TbYDT+Gv:Ju;DrЈZS! [)4im=N,TVFp ]@FEIґJSR3lTE3hukY41I6 P҉l&y0!a$]ۓ!&{VELCk ZQ> Gf7yp±['QR`TzVdHH*%\Ppqǵ?n9d*rmU1)Ċi-:bR[ð"1J< }3|\] "ZY\=Y6IoKa]xDR.:T: ) ^wPYzh:Y9=sPmA?F(\`e q{~=:<==59;=;9:8CA6?0<=;FC;?A7BC>@>EEGIBA:5GFEB6AC@:J:GH6MOCGIEGD;MMJIB=ONBMNIKHTUUVEPPTRATHLNKSR$RQ9[ZPROJUV\\FXX^^B\ZZ] E_]WYVec]_;geN`_bd []ZLgYQeXec.Lfcki_a^ffBaD` V| /U2`j!vov otU0aPx?p\\?\9qi\^_7O-#?]'ܖI1A71t"˵@•z1p|+xr!NYG+k-rdfo vr'I$T !~e.uX|RQ^( 8Q&"r`O,9T`ƬA13gkY.Fm2Af `m{(%MR,.@̪g@9gJݲ`99d)$,L.3$)D4$mDC&Yqٞ9ecIf%< $IoeC )F-zY dtP"*#''˩=IENDB`qjackctl-1.0.4/src/images/PaxHeaders/qjackctl.png0000644000000000000000000000013214771215054016732 xustar0030 mtime=1743067692.320636607 30 atime=1743067692.320636607 30 ctime=1743067692.320636607 qjackctl-1.0.4/src/images/qjackctl.png0000644000175000001440000000321514771215054016723 0ustar00rncbcusersPNG  IHDR szz pHYsyytEXtSoftwarewww.inkscape.org<IDATXmPTes_EX0.-k6jhNeh֔}hʾԨ(9}H'QQR\ERy eL6me]O\kP3s?ܙgsy "HlVVVaHH8"qq1Spp^wI^^gf*WTo241QA.,p<]7=23NġCe/vvvnf#"h8lkksO;[_Ǖ NcWT*sc1nTZG b9A؀F8=p9骗_0Bo1twwompc$xTl9C-sq&D/v,I]xFZ1Q nLNcV|+҅`m"YAXȈ\4V'2G6p55ŹnԞCdM${cƒu1cN_=L!ڌ2KB>gC㏡姞?3:W<7oݺ%ܖH,]r>7aK*U}b8z[Vq i"dž"Kú-`ttLB. 1=2BtU8+~ƭxCX رl`p= W3LK܈Abӳo4͇;NZƄW-K4sL~WUɓOvơ2> V$I"ڶm+UUURZZ:u Hן_i ]vRűc4m4b`}ḟ$ h$FFF~oTR2 ,vW0ETZZBT__O&-$-+ $I\Rv.HsuC2+^m{ qM5oUHFIPTcja5=<ÚeU@ nݝ9jw㉯-=?`s3NyN&4 L5%wgC5r|M%`Xo,_4E &DUT73 owe?a%27Yf>\bĈgyV$&^>[\$1 T2r\E\q9k&=m B0?ot7vl>#ќ >kQxajuzd ǒQb2X{<Ӑ*Od&DUSl.rYMPiX2JS ϛwzM 2|KS?m`X~]}tjTUzxoX.; IENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportlni_32x32.png0000644000000000000000000000013214771215054017627 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportlni_32x32.png0000644000175000001440000000151514771215054017621 0ustar00rncbcusersPNG  IHDR DPLTE     "'.&!!!!"""'"###-$ $$$,% .& &&&((()))*****+,,,2, ---9-...///00(000111:8333444666:63999;;;==5BBBDDDFFFIIILLLUL}py*U*yx͚5gMkvm 9b$D8/[isO>\Twz-[Y )ڋ _=6Ծ >ky&+ p9 1|huu@lٿv=I!>.'@qBhaaan}l[;oAK#'哪`G^FM,^S$1ymoooy۲ ՓkE}ȟ{oZ#;+HȄ ܀*l2bsϝ)\ DMLK\HHd<m//HH =vo 8M%@0xիWفaH!āɾah4 wvvPJ)eٔP赦iL&30MS!ZY;{{{I6llk{;RB_]]} \N1ciW؀y˥!vC3M]JT*Z"x^4Xpt]G Tj> MG|>+VU v*^ZA'Onpn!P~Ζ7Y=95$O8*XGIENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphJack.png0000644000000000000000000000013214771215054017030 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphJack.png0000644000175000001440000000222614771215054017022 0ustar00rncbcusersPNG  IHDRw=sBIT|d pHYs  tEXtSoftwarewww.inkscape.org<IDATHkw?3?LDbL4dm)b<D[ŢAŃ'"%*AIRLDufgkwӃ&^y}yy]CL>\@x9UL6` T{ fy`^%oE巧H&gsرC=޽{b޽t:mر#o߾۷o[lXh[ ۶mo뺱n[[[l߾=DvŴ@ K)m{+W#ZM!۶J)f9~T*嚦⢒NݣG?˗_A<s8NX>ڤ~!eQ.9yڭ[a`6mL^vBbii-J\xi@z|cݻwß.!D4={v_466|]9rH{ oVaÆ[ZZ".]$rYJ%mnnnz~~T*՘I(R.\yOOv-kjj7o:xĉoϜ9tOrB51::*fgg u-`X,.;åii:88\~}!L'Dicccջxfx<6h4߿ʲ,l(<>U]cMa`&\EDS2|i(TUfZ[[lFu+HfonvΝ_>}T*ڶ(kK)q]חfȩS>H)Bpƍ={46md2CCCI@UqƶؐiOBn~/^ڣfWVܴ5T_.J"}IIENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportlni_64x64.png0000644000000000000000000000013214771215054017641 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportlni_64x64.png0000644000175000001440000000332414771215054017633 0ustar00rncbcusersPNG  IHDR@@PLTE         !+"!/ "$"(&3"1%&'%*'/&4%()')+(.*)1,>*8)+-+A--/,F-<1231=4675796A?9:8F<;=;>@-R<J?;?A=?@=I?/`=AB@LIDD=HF*DFCGHF[IjEJHLTH4mHKMJ_P_T sMOQOdQRTQaS9]ZfWTVS``r[WvZtY%kd[]Znbg`2k\BYl_3d]W\xavd`b_k`Oo`Fjj fbdaf`egscCueEurchhigzvmkmjj/mnlpgytmolw joqnoN~wy;qsp{q0~~}3vxu}xzwSuz|yzt&}|}f{ >}?3nÃraC2ŏ5򾻳A۞I(\mfl|$r_|',! }ˊ!A Qr94>킰 x0XQ˫4=8Wi- :tBtj/w6 t!!@tjQCu  ":09hz̸,2;8Y8A 7`&N-!IENDB`qjackctl-1.0.4/src/images/PaxHeaders/play1.png0000644000000000000000000000013214771215054016164 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/play1.png0000644000175000001440000000040014771215054016146 0ustar00rncbcusersPNG  IHDRasRGBbKGD pHYs  tIME#-IDAT8˭ Dmt ]C:~BJ%ɻpm7-)Y0"BFxQfwwF^c4 \$gci1u6 5ؿDXk#3]L 6^LBIENDB`qjackctl-1.0.4/src/images/PaxHeaders/xstopping1.png0000644000000000000000000000013214771215054017252 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/xstopping1.png0000644000175000001440000000045214771215054017243 0ustar00rncbcusersPNG  IHDRĴl;IDATx10 EWne;r$vjr!30)d8 8Ty# y=>sc7UC`DdJ)f#u[? @* +JD4lcgk1`q4 ܱF\9F\&UskhB:nY\!""R.o__:zX UE ޼IENDB`qjackctl-1.0.4/src/images/PaxHeaders/mcliento_64x64.png0000644000000000000000000000013214771215054017623 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/mcliento_64x64.png0000644000175000001440000000632514771215054017621 0ustar00rncbcusersPNG  IHDR@@PLTE   #  *.2#6- ;@.6H($-"MR-+0+&X6*%S ]b!T&71,h Z& >1,76*l$T.q'x'N9+[5 @>=~,@B5E?9+K>:z/ .EF4PA3-p9JG;1b>+LFB~8044cF8TMGSPNTRESTA\RB@iODWVT`SO]VP@lUI^_Kb\Ua]\i[VoZRT;ebULO+deOgf^efdqb\jedmf`V+okjooXroPrlexjf[5useb>`7hRxsqww`qlztmpb|zlhC~bzt{yubpSoNo{iw|z^zVxumofyǍq|ɕ|ŞΞХʭ֯زú“лǿܸŭɦʠܾȦĽ̜øôͼРѨӯɺիԸԲ٩ڶܲڸۿ߽ @LtRNS@f IDATxWkTSWVDEE@@D^*TZRZ54⠠($4 hBӀLAGP1Қfs֬ͽY+k>瞝iW`폱 y9tizJ 0$u4 *EGSSϥj#E"cl&d\(3T2t;" pj:hǎ;tRJ$ TJ"9*5 ןYX5@9]¾C"2Qa1YPAj||llIO0НQ(xާt-bH i@HoU] xdcy9 I820Gfh6 nkL=B7gG33V`O&zʝB0SIsx0V5ΰ Vua!}d5nO@V`gp^fzT*0U'T4 I*5ý K" //P9L;==}b;74jjjQ0|ni UC.. bPl]\P.~`JHBH@TH4n01{l@Xዥx;@)e^JONܺy+?[t,ǵ;׮e=lX(Σ L*ii쌳|i=B E Ξ 8 ܵk3`77=ܿ_; <+/}?@x zݾqwO,j$nQ:TUW~5HbO,z5;++լ/dpɸ8(暅 >?A[{ta߆sGEIENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportlto.png0000644000000000000000000000013214771215054017002 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportlto.png0000644000175000001440000000043014771215054016767 0ustar00rncbcusersPNG  IHDR(-STPLTE@@000542@@@0PPPPPUTRhh```jhdЬ ȶtRNS@frIDATx] D M ?,Vt+ <=0uZ|0Az? AH{Bh;@TozH#|no}(,IENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphThumbview.png0000644000000000000000000000013214771215054020132 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphThumbview.png0000644000175000001440000000130414771215054020120 0ustar00rncbcusersPNG  IHDRĴl; pHYs & &Q3tEXtSoftwarewww.inkscape.org<QIDAT8NQƿs쬗XI;FPPvXPh^9&EF4/{7.JG;u@]N403@5fI;nO TRESTAUVR@ ?CDlUIXP^_LOcdPMfeLZq^V_heXegf^efdWoW+wjejsrXqr^b^6tqivtgofCl{{gBn!>}pn3ezqRy pIo5pO3%x{XMugŊmĊ0bǍX,Njpǡ5¦|Ŕ{Ϩ_ӥ(͜nׯXزϟԫJȥ޼Өܻܺ%;vóͲ5“Aڶl LݸtŭUŵɦʠڿ̜ø2`nРө` ӰokS5˽+}Я٩ڶGيپܲڸ֬^rnUHxogtRNS@fIDATxWkTSW!`I Q$j-VJGARE@jG)/Ay&R @- Bǘghɳ?t9k|^XwϹ{Ln30wLccB7#o*Lgi*6P HR @,Յގv~⩸I,"H$%J^WW3rQaLv`} K p'߄rig۫6`}VXppp43#0L&s˹vb]`kw*+eff&'GEݻF}ɉdG"I$';5|1 aF`bRdM( 54T g=HR)THv66VllNL&ʲ3Aݷ L/2dB g 69ghRk``H~.3! .H6VD ~6 $v' hO*@dH$(糹 2TB GNFƍo@]T*%$ H? SconE]6\ ^ c o 3:>OEF]yй2 Zl ^#,<{_OJϏ?ydXX_ϟ|6S@`8=~׷Ջ rOB6mEsfCjPA0`~)yUCݯܹ+CY3111gjO"6 @/}E1k56,@xkZ10ҥ<=ΧXoN@ez-:9P ,i@(^jR=;ͅmū!~a)#ƆzZ/Xel v4/4D_';YӇP70[&D $3GKBҿrףW@CC}q ,TO'|:P=J;mn-,8`@SѨu%L AWK=^uɶ ~u> 40V&R Un^ET֬>,X 3uA.eAJY ,+ѨpXGPltHJЀl*7À+4N QZN,}Z$;@(ݧAW4*.!0ghAA|ŗ^Ęrm%Q{c݈V'pTnaѬ2i`Z7q}|B]Ƽ }[h`dE9 7x]IENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphAlsa.png0000644000000000000000000000013214771215054017040 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.318636617 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphAlsa.png0000644000175000001440000000175714771215054017042 0ustar00rncbcusersPNG  IHDRw=sBIT|d pHYs  tEXtSoftwarewww.inkscape.org<lIDATHKcgiQ8~"BI[(T܈X(LEtEnDAq (pSq!tq1(qҌ1&&NG{WM]B 7Oc||LvwwmhhЂ8::z7??_<ՅJ7Ҳ@EJ裁}}}͆a-N8dR5s|%osk4yV,˖e\%PccfF N7uuu{e2n+4r|8Wr5p SG{uA@Hz5ԞǀPUOuQhjjꇅBmBJy!4 )% q/ɰڴHT E6\.#K*j!6,Ky4MW݉PR<_8>>%}xj&?c`/O#IENDB`qjackctl-1.0.4/src/images/PaxHeaders/stop1.png0000644000000000000000000000013214771215054016204 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/stop1.png0000644000175000001440000000032214771215054016171 0ustar00rncbcusersPNG  IHDRasRGBbKGD pHYs  tIME"MdRIDAT8c`T?b0=L#DZt! 5`$0102ؓ`Ad@"2ś'IENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportpni_64x64.png0000644000000000000000000000013214771215054017645 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportpni_64x64.png0000644000175000001440000000333514771215054017641 0ustar00rncbcusersPNG  IHDR@@PLTE         #)/!#!2&( $1!+B$"&/!# %4-D'(,4)8&(&)+(.*)4A+-*1:?D,.,>^ ;=;IZ Ms#IJ;?A=?@=I?/S]AB@Zt?CEQfYy_bDFC\Vf Xbp[_elGHFJHLTH4fJLJddxg'YuMOLhOQO bwenhjmRTQ5`faS9v|nqs8_lTVSut}~ yuw/j[]Zk\Bd]W-q`b_k`Oo`Fbda`egscC$}|ueE?xw4~hig!jlinlplnknpmoqn-ހoNqsp(X~Cwyvxzw#7z|yztA|~{}|(}f{~}?n 􄆃xȍɏ!ԓ8Χ^}8絷ɵɩ÷ľnʰϵgftRNS@fIDATxݗ{LGqgo؁3W5-F ,AhZZZmЭ 5JQPc<1רسG ۙ_~L\ciX#ys,^F,Sm4B\2qj_=87/2;([ÄVغ01`w8\W GFZg]NLKϏX߮V,%aNl4yEV %P;fq^6ȍ9ѡ~V7U~Zvy09ŗ(JvIL {[RR5ۈKp_c%-$Mᕗ9l(xdϛ>QEslJ7@:sc= tٓGpڱ4#H\F,͚hHoAs i6|5Y5pI !88( =7*&PNIU5s҇%"Qeu;,xTfW}AM@V9?l 3pj2Ge vpnjB|bR֎HvbpԌW!^IT /,A6~,E!CP,69wIlw9?I,éQ nG:D'6.PYXs_,MƘE: `,`cE-2# .U$t Ē`+ g/^zZL8 ĶZΕrIENDB`qjackctl-1.0.4/src/images/PaxHeaders/graph1.png0000644000000000000000000000013214771215054016320 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/graph1.png0000644000175000001440000000440514771215054016313 0ustar00rncbcusersPNG  IHDR szzsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<IDATX]l;NRMNKDRi* PG7U! !q3$- *ClB+Yvij'R8?8q_]|;iڑe?sWb!5|?:,>K,3,YUܰ6r؍Hـ @G~ KjbxڀČ6P0d##A>!g ,~33-6c=܉'KRieYڕ+WF/_|Sx`.@RUkdG… g wɓ'}饗4rLRaeeߟdjJVcuuEq%aq @iV%LPR`Y@f_~? < kGhg>%M(r9d2 ܉𲪪b]iiiM6uVϋ/xˀhbEgyy_WDG=6Ыm7xwof!˲p eQV)JvcYmvn7,cR%>䓡3g zp8c~˲4 M0 0uUU1M4u˲$ χ,|>~mTUe}}EL:NM(JST(磹`00 dNRZeYض 4jQ%4`iqq1}ƍl6(X㡵.zzzX~7,T*4MömL0 g_[CG]({ԩ^}UOT"RTBtttd8}:<ev%Y>gmm EQr9k``iR5J%ﶽ+OH$;j {+ƴZ:swE8|qeeťjs*Zeٲ(ѻJƤsRNdu6S6CҬU@ߨ5kviRkNkiAtWkָ9u~3ߚSv Ӎ8ڞ Ã;IENDB`qjackctl-1.0.4/src/images/PaxHeaders/error1.png0000644000000000000000000000013214771215054016350 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/error1.png0000644000175000001440000000052514771215054016342 0ustar00rncbcusersPNG  IHDRasRGBbKGD pHYs  tIME !ّ/IDAT8푡npIHE !U;֍Gx,ef 4C  <x'x6_8ߵ!vΩ@[P6|4RC)I4/P/1|V+,%I6 6wmi*}ZЭ$}(L˥i6ALl؟2AN@>p~,Z5BIENDB`qjackctl-1.0.4/src/images/PaxHeaders/device1.png0000644000000000000000000000013214771215054016456 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/device1.png0000644000175000001440000000076614771215054016457 0ustar00rncbcusersPNG  IHDR szzIDATX;N@DQBC>'ٕ@#Hg9@n%Rxl؉!YAߥW6iDcLoRZpOg}#pů>8ZOD5"҉gι f1XYW`& p Xw+ ܴע"εS(љB192oH~M ǹeiw`],Ƙ;-<֒nU LxQ$S{YREe.`Sb$V|fF(UKRD^f R`(f )PC}>ߡ%mk t1u8ϓҜf߷!LExyXd u\I6ܐ1m9AlHW "!dIENDB`qjackctl-1.0.4/src/images/PaxHeaders/accept1.png0000644000000000000000000000013214771215054016456 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/accept1.png0000644000175000001440000000027314771215054016450 0ustar00rncbcusersPNG  IHDRasRGBuIDAT8 D#u]Ùt&U04J?{ ;/~BLD0@hd l dp^ ;=;IZ Ms#IJ;?A=?@=I?/S]AB@Zt?CEQfYy_bDFC\Vf Xbp[_elGHFJHLTH4fJLJddxg'YuMOLhOQO bwenhjmRTQ5`faS9v|nqs8_lTVSut}~ yuw/j[]Zk\Bd]W-q`b_k`Oo`Fbda`egscC$}|ueE?xw4~hig!jlinlplnknpmoqn-ހoNqsp(X~Cwyvxzw#7z|yztA|~{}|(}f{~}?n 􄆃xȍɏ!ԓ8Χ^}8絷ɵɩ÷ľnʰϵTbtRNS@fIDATx՗mlEva^ZDBYGQ7!警-4`-R5G,[I()150xRShu ), {?ܻwgSw/̂Γ 覽+Nu+*d0ٶDg\Wc"#ژ)fed @YPxdj)(oB'ɿsdTZ#3%Dө[ʳ2KTsJZVZ] 2n;)e,25ˊ/ ~ϧtȐKށB&(Ή'`65IENDB`qjackctl-1.0.4/src/images/PaxHeaders/messages1.png0000644000000000000000000000013214771215054017026 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/messages1.png0000644000175000001440000000047014771215054017017 0ustar00rncbcusersPNG  IHDRaIDATxc`hz?/Z>>zgD>?{u2Rt%ß2C@YăG2˷~xɛ/000%juͭl<`AMĸON{]&?Di, X`/,d??;/?rgs@ $T@*d``ULJS  ?^h`MwIENDB`qjackctl-1.0.4/src/images/PaxHeaders/msocketi.png0000644000000000000000000000013214771215054016754 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/msocketi.png0000644000175000001440000000115114771215054016742 0ustar00rncbcusersPNG  IHDR(-SPPLTEind  #%;*+;.0;87$DD=IG$JH$HG=IH=LK=ML=ON=QP=WT1UT=VU=ZW3ZX=^[=b_:a_=b_=eb=fc=hf=jg=li=fffnk=pm=so=tq=ws=yu={w=}x:}x={wIA$}|4B$|=~=}I==H=:======:=T=====:iIhAhAI:j:I-IȾ:kºhǿI¼jI:hLI:9I1I9:B77>9A9:??@ABvJtRNS@fIDATxc`NVf&Fzj`@_y}"KprZ^FdX:<4ISQP3G,`ɤ)ɬ) 0,iI@P=Ϙ' 0H$[ ,땠)đ` w8-)vB`U <;OO. X@T]_SSK, '#%!&**`G d%TYťIENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportlti_32x32.png0000644000000000000000000000013214771215054017635 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportlti_32x32.png0000644000175000001440000000257114771215054017632 0ustar00rncbcusersPNG  IHDR DPLTE 24   '%-.-/'&/045'(&--0/ 5625#-.68==-.,54BB7:02/AB231342-78463$=;FF685 LKRP9;8 FHJJ#IJ=?<QPMN@A? XV&LN^`ACA"QR7IH[Y9JJce4NLghhj"\[jl+Z[2WYegEPPKOQMOLdb.]]rsOQNDVUuu,ed3bb:`arsF_]7ff1ji8gg@fg5nm]_\!z|"{}Flm`b_:srac`(efd:x|EttFuuVpmhjgTruB{ySy{M||mol(Tz|oqnC5QLFsurtvsytsOwyv4^uz}RGy{x@O|~{u:^R~NZ`JlUg=XQ^qCTnVuq`Yc^NwXsbiS{deXhj[§o©bɣsmɦvɰxiϖjгösz֟ɻ|أyÿ¤ՆǁʆδҲնܗ:tRNS@f0IDATxc`@XnP"[c+4q_>{D^\ S~:&"biW^ªZ;Wи_RA^^͋6,~xrӆW1jw~ X>-}}/#[amÍ_p^8Beӧk?}`oN^~sJo~vyR޾ׯ?g֤#09vQOCلU~J3/3L7311}_FoV  __Oߚ@|Yy7lݳ6wџ[.={ ~jb3/m/}~Pih16%bʶmvRr,..Xeқr2Y`EqlqE_ 7i}piKqllq m,A:tږK[WĆ8cM5\hɄMsmG {f]ڲCQB{抛kWW+L ƕvοr_ǛX9Ε+IENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphFind.png0000644000000000000000000000013214771215054017040 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphFind.png0000644000175000001440000000252314771215054017032 0ustar00rncbcusersPNG  IHDRĴl; pHYs & &Q3tEXtSoftwarewww.inkscape.org<IDAT8]LSgƟ=ZJiRbF4t8,N 7\#1Kpɼ.[xX51).jYF0ActإJs9ywa1| \'?`!" 9"PT&iaR P[ZZ~e!D`<zJL48`9)(( ˲}E]I,?zqJ)3 0ƄQQYn9 !RSd2l6 3w2,,))LF[ZZ`$!D`2 "(L>??ò`0X;=4 X,@So1q&LDBzA_v!ڵk+ȕ555G庎P(!$97VY,Cu'<(grfݮt:&$_93P]QQڐLŊ9u~?YXXڹsDwwϣd2IPB!EQr|I$reKY,=''QJj5vء,,,LG"7583efEQċ/R6MaMӄeQuAE.I@}vjo04Meee^]s94`zz$)1&b1$I0 @$Iuؤ[*Jr[[իWt: \VVWW+VUU7?nଯ4rr*kFL__O6\4W:޳wÇ[hwwu:jii*:͛7M744gmx.pfr|bqH  jllfhTu\hPUpγ}PD8_x022ff,~b߿=ǽe9wp >ɓ'c##QmjjOL<6.]N>q8#pX,s-&dbʦXlmx )1;vݻwjbxxukk~[xCzSVzBldmmm hb1H$4uRBY!jDU@`}Gq3/ oNEb6y{ggԮ]~@ަofMlqa6uIENDB`qjackctl-1.0.4/src/images/PaxHeaders/msocketo.png0000644000000000000000000000013214771215054016762 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/msocketo.png0000644000175000001440000000114614771215054016754 0ustar00rncbcusersPNG  IHDR(-SMPLTE  #%;*+;.0;T5.Y:.Z:.DD=HG=IH=LK=ML=ON=QP=WT1UT=VU=ZW3ZX=^[=b_:a_=b_=eb=fc=hf=jg=li=fffnk=pm=so=tq=00ws=yu=MA{w=}x:}x={wIm8}|4|=~=}I==H=:==ZLZK====:===U===:iII:j:I-IȾ:kºhǿI¼jI:hLI:9I1I9:B7>A:::??@AB7tRNS@fIDATxc`nN`@_Uyc"KprZnzdX.<4I[QP;G,`ͤ-ͬ) Lii@.P=Ϙ+ 0H$K ,畠-đ`-O8-B`5 ݘ\KKN;:X@L@[C], '#%!&**`G e%0phIENDB`qjackctl-1.0.4/src/images/PaxHeaders/mcliento.png0000644000000000000000000000013214771215054016750 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/mcliento.png0000644000175000001440000000037514771215054016745 0ustar00rncbcusersPNG  IHDR(-S?PLTE@@@LLLQQQYYY]]]```kkklllwwwxxxtRNS@flIDATx]  Q<+[BRJ-1UTbr30 GEa`sa`i[!KHW(5_L tXIENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphUndo.png0000644000000000000000000000013214771215054017065 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphUndo.png0000644000175000001440000000126114771215054017055 0ustar00rncbcusersPNG  IHDRĴl;sBIT|d pHYs & &Q3tEXtSoftwarewww.inkscape.org<.IDAT8?hSA?y/jQC B J*v!BonB7AJij:8,BLJK0V?w𮱄Tk~w~sp"%155<.X le}i20g棩J|GgiM]!ذ@8rll8# D"+++dK@Wv\zxk333K_u,P(DV.kkkkKu~,y 9#{4M.3T*n ۶Bi۶4 #\ PhmKujx<4˲RKXx{;=+ =)r߁y,e_=`b ;, o6?ħL& |T ;N/DQwvZ}Fͷ:]+iV^8 |Vz~ J}I.U x"2>(wBމ&o(kIENDB`qjackctl-1.0.4/src/images/PaxHeaders/mclienti_64x64.png0000644000000000000000000000013214771215054017615 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/mclienti_64x64.png0000644000175000001440000000626414771215054017615 0ustar00rncbcusersPNG  IHDR@@PLTE  " & !*-0 '37$$91;!,#@0%C,+#EHM*5,&8,RP74)/:1WM,6:,[^T( \!8B>e!8D:b@B5,N5h$BB=Z26KERM~*2b@5`DIUJGWFTRE,STAx8)OWSTVS/@hNS`UV`[^_L-SgY26ebUcdPNmYfeL<]g`gf^efd@\rdHcpefojppisrXqr^dxk,RuselvqkxlE_!Lq~s|zl`qu~y~b||u/Y>`^tw}o}}iwxauMnAf}xumZtczNtzzc|umŌ{ʒěΝ˪ҥ“ͯĸ±׮ŭɼɦʠȦ̜ܺӿͼРөӯԲٵ٩ܲڽڷߵ߼  BT5tRNS@f hIDATxWkTSP5("@G#F`#6>Q;L5XQ" A IBxHL 1Q BZ=_Kǟ]]߽Y+9d޼WQQQ1+1[7*z̷YHEV^ \ |T %냣7W%))1H%pI%XHb!z1+:f]OLfy9ș+c;::ښgv!ca"##""BBBmNNkZY,--q+)kPѶE`HhhAhh{VgNҀlSO)fl0 vA=ٞUֺ4 ruupp15r枖$Uȴ1'Jie:Ar`ix:8<8FIB~ y3eqVya͚^CBi)dDjN֞@Hzuz]gL(!wao ɞ|&,N8yłXYt >BȭQPa׳U A_Bl`wUrT &䴐JKi)I#YEgA 5#>0A7sՐ 4QyEEG@?__Щ4klZ`Y ;tIufNdr3ӯ]UEg 9./8rN#(tS 2) D k]5`bH^tAʹ籫ꁁA/22) d).JiX}}.5i/>|U.LTBԂ@EKJx?KzL@F&Xd~ƹ$@(6&CPiyi2)\c0:'\5 Ri ngP o3.h&C80D"Bt40 bt5Y$%@pzG,` x.p \aj -֖US)`|Hq&ʠY k2E6j) ==텠`®QP!Ok\P`$0&c Q s %BTo #؃F~FQ(zzKt.Ԕ7,K> _!ӲE. 3e a0H %QT3PSPJAFB\)D]53xeJX{o?#~OO{8+K Pdz|hPevμݝ7_Oq+Ke .@F֜1Bt+”P+x1(ȀucmEWH8ԔT?p>)55GT: ) @ٳg|9O4  b㞣a8ގ6NAeqpUbр90=)P \e|Zֽ7/WvÏ&:s(fAS':xā!l >:xɄY0'1Q U}4,KDj~{_N=>`jL.?T2? OPSlcAee.0:~0:z/Ǻ!8Jt"؉11(q[|7n\S!74xxQSs'O_Fs}=zO(έwkpC):{z:{;z.jAԀݼvAO\՛YYYY7Ku4DGn >i -9=m߆)5Ur-IIENDB`qjackctl-1.0.4/src/images/PaxHeaders/status1.png0000644000000000000000000000013214771215054016542 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/status1.png0000644000175000001440000000107014771215054016530 0ustar00rncbcusersPNG  IHDRaIDATxڝ;hSaro!MERD +c 8頃N+M(uV*֤Ԥ49IlB3~|<exlIɇ#O, ] 1ٔCkΏR6pKARu-pusy>U !4:p9((KY\@@)'sFуߩg +#׎]V/gDⳀʷqgQFaݷòڗ4QH׋ E$wkZ__8@hSbsErᤖ_ |P++xíH(BB<čۃJO;ͥf5tͥj`ygr=g[ܩ&,KlMf=+ S`Uj{Db-}f&F |#̝Mͷ~Y}'ʲY-zVyfTB ՞ [+IENDB`qjackctl-1.0.4/src/images/PaxHeaders/backward1.png0000644000000000000000000000013214771215054016775 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/backward1.png0000644000175000001440000000041014771215054016760 0ustar00rncbcusersPNG  IHDRasRGBbKGD pHYs  tIME(%JLIDAT8˵ DZ&Ԥ9dd E"Vkf yzo&fyI1' xi>%?B HJw3!rQb,jsHYeLTM$O7(ռX%oNwIENDB`qjackctl-1.0.4/src/images/PaxHeaders/xsocket1.png0000644000000000000000000000013214771215054016677 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/xsocket1.png0000644000175000001440000000021314771215054016663 0ustar00rncbcusersPNG  IHDRRPLTE_^%a`%lj&X\\af[Y&cBqtRNS@fIDATxc``.0: & ؕF?MvTIENDB`qjackctl-1.0.4/src/images/PaxHeaders/mclienti_32x32.png0000644000000000000000000000013214771215054017603 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/mclienti_32x32.png0000644000175000001440000000313214771215054017572 0ustar00rncbcusersPNG  IHDR DPLTE+2' " ( -0 ""7:<"-#AEI21'M JQE&/62450V97+6:,1=3Z\ 3>9>;/<=;>=6`?@.^(d 1H69E;g#ACA!W0i/O9n"?KAi,*Z9s'CKG `8JL9>QEu)y%o7HPL8[ADSMBUIt/IUJ++VUMTUS*K\J5NZPWXE2J]QRZVJaNZYR[\I&z;2,PeMY_VLhO_`MUd^WdY2JnS4}Q1M\i^KuVghUWqRAYq]K|YG\BTgpl4OqpWNYIivkD_N`JfmzowxdK]pyu>[}~jbuv5Yzanu{yum|yEoqx}mv|_~voǎwƎŜĥѠРǩ¶ƺ´Ŵڰșӵٱ˿ɰӼŻ̢ɻܼЦҢԪձϼɺִڰؼ۫ݹ۹:tRNS@fIDATxc` _~o >~|(Aٳg=sd?gMTZ**r"+.]y`7g+ {ǎ꬯+o r1ٟyolee(r ؄^~}sg0<im+'x؄_;6ɮHג1iǏ_9kf; GѴu֓3W8u`޵lr".y#uE''(olD[vw6޾qԾkg~bؖN?4`ńΚbqHp9[ΛXhrl@q[+4yY &<nzcsD]??7;+#DQ@ic*a#I;<@S ?_m 6Q3f0 ߿+JIM sw =q8Uo?~|WO=ztٳ^:I+m[jժmmZaӚ5 , e(_ۗPnΌ%wǧ'M*=wl۰j՜Tj߼ɓw\tȲ@^^ fgjIENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphZoomRange.png0000644000000000000000000000013214771215054020061 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphZoomRange.png0000644000175000001440000000254314771215054020055 0ustar00rncbcusersPNG  IHDRĴl;sBIT|d pHYs & &Q3tEXtSoftwarewww.inkscape.org<IDAT8_LgZ HYD((a2()n. ܲ?nsQ?Lي&&ɶ /0: *uln&U.YI:pX&-(HKK}׌9Mv}:p8j 0TXjh\e6ukhhhСC9,/,--}b,2^W޽{8 (,^hp۩ )FQl,K'pxΝ#===2 shT!8n>-o;gې(e߾?|+뿯-욭[nNE';?eNR^^~ft/57 Z`N;zxSph-殍7h+OkٳgƻqQ[uXb`^3|*|T)V*F'544ׁTݻπ@/(>QŇ_|yVU  ܕ01L }"Ij:م>WUZVqA,7n ONNJf9ҔS䗗@߯H4u7-dZOb2̬ͺx;~Go9z/;"_ouYYY.uRIIɗc$8V9G9D?zlQUNg?KKK37mz011~'yN-(ꛚƂt:e5vvv}Sv+8VXXRBK"1 %%ǎBN;qĻ4,///WR Ioҵ X\rl۶Wz^W;ƀzߥHbHҕ u#۷or* b0]z[YY-˲8ya!$|vz 3##HE=` $IRڮ ---@ A^M:,  QVVhϞ=ju}oݡ wh\DRW\)AYbŚ AxHng0tS-liFi.aSuǗ...ݹ'fRJ73{\Jyy "qUDp&e=@DSD4_W"Z3;"3!C1fnRȭt)%٣En33\k=kP"!"?78~[?V=lrjGLZiIENDB`qjackctl-1.0.4/src/images/PaxHeaders/qjackctl.blend0000644000000000000000000000013214771215054017232 xustar0030 mtime=1743067692.320636607 30 atime=1743067692.319636612 30 ctime=1743067692.320636607 qjackctl-1.0.4/src/images/qjackctl.blend0000644000175000001440000062517614771215054017243 0ustar00rncbcusers]`TU2eƲ.kYuF&R $D$T>tz( !@BHEuU%?ͼy UO}quot/mHVp>3Hp2l`Eo zP=zkPn}Z0ۖS4sLZh\֮]K7nSJDիݟMҀ#ɸ0 % ~ky&SȮ /JMM%K(Uoذ9º` 4Fu <7b d~_q)rmw01rQ2(`Ak֬qa/裏hժ\92 OÆ%ɬ1c驺;tmhh.ڵ>Co s?ƾx-[&Z[O;v[p }]oyE ͻ{Ɍ?֭K{졓'O*I#㽡'@Tល[ VciԳ3\W1B}_z%܁u]G_==3J{Ϭ>l#o&^-_߀|+2K5k~,Siܹ{/}?{`jժE7|3m۶]5|Jg=!CR^^Z +hΜ4'#+/q 6LĞ/}l5qȽ{[n|˲9';h {fXD'hilqx28qС 9s(`/͛7'EJ7º&Z|-;v}S:t8x?Eg[h:lDC:{#opEvC ),, _lϕuyhĉʞo~'?㏿SFM r^uC]6i%lbE ť\林4/((`[ܗ;6o?yOa.뮻^z3Mb{K_Z[9rꫯVw_J_~bK_'?I)^gz՞5WU&)7uqe3osO.?\rcjp<]_a\СCOӌ/Vҗ<c~؏Ee[kp?¯cm`uV:x }gr믿G|Y1ɓ1؏g׳& V1JHQl_blٲdӧUߞ]taΑOtŮL-8أ|3 '&c-\7{O_ئO{A߷Ӧ{׳ό}%]@2^o=(xjc_|wcOV9o Om=D=SERbD/q$NY CS2ؘ߻w/~\oTcXTYŞz(?y }@-6(2(%%fϞ/ߦSN_''a?f̼ U8o厗~Тd5#˚GuY"1t⧫+s37`W 8 ȿ;`4h<%k|bh>,w 4j\jߞ`%~Iy˃Msy!~?KI=?~wx>p'e]k3.&n ?b&');vy>Gag?mY+;9=Ta=lޅ}c?2ڵ^p ?8Q5"U9N7?^lG߷`u`r?'c9Fac/6q ?cz\\c_~"?K?>-V09YJv^/Qk~JC# {^':߂}zz.Ѿأ|am4{%YĿs`?r(|ѐy\ϑy\] n?a[=޳M7g[<؏Hr.?c1chlKԻ(0__9j>Gd X-󸂽ǔ>{}=>O[KGUQy7_0D2Аd;*&_D)ViiM4{V4=߬{SKd|l&S{=.K|'5x 6t>cP_VԯW 2K#Τqфq ye4i*6s=͚.IF'?e]u>Gd_MY:P_fͮHrY͵SԳw9d6fxJ0ƍCEɢ%{032 1j*m#EaoMYgm:r/دdg^]Q_pQQbB}oӧCiYF)m`%_̲9&ޘٗ:Y}U+?-ߪuavڶl`Xc/yVroef+:!؟rϸƞKGw1O4_~|}?C~ڧP:oI4q6k#͞-EWhmI2"M0/>1V=u؇<{}Z ʝ/~k^:/Ny wC$)0~?CtN:xlxx y8f;>-X6-]ž>SUTH6u܋]wޤƴhz31;VLv^/>/gƙ3'oNoLCV<5ڜQ6ݻђhА L:`Vf&e-GrЪ$xDpq^r{v(v]دeWDJ>gV< nNk4sNglqK3 rdl{?Ng۞u>G_߶%WIEg' {Ay>M?Owoim()zM=߂V? n4yz.Y }ޗ !ʶǾ[Il]l_s~6m{=@|=vtw ;ҧ{E(WVˊlVF}չJc*->?ft]T/,%{D32Wv]\`ߚ"-BwWf?F?#m|o^ޞy,َlBШh,oWVVayz璭+ fK.b۞e>Gq\~ˊv~Ӆ>;}eOfo`~W(sRsL,iv8BקûЈ/<6d? #c3n>yQlT]Wawr>Oc,Ooƞ{uw7?ߑD S[Y|>w+3%ge]r;ߐC[k>Q_2w_m{fġ % У>̷*\tu\tmo]}Ů|\^g|؞ى>>ڍzVcE^"iy޸- k/fϜԚÛc."b-en>Oi|wՉNoxoY+wO=/riQ;؏%6J]؏}&1~bd_r/}' l4|6' վ"le_1%-ԻgW:_[j] ]F .X)=Nijc.Oa/syz_IIM\Wc_.O24)C_Էk(^#hƐ}wo= M6sy>Mdgm o{=|y}!Ɍ.k/m{_<#s<=ߐy\u5g}דc?cvʮ'د-h় [/o/~{ل.,cטw(M3#u#}wՖ~Qϲoi6R Dw_W^˶=]ׅ=1s;r gO|uO%rߓP{~~=c5 ?[llBmw#D}Vd=ٮ.~z>Gy\q`t[߽C;s+ };bLچ5𚢆s=z^ebם¶cضh`Mk7ߖc_ݳ,WG[~aOyMLr//'n14\l',sloî5fqe_oh-i\ }Mtfk\rv=/<}~ƼGDj{yXq-MKΗc0/k z\m}~[ȽSgٮrd.oQu~5WjOiCTGsE<>'1S}ʼn8$ݒ(r/>ʮ5>Gd|ݘՆ[*7W:+>;YS[|~Y/Sv#r92kioXDju ^qy;kה9sa?_::#bW~:/0GZlMv ؟5ߎwcM}{ׂ_"r>;2w?I=;ۖ7~La:BWSxUWoVߖk~cZK~h>GgGmܽ׭>S/roKsʻ%E绰?ЕNmɽ7]~/{mMyb,؃&opZFFjGl;&s%:|߹d_]軰ǽ`Tۙ2\$7ts(/}gv=ߐy\=oߖ쉯Ga0oy3ָgCN))6w˚<Ɠ=C|wN ^ɣϵr뱶Zt~˱6 u_^1Ry ʘfNxE"}ϓ_ 5͑u؂'KľG_O}t#󷣍=ei`|W n")n v Ф+hcR?c|+?m^o}=%_{`^oeWPK/7kuY˂}寕e^o޳J-GN+<%F$Mkyg|~ԷgDv ^,Pݾzⳃ{أ|Y4 r*Q]FBsfӰyBJ{LswѬE[Na?X{/ 7c0{|ki!j,ݵDz5z_FJyhuklhCԿOTq#ݸo|te~(Oy칲U\e6d^oeqʃA?ǀ) h܄)4oJNQ^1+ R>.a>K;b=MvK^ l!sjX1+~&Ϥ7fubYZ*p鵘 6Kk7hmE7u"Xm~yMqʉxq~CR=Pg⥹4dT9L}}+ھO|I ߧyKh~$c;Оu#h>kV_ {sߎ}e/`/`ٟF<;~2 y?ɔFhe4l茢5=QƼZSH9m(8JWmk*eoEYjF(]s.krWOsq9)#8NOZ4qlZǚ.oѸ3h|"#(۰߿{;znIyS~+odgNc wã~zh3wL`(-WoҤY)i4w>{:=]L7(ߴ>mb'͜8{%Rbi:nܗ+?]e-^&8Y_i`elN̢9hѲ:3h@0Z >Z& 9. mTZMMdvKێNҺڵOsӖJkGbV >g`a/hAwP.[`pbL&3fќx9s8{^;u|Z~FN2:5VPs& mظ֮PmÓn?D[{'MO8`Bڼn6mX5e$hVrM^%yA* p/F37SN ZredӼ9f^}1>Z##fflY潱PyTЂ;.@gnO[u}Xr͚[H 4}ܥ#;3".ӟ5h؈dJJKlg9y?oy+hہ졜1R6Xr&L̢9S 3 :{ 4l/ys =ۼ=?q\߳`4&߼]OilJn95{)K)mVM{3%+vPp|3.:u̟6=ƌM}'ӄ1: ]E2fi^Sͧ7陔4mKw n3^THSwЧZϺ>22/I o /,#8Ѵi|1\4J;n\wn?βsQκEz+HoeOF_iu,oъ{x~p/KN[q&M)][@DAl27}Ri4c2Ja_3Pg zd#~ѺJ'|D3S3i%uIO|CoXypV8i 'fe](f小bz=fxd8*\Bv/ȦIoߍ3ЬY hbr0!Ҏ>*Z$kY&m*-sYޗw׀h{'|e>M߁d;~*a?fm$c,ʧomY+wl#8B󲶫ͽ ܯ.{:$շ_,;-}z#p|;~ƍ[ks]׏lG -7$yxV'O7}^Hu{ hcMPP6۟\rطu A]]kdnyzFy_>R(U]bF5 ]=㢺g";!!Gw?jLTH!p p ʁ J_Wun"+^Im/_j:A{~l#zs7y[>#Tէ5?aǬ~i\v]_vQW uhMỮ1|Oc렏U.?hK`Pvj1$ýUjoD}־?㟖7TdW#u_UmΏ^ӪvF|Jޞh9hAGGj3&ks>4:Qoծ5;7گ :\Ff}[)#o^EϷ^!h:&~{#6t4]b O:S!=7qtg5vkuiՠCW#]Z~#>k֟G|Пg#]=>LtQZ=޾H92, ~V\L:kTZ +-cpulWwLw[thRv^ b Uנ3aϿI>T ur:&lrZ궫l q:}&xp%j'o<.5gUकmI] pu~x~1GLX׏qLBȑjخ٪_)f0B DGcQ֐Sl4ۿQ*T0p^Ђ-@p蠐n3f\|HG_rkoWQ\iӕ/ pzx(yYl[x&}.q_^3tR^q1p얗lWQ|_EAyϐ;o p.(B"_KEa#K}o٤-;۹`FiǨoRgLʷ44O|Cٻrg?h߸QݻNhwDSu5ܱ? zYÜ8 t%{5}YZPЯqnn|.C~ϗϬVw# usnT{a LcB &8d]#οeN^;&o~u<{+ =:͟VpqnPcǪիU=8*oj/沔W>\g/wNʫm }Z=}t1FYg: $;8!㚟HzXݥNx6[P]M[&tT_'<WϷ3dðT^$NzRݻv=ek;kyP2t^Tՙ1/J^s@d!Ƒy_ݹ.bѨQ#DFK0NO(uv23'^Ck 8P$!d`zh- ?\ڪ-7ӔH f~YIJ5V \PB'ָdqK }z܆0Vq|.7j|UTŲmذyҸ-’3*JHp @Ds.'˛|;sTUn<}v<oM}m\NīcaWHv?2.;=;%!컍#=7@WG!=Yˈ.;@7M!=Yˈ:Cz3ۗ!CzaB9tDzn:=[C<еtHMwD5?xsh:t\M@gQ@wZ!=տғ@WS ݊t0MtD4=UN@?.  =t/z}Mt>nMA?M#]NMtom-_Vg5=E #>kd"__G|;4=߬G|jz G|ПHEyiG|Їiz|}#>hzE!>4=}#>hzrG|Oi.."__iָ[8wjz G|ПHw#>k~*mAV#]=d #>sdaw?k~Oq/Ymw^:oü_TU pA^*^ġĻU,a2JXp o}zũЧuspa{QOV9fsaU-?@vJ_X(씳-a 5T IJcZ_U,vKOVI3?8„WF℥=%qapA 'Mf^ۊwU8\v|4ԕޤW{ fs{>*yUK+oKJf2k" .r!o;PQH6VY ͖Huu< 9zڦ6^sX ΛPy]Ӈ܅yO(ևNϰ^Q-C\WdtG#%\T$tI{JbWlF[E>%0Oܫo]g!a{e?#?^!nG񶛼|̄r/y;Ż?uW0px徶Ͷg3i'w،Ko.xtՊ m}lm,~ycc=pJN W="L9|SZu=Qtpև=jO`R p8p7âϤ/j]"m-՞= Xݯ brDo@_ޯZb52SC}>ZqƁ98CÁLׂl˫! nժ+[8p1. W`egN\; :|Ca {H#G-Sp/WUoY%{XT$v\ \QE66%v[$]>>rNv#F^Ű+:=c Ivl=$%~a*N xU{/Ȋp1llo j[Qh fH/3xߏ<(T"% y\N5آB/GqųEZyiՒpd &GE>[>5;K,7Jy8Rw٩=+5=Kw ~ fvq;W+ )`]3vl_;3;UW:bnui|c;̩vMywB5|hf[W~W=zo [wЏo^o{c>*[Uu⦋۱鱺#lUq\PBn,/; \G4fB.rK?sד5H\xX:(,!Y/pd &Gpy1*v 9k U 7|A`DX7]V|Ui;+6N9 :ȯwN<ѳ!\LdZt{q,9]y ?ᗜw8RPѿ5. wpEq6$|Xwޞ`\(iQ!-~سPy*ԞY&f`F}ߔ FKZɭoɗt<ߏD맓jYWt o.qi 8:uF58)E}2ނf(DF[>! sO{deh֍c ǜ4n =N 2>[P7"?mo򯉅[zl;_E}nܼ抪v*pZ5˨GksGEn Ϥ}?R^s6lfs o݇H+,Gs{wLctH| og8oղ~l ::io#WS}XoV_ebk̿8_}zuy8BA=#κOG@Ӄ+c-ʉxkx!h:܏@7M!=бG5[@tHt_Ix;讪Ix =7qr"!i ]m~:~GG;i\\ڎ@?.ED@KEHrcYG|H/z}G(w#>hzG|?A}#>hz?⃾G(G|Ї}א.==⃾G=N:}HG|;4=m5=]m^!>kkz E?H=ީ.zXA~}GHG;{_:߁]˩?=ZS>(@XgcUuaϲOӮ`?J =\iKtmJ0ļ A{W:Ƙ%UyUw+*h+3% y;@_@82q ]G]\&Ub:&.V_ӴIku^CzG/^I^i:& װ4?:ȑ+er^K糼o~C[, 8e/U ?+uMtج$nJ5[{`6yjReb59-܎eSaMƿak>O:`+.ЇЇvm'wI15~Cc9J%h~Y4#>1 uz3 wZB$Wof]sf~-$F*^R$rҞdK\(R].șvl=Uӕo:p.y.˨{+Һu"loe] 2* bTn|b ^3H=׸>9Uں{i UtwyD*:\P_pEߪM@(sv.T]'~=~՟WnB˟@5ǻCf.n%.Z]=u\bt߱OHb:\؟s?{u)`.k3d&kǥ}&vG?ysXW.wCAϥ7.Vw+u0Ƈo!cۗ|w]k2l.՜{74%^Cd=zܗ3lW#G-!<8aW[_dH=,}|.8j5^; Nݎ*887e6[-3C [%DƁƯ hY5R"T/\$%r\&t E=+uYWd}7FZI og'lB Awl\؎Q㢢%KkIApJ++;9ЯM}&4#9>ĞqQklǶ?p~Ua$rot{gj,rn]6Ԓ/z\6l9Kwxo!1Rq_J%.8/UNlM\aw~;}4fݑ{#E)UviЕW0r x)T`\YɸT~%p.'2I,ruH-J6%},؟=QooIr^j Ӆ-zOsP5׆x-`GSYNWLN ܛ1% p p p p p @T7p p p p rp?{1nGS׾zoĴo4rߪeN=c/{+QoN}=;-.ݾUggNUlWJy^NBUGoC<5sQC<yӨ']b O:]Czn:!h::mG9ta.'Cz;|NwyxtHMWB~:CzKIxks-Cu:h],z#>4=K=⃾Ghר0MtOkQ+=⃾GG9۴t 'ʏHG|AH:4|.gCG9G|;5=]!>iz}nmzA_G#]У#>rzC.}A!]Уx/O;XA?$ʾ.=5jdx_6{Id}w~X'X?e}'{wН?\R$85UyOn r=c o}QK$-dZP_Rg9KweTd-[Su.ݡi1ڸZ7켯y&c.xae>KRDT)4.ok_bk ;eZݎO;.$Nk\t*,p;U.b_]rd-&X3CO|m!Im> snÒK~Bp/dK+U8?<_ԂrGTw>_ q{MUiIGk~ޅ˛KJ6636G1pŹxEθ.sT،KgqG ܌K*g ʒʕ;uO˼8` O9Xy+9&\YWޮE!s3~f/կ4!1H[E խcT\P?w5ctb_36MGjpxtnGv";!!~)8 *Jȁ@trO;UUΝ>.j_hEa/=/u3~6XWZe׮~vM.gW{.]?õ$:?Wv@A+v7-=LaL+vQ}-6ʿ'k Je=$jTÖh.t wư}W6(p.xpRK[\pT]՚/5tC_VYSUNn}Mzj!ـ𖾤RDe~XqC3q&߁k7qg ׬f tszZ\>(Tp6[?ۼUxO㧃Jy%S^_g=(mn{\w+'| d :!@߲a [ Ԁ K{-7}r,]ͧXcC:^s7>9&k?'ݮ}#'G8ҝ|*}2Y"=ޞrTZu#|_'Oݭ5pyC9Gnq~zЗ1Oi?+]c13py[Ev1ʝ1~nf~2󩫗rO 6]'ݮzwWSRIUrEN1ړɑnW9{T\ظ:cXsl-ʔg- O'^ÿ@w 䜡nWn TpvCE\=knOx >u |쳴~*C_߻VKwSE%DvL,]ncݬGn'r{z)lO]OSlτ=<-Eͧ?[\= zl}'|riە+)}竑}2Y}ȝ Ott ex'́~N\6FeՓOi>=ŏorM8'|ghەg7 cTRoy)K82ӿj{ |jە+:9oQ||;XɑnWVRvtK|6,w§| OyZ?ve%E=7sRܕ^e\1|6?{o% | ~ʒz'v~fx\V*_ir>!:7Zfk8[C?s| |²~L#v/-U^>>/cO]''?vͧ,?>/sO]Y<ٍɿ_^z(rfOOt.=O%Z?vHZ4RY_>f üR^ze#?/Ue_Kd'| [խKSؘ]K.+^T.v}$q9^F/OeZ?ved>DwȄ.+o*(u~ցO[t|ɹ\''c~| |O}tɞnW;KSofeSNV>K~~登Z$rO}_ |Vjvuw|zk哿Ԟ|!#>/cO]OY&ӟ*|z>/3G'ݮy%~YۓN7ត% |k~J*PZv.3#\$*w[y |jە~(󕕞Z~ qծbI>/#W'ݮ mtɹN'ݮL$5*!MO|'|c-a O dߠnWVRSzݢ˔^zAqx7XKWͧVK{܂O Q'ݮW2//j' r >96iەDݢ~=oudKxPuokʳ| O/SX' 9G5ET{y#wl^34B OW >xǛnЦiKG?iL%~ʡg[{jې5hӟyd'sOV{O drv\|שLט}+r rK uKܘhO I˝nWa5%]ma-1sT1ў?e='|rt65?:FG{I'Xs).'[>Kt |]~BfW񐛨)e?8oWl/Gh>nc K|_'kZ?ve%mUa󆢾;Dq lzTQx2>nWVRW={vN,Em8R6]Em76B>/#F'ݮz򐅥-ƯbG,m_zT)x#XF|_'gWt!6&6.#;RK__ joոG tnW&ugdώӭpyC˖G)OaOaݵ~Jg.};Kt\do3m֒9 |==|_'Gt9ch#\^mP=6?( *'9F/O8t ‫fC5R ҟq)?GSS/ɞnWVRJz1-n=J/oo p|/rnLW |zjەD tûF{sCw%T_!^K'ݮg7YRWsY雗1_s=:g#{ |~J >?sgT^1YrO0OZ?ve%E={WrTq=ӪK7i5ݞK99O O'ݮ<8z`ko7jPEuiS>P'ݮ6|3S5"5 |~Jzv):*߶_^fe\_`s$}/UI|r$iەzo{ qU3)C2TZYO 柕"FykVB./dzO O!Z?ve%E=ygBEN%U^e\;ui!?j K|_Z?ve%E=mGHl|/cO]YI=nL\|.#Ck8|S/;+O nWf)>STxd\Tdi8àP?2V|W7~.'|;~JW=M*~ayGGB't)lO]Hԭag3:z[UkrK ;;hv Jmlvg^j9֙O nWfq%/}O]YI/K@r *k=+t)lO]YItq(<&ޕš~Y>h*>/cO]YIQ向Ry[)WZ |¾3hOB>9'hە]OM*җ+3WnV>S~Jꮧ]qTy :MOV;^'| nWVRS={ gAr]<OIZ?ve%uӥ¹WځKy])z7CB>9'kە]O[KkMOtY+a |S~Jꮧ1`Xȭ|K>w5%bO 6M'ݮY5V4|p{wW|zZYO 䘮nWVRk="~5:T[o7y?_»u{/'|rjە}A:mٴFP`ĸRg\ʴ_s! xP(LAK@5H4$|jZ[xaX (^ah ( FKs5}=߽,,; o֫ix}r]~w//5׫c짡d֧! C;+gO)9Ź>_Ok'Wih7!okx~\?aCŞcgX~~xso~ړmv. 8ߋL>xLd-' p=9/'ia# C{pƏY~b^qa}8M'-{~5|OXlkQuI>`OwE~a?WOX7rjk}7>OOQ="vd?_O'WqhL7={ci֩~xst|ǟT<&`%4>/AWYӞj}b_^š|TPs,15 HS?ō"߃(n>_O'Wqhr.lYcqi )ny?&fOS֫84^NcGgo8x'=E?M{T *2.ېv"?/1~*~zS]~? !~Klwo 3f?_Oaz IF4.!on'nw\Mf~b `z I퐯dF%gNgr̘~a?֫LHV9Xψ{9` "vd?_O寇~bšZ!_ 54~K\|3ik^/1~ ?aC_%Ovbo;4~fuvlkcF~zQM' U\x햜tU60awa77>8^XcTO U< ;xG1;/֫8f=WS>K\~rBOS. UYu2-q~߈.ՍOSa6*I29g4x]#0/@?qx\P1~* ?aʄo3i?A+UkiqÙiu ;/=֫84^[ii?Ϻ%. 3f?_O{'WmaɘeCuIΟz>ڪE~a?qv9 LqJc<}ԋ '彟*Aa }ng0Rz/m\H\e|\._冰\n-o&k-׹[ucX>.wy_~Zllђ/Oyr$m+pʟN?n-"=gA5%~f'S;.˷ aܜ3g} mX]Z\.o fy.߅_81%\>.oq9O.i9űesHc_m.|\n6:wҥdǍG6^p6bܬ1?_+9kh˕wPp|\.ùd_b{/Uז߫]u%O޷s,đ591C8?-؎{.Cmx~`~lGu~ -4XΏ#%g翃<_pߴOYuQo~[V疧˻ӛ٦OzW~oܟS{{fOɈkKǴ_VRG5ik<N>s583/R|0 m_ڝtr$ƥ1)>|&)<1tKymK261ﶏny ߗPN '=fp dy`^ yaB-ɍwU|Zl^JY-c^L˂'ӾŁIEdjȼ0K塐+4=>gqz?H;agFq._N "o{ c:|V y`^8?+7cIby)J}'Y<~Pc5v騏%̋O弦8;m4,x;>!7q?nM<~vyϿh`=gͽpTyv[1  ̧\9[8//; -_>sȲ%ZlG39n@=p /?Shv@igX7gaEOaezM\\>_ptzƳ1.B4?oOƏ߸8bT{q\/|'UlWiܦ=Øˌr1/P q1g'8yL;~bᄁׯO2ݮ,'o~m_k( qτzX!{=׼&M1oV1xMV`|+> m~-s*-o@?Vy4oB?~+=Pl|DZ"~KXf'ZN_u*|wkku9;? a-3g߆60_?n}yZNKƇo|r%F!/WidW$dg^S0!9[kS 2y_~&cA,4ZoX@t߀UXÂ{]QwsFu.bMkAZ e}{Y'z?~~\|ܓWUyO+} }3+|&өV{/b=9[Co$`8gie"/tzt7mp:ݏֲc"ve"?'F<> ?/="foψxbē";}"~A/E8$}#/#~i/O2WE|PG|H 7QC#{SZw,E"Y/e4F*F|{DPߋ&M-6N71boߊc+V[1boߊc+Oߊc+V[1boߊc+V[1bo[1boߊc+V[1boߊc+VhuS#>,#~MGD<-FxzwF񌈻#xf 8| 8_t_W u}\>KK1|)/×bR _K1|)/×bR _K1|)/×bR _K1|)/×bR _K1|)/×bR _K1|)/×bR _K1|)/×bR _K1|)/×bR _K1|)/'8^_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE [~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1y~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE |? 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE ~A~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1C/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_JE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_ ~-1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE O&1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE .1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~31"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/x"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/b_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE _~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE |5~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE #1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~'~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE _ҿ _~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/b{~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE ᗟF~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_6E~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 11"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~/bE 1"_~߻/H 1"_~/bE 1"_~/bE 1"_~/bE+?bG1#F~ȏ#?bG1#F~ȏ#?bG1#F~ȏ#?b_ 1/7-Fȷ#b[|o1-Fȷ#b[|o1-Fȷ#b[|o1-Fȷ#b[='#^4bUbߋc/^{1bߋc/^{1bߋc/^{qGΈW{"1q1">>G|B'FOOԈgE|ZħGƈψxvo%Fό/2I?c @1b?c @1b?c @1b?c @1b?c @1b?c @1b?c @1b?c @1b?c @1b?c @1b?c @1b?c @1b?Xyʚ1b?c @}bO>1'Fh[O>1'Fh}bOO>1'Fh}bOO>1'Fh}bOO>1'Fh}bO=O>1'Fh}bOW>ʡ}Urh_CWо*U9xh/aY^1+F{hbWq}l"%)|?WF1h=2.s*1!\~S'L/G%&FgDרDwg[_tk Yqe/_+7q80toOI2SmI2f̔֞ǒ͛d|Џ c );+? U-0JVL cowɪeܟm~iuO$o÷,ҥqRHW&mmIҾs2uw|FZܽ?n/sGSø`楈<0/W9ωηzIw!/=f^NIˆڲy)`{it>[<0//O#IIxa $r`-O}"C-c}QE<ϭ5ya/B^03yV~(y6(/ll|m+U[2gyMqvhxyY` }߱!y\n  w%58ڜ>bzm>Ys/?kΛ{d hϛ?o܃^/X|aljsd.]wc<{sΟlΡY{CZ_ϮaEYh|Y80MދlCތK --vyOpqgǝqq1?0$/pk58w>=m{z5~sS583/R5Οw'kaܹsz>AjL՟|zw9W'+*9.ּM-i-Nj2yaop\݌\y3o|{z_ټ4.auMW'--v>^m`^d 󕶰IA޼rg6?q$[żLc2G9y9Ibw6m/^ۿ0_¼0 |Gx^^=/"d ϩmM"c}>os'v}⯟<ꪮҚ$W-'ww@廽rMO7Lw~7::?ݐN~cj+MO屻;>5}V_w-89y.bY]C8˦N)'tk{Íq_{ knnm޷uGMZcmXΟ|/y;ev<ݟ߲,cߎ~n9O.O_?=ruO?ܹr/utJog7v>vWiIk&Lˇl~tXίژےaZ.;X%Izfuث]27;̇{щ|z}_qG:GՔvn\}]]ƣ:w⨵L=wͩc:m:YXȏj?^FVj+:^Wtگu7<=>˛͎cM>7o„5m|nwwqܼ_pq\09ݺyKaB9}u}Kj33^dO/ͰX;8]z_}n;CޕSk']rk-ހM|m0ΩjHsÎohq8eפz|Zy9y[xa;cyG^f[ty}C/)˻ۇ]o8g朓O3 /?gy;6Af1-_+OS +g~:{ɢ%42P⻇0zyדx`?_OB?+'p/,K맡ğ~jO^NM/'Wzui~?낹.Yrys=|G?݉V8.S>~>\ų'99.[>Ĝ%,_ztyj(xBōY,W8g Rvǿw~aZ mY}Ay`^>26IﶇzwQW>g|oºڳd-ǿ}et?_ׯO}^gxVmjLJvqIw]!z=a{yky)|mw]!RXwk`^pXO5-U_wR0/R6lN^5p^jCF8˭μ0 g|-w$g^fƟ? kY17:mU>|_g_z~Bǟm 4ǟf4{h@=f4{h@=f4{`X=e;fP=f4{h@=f4{h@=遡]O&=yw dn=2[x40qy5ݱ5Ofc8|Eny`^ yaBLyپۚy)>|64ǿ5syaaRn>ݲǞU|B}Eg?5+ QϷVy7{pF-u %~=Пǿ?^`uߢ}j=;GwNj}kpڭ;^S (gfdM:ya琗R^|_5)}ق5[ö}y`^ ? yaBN&1yZt>/02c2G9W&m/MGXxMGߘya"xʭ`7!n.vxk_kN_~o{۫E<~3 us4'm?c>/Ys_s}׾ vݽI_8bPcқtIkwgy޸GִSYގ)]VG6s]l}l՚kY;?uKxbzZo=ֻ w>/~:IK?|k[3񙣰N:nHveMmaܛA:c<~^q;j![ynw~!?X=.sQMSr U;Ώ qq+Ώ7+c\q8clıj\m㸝>l1XyfKu~SCnh's}WWgyOuv^<3x`8g ij^Ƴq<3~Y/z,z^x,cn򌟆x׋gy/@_l|ѩ?J7Y}2Sw8e_l_jײ`JtutuX_3菙0U3Z.k9^*S 8lai N =/'5f4C~W_rY2_ W|Bǥ@Of~9. n~%!|և)O~?42]yE'WI}aŚ91{'jl? T5h!}<0/+VһMs;oc}ca>ۮyxYTf7^0o?ji+ahVl<0/lr߇lr{~h/O'^czp 7b{8v_i5o/o͗k~.v':s֏wYwD N)ƕګcZcN|gKSjs߽DX;ǹ~?f:'un 0W:WνU2^!ZCU&okB@{^q\71̼0 [|\;/$s8l7Ժq{(tAtqD[UJMR//q-1Qʖ>|ڕ~튱nFGHsע>;Wy!X_8ּ㇖Jk;"C2>$okgfo&; TyoR<~b· q˧GQ וZ{yG2<$sIg]eix^l-ooWmz;k^s!<[C .)ǝ7~%Oޏf>xۼ6g= CKng9yNzi?o8ݪα]ÅѴ=o?M?sz2eOG~ߦӭ(7j4,_dΟ{;.>WSV)b/l0Y}پxdW<$SωqqQ,ǸUc}ոd9=88?3W8ˇxQ8c4ı>ƽ~Kc9-@U3?cܕc}Kkr 1n8c&ı>ٯ5R5?YqS^1n8clı>kc9ƕqc9݊8Ǹ$ s?1n#1n8c=2gLmXq,=caynvyxg[vz Ƴ< aD=oxg4ij^kEs,g#Ƴ򌟍x֋gyƗz?_섅y`^8S+'pӮ?3I&t5K{dyMm z%>Oy\]P?w}8~|tz+.qy\~8żǰwߤl'{-pј//I>/ΘsY>;zλ[2[ }qFfr[|+j'5 y|_!)fkDC>llGTkc~o/<wY)F_أg̜%g.O2!/n=W%򝚞ƗLJ>W}Os}=v/_)j~x9mt|<0/C^N4ߟ葉v~#Pwv9 ?8B-{0&3sJQۏy)Rx^&y慿gdpzԹyY1*Y}~Or/'w Sp|ļ0Kaϐ+4ڼtΧezy r25:ٌ{󒿽nXQ !2/R+ Mm/NԷ0õ ˋJ}oM}[[o5UſK;ڱby`^ Wh%;ՕCY?o޼r%#ǽV_v^i~l4y`^l+p⃍KI_RLJI:v :k|ߏ׾V﵉Z@uoi+mko {C#/[7͆vi굆c8/1uj~eo3lM8 cWoq+/ʉ?;zBTo.m9|uzq>vuVNB-j|[<0//濥lq-73y)|98M<kgy{gn/Br-|^<~>cy`^ y}c!P?c kԿ;uwwƭ^$+Lko7/B_usѯG~%?3Z| rs}{%c>/~+,uс?Ո|6HkY-ֿt|./?$?^#o}<,y~߽K<av|=ז{8ǟ_Wq<~brKw:x!xsWCy Ǚ}@{y75; TyoR ^|%idRgg8N#:ݧ瘥׳o0T}\)oF,Uya+C^ii^ߗz^gR{7=/ܼsHr}oD;X^|P U˫VWKl^P-PKyrSM-y j;<0/CB^<lySm] ~V[ 2˥}*|}~қ^ϲ=c|B1K WǕߏK`kI^~̋svz:˅c Ӷv:L>K.`hfFl1<0/lEKe0N )Kcn>a֛WЎ1^ <˵|//p4H8ߒ]Wl9|^<5* ko/I:HK|lG^8=R^F$C^|Qk~czy`^*8n`B G|qܙ|ث$m.}jty,ԄYClr pWyOKII0g:tmۏ矏uYkC|>ejyy1gol|yZnx1.3x 0ޟ3m[qϜb GݷV~x>##v>8n;2_g:Xc~oH{6_ʻ#R]un2p~W`ߵLh}~$}6O-3[[S̼z^S6:ג(t߀#yߵ<{?sOf:.]O)?b1nXZ;?cı>X/,8n'q+N1XM+h \OYSݮGgyF<|'"lYeij^η^<3Vij^[/,g܎Wi?3~Q^n?3x_x~NYzY!,?3pt?֋gyOCuǟ[>rl[rWW. JG1C!ݕr#6{&%X'_,B-b5e۱؍"ϡE;Qy=/z|=>֎|y) ynח{4}^S[naGB2_a9>/S>^b5?1ag#?nN.i6Y ؝/Kr<0/\^>cj{ͤϞk|O<|>h~q;ףoG^d0.uLNb~~~˦A^O{#c>om_?=Gy+8!y,~me}ZـylI}hO>}rϊ^|u}Z}V 눿t(8or}rCm\zx;֛~,igg?^Ƴ< r͟%Y/͟_A;s\f4{h@=f4{h@=f v=z|X};},x?w_mvK˗;!~q,N}a} ]5~2gO%DGEW1?Xd k!_iQHzBcFlCd^x<&M<㾳9gGqj}dN֓K^{BoAR[iy!Za毻tIz?9M"y^N8?<#dɢe##|3!\/,^ҝ$u~I[aszHzQ3=4ϟUg ozMgyο/v:=;Շ~ㅟϞwGxfz>u7?}Ie>3}YvZ:+};N^=3}k߾>3ywN[>?]AfW*vz4}&)ےF?(~fs~:x=3ڌg83RI2yEƿ|q<7.7Ɉa~lJsgƳ a\ky~Ll} c?lr+"|xHxގDZV 1.~~1nX_5.c;Yq!1.~~1>/b9MCZ=r[8Ǹ$Ye1Jı>Ɲ=/WAc [Nc&ı>ƝVrc9G^9||&n|>ll,?z,2Y/2+Oe<3~#X/[/?qL>Y/ gyzN_x _xY!2.^/ zz,igۦ:_xֻoxgg?3x߄xdz<`z" ?3Y/kuab! c??Z+|-V%9ו㽯%;`s<0/ɞ0~te]kǶiUq{ע/j㸞=ؗ;5~|ɎE{z<R\>h`r^|cXO=[rܺqy&%<־J8ρI_YOkIz6#R^ZkVD0 |#KحǼG>5w"<ɻ(8O2^~~q<5y`v[-?Q;u%ϗg[~5_xkSt y6= EǞ~_qq9v8nG sKzyw^4~cE!/WXg7.=?ԗr~H9=滤6ߎǺHWKl{I<=~鉝ؤp<ߣ2cag׍Z^bvttZ?r5pС0h]hX.آ7x|2q3x]f3K޸Yq}Ukim{Vo(2RBs;e{ٻ()B=PC^J轣IH!4RAᤞAAQQwGX"7owrsIDd`3[޼M۝9RoBݵ*Lw4`  hfpUϩpqəJgEPiu9ΑBCY^H-sM8urQ4}zNs U88/|.-xEq9n]69 s}`WL 7)܌NpqMί:EI:> <5yt4N<3K?1 {jAu=S߂?#^7O2)0OokwSI0N-s;PgINO{W]"9-`lԷGAm/{ߒ?y8 .9h,ˇ9M?Vϓ<Zg<'xw|` y+71KQۧ(&.%ˌE'8OyӒ٥e pSu}hsq廬sM|>2KvcړE,WwȟOkpSGKPʼtWJ< H,+A?,DUHr!ձj$^  Xw y^yl\f2 {xlj84,g-@p"6a|].Jz};9kús=/G:صor?ї:#N9qxl9oX7 \ʁ߯rhal uv̈Q,8?\@~/Z{c\*0_m&gCE8À %u7b2 B7u(y/*6`{v>ȇgpy0AhW1| 1>G,@4Du7LBGg%e&c`0U\Mlrkɹ=^bRו@A;%B:˴RKzEgfDfef&pI)8wkVN B:ԋ_/BR |ύDs*zc~ MfBz\tlFd\zzj:d@{W &FƥMt;aOxSM~9zZޭC(zMLq*Co_" b5=ݽRQ5Θm=&5=6%@B=Pͫ^T_^$n _c^/ toݮcuNxE%'Yt'.!Ojzޔmz9!qva%?X^M-':T̗1YIr85ä]M/ȁz732#ӳz's {+_315*rW(~ *1>*IOP/C"h:WD:)iq)v"u@Pkr%/ˈNNsJ( B=P/^.6:M,{W2ZOR ]r1Y)1UZQwz^9KP_Y饃ZOi zDged&d9>).&3qbAk7QT,Q+w+ԿzEPP_+61>>+##XUS,_e^/56)5#AU@P+%E/ČT;Q^H &&e%{FP -j/ Lvs}:uڋҠ:ֈizai~?>5V1 @p^&nE&dƍMB=P/2&)Ug%Fyz!u;u:^AB}!]qUOLRSqzmE}!]FZRbfdt&)^3$~dNz^J">RI͕LuYHw)N]!0*#B =c\ƐBԦGzL_~Lj|!=Ѯo̺YD}4զGzL?G9 1{LHu(![1=B@^jA!aL Z]\no7e?|' GBЛ^~*I#_Tx]n #B0uZ6~ʘ2eqW-wDЈ72gq8YJꭱs.PQGa_=r|rx7%y\rNhe瞛op b!p/)5򺇜P["^p\`݀r1MAlX1|YM><oĶru*m'QC>J kӖm} VEtA>*/ˋ>`yA姼$"vm3_[^X.uR5G X OH്-?  'zG?C㍰$>^2TGR>$ٱ-!2X_ ^ӛ)9?aCdc9lyߕI΁\}YR\J~7:DQ'=ql+GDAm^o 9gjf\wpxjrZjF"|M756.3=s`L_yC) cpe ? _Ͽ7~+Ơ#d~yT[2odB!sT(,# qtqfɰjzu!{qO ^=(5f|\fxjS`7Mzv)?-69D-fZ;Фhu6!kz|%F;r- _Uum|cӣ`gMCx >sR_R/D'cWz%9M햵{n4k|W iH"a1alz|'5q,v PE>Hݎ |9,>w8G?h-)qvL*v83<&G퇘;e34cc-_iqr5-ciڴ<~Ma;fN;F@|?i}BtF퐫m>O>69A<=?7.|jzć#O/~PMSuuD!lr`0V).'y-NC"bWӣTOPH8qzsi qALP8 J9GgQp2N69 qAԟ_.jqrvu5='Λ 'QㄹS(wGԟZ|(^(S>69A<7?7->Jv=On!c1ݠC'!:6iRA.G>EV9A<W?ԏLh r.v5=J>Vyvj1B)4ScWӣ@OQH8@|P?2}>T TRz)|  G?ԏ\->=RbT(S  V|v7ӏ750,1ǥ61ʼMΛ {LćIqO BzXSH8@|L/S|(n_Ipnۺ>69A<~ ߨj障>G|<4ʱj~RA?Ç,eLOMIvv.4>VyxcSA?M? d/'j7c1~}|'#>Φ4> Mc|ć_E}|}O8  ?Gh.tƹl.$|lrx >?GwtDq:)$|lrx >Wݳ'q77O->a{;3=??V9A<Smč'j) >N4>VymP~dz'j) >N4>Mc|T#F~eP֘8gj7.4> Mc| n&/&>NN*|Ji|LMc|>L|T8B&'/NuG&Y@sU#M{`<"cʢɩmf}Xv#:WEã`]nm]'m /EA>|@?ib\M2:Y|admr=,hr W#>d^ޓ/ %,7(/QA<iqu}Q?Ə/qUj5ڽr;H=k;az[?~N<.OaC ?Ill}4 \16":G?w:[e`@(*҄lrK% SI->\zL(DG5&Oɴ~KӆS]M\cz~aE9V~lG0=ܷ Z۠F~C8 =##wјF(W雕>&t&r\9r:jWG,3am2 $Fp ǶΑ/+iHOb%© d|๑\#ߙ ^!i%-^Α^};ԃ^C,m9N+_x9?#! dB.'?UڻrېsHOEEQj}:;i\C%~ odLQƛ]o@KcB3C3*6UtoKqt.?ti ,>wQ`f7J~$C'(䟽sJvhOϡ% :ef[]Vmc-O纅5KpoI6f ujei!?,":ssC!*3Ce!br`ocI`4?={±ۘ4WZ pL?|bypR%!U;Gm&Bt67_RI3cˏ!Ki~gwL}BZ\I@յLnO/jt&͗ENYKʯ:!A--*T5hnL,c+y἟ L>5K }eNB9UUde˲ck®nZ{ K0p'|P>j",+y@xu;_>A¥7}zj#STΟgv*V.)Ήg…[R0k~•>gfyтxy4^ >|].<`lI$d TcEVӄov9TI#\yVmbڥ,&gZ_eL}>o3QƤ=C8o9{S&͊ ax 2;+$v>X(ϵl9Th=Xy1W Sˈ2J1oN(ai1)&ݻm',?S&';4_q{-B`oWj!amsk1i,2ȆL ) *1i~_X]v0u _7funH]!LڻU,O;̴sь5,^A,|OL/Y#O}ýU_bX%ĊCBf7dҜ/{T3|ԎI0cUnRtb\DH/zgO/wgsgBOv|Ml`' q7six_?'tZSQ<Ӽ^ׄoF !V 1ˑB7 |IrKQ]ptbb|Nc\'rb3&Mĥk2ifa4NjIs;vQfV.MZ:̤mz <]}L;O=PXRi7'NT23%3LioNvIKtKLQ>brq%XX|+niLq5W Ȥաآ^e[&M,^ϏWW/g-?ʂs¯K3e_lTX.1.)6}-x;[L/ "{ß}6WĕkL,?}o'9f@y KkY6H<8+LxsBS&ͱ}i{jǤY(Hm[0iXn ⯶9z'SYͳ_= gULc T_˵0vUK/egѢ6b̧+?ȴŪeo;ībw3U&fz]eҔ)?H|UPսm4uz}w%} b7Tܚ,\C&&3!+LɤpBJ6#ﷅgGz8p\mveb l)2fj,q>ӆŊ{[Mxz#^Pq&Tq[bKK'b${n1i>d~XH=/X0al/,6GN`aϹ!W:1iV!.Şv(>Y’] ,d}s'~˴ėCKML.EM/~'vFqŝi3i }^zy>YY.n|b6D%>:]ը9S/&Y3ěҎ=6 `frBM|ܛ)%Ąޝ%~+WbuZ]^y8Ӷ'vI6XI\+c[٘5b?q G-^Gi#4;*^Gϓ⦷ C?fv:%˗:mEs1U}*A$T L9QؽX &^l*^2%j'>9#&Gk߬*V=VY|(sYht=i`Qm f}b ${ċ1c]& `D#֜7W*;X)3NZXbTGKf}},C6bҌ񡸩`ØxmHu}#vm6$;@mK&ۦ},!+9ʤ8wp%{le:pJ,'aVK>+Yw4eO7.M<Ή$Wl>{oD_3o[֧l3b-nwP˩'MjuYt10i5JeS0zqۥظ)~V0`nrEwΊ~aٗ,/];'-wbLŝǘgNWsRqL>G^&% |Ϲ(z&,L$\";_+_c/gNWFF%*^kcĶ31j}[ug~gy34B|_!oı2_%..z+uGly4eWǍHbllwO'%ä xxOyu>3[6gE=,MS.2lq_Fa4zW>bj^_-{Ol%n3}GXxIsOw=:c3f?jߙgj~_\P:ќq/'ǿ/: ^t=Iqώ¨;l>wN?U%īS<3 [ڒm׿ s/ĈSvyaŴ$qfKL&mw5Nzn+ ~[טeoE .7ijë}2߾'lЗY;)n DűLE~{Ƥ2i~j^U~ut+^°#62ˆLY)K k|} }KvJq૱L% jXlb߰8Kf6 z_kCKJ.ld( J &ʹR!)?%3i(e8mn,k+gUc|a$q_cSyÎCě}~bҴ^B25PdmS%C Zgm\ ֛%lٚ!ɈE'0i4O*֮ajP˴LY[U5|Pu30sn5DIL ?`ْ=W IjƽJ^,oz`faQi C M,MZYX40曽3i~oYФavt Ef w25/|@kR _- 8 av9TOg2:W0Z09:İhR]CRzKQ9L=smc׶~X vL0;q7̎p~EOu`ACC7X<}ifegzmeK-IneU ;57&:6I{2Gj!$Q9l<(OZ׷eU⋖yW֐Vy峭ѭ/ӿjƴӿ|F/Gx6Oumu8]t]ym/G<ԫ*uӿ+;_j_/ 6i`~t^+C<گϚyWwI K{(6ciuzywqbX/^A,5#蠴qWi3d%e&*t LIM -oZFЄq1c2XP_~3XT P_ jX {x |}GNK28xiGBǹۿ~9"^T:v-l΂=Ŋ18"qja!!…zt ֤KF(?+3\>=#ч7_ɑU88jcQOLSnlT^&aGskM5&r|TԨn1bQqc3b³fsKb|^LIH;yb9'3.hi2~,7nFfԤ.8.uB1iO?yBF)eMh9wjϵ8)k nsU'M~zڴA۳>3}rnܴg=?8%ӧ-#y{un/X:G3E۬_a/R,`ִ3-nʥZ"hY ZpΖˋ/-YJ 巽weZlޥ%ܪWVXz}g/n|}C-os'r{D4Ӈ;?Οvg6wdw~ּߡë}G9xБGrsze˓/Jg_Zė8sgN] ~1ҕ׮|wW9{w8ۭ7ܻ}tn?YxW8g9g^u_\>w*GMO%T|NM6Xy|R .Ukw)W\hje5N }L2߸y]]9aחtMJ_)Z&i.ViYA7}׍[جr˽~g̗Izn=}քg n/ƼIohgV[?7qV{Zn7s0F2cfw_e>Lzkr+[-p@- >jJ} (6nYGR{,jolfŶ튞^~;'~d #giFΡAQZǡ>{ımgm9Dҡo72FDOT){\]}_޺9dp*;k_Mz_~i﹯,V淣>fnԧrл]o%# %Ojsz_ ;>[ޙ=qՒ3ַ{!n#vno]ݜ5-VZV)ww73' R⫇m1u|!,~GGm{rTxBg缾h룇ݼ> 1gK|FͪSrgs -{W^[SS0w}I-|zʾ6Xyt AOyt: 㮭?=`zxvV@~*_o͖tL<득;ڬuW}uǭ[dTkx^b#koFT/:nP;,v~lNk{KFSUy;;bKPRڱfwp>{8{ * {ow(k_}kQ%~~bS}[zt坰&}8z93:Gf3̙\T}d%93Sfz ĭmsf ~|-l,MVPׅ6Y83zΙY9*2h993ZNYsfX7h@+Ιa}sfR9۞Nl$ݠ/xZĈ ky8U2{Z2_+Y9(5$?I.#Eg<нG-} L:$\ydgi%Gesyfu5hI@`RW_aN3ateTd}Уظqu^l[ +>^{4&yH)H+datʯ=MuWg[g\oxr{_*<0sV'oiAaoހe#3}݄0aV \U>GK^]dGB<}:I>|MrLN ]пU6| cn -x;e_Ieڷ>6e!L^eᨋ-?^s=89BZCb*™\>]ܺ+wބk9$Uk赁SBlO[WUQ "nҋr +429ˏ5 d}6S9r>Ht3H, e67m!?ۘgS9 kY"xȾ`Bm`-0-[Y/-,zb=+я+CI&LOU9I[}a@oAi|Bb[_'#^D43C:^KK~+dQVqpkZN]+m?#UכX'u?Z&DG`/;:9ޓSIh-7䥬;!-}0w!ZYU(/dkQ(VIr < ZJ(}beUZnbjlꢏ9gD?9rZ,VqTnݙ͔1F-Q/|H/wSnsE/Yzs^dX kQSb"3g%%|-*1 "7vs)c"I} (mgݷH 9stAWpעhҾm#4Sȹ} <(!afz3s^yR Ѫe80~?T9OǶE*8gDaDrcX2Ӳ2 }%pTai$ VOxa4H?9H 9r EE;dQ\׃cRQ Aڋ}ZoA12OG`9*{Ags6'VR5FuMNHLMAΥ.Ol>_yq[mUb6qOHyO{<п_&j'FI鬇jzM _gVx慢aͥMQb@|P 1D()c3𺠱m|r閔wWmDrVscD 3:}CKW7Wӣ^>I>8SUx:L`6' ^!N؟°~@.LO)8o{n7,5=)/rL-80=G+UpF63 '<{##ہߙ}:gbGbY2ݴTgHn"n ^ Q/C2911#qLbRb31z^( O\Z*)(^/5<866 =>XX9܁1_Ş@YN:_+1mi1(W|xC]58SʤCA[ޅ xNV1_?uTb̏1e( 5s+y]L/ݽWW\Mv|rرϑ:1vXkIYOqG|Hw˽DcvGzcX!k=WWm;l-66=5+@iRvDK'4DN^ VbS6qO킹7-0D B~DeZ|\q5=M7Op($|lr#c`Y <z|Z|\\Mz9c 扰_'q#NoP  8ZMfa/|ERkRB skV~a.˗`):?aJ/}.yOa sϾd` Sj*'o\t_sus:Mn,-o+*۵l3ˈʉsnz/"̼|8m~IO6\Hxе#Gcr@DH^FDgJyA/+'|p%[RPkP%ivIZ4MOڭy[I*\q'03*_ܱup➫ed;ąA:{<3$ǛaR#tqCm ~f:0)xZ{)ik{0YG+ȹ,;<^< ̳ ־DS8kBkҾ`gOڗ$FȜ}[QX&cGgh+w/&%uTP6l "i)?rm8mmmچ3Ɗ؆;: 4ul-#2{:nYmxKki<Yu%뾚ШϐFE9Evr̢c$&,:}FzT6\o|^/9f \#mÕnñԷIEw9^Nhm8ҡ^zz[[Ym8zP_^ij1. ^m6j:kMhk'mi[iԡ_XAWSqw{m@jeny1Emo!헽35;xŃğwy :>6K Rگ8d~㒖Zގjx6W쵺yKsZ< vO%sʼ.m sOy^Uf'Qі49xsw'!yJz(e gj$;[~Hp d$"T<|RUmU緃fewZpGِ袛w?Cz{txϵ汇yt{ǞA޹ol&^| xF6ZW|cQ֣OcvϝMzc *la}zpcT'ϭcTZĢMm%Q~aS\y5}7x+RflvpwUYʎmMvZ&J {s:\y}w8 "hQ+-VEl.>(5ɗQDuCO`"=v2Bn=ҞvU6ۦIzN8i8ANޤ䞀hlP*@McY('lynʴt09T^Umcl%Jvh$2Q m'-m_EnF,N/ QB"GA|bF)q~X79\=ϥ~|^HzXB=P/ z%eM"Mh#ci.npQ/dV蔌he3Hp/p~8P籂yf*g;{7JA0pK4_ooVz58[wvK0>++@_~^WHSb̏q퇣-G D8ׇS{wAkS_~6\pi[TIGcG8dviyDݢ \)>oj6i:C|P|`JRGczjoN4 Sn#>(> {QA?g`j&*,误(ᯫm0JD@|P@ɳx >&.#n>Z|'/.ono? Boi$8.OzWӣ~^!EXʼne=o{'$-N؟2M89F^y{Lo] QƀSqL=~t#? Xa/۱T3 1Չ ~%o8ґUۯG0?:nI3#p9$q_KpW0F'ɺ\>eQ@ɳ^6^-g~bZwPnyw[;@> >ny K!}QXy KrmNEdb0Oʲ{- '|J>Qb4yݧtrzxޠAgϞRΝ֭[KM4:tʕ+K5k֔7o.EGGKd6,_\j֬|ԭ[WW|ݮ];),,L4h4eߗ(d<*ɆNGub]PWӣ~ٯƝYUYP܎l?C|Pp᳎Yh;t1[%Wӣeޜwg%@ <㧲tGi&A<tȂ"$q*v5Mho}vlӦtxŧ]٤;{ȓ)VJCƱњDzr=;' |4๜Lz>Uv-e]RɈ/x:G׏òԜw\*oG)_* sOqOoW8?ˡGaLIwAn9xx&9yք<tqݺAdm1ݹ}Xmg oOlgQvH+>^JyEȾ6)1Ȣu5=eC"/^FL@~$q88D@|xW(n@zı 6+6yʺHb|S#\xpA|oet<GL>/#.a9R*LwP|#6|V)!Tq7'P\Si.ƈ>qR$=s~~]BEz#ci? eOg~y31>CϜ!g/y\Ѿ)J%i{]Z79hȚLd+v<ʁ>PZY3m O4B3&所r@Jqw,x >?QZ|\'6y*oTZ&g?6*x >&.[hW<0g(W8MP98!՟>AG<a~eqB90oJʼnY=N}\Mz{!og(GQP%:>sU7^LJz2f X?9qgKjZJ>;~C?˿hZs}eR^ QʁZ\~Ìc0SFG-x'Y^pXL~ 'ML!tHU>{E}׋8w/WWb8|w_|pf8c)xn7cMv0{w~0kk7]M8{$-Hy!LnHm N|EZnjqrujz'pK8'a- qAL?S!C](`qB9 -IOĉB j~cƑsp>Gɞ#a&'φ~ʁ'q2U~)<:OhǮGiUf'P'?8!.OS?NӰһޓ8dtXiℸ Nh4^$R93Q?OӉO|r)Nܧ nw+<λ:E:/y}~U0=ˡ"/Gzw8;C9q'y:o5rxJݧ $1hQ(*>*zv=cD39p^{*Aq\&ג?9 Ird.5:!WϻGr$bg򬗍` `!]1i^:8P`!yOk#C~[=~RHA:+Ζ i9{8@' FEb9؛[5tjM(о }}8WK*C%!^o9.Gʖy/9*! Žs_r?8o(orzYJ x5[\STf1)NqIROԩe]RRPRRHR%yf$mۦ!JIPEܪ̫]'Qж}kIiIMWJvYj_&5Pڶ,TRW\Gz>4K5OhIh[N%VuTQ>~#{ה! ^]A!U=WxRfI&}tdb#92$BtTÑ7zHK;%}wtdKOy4K YQ}jI̖14nd}9}_lWNJQ_ک?挲HӒt-^S_KO$F$$XI#<ϔ.,}!.bs>p%A:rҬ A䄦KSS(υhcr˵4+I'H_Dg:Hm4t~$}7VCO9#ٯE:9@za+3;HI(D-Ut;Ek#zHgge\rPW$]d>KH&J. %|t`Sɼ,{rQF1 -,3[P>yg]7$_p'%dߒ2rb[0}:Z._OZk$-^|Ime_XU٧^ ?#kj >e' EHS(Vt\cY1ܵf$6./ VMjZOTGXG">.K4kIn7)NhI}QA-^.P/ԗ^j˾]T,衎P?Oo `rI! P^N@A}Oԡf8tQ%O@nPC|P^X߃N bi%i4η r(:t>z! pr'o\&c5_Vw ]o2vz64yٜ0CBi g䁁`=]ngFf X}X>tkX; )\?E,p=PgWY}f!T$:i<:g}7۾ҕ',[:ֽoeӒU/2<=stFB~7Ӻ{귛/uk>Hz:zwcƘs 9<c_fE;j?I%?2֦^ꅂP_^/3f_Oϔ81e1rg}i;@uˬKViA#ĘcX# ǿt_fj|/忺/s^è e(R!&Z|We-`w3CO^oBlw`;ߗvD~#.ojl\XFl|ԌcLrT94G"iȐ4SHM3%!rҡLp f !M. duZ9g+ww}ֳ ]~߳ߡWX?B}sud.sϫi35(#6f8aUMfh?WausJ]}}qۛ]%Uğ u갾C;uSyaM qI=}}qo=x+>}ϞX? v;],n\[ǘ}A|7/SvZVs<'O]?} cFVo}mv*er=MϦu% ߺ&i_hoUY|x{FM*;ݢr;nk7|ҥKa;6G͏_{ȗ*U --`+ *W\P|y#6Xߌ]l[WD_>F?}WX HԪUN:za}q2;~*TpletPAÆ N?c9AիWwk9a3}ak*U Vogg:эxy]v-޽{ 'Pb7} 0.1P8?f]v_pgSN)_ˇ2e8}mvF*qGC}cSvT7I&E;o/"qO5@ 跾Ri1GǷ3LGmG}b1ΖyjE~8|꘣,!&cb_,m{/[VlwUx`>p`?7"Zߡ\%y| (G*G_tVszǯs׎l߿&'_8D,?z`j~/[VXާer|m u[ʺ~;3r,*]]qQ^Cwu;e2;.[vfe#1{xc篴?￷_<.ێ8_~up:Osi[Hva\vCڛǃ}'[ۥ(z}W|^Tvע~z=h.'+=4!Zw"fv]N`O>Nx.g ;ogS뼃{=ҞwïZRM*p{Ѵ燋ηi=i~>oB,sp HCkz]W!wiq[~! uuXšώz|M﮸5d?zIj4iOwg0eDaxX|lZԧ Zۻr })gOwa>UN=N{ӫ?1u=b%og/3o+ u _=_?9&hWRǞ6ϯoqͧ g?Ɲz|o]ٵg\:m]Uj\;?41TQJ]{|PSouWѼ?a6FvJߵ.Nqۛ],{oTg(zAq9KewCpDDTmSk{7V?oaI e[Z)Qa&i_=m;~*@Wγ*k:sؐ^zcwvznh)̃{{^xX|B>o=~ \t*=Pa<ۏS|?kd y(i߫o>x~`q{y_qܺn]ޟݦG}ExX|::h|.n{op /kۺ}۞}/s~)pN9?5NmcJv8TM;o2*CkFQNGžW/-ķWá4}p}kWmk`>kor>'k8<2U7}1.S*/K]~whKXn~&"[ya&+K[qS/OlşʒvR;o7՞yQQۮ3cN> tW >w &h_j9{'Ǿߎ.M}c~?5vS2l<yS>+ZY) e>+f&GH<)]ϘJYZ_WL=KT._=_m=c3"WxV] oJ^7:3xRk\7q = ɂ&& m3olYpeM s&:`G<4%gQ])^ss}5S='Ir8lq< c mjokp/+3x篜S'í3̂z֘{u-x֨_3gY/u%F펫cW,o/-جo] >ƞĂ\5tʳxؓw3,xS V?`ţ9ݿa x&jV?<#o`s_F=ntο{׃z&=X`=SgsYpǶp,6s9qh%]ӝnX =[y~N-XgAs~~v^cy63lyxJƦwm_SmO.~uw >9H-{pjaG_ԫ*%{yV3jTNÔWG}qS9>p=J?=:by.z$cU8fNXE^q}*A=Ψ rLxGqmEmfmKWH:w兟\>l=KdړmWmͮyFhG6/wdWa_h=—l-+l`6*3;4$->}6zjS{5o4if]ZS;qq;ڶOnۛ ݎýE_gmwLw.ʱʱ2lɶҽcmbY{[` #w/^=;?~O'5r=δ*{l5:JWMߕ+tbvٕ"_wU}bv]6]{ɖbfb׿w{cuߡYXb+E?whr?kڒ~əzeC.o3נַL1}98ޠͿ~> s]Mg#mJQwK +n{^:~?~ߓweșZ/jP%w;vymr pi0_}p㎍8[77?ߡI{9ܿj8V88yaYhoj}UEEoV9Kwn)Z{7wß_x_[Qo[ťw:~ v|xX|BZZ4>{|}[{7ncא5PxX|Lv{7voB|pߜxv\Eo |jiwSqͮw,<~;ںdo;u>!@/?ϭNn=|ŸM;ͯLsf`Fs74d%Ӷ#Y)|ų6}Q=4m̅{Jr{MYyw}^Su(}k[d&d)ɨ6?2giˮq 5beCqgf씞<)km!IzBC?e1|~~1{>e#m-8BC+mzC-;l_qD?6O|X,&\y-YJsoXuBmseKfMm|N2#|;/˖͏u0c-ף8ߵbsmϹy[vtr/xAhO(8=ԞWZ[(j.nN~Y-]m];VnxUzUGVY׫R\$^'?yOoVxƧƲ$gvCKwGA=vtq_}n[|ɶ.=l[eE%˗e1^Se_˫W[Hkbr~ݣ{zTu,ܨi`mѶ/J FyktFyϧw7p(ʏk,s6.}^OFV/U63'NoԴcٖ߭c}ѽ&ɶ7]8yd^Kf6.EJٶ$.&r는>[xmkwFyr%oMMM]_Ʊ"%mSR$ٶ^; SOt+!Ԋ,]hW~y̙"^qWy^FfwbXO,+_sfΆ]sٞw Okl뿵_msq^_o:\:cOFɎ'˺ ϛ,WXlk){\MmHg,6^سFw˷MjpiĴ >ju {U>xM[} }c3$qC<@v.W'%ė@%mH]b_uI>奪ce-m>s*O-wfPk飦7Ogos@ٷmZ/9|nIV3jw?K9l꼄uqEǣ-5/?k>y 01a_z]!23O_[_xxߊ9%s㺃6;ow<MXvW/E /_Yx[bsŶm:F7g_-M"}mz]Փ}þ+e+xj6w{yxþ ռN ȑ/;wo@}߉/ٜ_꥗?/ʊ'3kF$n{V<'3#wXꆶuےW[US|Rk+?-vu٬1u6qGKOX'so ը-ڢ_xk#OASm+裦COX6k\f߯ |3m_QoNUd4֪:WF/~WO-/Ce_=kx <5#}q)kۯZ6(B^n7gNY&/{Br&gvȈmzP>yK,k= }W:hfW珛TKM]Axrm͌G_ɒ2$.2w-잒xߦ')kMxg=nY\++[NGryWi>xþSU+:9a N a:lx~/=%^W߷(ȡ/cz/8?o ?)k;w%n-Ʒx#qC.M<7QX\$)kWUkkorQmC7b+$X}c+u-lfnS:E"}6*_s}M,u2C[/_9 L,%%>.=e5x_&+/<\Xl7IJ4P>IJElgG*.L,2*NeNy;({S>j/xk[?m/c݋#(& [r661336䨭>#VbYV 9#K<;[brb8:j XhKӆO96Krq,!^n-Ƿݰ`E{OӖ;{}vk;%jx\_=_㡏\c3\Zg翺L>;5\Rs*}v3A]Kx;5/99zGvKqW~Sykزx7GvKmMMo2\%{([#)?;5/sg;5޾5%/oؠ/6@b/nI-9~AzQP"xkodtbo}t%ɥU'r+ǜ$=7Z1D 8ln/OnXrNm2'r^X}G;A]6FyF6Mh8xӵ \3rYfInQG^^Mt෫dqmƶXɇKS2r%v/׫CCr"bw݄>Z~>bK'v)gm>z)WfXL> NJrȾ>F.>;L;7igz*0VWRi#ݨWSȵ2c>@_G|]e~ÁvY_| &}߁1_]ý%6],7Xݗc'ߖy?9[.}Asx=(+^~o*QoTۭeZUrKV0Freu$zFU }=H[/ܰė{<~kz }OL?YrS˕;]fCInASx}zif\#r?rg/!5%7ъec2_.AOe(b_Y}o|}z}~;^CP/z^u| ģ^N$c^#/mH|;(*FH/Dc&_*hahGkK%/+/ya!>$ rGU_ISͤЯ-}-]}t_J} WFeȇ&QMxurm5MXEa_#4Wߢ~v5\EŇ?t2 uyAob~Anj_SC l.>$_(#uܶy񊫆լ4dqy}]Y)7A7JW|f5'v\Ϲ=󖮸IrozT,v1Ӷͽ7O Rn{Ij[}K} u9l}D`{b +Vo#3Z+k:wT4/~)_yΩ=Gߗ:Fqfg聝2;mk e!9]7ƏG&.։ҧ'smck>lb?]@ϼW$/ 0ޮ~ֲOү'm-[>m>v?ޯ54J?u~Dc}Sc~v~ǗtmT|ӶW [{U_ŧT)goU^ߩHf5s]"v6+Y{NXlm/?5:})oW=cT+6=jWl)̯rq-q:жn-woAoWV'm?<<Ԯo\յ;v\͚~ub޻Rqͩi]ljf\gѷR-wSlا/zv>mw=|ŨzCZc75|&j{ˍ寒u kArJN1ٵVNGj/9IUɮƌ跟{O^WZ-tXgjr'R@ce̕rX vXw1 nw+m*rզh_n`7_}*rNmsVcVW9Vqsl:̱}M9m: |וrYy_UW>goڟ9ts9̉\M;e< I}+ot>z tNr_m;!nǃxya;u=&ł[&(nC^c}4% {4Voej{ѽMxg|x?\iY_U:zw'h%ތ8ˏm|׿j{4_a|nūr.y /RۉOwZ*v嚻5`OʗkZKa_ect~ZbGO=rQ'W[]Uޣ>ӷm|wwauWUɱ'o6>fw5c+)g;D,)gv 63N|,0~PLZ,|sK۪ɴcd_mŸK%]}ݝuV=罭y~{e;D_{!}O@ +6Trfcl9\&u_ȫ''VgnGOłm3 PkT+mх﫮Izg/N"ua9֦{ųMNmpb[g^_*9[Sk^P5>/wu?& 9[~^k"wcu?amk<JrT{Q{GWg_w N,~/㥙/t7|c{Q)>Ws0iz3x_gpy\A|W;gpe 430jz3 >P|w>kz3`| >T|38P=&Z+ڢ:+=VW\O~ Dc:-+=iGp3ѣ֩l耏m-&_}B?4 腏nэ^0 dtקbo {?#0~G`  (KZMmEODvU"zjpG3$zfEU[g9|]@?F7zF/ ;g ~` >'|O8|.c bn4k>.'CN1;CZxS6.lwdq>.-ՂŚ8Zg;9n~&>F^,7U6zo01NS?ԑژynE0t iwU0 #fD0/f ސ ޠ ހ]0K o w. ޅ0~N l'ӟq8=vh}&8~Ui|nmO=9c[nY#?_)qO 7+uzן|xWo.~M|rG|{OWo./f!|griV ۂJw98'&]q? |vnrPtP~xz4\SGFjmaোw]>yyj/+㥮v8#FN g~@/=^Neq8#vG_ӗ!Í!]`b.01G<'|2\rIYsgA[u#g-o5rNiC_´-ϧ  |i&giwڀg}Pxi&g-*L,m6`rAa'g- |r|0m}f_ >!g- >9k0O >9k0&, ,/Ur2=[b;~6L}!4_ >D_} =u-JD L!R؏1=6AxE㿣$U_B0j3M-1`]2+:o:a~FǗ :,.8c6GtX|b<:,%G#k,5 YOd?->~ >#k{wFvMȮ ٷF}3`dm~@vu#FȮ U#<`dW첀}=`dͫ.|d`t`tz'w w \R (piQqp(4`ִYOfqVuf><<`36 yqp^:BfGkQh->NsL0Vϱ|N~[Q9q8!O q,1rB$>iXY9? |f1 L{0mO´Ol- >q8]6CGa'g>`yI6 ڀ ,L m]Di&wh*JpCQڀX6`STt߀E#Ef.Q+.ѢsF(狢 Ln ]`] DO΢ >9.09.>$g(,l3`r€sQ+`r}&OLn |K`ɻK&L~ 0y48`rgHЀɑaL/8؎x^010q2`b5*`sUꀉD0L~iQ~IQI |Y8&ayGGGG>:h0_Qt>:,xn#k1Ev#kqGGrGx#k9!!5YUd |d-Z#{@#kulGjʁYAd>VȖ |dޑ;>1,p(y%?&jL5[4&|Jg\$5!ʹ s:5[MD9ǃXx^_ڜX8;C ^0tLL !`|0t\ލCL )`j怡& 099`蔀C-Co 0w 3`7 zw0tz?#`,}Cgxs5M0?n"CCy$`輀ɽG>090sC 9ـܘ04?`_q>.O}>]|;>o㮆|]Zyw96rm۸qq>o.}]yw96rm۸qq>o.}]yw96rm۸qq>o.}]yw96rm۸qq>o.}]yws۸|]yw6rm۸}q>o.}]yw6rm۸}q~Ng.w\ ~g΅7Nwtq"%/>ڲ}ȼ$鎚<هRW >d^}tGMCfAjg2EW8ɳ}Ȭ]d&~!Z 5y7E 2Pg?y[5y5k >d։p&~!Ajg2w8Qg?P 5yEp&~!Ajg2D7:EMCff=ɳ}|&Z>d~᰾5y/Er8Qg?Z 5yoEs8Qg?*}<هp8Qg?QAjg2Dr8Qg?Y_Ajg28ɳ}0 <k (n);sj3G/;sBSz}N wj|ީI@S{zCN-/;5wjdJ0>dxݾCMChـ&~!SNt&~!S^BPg?(Z)`ɳ}T?`ɳ}T0>d0>d0>d0>dj0>d=4`ɳ}ECMC&]4#`ɳ}&Z+`ɳ}0>d0>djg2 D 5yF<هLѦCMC#<هL3ѣ<هLsѣ<ه1-<ه̱-<هq 5yhfPg?a>1x% qw[W2(z:9z̺a05j̺10)j ̺>6 [[ո[wuϽ[Gϥ[ύ;㿏u}Lxc!;:tzC#G0{>d:0u]E"e2' zPoo |(aSu>P/cN 2P#xrCm\~@щ;jc7!f?vw|%z鎚rjcoINw7.f?v^R5 |ُ:~P;Oq GO 2P|jC~^df?8;f?r G2P|UC~32@ yg8:"@ 9vtGxj6 ptH 5R׺Zt鎚 >l~h 5 |@__k~Ѿ;j6P>/v|w^pf^5諧g8zQ j6WwpG j6繎Aj6 |@g9~>;f}vq GP>;9~ lP>Ot GnP>?Aj6[>l8Eg NjE_u8f$Cm fChQ)l(8ا7JCŀ76IT5l\z'BxBeNJmǴ){~w?u8W ߭ *z|xLN˱ğUE-o%OwE|NOK| 7]j3ߒܲEmW{=eEeş.3ߤ ko@ JkV wcbֱ_M|0-in(`g _CEkr,?Tx>3"G0tNп EE:7`CC!ч>0t^PT. E }<`CCIѧ>0!sC EŢ ["0倡!T }-`(r/}=`+"JUCW }#`(rȿ)Vз09׈ .`CC?d ?xڸzm7`}qAj :30|B=RoS[$y-H!CmQ`ꎺSC~ 505A-LS3`Ɣ _  2z72E}dwF5E z0w|_2NWn؇iq3zO>PJ  F7 |)Q7 |4K^h&AzjpyQꍾ#?QA/'J!O5 |Ve=d`d]AM"C- 6 xQYEnf |kVbg-F"Ch=#Jgmf5K%a?t2'nqCD? |见l|+nE? |EtKC~7uC SD |w#5~Y?>E|/-YB5(q-~O|(kPO |(kPC/P֠/\CY¿Be h+>5(kůP֠?^e f |(kPįP֠HCY'}'bG{ >'.|$\~\Jyp0r_w W+oD0ypppupup~cL8'\{$\x_%.޷ 󄋛E՜9_k gi兏uρ# _>g.|.%\>Kn|-$\=I:pk*ךV c_ W߾f}-'|- _ 79!?W$|琄ܒps.g\p9稄k\pscnnsx~nO kFkw _]sЎw!nڇ.?;w:{^ԫa^Cⶀ]ze٥F.+ړ[+l__=S36@bo9R%,xJrGp-ǽNMH&My-r|dfmk:M?.Կ-h[i~Vٝ"πomяNӟVK~ѶG9YL跶Gg7-LaN5l}! &䑅|0X_6{ʧ+aH0~d c=`towo=f#2} fc}a&B{ {7qAp/җ2Bb-Ɛ~5{z'/7L_Kȓc&Oyˁh_؃ &6vl}!6+¼Y=f%Ock A&8a'QlyL?r(-?bk|r(GqՐGE>ׄD>-Ql}om!?bӓj (&v{D>-Qi[ۨNQlmŖK6UQlmťQlm:"Q|Y8?;E+m}|[_Q#D~x(Ql>'b QFX QlE> | #oB0KGlF%f'՘[f%n?J;Jǟݖ^NwlsDŽdy>d373Y?vf#y3f&G#34}ݼ=+n7lfHNfdy|N|vrco/ocxׄ1{VKo<;O;nПGmk.Jo8"֔ ˏ؎>=P~sBGv+vfeFEGTz9qv06; >><&pXbvr->ǥN.χr-f'(=:qf2kf&/xƎON]6ag%'z.bVo>֦,6GlNCL~8[>3_=]6!ocAtѹ(W5Ģ|QwԐ:>2Wh-[j辶&JEos.d6':]^*'<02/\a~v̇ECl_0&E;?s9ZFOяo|~?2߂9y;cSk&o5|Gƻ>01"oBNl_qm@9䉅!Pd>y32`ɛ[68U2oL{ 92os|{90'vZ5Wڲ"g.E!llok D/4;d)zsQXHͱ~c6C>fc#bs| >Dxgi'nAg[_`鷺C>X*ku&<~B:>M< ၭGg[ޑ8u3*X1כ/tmO:oϜ2*TmrtmOONGVxc5t_9V3:;Zy$8؋c2&|]}t6i?Gⱎc 8&5ml%9~S~|VYy9hLvs^es<&kyXΗ66{uִ}8#vmsEn?g쏫r>t},M9<'#1YjgdcXנdYfgێΪ߿xx/CxXOsy>)7cνCSMgM׏β&y>_3:;<1g}Z? 1w4yӯy}R_}l||1:oOMͳ˲UX}:faIcN-o5&@?a`ـ[¹@{7X{WYy[S3W,ڶ= |n٧WE[[w _ 兊_ڤZ{'=Dn O,CB&e^OȎ6sM}5{LS)uycn1gymC i9l{ j}JIG׶̖?W,;!Sn1E|KϺ/ !hO)? ?0kqU[L qbrcb1<628o_B͏f2fb[;x,W{r9OBKf=<΅8Gbn1g HOܱr[煹9'\Α+]~ןS=x9yd>&܉s6cJ*罯TYi7=D s*͝žs? +XYMIkemSiF^5v,𹿷:w^(XXyiM-Y]v^!҉hs9qO{<6UďaTC4ǭO{<)}K};nKWo\ôʅ <~U*pk"}M<&8c#F]hz?zkI}51tk8uy?r֞x{k] vO!:#]Ty8oIb|Ԝo{<]v{B &e~]hk͹Toc&5O|O<A퉛}>Z^]J6+ qx4)ۼZc:S[Sb }lEd} <-qͱ>,߭c}"O5t _ú~_u<*0k9hx®ܪgl~YC[Sb VuTo>njxN>ZƵb]er֞}v/8/OVշ]dBy߭xr ZsYZsM<=8rɜV*ݭFnnim1S_b&/킥?ԗǸ/\^֞U:nX/yKܕ+kV?yYv/xn,s;Sk<%19.9|h#O}}t9XuKw'\H}}xYqI᜵=ٍg )ps;yKc<7sVhqbc_b_Ox)V{Ɵk~}bS_bJ_rsK%y JsSV|Wۊ9kj]W Ķba K+(c"y1Uv-1wSc٬}fw^pJƘgզwPpV7ƼléهNVs6ε8z~?egU!V!f0v*ǶbzV3ǁĶbqvP+mzd7דV!^Gۊ9w7sUW7W\c[1xV!qMm7;;_o6Us_\uhYq2kĬy- <^$>axi<}?=xkrʖV15IDOjk]rӞwU*|Q~)~c)cKYqDhu}~.ܾ.oZoc#xw-'}s >g=.OyjO|}N,d~8~c)8w=87#c#xбҀl 8Tb;}Sn7ccKqyx^?V>J{ikOܚyDZLmXl7^Tjk]ļ/Ϳıغs'Σ'xUoTĔc;.yUJc7*Cs-&{]py}V_c29w@č ?{-}Fח*}8^,[nSiJ,ލ<ݣ9yqew2-K~F-jTY}ۿ~u̿?k"OI<=d /v?Ǿǚ2}}5yآЗѵus9>}Ŝ/N6}6~-|,ӽ's97lSgb.CzW䟡bn1gyߪO1}^ɺt>'+#s$s9}qi婇?SQ۬O-,O?[ffRnsn\1sKc-ƥo[QUBn1gy's9/n\[Wտ؈9[bb·ةScߡ^<~-~x-|ϣOg}yي?bx-A5(b{}Ŝ#9s3vg-,Ok>b k/|~\Mi+s;x-aܳkÙgeܐ1<Rcn1ʓ*=|}}F-sߛx-࢙yss-,O'[6-uJ?;?[:s:':o##s_<'_thSS7??ƾǚI<=dOe5Mƾ=?"?Ǿǚ-I<=ds6,[ΫY:$=D~/O&ٰt/D5Kޒ_cľǚ]I<=d}d>ͯF_^~k"O'X9 ίxJk"OsJccM8uocfLJ딶%=D~/O& YR ꇓ>$kbw28=$^kXOkf}5׺8=Du5p{I֍܂/W^ W(@y+P^ nijĿPxZգ+rްtt6}q{yc-o)~5w|}a{fT}<6xgLȣO|&[|KI#!/٤r~z>>?)k˲yzTֹjޗXȣO|[jrz&ӫv6ЗU-fyψ<ԤQRgE>'!)kkRo4wT{yGLXɮŚ\\$ _0=yًZ^IE3ha^xqy}b">wVbMUCy^;c">|VɟŚnly}n:D}3IY&|7&[R%_Ɏz>OC'>/j5TI&#s꾓˲>{:D}3%ϊ9?blyyy1ȣO|`9Wy-ó[Yx1_bGؗse70L}kZ3sbs~y [5ٞG1>/%rQOesblլ1ȣO|b|9w+i ٔ ;{l7g'>1>ϐ1vbFfUy?Ǻ}9GLƘ)&97[36/o+y`{| AYO82%}s#c_bOqmԳyewUKOZ|mFe yG9|wlmYV9eYzq[ {,;0,kK^YVwT;V3;>>7y|/O|Fe?{~!w=^\Ï=#}"zN}{lk'];>_=1&x{o5k+s6s߹Tlyj86k7W>l16;ܧcx(%X['}kL6鑜jk^Xjg ˊ5Bm-6Wcg//<60/)<60XXXv>s?.Cctoy,*XxnkH\+ۚ׶8MڍɆ> +\֖ĵ)1ch[}XQnskQ\s5*Eq͉ks:Fŵ(9qkkщŵ(9qrzFT\׮ww8^ PSADwpwRwUwCwF}nqvϙw략cg듞z3vE7aί-O볅S|xg듞tV7~nj/I,MϨ7fOϏ}}?V6En|oOY}^PVTeEnn>4O5 n a}k|Ճ v'~ |?A>QWU1g}*rsR|9Gjjs|XO5>>5Gl[V7vZ[Sb ϧMjj, <*о|?9*0S<#O>ili?*0ƶӘZkcFjj 4yUaOƌ<$nn>;'ݶRI6{&^[SI:cS_RSim1S_?qs)xJ}I}LǷEyK죹OԗǔH_xKcH/柸wj$gt<7b. <%1ş/O|wFY/)(/OܺK/)zk}<[yKca/OܦW/)~u %A }OߡoD>]?<_ћc]?Pз>]?ݯ7j>DO; cpcz_EOwpW맿C-ѭ._+W>83%ۢ}5qgܣ?kǾ83nc`e'xƽ /p;t"qgcѿotϸM_W>83n?tljqqg܎KMb83n证U78~_'Mw~诃kbw7f荱/FOk&X}#O맿9.?EO-p}Zا맿=zS쟣맿zϡ맿uG_E Rtwwb]?,ty ]?ݯ輜|`V{cy'wuO<~ bvަ觿݁\ E/ǶKC_G ݑkga4{+ro1qoA.GHp6x-usxƽ Cqg܁ȕȝKc<ވ\ @Πqg `4{=r*r؏cB\p.5#vϸc|\nwoxt9W߱83ncy|r^}vϸ @h=l b܀>N Ux=~m}{!r.x5nK]+џ 6Ǿbc^#SFq'';b?iy.aOgہձ @|\6@nE+-`ⶍkgak@R~'&9܎>Nw@_ }.Ka)O_o>z[& G@a;7EZ w/8 lcNgׁͰ+#g`//M# Idbpsn9}c`ⶅn_m`ݾYáa?^w}|dy|q73Ǜcӱoc^=a?t8_ױac^[hWGsrw "8< <6ǡqi'`5[smǃs:FC7{[bw }vlnsqq|6ǹqo G&0StnC-w~]\\8r<9c3m۠|Pam"}!Oa t;nú> *n۳#Ac _ ^nTܶx!;w긵vQvz?Y-gMyx16h;gl9O+.xZ'em

8/\G\]#'=۸v׳Wϣcnsw=w]o ,nsw=w]4ms<9:8x<<. Y n8{=냮cgknem^c>8GB"G"]RuxuD.D\y5ú4B\.B:!v1G۱=۵ok}1'" ucm}Rb/b5x[;kq:X#eH\x6<ľYck 61rر"50in>z<5_x쭡c*ıem1=^;^=1v5ز%۬m\c`"c`c^`=Pyl߭r)X(1C!cOk=ː~e d{Ķ=:Fz ckN|-}Sd'G "-wۀ*ؕ+c-ðT>A x1vC î؆n[<׼B{{$_+a{{,x4aWg=3u*pk9y7Į؆Jp+1g3cϸ炗-+0q{}ocϸcϸ +0qx?Ǯxƽ <\n]1{;x Xb n+ b w]18w;cϸeVa< p>8/~_VR~ OdvjvBNE_.e{Gp"r s lNfh/Si?r鏌B!eBT|ar{g ^܈| @"!#za }A@EnAD",밟smsp4;o+Vd"r&2iIBNCw y 9 Celб6ۍڞ~ B&!=o`6Cc۳]dld(.r:o~)u}۳Tګ? CC؎Jz=XEȣHOe?ǁa![c{c"O"8p< ۳?L71V<wFFY؎ \XSZR|c&DF #jr!b!!m`lNj؞zt.\XH/}ǁa2n;gyH>:12{vlv+;\ -8 SF؞VEG.AlvE #)m9b;gr)⾟ /!5q$xwj $p y9m.ED|ͻ&dm2V:^7!"sэbkm*q8^7}ϐi] )б}bl] 1ilyyFOr(^EAȷyy= Z+kyͶ8t<:.|5b:趫ıcmiu y Ukx=o4_v^GNEY\o.\7O5o9_ @{Րƈ~mx\E@`?8^^||\9Ƽ>~**w 7÷~ oH@vC<ƞGNFB?,uwlHa\c\k9Iȟ3`c5SCPYDw@aזqn u=O#' 퇾k [!/#"wWȓ_;_M"qx_OAC~Fw~m3]OJ݆쇴F%r #~Uo!룿^9G#+aq]J}ȑد yw o<67gMΈb~U Ksk};?k}97-#| >9 q_c"%諑}ض!9qhc^UztǮʋtx,|̫kw+%cac^uӵ1+"D۟;l|ڻ6!kzc Kkthc^kб>HKtc|@1?wq9i<}3AmA0AwBzv-ϐ)MyyfxfN >1ᘾ41_Y.m ރ'myyס^UBf"ףؗ wBwa>#{vѝCk<ǼV:3r }6wG\C8u:C6엁yW56|;h? qq=q]:f!/g0_@w8. Y<ǼynMDx Aϓ/=oz_wKK;N/}ˎשK_Fwcu}6J$9켮^xS,92`%9"R)C*#'c?Cx>283\dCd,Rϸ #㐍خbM#:^Gs]꧿l<8a~[kk7觿lLD"~O{y ~6cH=s~ !#"mخGOyzS?S2ix2|32qzO[4ADϮ~_#"O!M~7n:xZ4Cfqgg=l7yivϸ?""! 83~t+ۍc<<4aqgH ٙ1qGJHvϸ""SFqgܿqgC`+x5X@FNA~=XTC '#`lD*! ]z;c{r5`cvlvE:#[_ڎ*DdK؞tBwmlw%r`3vlv@G6G۳Hk2zw9h;g"/mlwvlvBC6AlKXO1q?GAj_z}kw lx9|χ1q#G![1q?DD6D?<4iD qg#~fw6ds@46r>٠x]E~83HYߝxƝTE?x}9Y4{1q! Nqgܗq3vǙq78"]ێly|\9؞Dnu?}(_Eׁw{o~?Ո nݬ?;g{<^ðxv>F=>썾dkG^C.D~Aן [ :[a]ώ>#\aw=u]z5Kk;zZ{# !zZ?A5=zZWǗ+9[Gi]~e؍rzK/Nޔ{y5ze q> 쏾cEZt_CJ9uLC#@m]\1F75c1 DDo8x9~'>AǑcw9K'#Ǔ!._ ǥqxq^ ~|&xqܸq7 nu9a xzsxqxr\y :W]Ait8^&qw8^7M[Gi]BGO}O\(h=k5q > nuYx]2 Лw=oaÿA.=N/[3Rp8GHkH' Z璟;!{qlkb7!5z[=K@?_ZgmȉH;\+"{qxx\.Ou=qxx\6[gmݛA ׍>pl}k8x<<.ß퍬@<pl>Bn-'!K> Z3pdO Ѡq7_׃c~N:fnADE#7×7~|+Vp"ye\mE?|{x;{׼/o;g߂Imv(o;gɠMrg߃wS~ێmNbצ؞,o;g[+Avn{#xtO۱= Ev۳ݟAϹ۳UYCsg+o;gb%gA9۳@ 'mv]g۳?Lp vǎv۳?ଢc{,gcwi= ꧿؞ _bwk=Tslx*ߵUش۞z`8},؞hy˰k=~t3^eW].k=~#ko;g}mv_(:~ێϿu{ |uv۳]=_o>ݿ.@wz'<|[螷.k7_~t7O5n*nov5o= i=uC/v5o> iM{|π맿yxς{w\K?BO4_oѽn<|[Oн?|3O<|[>ϗ; /bj7_~s~r'iv5oCO4_o=6A N7kS> >n> ꧮ9 <MLP?u~uˠ~[/ۀkk| l ꧮ}X||O];[`#]P?u N"P?u;;k_ 6?k O]`Sp ;%nנ~ڗoAԵ ~ ~ꧮ9\ ꧮGpp3U` 'WP?u_wP?u-Rp t^ ꧮy|o6=8}~յ7;G Ppp"ko >܏&`k6w+!9|}{}AMQ1;k/#a6 `~n  oꏺ6`[~>  oꏺvMd?y^ 7G]1 ౠ?s3;k?1ox"x4u'G]@a~\ ^v7G]{7?Ucާk?<v/{WgQ~x9enOscWQ~ 495`OZR>گa>{=xxx6x#h{)uMy voom/壮6 v{?xx2 h{)uC.Cy;R>G'ey;1|Եǁa>;<vm/壮8p"hcmAKk|lw2 Nm/壮I@)ap8> \A[3 >\`p s9&'A94s_π>wYp+9Lσ>p[psY`p6="86_w;s+.k͙6_wwwM@k6'l \`s|~܌E` ~ϝ׺duN~_z@iu5h?:~ Ocڀz| :NOu9~r\\DZq{8w[7kl~ ZG?t;ǁu|̫#h9/|n?t8_@A-q"m9t'ϛ;~lqWω~s^/@?sV) ߛ*"' H$Pmm.H[DÐ}@NA!s$9 qߣE11E۱+:숸xO'6UΈmh榯9c.Ƽyc a)86_#Ga Sz|^;쟣G7G ~.->3/s?a_ ,?_'7cߎ?|=} ހ}8 pBO ~[p 8}wgȢݎ|ڒ-=h?~?_ @7_c`W觿?fJt?k3V?'~g- k{]g~8{=دqG?j@|ژ}sp5h?~;_ 7t?kC.M觿t;K7ݟ3o >k{/~ߏF|^ G?+T3o#"|K1o홏yUb_v0w@n{c^_koVay~Gn{3?WVcy~kWG=/D\>O >__ &홏yh@k棟7B=1ՈYW}ެy~ǦOX Ǽ~Aoٚ=|_ln{c^?#ڟ r|nL'7E=1/#9}y~߉9홏y@?o5OSϛ>S7wE|!=xy˞=맿7^ﲹ$#O?nP}e-q^=3mSfwo+ߌux5_y+P^ W(@y+P^ W(@y+P^ W(@y+P^ W(@y+P^ W(@y+P^ W߯7P!7PR<+WfmH4 ~ oxӆ"𖁷 u oӿM}}n7w {=x7~_+Uo |PG>:O |RSg>'y|A _e_W[kgد=֕x͵R}?4^/7 qMox[2Vmox;%nwG=x/kyV,<7[Ϡ>$𡁏|t>- |N(Ł/ <𕁯 ^5Lu5 ^ox,恷eox>w Kx{;> _o |PG>:O |RSg>'y|A _e_W[k8ooo9L0Ɓ7 Yox[:𶁷 }x=\+ݛRṼ >b-T?(+ Y+UG赼b:)ZJ8-ا>g-Xxvl??/XS|Q/K˵bᙫ)rOsQS߂}Mw8*,rW`t-XZ^B_? 8E-\G5 fkysIr-Xx>^kys-1N`ﰖW,<3St nkys,1N`﹖W,8!h>>O S}ZO |^ }a/ |qK,ؗW[_>\|-rQ}>k> ,_^?7MY7 Uomox!;%n{gགྷ`~k>"с|b>39 |~ _$/_W*_ J$t6}K>{%qx87 y-ox[6vCx#O}W'}@ [}P! >#}t`3-ا>3 y> }a`_gY/|eY&TUE~`n ~i썃i7 "[{`om])ػ{`=g>7~~k >$؇`}bO >-ا`}~/(`2ؗ`_쫂`__^3{oc.BeHPZd%ZC!&*$SfKJBf*dXJ1+3 2RwYǻoDZ>?u}]y }֓yzAO/<}􅞾WxJO__{fO<}c~Oy9O=_'OVOO< zzO/%8!2赘~9f܈Dr+mjCm'"'I{^v#W׶.:scy34?G뙚=}Z5ca^jS*_u"+[.Ԩ̕4iϽ4P+mj φ㽣פ-6%&FZ9K=^8oer<qoVAǭܖIcILߌbz.z&5fS^DhЎ٣w|=vz- vscR/[tJ?4~&c?뿎*7/\ou#2^m([HfS1.ȃ -U{Kyː{[y58yݘZWMqIM*M97$7$o ,&__8Cy`ۢ |m鷶^(tj׼~%sq-Xr-4@;s/,>zͥ6d/R,|B3]KS7ϜP[Fw8?9 8PY7Jm`Hy㻛T<6_k23Fv\VWsAĤ*Զht3"Ų6Oaiaj&>_~@ʲۢ+NqCDLҏ2eZ2G*uc9tbvc~g~s膽;#GN{u΅uD1XiOaE_[I??G][dQڂ؟w~xjnN4<# #ek^o>{6f.Z:=c c?o;Z4ڣ}ڽb7}P+a4ܠ+5[{[wҼ}~h2Fke~)V/_߭߼Y[6ڿ{BtJIm? Xz7E3]3=w-fS;k뮱Dbufov,gWh~Wz?uD̑٣}|) yzl:䂼}-C4'˹O$}-1-O4a%qfh” p'ZS9%=vS;~THY;i. ێH+#֎_JgOפQ<+jpQ9xVVc]xL_5B6>X~#nL\ѳ㣔n|//[_C|yr,Kq~\}O_ |yy>#n2[ # Qy DZ0I|u櫩GG~PǷe~XUCWFB|j{J%Wm:wUGiWsF3Լ;RnGw/+{Vͻ/jmd}Uͻ4դpyg`afͻ4f*X0ʼ۸Ƃ˷O]w*y!oO`t(kŌ"aoxfA ɬ)4B2.{Κw4Bư~T{}zLBδN(hG?wio֎}~-hǹg~91hǤ֎ 1`xpGGA_{3W*Nu cscb=tb,5ȫKȫBm ǤmSnł*ǯuG4Ƈ[?b%ez0>4KO-6-bS[ګy;w\Ks-y㉌s֏|b/UדWԡ*v$6fb s|x0_|֏xR0_|1{B|A0_M|N7gn̻U{;?Z? Oswkn>2{G̻2>:r5"w?ȼ{RUޮ(oMu=ae=8ZNOXqQko5U=P!#zcxBKm41JhOR{ѵ:8? (v|Ҏ)j:xq( Ȯv< d$Uz+|`[Cz~j}sGzGx|ps%W}l_Yyu]{ຉe>}*U`_rK&* %'ھdM/:h<s5>.IgmuGԵMܫcG˫_1>!^ʔf>[쯶Lg8]<'\}pGg>j7}-Oq>%'NXfċC&ĬK'2_]*Y}4_՞jw/ c=wA,1^~ 9oD_?wGj`2CNv\#2hȶ<"'Jt3V:'W43N73#ofJdfp';UCu F*Cv %H4ҨLrEJ6;5iַ,=xMKkFϚf>ChVū{-S%:DwR$'ψ,"~+ oTOZ/h=S}Ñs-ܮ^jП.yjMg8%WtﲞͽĎZt/m̤, ߊ^nOlgJv58#zkh7w~lBm|<^G\G3 *SƇ-1$вq,W곝j{`aWg<+~#+'Q} _o'Nǒ ~svwaʷvv@hر_*3A/~Rڰ"\}Y^=?Z4p}V<WC*rTI$j aE迼ZS_+/9H|ҽf wFQ=**m{^=-#~Z7A(Wc7̿(ڿ(789܋>kd| kȣ1t(coj|dI(TSE fC=;4~e>gh[QL2~ԳNUlS_Ӟ/K4i> eW^ˁJC/^^Vf/}W 6_r% `{SK9 _|'ʜX^!t 2ץuU3sn:$ʜQ]7|>F>濣g_15,8O׷4we3u} ֹ17Ζ664mczGlt?R7oeėS>elx YW_ku Ư}c_>}NMZ;N('Y1wdY^[4~7[4wkx7wj>?^|A0 Ϯ/1t}%˧#_jyx,_/e~aU:pѲ<75k}n:i'zgQwG;jG,*>4%S3d<]_v0?O8Cvj#LK]X?PT|U+qi(/꿡 P|O[o߮`};r{;XMc}{I=n 7Wx`<`ߍN:{\`6w!`um/Nd*O 7>W&P{z~Q'wdgVS³^F:z// =غY&*oz۱7-5U}C~ 5*nr/+(>2*tgQY UBI"BqҎ^kj_eKP1xKݩ?8Duxti+YF<ٻtMUUVUoG:q}ѽȎK%8M,,Z:yp}ܠg\Hн4Y<کޫ;t}Vov *˃jAe2=_ȫJczV^grs=3!aWhO7em{x!z9U+}zRPf9#iP\WK7ϔ_ٕ۔'ԨFW\/U)jԎxSEi9uA_U,&ѳLPA{ [x;g*nÃz+z(9{]_oA;ng(|+ݫ.ko'U_RvZtP=ha^> 9es+ßţ5-,n }wڡST>ny{W/,_z+IyuWGߩv[%־]Bo-8'u”IS*Rc#m=P{vmH6jTƚPHsb쪺N{u;$r̠/}(Pȝ=k׺tSS̅},[7WgU8yqCZ-}rURp@O;{̠+ԸWωp}j/EjG6FhNJP>pRM9_ިjsMRMs O>#(kUT,5+GkPﵝV{m&^ &Xn8psT=y.e e|뗜m~kVˡr>[v5=b݃57˃n/ yիj^>6+&$?i[8i^LlF6剱HPoVbCkfcÃv;QwoBay#Ggҁ~2eiwZ}-Ck_ FX<މAޝhqķUwڑA)a{/Y=sz $rXm{:JƵC@+{qJ5ZȳVsОxrjBjux ~+?{?{ COgv}pq_-t&mYMӟnV7V/5_fP͉ԲEYѶgʥ9:𹻒kXCܞ"ߤPnCLmECz/{?zUNr.7ũ\*vExTڱZ=V+t>^soUL^s-~Ij\Ky0!B}*xń\ Vӫ25=KOmtFwv\]fXm_3A{ϷDA<:r3Tbt{9GZ?ϑ{x̟o(zqv WX| ٲ>eV^%NkO4ي_u{Bm KI~ wfK}:^pnS7ޒ7k(=AߡR[bQퟥPż6@ WG߉9vϑ cCP^M<+V,j/ii/ BmLJ7[kꭩ_.ߢ uj&ynE_KWzvi8aWw'v 9fu$C[{ɖ^7藇Z\!ˡ^}߱ [<{ƅZf{{QNȹݽ"4ٲ!Բۘ6Yk(,/r㳡ƽ{5Z׺C9o < V9{I媡Kx_)y#ro4ZQwbUݓ1}uot/@;34/q}vnGyz+>:}`A|v]3"6ܪ%\G"WvZ?,{K,VQO>byЧ)*6s,7 q*rwCGޯ=aW}zjieFݝx@msGG鞪SeD68SGN9zl%j?2rVwZ "f};6S{'D3ֿ5߈Y?/z+hM>ҳN#{/J9ceԿI\=Ɗ7SPQ8zvdKj9ك6@}uQ\PK^1A=ގWd-{&1xSXIA[K vO^ 1kп[;b_^m9ϮʸVO~ Y Z<ΩAFcqX7#oj :<eq˗#'eF.VS|t\[ȒѡOٴlB?<;V+j{%CyqF&6ʿCʿY5Fƨ{Fsȿwܭ]-aT=}N)O8z_UܨRP&*\'CqtNy@;6q8wgP{}uH:(7wAWu:Z{j>m*5}k*nVbW1ϮoA>vۂ^h%+ުﷶv_nx}_u嬟ɿj\h8zq;#] =Y|WyJ˃j _}krB5:޳ i.sVIkbgzvkG6SFvyP}@;}z t][P[5ٶB-@5C߅._WZWp6F)*j_C:52~-M?%eE 5}]qM=iU;.*hGxSEiu}Ok}AݗZ'G_wl5V1Og+%IwHq;ԛr] v}*X1X'ho((j'W,lJUro xRbqߘڡS<ۂ|=A\Zrhk ;wPl=BTsgalʩvs^O]jT֞8fhG~WZ,'{6Aϔcz b5{dP#wVSvG|H3/ݣ,=iSG+^Pvrݝݭ~u|i)r+U?.LQq}s-}Jy iuZ_em6%Ag}`XZ_Y^gRA,hlU }jrU<藐ptkj;}>=c􆇞J^դf_ߠ?\dkhwdyWAʚOiF ׷\룩\=Ϧr}2MNr}E5p}_}r:|;ɋm"߭eB/qݽgj+s|!eT*͊V-az6/GgB*6t!~kS\ʿ+Gȿg Nh&7YGkZh|4J|_#NﺌChOe^},o9߶ZLJ_evn(`~z诹-}ZO;_]9Ҩgo旑kD_mģku]^~;y[R(swC $W"%ֺ{7r< Ć!뿙) Xֺ^٠&w5 ;k1#bn>z|aZ|*8&vw/WY| 8/yi,_e L˿?VN嗖t/^)Gl|X`||fq6>v%G6>>/56~|1V?]X`y\{y_ޱ/%_z`~i26ogѿ`~94>o痱6~_.4޺L/X >g_`8֏efq][?^Q}'Jo?ŷa}ַW8[V+%- [ߊ*n ߍSmMS}VE؄L[P] /ԭ5>FY mAcC?b{4>G`*cˣlr|0~_hF-Im_&KOߔ8_%UI_ݨ`4^mι9Wώ֡3᜹o4V-nߩ_='NU|wr*{g=><s3ڛZb[ kϓ(4-ޯ^L^j'#&GWH\{<#gպ ];FY7XzOlk>Єߏ_Qi+v9s7M4w{Jm\x{=2B{'Ys==s#sڽe-ƦE窑\{O|j?Ĺ_ [qԞmdx@^i+5B^U*"U|[xnQY#MsO9Z61J>Wk0מzwkE2f Ͻ\sojmZm4ΫÂo0V*œꯡeL`Nֲ[qq;Szzܛ^:wIg8&k7qwwRءGZ{9^hz1A?yCbA?O[flGyiŷخ I -}򬉕 kޣ(WGc ϲ*D `ye[\OnsWc|]峽]6vCc0&Mqti88o7sYwG4Kv >kp^|,lhGܼE.Il8z/Fơ6o j`Wy1_]|+{o~yr`>y 6O%Ɗ`~NZhsKWWY6?{(䕭 /(kl]X´e.*䳭G|zt[ƆV[Ƒ4`383XdiGw}o@K߮ =ߗN9XxeC~MR48Rk8Z18kz86lYqQǩQS6zmS6S|qQIS6lzlgYqQS6zS6lqQǩǩ9S6zs}^iћ9TzM=N=MX8sz8FAll=N=sK=pS60S6S6(}8hR(3ԃ>ԃǩ}>G;Z1ʌ8`8`qF V/p28Z1,8`/8`/8`qQ&qFO8`qF/O IOw%;/)8Pۅ泌xFWL? xT#lfw0/o)x[a.; s;U›#x?͎#Pa~p|ǙK :X/8cV+'8Nu\ u+W;R8d k= Y:1&}~8h@=Fk}>8q2[=?l68h18ѷ{{qcqa8s(sFqaaA?Q~FA9q2{i?(sF?cgyqc9qa8/'A?Q~FE?8F=?l6oqcqa_86U>r4e8ѯy7dz3 x7 3;|psx<ltSlLv=񇍞[?Upcqa'z' 79q2Spa8ow4eφFqar4en8 z :q2yEUp}Sww|08NXqz?8s5q3mg}x vX0p:k38ێ3 qy=Nj8r㌧gLs8y7qKljbǫW!!6a!6^S %Ć?"Ćb uDŽzBlBlBlBlSBlBlx}!6P o$Ć7bßbÛ/MfBl8 BWbx2kW8lv8s.lj>lj!lj1ljuQ- 刃흂8zC&ljCVljC!!ġġġġnljCYljCEljCġ-^</ ᭄Blx!6N o/Ćwb; ᝄBlBlx!6M .Ćb{ ὄBlBlkBlx!6u!6Ncs}>P $ĆbÇCaBlp!6]!6=!6}!6|>R %Ć ĆbcqBlx!6|>Q $ĆOb?b?b?bol8}1c' }EqWfVWf}+3IXؕY(nFL62E\▟p+󡰨+3_򙘯se>|)nOue>BNqeژ"V;} ml1Om&nsTiBl'Blt!6|>S %Ć ᳅Oτ9BlBl\!6 !6|>_ _ Ć/b ዅ%BlR!6|\ J _!Ć 1!6<.ĆYEۀk.xKxw9a8\O!6~"Ć !6<*ĆprҮk!OCDK8}I^¹^Np%vp&NߓpG^‰y gY!9JbE)rNߐpbH5rN@lmN m/;(O̙/&s3/Sxua5b?,Ćbk ᵄGBlx!6Q!6^O \ B R J Z /Ć7bßbßbßb ፄBlBlx!6!6L -o)FQ o%ĆbmvBlx{!6Q $Ć$Ćwb_bû]WnBlxw!6S %Ćb_b_b }77pN[?ǖ<fo-!5T\}cI mO}fyKlm|}iLmѯ }lyN.x- ?9b㴅xuO rg23es_#aů;>Rmǧ [1NDӅ9}W9}ӛ zʟr8LwǗ_u|omrKL8N22TWg5+Pe.;cU?@׿Sف[ܹ?ʇ~qe>Z~$n}e8$!OR>^H9 !ㄔR>F1h!9%|cBr cwr >L1P!Cr Nr N|8'~8үwr'xMLal8y g`g ᳄4!6|>G \ +Ć!Ćbÿb Bl"!6|D _*Ć/b× _ +t!6<&ĆDžpRBl5BlZ!6|^ Ć-Ć#Ćob7 ᛅ-BlV!6|] !Ćbÿbw ễ=Bl^!6|_ ? Ćb ᇅ#BlQ!6Ɔ xOYLAXxN;}cI mq--5ZЗjMm ǖ䂍GrI[#6N,1qA%>6F# 9ew{!6!6~B ?)Ć(ĆbO gBl9!6'!6~A (Ć_bbb/ W߄BlBlBlBl5!6/!6o!6ַĭ kuCp.c'FiwVljO67'8N8q/9elj-ӯ'|<=o%/*kO='%_y(h+08qYy1?o.!vɮZk/}c@YЗo'}oLLŅZő[|;9b@X_?hFZү-9ocNj[ I6kRaoWf5\fW9UWfҶ22S6׍n}t[_Ǖ&ptҷ:Y^w?ڸ-b7BvW5+?]h-|ʳ^;J(;]y֮7]BGJ<@,qGH-}+&n,Hy=iocqe>]iue>ua42sm&vⶎ f8h1L8qcqa88h1ʼqa8?t4eFy#I8qcqa8?~8h1|qaO8ы '>y)Vj_"ne(3t7pe[]vet+SN|'*JB{>~ޛ;N{S|T7W{S|gB{o)5^GhMݤ )󌬟ә;h/\rw8GgLryXEg\v:o茭#NY!c}pi'GtcIr4efz?~8h~8cqF+qp(3㜇pw1 /}m{=_~j'y_ޒ~sS=랅| tmcG)xks O['R6w7NwJہ?HSM/{Կ|>+ |!{;$NWSCSNkag0g {>^G]|O:Z w#S``NJ9:hq heC;lM5m68xe` >haC6pȁV2tjpc{YS:_أ[1@"E2P7x+OV"?1|hȋ445ط@"E (2Pd@"E (2Pd@"E (2Pd@"EV=sW=W"E (2Pd@"E (2Pd@"  ^>E<s(@19Ṕb:gb|FC^aNbOOÜĞ'yc>}#_ct?f!/0'OFCOS}I>2-x|9)rŔbs(@19Ṕbs(9P> coؘ_hȋ4I)꼱5ߘs1̔gqĹZ/rR䤘(@19Ṕbs(@19Ṕbs(@19Ṕbs(@19Ṕbshl3S_d@"E (2Pd@"E (2𿐁@"E (2Pd@Uʾ_g=KgJ5 78msKv٠TڡYt;NCo)OtO$񴯢>ŘM=Џ]ѻ;;Gn <N}4ϸϲYz{pwִπ#ؾ h=c{7~.裟װ}c+п食 ?@p$M^'>食yx6MҎ@OD~<~-h_C߀^~> ^IG?}aV#ѷ͹>)A`Po}w&cyy}~ z󺻙֟3f G{B;G?vF6]*@aO_ڍ7?iGDXڭ#џA@=l{m*/s6<*qP~^Ov5M?}7= @=lk6=~mZW]{σưϸα-Ac،gin eڃc_a3q=ǽOưϸv^4xBuz|mưϸ;ga3q}z6w?Z-7S6}m_6Ev(MZp>;#6=v)06}1יכמ6}u浧M?}O=Cs=4'[к8ϳ目P׺@oG3%8"9 ` MZ jhDx>sv!90 s-yn΅`'&9x~AOߗi^A}ӷ#:G?}O/@;gOhˠ^@}w[x=`48ǻW M~[I@9W96ہ :(| x9|Hxl ^z>t[88ǻ'6uk(qw8ǻz`kp"5q:8ǻT"R4Mk4qw K8ǻ2Z+ڵhS8ǻ E{8!sCkI v`=h\Puuy<~MkAz<:ޔֆYj[$T{}&T۟Xizyϱmhݞf߶ ;m1wK n3q;p8rNp9KBxӮ ;״cB;nLQx{= -1qy,!1qDGu4#{>j'+[$T{<9Mxg&NOǑ ~3mYBǓ㕚e7xr7ٝPϸkoGmuoFxE]P=㭏^/1q?Tp^'T{<9'w?Px~/=;z9$T{<9w?PxG߅{ZQϸ/G~tj'k NAjeS?BL6~O'~=*xo49Y OsOZ8?x{! ^ 'E(xRЗ$TO?}ǁ/?D.g~~0x_'TO?}~@?Pm$'swF~B3&TO?}.6=K3N9m^B|Z'TO?}K֡-' ~/ץPm<}6%GiЌ^OYB/~Pm<]HF q/^O6^E O7i-h}qo២-N6^{ IoZ~OېfGghH6^3Ӵ?%TO?}ߡ-mL+8]hI6^;%TO?}6yڿh~73xٯZZPm<4Mu@duћN6^AoHBϑڀ[~C~B-O6~s`Kp+0NkɄjeOFoPm@pop < <4o2uX[5=~-}9q8Ÿ 3/kѧ/\[i<-ڛ{黝 7h/% 7lxƵoh1^)~WS闏 Υ-f3}7~O<7O˼} p1m$߀Od3}7Җо͓2oS~z=oO~v=g\n o̗ys{i#_>WlxƵ Ky2_OH:19ElxƵ|57÷?|G?棧Ki+ߣzϸM-|o̗yL>c_h藟|4qs#KJ8;IXKў쯏~z-;} ^v 9ޕO_5sg؏~@;觯‡+ι]8ǻxsxs-x 2x F{ v9>7e{ ~TK܉=6{~s>3w=#OVM:}Gw=eG룟bM|z߾h2v4:}Yཌ%ݻ$cݻ.z_tnw#  )8}*ppop 2?~~룟?~g?>x!|>p}wx008'K\=4'gG?}7/__kp}LPoL}w*g G?}g? >%fp6_> |9};> ΧpϸۂۂSձmqcJp 8 =1q;;ws ne}_pϸׂx ~npϸ ?~^p}ӷ+ x{O7fk3M[Г^u Їc<z=z]76~^^oOf k{}] ? Ch>Oc_O_GОOpׁc@}wch_A}ӷ|=~.~>o ꣟{<Iୠ+@ϸwOvc<~~ x;|>y|p^4N=~9h5|:=t?@ϸonϸ5''1q?>z|83nK_o׵ >wG?}^:Q>!~N^GÏO_ד߃ZuzrLm{>{ |./]o/h=ZеP= AZO~ +x~ZON O@wA}pzFw>?h=y7kWzzzݞ꣟^^^g p/A9{'$< ~{Aϸ7\p] x:[~:ߜ??Bm>|s>ܐ>|s>kG?}Oς~Pu9~~>;t> 觯0\`p#O_9p}OAO_j؂IgG?}o/~߿~A}LKG?}O߿ 62v~5>|AwG?}D;_?-Zzp|~D;_GG?}-_G?}B;_?| ~z=8?;Z}|{>|zSp! u0|$3qgGOFxzp>Bo6| mithϸ^Ϡ7@xzpo'83׃~cqg\gm_c zNF.lG?}sIg> k IWخ~DlG?}ۂsҿ+OҿO߭@.c ΅A vϸ@[ovϸہcƂ{ѿۻwü&CMnl7;tLxp)؍nO:|=n е6;83n'kh7mnMEBخ~: 룟SG{x?s#x FKxm1 {uu5O A޻]g\o߄ y9|}G'1qcoF? oxX_^;οp~(ڵ}h@ϸC_VXqg\qg\_o x]~ڵc ꣟o­F{ ꣟ރA[|G?}7AZz_փD G?}Cu~:WC?G?} mx4~zz>>^^^+ǁ^^^觯kAq`WX|q=r=8<< <<tr=r=~ CGǃ@ϸG;'G1q]\/#AϸG`783QDx h$hbx<7hdp$x~^ OO_#׋a`oPu=rO_#׋觯p0G?}]\/NOO_#׋~>zs*8 <G?}]\wNOO_#3>>ki=8 ꣟֛փggG觯`P޴< < ~ZoZ觯ӳ`y|GG1qG1qG.c8/<_Ϗ{ gk;?#yt~9Ϝ'Ϸ3<}'U<AOo8?~3x#;o Zk᷀7|룟}}%?룟S-pW$_룟fW\ׁGp}vO;~Neѵφ룟a7//Y>{ۯwF_Os}׀;?8ǻ4O;e~wjpGe8ǻ]l%D_;w7ۯw@_JsMgxw_ ngs+qw~9-z,ss`8= w~_ns=K_wA_nsdXj;/D_Hs= -ߠ9zo5>;灛?~>vSW۟O:zcA}~Z{ɴf\չ~fp6zZGWw렽F{ͭ p]1q@? ~d83` {1q(83hϸ?G6K1q磧-О_c<~81_hϸ@ ~\#83O7@;c; {_ ;~G?}A?^W>"kG?}~l^.Z} = <{_@V ~ZZ:z;Zh}Yts {7 vKk'،su?ѿG+>o x-? Nqgܳ;gKϸgMqg3(p}MO`T}4cb꣟BN>;*ہ)`K'W\}w `o꣟_? ߥˠ>;x;Oa`+77b}w(!x(ۀӿ ~?>{_O#G?}. 7>}h^/A{?~fW>l1}p*}_Ʒ+=}mhOurq]W觯 w~_h>txqn~~G?}_>}wkN{=tݾ G߯꣟֏/w>}wm:8~kO~G?}/_E}}o{}{+? 5/O_ϟ}.a>-6xzܧKm}p&&食ہߜ{= tN= &~觯ߟ >}p8~Lq=3@I\ĸ@}O>}oc=;=N>M|.G?}hOx#kblG@}O_}n`ۀON$T?Y3kVAdym?H6^zk O`;sq?I6^)z;j`{pe8g/%T/j/q/_K6^%zg O_E.}&jeߢ}&j[<lm8h>xh.I6~=w@dB/M6^{ׄj.eq?PmzA76F^+xo]uRw#zq询?Pm1A O O~DnPm j駯<6FLBЇ?Pm je'wK6~v{']Ad{&T/Pm<~4N} {B_ O߃`O8`&T/> +x{(8 'A>,xk3G$TO?}#Adc碏J6^>/x{8<<'= xo| OZp0x!84N;}1jeaC_ǀKS@d#NC_>5x;  ^ '}FB+Уs@dWkƠ x{8 ']&jeע/M6~^NǁׁW~B_Pm  ൠq77I6^}#zbB[$z 8 4N:jeћs6~n ZoNF?])-/o x3kVpx;' z*̈́j~o '][ 9 '3.sNA%Z?ǻ@}gP=^_OAt)Z?ǻgx?|t?~NB~w?p&X[EP3|8'z6zj~c'' A}OnP3| }') 9=9`kp. O 9=çMmA}-Л'Tx"pKGV>y%Txno~mB~w`p#OSs{σ;/>y._N+gn>yWНsu_vBgB~wWnBp_P<;u> 9_ D/BPAA}^7=s< '?[ 9}#A}ߣPhwQ~>y|1 9G= Z?ǻ ;>yI迠'Tx;\ CM7+uHPy9[y=Wx;t=֢YavCk]B73s~lRѯC;F~->zc\6>1+T3gecmgѦ3A:_{1Ե*2Pd@"E (2Pd@"E (2Pd@"E (2Pd@"E (2Pd@"E (2Pd@"E (2Pd@"E (2PdN፶_ɡjV3 Emx*ox.wcϟ+%nwG=x/ |HG^>.O|b>-|f>//_ |a_[/ |i,p}e.xM-ox7 umox!w s]x{3ށ o><𑁏 |tു |l'>)ɁO |jg>+ف |n_ (Łn/^#ks==Hr[*ox.wc[x{' |@G>*с>&𱁏 ||'>%O |z3g>' |~ )W_VK_/ {v5e(ց mox;)΁w [x{' |@G>*с>&𱁏 ||'>%O |z3g>' |~ )W_VK_/ _"𖁷 |[&𶁷 }x;%nwG=x/ |HG^>.O|b>-|f>//_ |a_[/ |i,p\MTjVj^9eެsXr Otut7ܩ߭߼ӲO3ެOJϟ>BTxϿ>#+>$fu}U}R'>)ɁO |jg>+ެ1Ϋu*Y o^yп›}C+d4p?_!/  E-oU> 7+I+mox;)΁w [x{' |@G>*с>&𱁏 ||'>%O |z3g>' |~ )W_VK_/ d:oW & U:6 ]ٛSm~gm'p+6 fk澧jj澧j澯ii流 |l'>)ɁO |jg>+ف |n_ (Łn/Tځ"𖁷 |[&𶁷 }x;%nwG=x/ |HG^>.O|b>-|f>//_ |a_[/ |i,G& U:6 ]x;9.w {=x7~|PCG>:>6q|B>5iO|F3>7y|A/j _ |IK7e ?[2VooNs]x{3ށ o><𑁏 |tു |l'>)ɁO |jg&3Y|NsR0E/4w_xi\uxM-ox7 umox!wf΁w [x{' |@G>*с>&𱁏 ||'>%O |z3Y oV]Ks[J_K yV o^Z YMK*yiiVxҲK-›Z޲›ZQ7+M2vެ>޼Ա›:޹›TxRWxR oVx o^SJ}WK*YiPC*yix7+ |T7/fTx oV o^PJTK+YiJS+yiZ7+M|F7/Lg>//_ |a_[/ |i,BxM-ox7 umox!w s]x{3ށ o><𑁏 |tു |l'>)ɁO |jg>+ف |n_ (Łn/}w Sx#O}>$၏ |T |Lc'>1IO|JSg>3Y|NsR0E/4w_XxM-ox7 umox!w sgp񳷚}..u?uO=ev=:pvi5WGW:VpTs[^ư3L:k+_yZ)}\?"?-D=z(p·\]o=Vv~jn^eu_S|=}eu xJy5Ut\57#k:Nzp~"/.t^ouvI} }_8*_ܺuXn^w/ϝICystYDV+n{#Zv5^Yqey|sܲ9Sy>9՟y^+̫ Zɶϭdh?'|kR^F5/꾷~YX֍~^{P:X_{u׬ g&nnVνn?tMʣ~v^?136vq{9Κ__?=ӥij,d"\v"E _~9]؅_Q*@;xv޼⽨nV@UoEԭ7"r5lPrڽ8F5E-1z0UnX1ax;?nv`U|_㹊9o(0G1gyS|(2Pd3x>L\gto\y=^Q=x>XsêmF_\5VTUfKub5r61x)Mz>8Ң2D<븽<<4_ϼaR^Wd@r`zUFɧ֊SxE`1y!>X݋zJ:$׃9o]R~2ՃNF.3aC&Ճǭzߋ]kO|vqV%ߓĬ@3җdw\k,GGnjdIzz0Њ=׃^<i\~$yPsWũԃS=7#OYI`k̯羨ϊz~F ]dvus烵pyXWq;\ׯ}&P}~5w? ?z0knQSW_E2`[c {soߓRnT'V#Y^8iRoZUݤzpE=X^[_oJe,~^T>_UŸ"E3!=IM\V},ߓ~=XA=׃X`9w9צ\5VTULubʌzpDqث|=*?M\>|Nr@UWG0cdl8ra~?+n_Ud@@,] Q}Zj1šzpuxE`u]뒯׃ ~ÉkV!X=OJ=T:̺g!{|z ~KIQ"s'ˊDEw"E*𧹵kQhz0M!後M{W;j)BzzZz!l3`QSW_u(<,׃9o]RvK`r=}CI`5k`׸|-P|4x>|W_u (2XJV|J烮o}f{j?/όsWT[ԃoE:$׃9o]RT'V##G^ÆM. Tνss<<:WsQQ Wާ@"5_~zj=5UT`_`j׃ԃ}R=j2k?ϫ;z0_.t.kE@"+@3Wޗkꐦփ`c^y=^S`Fר\漭v=J=xlSX\f]{7xGuǃ&=~}QVkA_z&E]|j/-bS|(2Pd3V~{>"M.ԏ6fQi=^Sآ +IWz0mTU!Lub5ruգG4 5TԃZ$:/2YyT7_]ʋ (2X`fJM}>X/Z:1׃y=^Sܢ '%G:$׃9o]RT'V#oZUݤzp E=XԃNՕyhNb\" WߧllVq/Xz0+n[jv߲rUKsWSWkS=j2TII؛;R_|Ep{|0a~gS{W*2Pd 3 T^ϋa5fLQ׬ȫCr=86孱zp0zT:̨* ݤz`mzzЃp^dϳyh؟yե@"|p?rrkW~`9U)_u)cuHsW`*T:̨O2r!g߲ʺI`ͭE=Xzm5y[O$Usƶ.(2?^ϋ&ZxMՃ5?)~^\t[#r=`*Lub5ruuЩN=)E=XW<ܗNR6ۊzZy5VgUPQVsQQ Wާ@"5_VXva|nFkeͺ`\ץCr=`*ཀྵLub5ruuq#}ρO:僔M|E=Xԃ:wsye^+^E Xy|=(&փi=^Sܢll`j׃ԃR=j2>WC|<~=UsG^_ԃ<4cE+ (2~h=65SFA§5)r=Xוϋzz%{~=zPOTYeyX5VRO`QaF@?).5\`X?E=0CZKRO.񟭧sMd"\(2Pd`Ll?ϙm{Qigz .T&}qsVM1yO!֯=آ,?sXUz0筱zp$zgLub5rQ6݇ ;քM]ԃ9X}uWGj.39a(2Pd2PV'WgcUjՄ/kZYzpnQVl:0S!y[z0zpQSX\fԃÎ:PӪ&Ճ5zpUoզW}A8'2Y9Tԃ<4_ϼaR^Wd@ʪzZ0BV~5˹*buDsWũԃoz0ՉeF=x#G?nd-Tνw׃ |?/nS8g"E ?Pz{QK(!Wz0mTUwS=j2ګQŸ4X`;ʋ]>E=XILRԃ RRt(2?O~^a~^9w煫,Wb|`9uZ$\Myk\L_\k68yIub5rQ:c?y4`|=X5VuQ6P) (2`?XAFZj}꫺'Nx?ՃGusEuՃsz0\\漭v=\H5N:#OՃ53zZzVgUQ\ry)/2PdeZ2V^z/zW|`^T=Xꩭ.e]Z8TLYxV} &n5l8yƐUS,4~{Ϧv].vx/ǖ76 r{ͳs_|ċʺS#'2x  ֪W=Ew!9m3-Y}=\2l ǜ2rİ>2_獡)Z~[aJ5>9[zޠTzQ#K[1_#fn!TҙQ'Q3d[6xȁ#J'viؾTySa!O( #wxT P 269ld!84xJR|ܰǰac=:κٵ%/QI7HZXk)ZYvℛvFwセehnz衇zz衇z{f=Wk5̙3g3O9Ϊ8u^uZaNȝIytH@lt;\}E֏k{9vNw2֕2lfSj6*I2"a_ՙΌH@ꇵZ>OnS/"`PGø|J,=,DavYz`Z>Zs3ir#W–aN?n?87۳As,*Mj؞fN :DVI4AcH.tam`.f|*0d_mY(i6Xr!rb{8]Ebl6aD_=V%h!dj:{`Ҝ4{ PFogp4+0?]&Zy )w1Gډ橀q X.Y; ̓GFDž' BBK'sA-sZ2t-U@D6?RKN0"/l 5;a0LF7,&2g2+A9g!Ҏj:y.(v:k•@bYq&`/ˏߖl駕`DqlK1  !_, < 7Ux'Ʋ?oa?mY|nTR@o/wN >)^'6jICjbL҈uc~ .1M L6/fx:C1F)B~e5~Iq XfQ^k֚紆 ~D:G!% [أ)cƵO6ZFL5Ҥx' @@_  %n3X._'y_2GZwo >w \^"U=~eSTVBK9h|6MM|3uo4_ Q*cEQhX/P,FDQ@TNxrD`,W(p? 1:yG H }‘Fg3׾cm];䌘]p0=#4 _}=]W1S/D?; ᘊP z"[i Kh Tzl4:I=vbe&nGj<6=i$jЁ93)R@eFPm\hf-h0,.(TY\v Ou7'O,tZqi/mq)TeYU#)SCVw98bP ~=o%j*" Lv`ڈlż#%f= )g5_z<^YJX2((4؂N/ɶCoJkߎYGt@SF\0N ڬƞN ~?ZN͝^ʮs9iKQiɆR.(Zh41BUY E픂dg4pA?D͸ qD0 w@/;ϕ.Ro9Xb}FkĮo:. T3+\Uq{s 8`NmE(;|A <:<*ôXaZUH4jR{j"n!k!hݕ[kBZy%KiX9=ԂWMԻn^<\4au(`8Bqv#^QbN+ؽբ  (J]a~GJ]XB .j *9F xiDqiEJUbτIZq.1]LT"ef_dWdB}.3_I7g]3țpM}:x C k|KԵ™,I>hEzF#eT4-9ju`{}i,eTĄI6I, 4 8lp>vC% Z 3@e;6'Yce{)%z|o>x.F$vI4Z3VX#&!%yOAg>"."u)#k]hs}Jh@ae yE=p`Z\Z,ɐcNw 7ݳYҗ[s%Snτa #Av-xb6gcB'g a/ufM4#+Sj`weրdL!^Zm9k4$7'-8DK_'\D=:'7HG*G3.#:i 0^*† ^2lO$tmki:٘$:(ID ?߁^;HW+*%6l 7yUJ$%g[fI|*$VqcX%aX4H\w{G=lĠvEgυJ >g8[N0Pѳlzh9ƽXXRaM]Ly^IȬ0K .9Cbr*k!i0bÍ x]Al2*"X ta8=B ƑT@v^m I5\x& Gd!T`Ϧͧ$2 QF>2,+GְsPfFd6|ϐ.6ߌyXjE;y7N_kxq w<>LEDћqZdѮ~b;n]zμò3 nb%ePXIAˏq*FuȄ}eRGQ%oDB>x͎7s %HI,0dzj]Q08*)|N<=9" º(ѯE#07E!>MijyyI.8/; PnLeDE3x XڭyGW6.8q.]ٸD6Jbc¹Kn-1_>q*]Y@8#~briҕgȠj^cT8RH 3 Dk'JXNr (GV$Or0Q޹|x j @_ &ז1X~kͯS4`ش 6s7gW?dޅvퟬm8qx'矮 %I ӊ =2>L;E*pc?^TI^3tBVSŵ?keή%xbsU?kG4ic֐!j FfS{[vLZ) ޖ̺Gleol4;:CcsKY?%#&O) E֬APka90 ho.[Y%]Jįb \v\b'AR#G1x-- &n?_*xkFYG 2{ `X Q۪{Q m,T4"GH4] t/( ۰B Q Rms`SM8(bilq)A=\B]:/~:rz&\ V .0qE1;C,OKΘclaCD:yVXd?\<^oa[pF[.L"C*"(J9 6YfF-Lqtb"GP+ ꊖtӅ&#.{s}Κ8wh7"Cԍ8k~[UHFn39"dQ.odWKImPPlLN.vWJ [3ҥ>H8FlOTȋ)9HC#v+[n{-r= l{OI Bwa|ϭΊ\(!|6߶*6;JPVU,‡'J99_ڲ4yPm{ O" k 5 `¤Y& XAh n*:RFCQ1,RvXTyM ` ." 8Y-4^Rc,UiA2R!L]ֆX Cs^~#a\4*Z}&}i;Q`7L;n]*1_OBVt$X~psUsUZsC:4cpvRI*F)38v' 熮< gb0^FyEb\vj|WGi6!e,at䉉0w>]Ԓ}"mج%ib%<'rzǬexYu$HF\BFV$=(1VPh_S+Q4Wɶ ȻaU-0 2y^ڟW&,"dWnΣ욥:&QNw}h>+34!!ѹ+<' H?v Vtr%;(FVZJ׸h M 1ʴqeد Ҧxi*S~Њ/ldgL;Zaܗ=Ja"!;O'~N9g?r5h7mS#fSđ0vw(oV[ \΄^klҴÊ+{Ny$m\&ʬ90 > ^gJ6H m' vCRf3_ +k^'+j~+bFqV~iQIJ%9h_+qWm"k w X16H8rg aB';vѶXXܻ2ڳAZ :!Y+XAEǔ4kn̆0hZ٫%4ZHDrtboI^FOG ]|o 8j{ϨUC]ěD<2p6#/I6ffvFp fGOB}5.#Nh-vkmـ:zc5,dW LQ-[t%dg)%ag8P[l:ͩȨg2-]{Cxue)I7esV e43[SJLIbʄ^N-c]rYa!a<%%eAHSK83qԏUac5!2!M(nBRv%\W".SO(PMli˒ sxḂt(GM(Sf,v)ɯve`Ł ?6ެJDkv^)(( pFF=pO 댻 6-Cɪᡝ1^ߙf I$8O1r,INbQ23`1(D?Y|a,@mY 6~L0 n+D"ꖕ~X/Dzf:_ܖ8^w@2tQ9 a6,@ `ΘaAȢ lǮ~Xh rVbE6Elj=9 a& 'fupΌXa ߑ Ja21K%x;NBk*'R;ծf coz4į/10@l5l4 cu֙^{ k#e;D-Q_}TVd\pyhiFߤX]1x=ZVaR嬠s7TaM6~l!װ0 Q0H Baґ ( )zy#A9GD!GckT*b]qEXMZkg8#)faC{āJQ/\a-NZ"x])\[K<ԀU(j/Ȏa_TP32Z.>mkCQnEm?nʈUqtW*Ǽi/.!ADRҁT(W@Wm9Ik✐EWl>FDr>Eb9*iAJj{+͖N8&rW%/nF5^u\kW6')>9лX;s7*z8ŢY1 9֒lSP7Jf%uE9;E3F ycNX졞g%[4fTȩݒ]P\SZ9␕a¨ CDǬu9)9v@B(Um7JkU5uy$;ʓ{]Tbz-yO0%O׍9+Y-犐*+qÝ|SR8WZr7Bۑ_Z48W*96/fqVzF&jEE a1F A(k7$vdoLQӑJ x#'DzzQF7(7 ;3 n?:cCJHAՈGiݞ IPO5pr N⧐E-=^PT9R@J(^gE)MY ')4U79VXjZ,k ErzTUf rz>l\hx$ [2x%'7k>;ȨcŻt[&B'ŠSV::J:2M\x426F^D4)+"lٖ  |t C戏qI*Beb:KVWb{"LUF3Md9 ߀/D@^)Oj.A1 5՗v a\!mh!}Q'37= s̑/WbH6aCZDb¹AN5-Tzy1ϴqH';JhR+T]Θntot(j1պIiF\-ݣ0ja( ̤"V23Ps;8"`CW5 u Toŝ6zR-F:|v JmP=TM]Aܐ'[D9+$@iLE-6j pvf0 "[f`v4Yxw43k!֧%8d-AaOaF #?V5Ō l]q4L5%-n p#L*">h6e]¼jE>xQr'\h*5貃F*ꖹW7|H5]F܁X+gxL,UrFHEySNů"@nXw呈Y_pG g }( -xEN:;l 0|D+WAz>0a{YZ%P,4(CM:5љխ=G>Ӫ(s$kTz.ٙG~®#tk|uVw*L佇{'iC.g)؁bN: D\sGSR߮C1bImd !L+zSk4 |&t0tM$n/w|$=o߱F\F\ QU2 qhF:)gokъK__-98U^HDkn*+KuKΧJwt\%$ $@yR$֒"U} `;8A.<+Z5O6vCeUǓ^c!\"7\B)1U-A*GZN2VIje| ^N|WwzL''"C[E-Rqx8}&H|o $ZsqE9U|ދ ce ҤShǃ]}#SX_;#r]fJ$1 D\Tbw=PSՕ`zE c~fLѦDԌkoM?p/E")RFk ոHg ;('T#7ncA#|*)Ajg11)>Φ>@lbGP̉8f%yyazQtqA TKSnp#a m51(UAq""T ̛tn%ͼSz#kk`Hf\MN>Cm`YMyK TFYlHk`!{LWɠE+LmF=N丿P4XdL}B}׮e0Fa|) 0+fڥSĝ Ӄe뉣kqe/9W °(+WT¬1'䆷b#bwe t aTQ=`Y 'r`$IEM&yF#Ŧ5^LA#J!"-y+"'i)j `c0l `F0rp{{mHdxI-3ϼ,{ψܿj~]2ǘC;?l+u^ZKi:[gk`;_Ngtgmi'4\ЇT?/H/%L/8'}V&o(SW!Z[1;j%⓮yE<;V䕲%RzʳT+ 4xUN~~!M UKv|a2{f1zE]F_+ȾT~y2g".; \$\= c#7V#"|}cL,"WL(~D_ 1fR" oHtFL 9}Oil a(}ftd2n|/7:= JaB<>M5?3 ^Uj[Af h*ݥ@iGf%z4_.eax-ӄ axW?uш]M%9(WSXaS Q>pqUN "VYbRfƒ<̬@Ũ.?kȞ8h{F5j !`iw"Fd ΡS=4DžG)V0t%?"`f"#e)>Ȉ;at P ^YBJTδ# g5s9;j n} l -vo d%fwHfEfvfDxš־Q<蜎'1nbUwA-ک85)SԔb'xQ>+d<![!΅(>GڗH@%`eOc\L*&{zCR+},#JUgѬ$:T'ÈLbEpj:[-iS,JK+vl_X X(}SQZL |t"uނ*6 νgw.".8&P'ވ`C59 >&,bPK-^yJ;3e=cpe$tH8^fc/4JQ2ʷ|l8g;2DkB- EZFJiq!փF,dytq}"bQIj+;Ew@7 *Ӄ2J{ݥ6:qeɑI}3m b,fυ@3Hk7)Vh=4ء {'&f![2<qyOka"A a,*x'K"cQl6- 7U TA8fW,lh2or;d> SX Y8FՎ8HEp>T AJYHO:δY^ŏȐ*5RDI*ϖ|6RUMK%:FRxu:_*iiPpހ"#Lp<_! >b FwXKOtv Lv\7!r0-Cߑvngn`j/伂&BϢNN<(y2h,&3sr8HrQ;EvHL(|hO#q֕;BBitc=\)D<8$9_OiD(.&-r#BN#,vQ4(cܲ/؃@LEC52@f̺I%=l(c6 VN褮 ƾ-aTS0jHqm垎i\)cdQR:=/5nTu0x->VNoPYYŻjq )Ml͆_iV-"p{\%P 7 ꍦ"$VW<Z)whF<(;0,M<Dt%_AhY;1IxČs>k#blĝ0|>ZT}c.h]WQl}E4l]w!zY-v%z0/KzUzA<RzI:J),*rӁ!?=" Ra N$jsRz@/" ǾŇ8FYgnH:"9% rT rßxr,J3AE.0j;X>^ 5,(0 HKqw6b 6E΃`N0 b1}šJPIB( "Ł&w}0ު}e*[1þ$ `Ռ8lp @/DI%B6osߏFЌdV'L ߭5|#oCchf~E0;lΨ9pcQG&F „mf G9Û|e{Q;L'vu4a/OH/tQ$G 3#xwRơ׉:PU~S вGCŢ?5ٕ$+U6IpGT&7m3HxțA{ɵhiֲ}cu:fa>rnEӻlfͱDPܑvNꖒif ]WBG$̏{(bz \mBnvRqF 6WʸaEI&>zib?LR3w)мDLg0Ny-W"Wvz:%7T :|@M(ۦws jN\ e:DґGgxA#R&xY<2<#(Iѱ\!+l͡q#'lp5*o@2d;kZFR!VM''7EŮ! 89D`-vBqO/( 云6D?T,4 x{%+#Zl 6wyigFQ 82 a.mTKLR?yn!1ayTD%˧Pd.l=1xtl^JRV5D V#Kry("=S넒s1@tT0; $v C,`~(*L1`V]*TGV>NkBoAx}f J4Q2mÌ%RUnȼfhg\h'DI4L13į,<;ZDZL_-u^ _RƦ|,TU=č*CF}b2'Oͧċ)AɴU\cmkY;EXGޘЉDӘL\P%Ϫ2il* I[Xť S} ? ̀<VהF̱ʚ 1,u9WɾEݓݧl.UE3cPYQcRRe߅,?P1`ᇒ]>h`czY%kFGR{㊰s&O%D|^oY~ͻjOJ/%,+3)tsġu4l3xƬG"O|U,~r,D!>]:fƼ.tZj#Aj]\_ (Tl`4n c/ UmcpL:7Zf6l涐. @cQ"Xg;x(P´`}N*\U8QgE*-KW)VU|SbPN7I.g|ٻPMQ;any{ Z(W+Q*N"g_GG0X_\HPt=D#76 }er6cVR` yD#XtԣM(ٌ'2)11'2Ʃ>熆@e3%tZTK0ؗM*f%7++ y /=!,Š\dn3 1[|<,K w I) -D09 A1G;uBmj:Ab'rafR 5UsYy2I>Q-.+,\r#ٵKv,F\#*B ⠭~fjuf`|kja$ȑ췇s_[PIy 0) N- FNNEAv)Z ?˺ZyI"mʒ9abP(=,yHpT`QBVVDp:^E'1p3)|+sBfJDT㨤|G7}ljFvT{@|-jbep`"S"ZqE er+5P4sLTO{T|W"N ѹ<*uS 36I:d6娖=8۶qBZ pkU%#i@Prd˝,V6f{x CR/m'gfoA gA,B(ZHF+S 3B`F/AuY/ g X4zŚJ t>ʿ$Zngg5zR)Jx|7vczbC +,W,dz=Z^1lb{vj $W~}x}3r~>4Xue.Qk9zȹT+fSmUγRYXɨ*WŢi ZfqG=#ڄa;̡*@<㿄p쬥* &!kYrt K|>v@'hh*QjA=\7N;{_I*tҐFUU oPXG}l#րZXx:[چ)x^ʇ`_<8DQ`\TXJs*2˽RI$n&j,_Q%m4S *Wl!&γ?e& UUzK!˃{YmGr|9*QeγKTGD?t~D7 b J \uTJtչG{\{'r61/BY׊]z酓YN"8k;,rS|1t3z<2}] >jS"r8?kqC;.[9U}ߣR֖~6ٵ (3~f5pl=|0(.yVW:}K:;YΛ$2N;t{Up'=8.!Rt yQetQkOm ɍcST7 5ɍuzG22tj7"w7O4Ynq+vDvNNt⸻':j;󸭅2y,geY 6b~/sP9R.7+:'N?x_54V%xxwexqZtj{9]Dž{Rqxt/}VQTOgXggu=a/`jH\.Ǖ~Sҗ_%~/qZ? ,ND'7NxECvR_\?-eZbCbVu<ᆔnIVA<ǣ9.;lW\lӨ=M)V6rfg>]; y'KPFm[8&BzOQ]R7D/r 9^^|] bs~ *2s+z!w Ţ$ʝXȸq,k! &:vTt딓χU9c&| 6 C<;#u̱Y8,43/brS"$Hj.N0o.W {pd;B r:Bkᯖ[<- eOoB^Y ۹af5v B9f"w^lrXZVbsX̄[1>'9?&~wJ*|h\ˍ C_Cz@=7N4I5D[^ݹ!YXl፰ V✝kjrFO:SGnp 7!V-^N931+'˃ʣz9SvBrJ{;SlLkV91qyF|YtWVϘZkrַ;^N6vDe]%ȍ8R\yK{\[ ԏLz}) :ݞb~dns'7S^mr$#2 Yz"v'5RQa4<"n[jsf=#qٰ6i+"(WoXNKt}gn^DER\$| .ORuZpΧaVG&u Z 0be 4@.2G 384q)Ɂw! Z1.u,VMW N#IdYv,Xy'B Dj3/RFjs7CeUKW֚yy2p430OAd{NykL;<;Xj6N'sPh! 9*fg>Ωj:L#kΦ]Eodst=&:u39`:#ܨc'(X7JK}i'Ժꁤk  6Ýfi_٘啩uQ_V\asr}pז`BGW(ڢKzz/V3P^y; 3o8VL]"$Xz>Dt ~:Y/_ϼ CD=%^xMAz#듭v X2)E{pi3enPP;0AңBw4)yRhe6Kwc4|>9Сgo='AKu;z0"ʻ$.)=z>@zSmQh05@ <+Th$Rx "Jmg &XU9`a1@)4S0t[SVk%Y{"B]hw*=\Ie! J/DBoR]/"6;q:ǒ V*~[dI;1(9YczP31.V3eSL'ƅ3V UrP#Dk)XMڶL"5=kBU35ky[#'@Gt `YRߛJ?N2HTL{;'g}okLu4: ]? ାuICy/k8^NC6()bӘE حy=(@ۏԉxpߑo=x,hǦl! ^ FSz%I{yl1qyK+.ݳѰZno99֙^Bk])!ENcX4!T8/ 7S2NZqK]<~߹8X>sD":N \ȋqC3pP[ eog F\Wj7I1YY.p$QoRGbl {u.wJ~rDTcapԢlx;  LA ]Y譮c|m#Ȯˮ8l8H $Ki)-w(ݒmv!Oz[#:p"?y(=3IMoHoMpz3NѧN n?􆛉-EK]=rӣӫ^tBz#nY~oO5C-=3z;E{{(=5IOu yy/s}"?(=Now'Igߠ/^z=JKMK#H(~H5Fj?yۡ7(ns;fD z/eoYz3}F,[;i>׷,Jʧ%{=taZv{oHwLZz-'緑F[Q6 0uN[#]xjMwLezMk\75߶t' K6VNүKgn٦ُ(?^ ۙQ|R'Ao4;itFK;O޻=#0O]-Ը͟R;F{SmFJjV,ᐠZu=_05=[w?!]#sjS%=z[oJ-7MoQBi^ߝ<pLZ#ZPr7CϤuwS&Q]I00w;fӛۗ \x}*wۗ/@V[4w3v32oN,rg3vҥo!x-PKw W050q4K*jƥ'N/k-t]Jn"$Rz@'_N#<-L]_7{2emw"3 )LL=w;ޅح'qii_}kЈ>rO'L-Dvrޝ{(g͔y/|oʽ}&OOOx&< |>9`wMěVyQZ}ṵ#|݄L՘J/$!%|pZmHyJ:Fy8a<ɽy{s:]9C8X1Ԓҋ)w$3:˽@XcV^/r% ˌ 92^FAye? JBgZ\ۄm) :mgS*B{;3{CˆaL|VRf{v lVr}Ч$?mxD_?'S CX« Gx'>IO&|gOOtVH3 El#>}B^?xw8pb!4 KkGyր`%Қ/:+ Wu'|uF7=of } }VN<'|Nwݔ/=l~M? O!ԥc=gNx77S ﱤO3/ދp&} $Ox ӳ><@@}H"> wpo9%~}}.u< HhxM5`ëu|S!|(Nx8Ap$4 ,ń{{iyK KG˔ᥴe)r+ 9޸9}SW.O%kͭCRkIRq,K]fxųۄ_^ѱ$ W0a 듞97CT([_1y”0#UG> hyAsRcW>'>ST§>Ϥg>s\>/$|^Cb—e/'|+ %| _CZ:7~A)7Q BV·zw]<݄!|/{ ?@ӌP! .R?JX#4y1qODIO~(g?K9~_"˄_!*Ӷ ~ۄ!.hV?" BޟF _WO#w佝 #eτ!+N߼/!-seϽC\7qdjOf[{'ygO$ V򃎽0=i+<S4)nۗ'e=8r!'3E:{އgޏgSل\?>; Gg]˷._xsR<-ÑKZǸ7=g%2p,>#|8Ese._prYxl:1㍧ A4}gDRϋ оswpnq^BH \"GL ^JeE7IGr}w}Hjdb ^ZO+ kp}%Ihڄt 'E6_bU_N[S/R|||Y\igRm_SstkQg1aBzl7͖5hwy }G(?1>~,Ws@h'?3HO"|2S>iO'|3yV|gql#S,_NK=l~> _H5b—0v_J2깏}9ׯ$U)F0V/M_[~yWoX4M˯LߴL߼J߲NߺIF}߾M_LANw={~ 'i~y535?G o$+8m%=!?=Oq_>Jo?%L˷r?_$d/TLMgd$7R;q8Ļobo~IPu:@~g7M-?멷} Qp\hmHZoZq].XНWq=~{ Ϧ;r޴[8~>o]s3凌CRr?A'Iy*ivpU ? b3Oex_U@UJP@Us]U P?5ymMᯎykEgS|ib ;>smcNyo6<yI$~ ~bJPglQ3YUQ_#7}= !CAօ"s8"/#nOYˬPFyX}9 Fk8B;'Wb"`2Gn Hp_ Z.j^!7f 7̂ ?1\Aڐ}`1, Y+Cq^ɵ:;!jZ+FP74:.IQ :Y`#~6fs[ކvQ:vb ݰ뽰ulppOiq?Ǚyۤ7wK0E$D ʉ䭔3{qa3YN^)t3F;8}! ?3yG;q?G<ݗts_1m]'/np}mLg/!+nh;^1׺+#u'Qst].DE;x#|Bp7؋w#堖Kx!o,uTʖGnOr@1~:Lo>d@j&0YT~Le`;8iI\xCoٯܖh:Hc`|-l@ʏpfcp9\}-l-`KkxV1c" bC@/+Q -GT"Q"kGTqrB%TrH)!bp/côG60Ӄ3`fg”y̘Y +d=Ӂl.t&y0C!/P B!U _

 ¸,wV·Fc}xp/aPJ@I#}YRܗ2PAy@TyV¬ U*TԀP jC >4 4fZAk@[ht."pݡ^ >z\oF$2/s27~MJMn՟ICO?ޢgWj n`0 0  @h۴;v5cw>EM~"L043`&̂eż0VEmEX`1,2 s#+0W*X ɮ{ٵAGcw:Š h+iJ~jo1Vۡa!W!+\<7I^Y\K?<< LjqOI= ;=~)'S#udՋ]Neehſ~J?`Cw2?i%NF<"?#`$93iy3-OP/7RRFW_m$izIY뙀^YuЉ\O]ڮ\Oz*43`&׳0gs`.̃-j(ː[ X `5v:XVOI&'ڌ 0;`'ݸ~/`?4}P?ø\$D)8 g,p.";~.p:܀p n >Ǧ~3Pj`d$Y0\̓ҿ x-Xj W?u2k0p H<7u3p;9kyfu.XSiIpɚZ5vE57i)iGE]- 쬍g&kTwI{^؇7><@x:̀0 f `>,X `9 Vo:X`#lͰ6;`'ݰ> p18'$D)8 g,p.p p57&܂p=!<3x/%;x#|?3| `REP&0`;8 .pC4A 1 &ĂB< B"H I )$RB*H i -2B& Y +d ,\KM}×&qU(_XXD 7P ?P C( (aWGU%^.\\3jZ"8_DA+:;?Yge> %}$ ^p,6BH蚍NfW[ Ssᦙõ *ǂL5Ĺ&qo`kq/ V?^ l rV/mHQN}Ąq*z6:HRdhyJԶZZdi-0;Z.`vvq9]_dga'ameRzqgNu7Mح<{ kX_3/eh$Ws`e^d|i0t!& ].4DGZ:XoXw90(mq#& OnLW[lyvr䃬unΈ7;a=kF3'$2)0t:eO%]]6/vNNI''yѹ7%z:lhni1w>yo3 wx.=k|g3*nggxIS*k!RXaUg mz?S^+nC6ӱ/XF: 6f[alvyÐ47AwO9v wqӁKK r Z~ q(}Eoi2gwȋed~eOip{@_:&6yhCHv~R{`?eϷ$fq<9ۉ5:&kR Kρ!\)sC# ;z;\ȏS, zӾz8Io,oR⑑FZH!#xT$B{Phǿ CIܘMLMyVM?py; fg6%vCH 9: =2DRR7S5Bd̕?r^f:LI}As Y@汳bf059!< D~B q @A^ C( (a7`Ź.%!~}[+ e,]zA+T5*WjPj@MO$Ϫ.>49 ! M4V5mdOc;C3tݠ; zC 8 00).59Cp9"9 R$FhZ#g XR)4q4N$L5s3i׎&krD=t2LL)fq=\ s0:V 1bXLgZ}wgrUN9)i5aY&9IW_Zv|q/gal-;maNwn{apI=?)P1p 8 p Nu߭e4AY8r՜\u2~%=YeLzgЊҾK$y/3m[fڶL7q+ ̂,dAƥxؙQvncu6wY>p#q|s*qaGNzF.30ѵ73%rޣGggN ߸N~+)):?MZ53P]a 4\@˄l\ہrxqqv2Es6Ew1BMŀ.{{1bsdF^S(~}ݖ\@BHA1cz85+?-S~tGW^S2W^SrWvvC)I zϴ.JIˉ|No|;s oRK-hޫxd3eOWj-KtqM B.n9J{aQ6ݘ[* nvƚq9]|qJ*?ڢ[(Wy yc#xoy!w!Rd>8`UF,-9c z_.*]Xcs<ƺN8~d3oWU -ȊRz~pSnAc pBK$z^[F_YeW}nP.27'wQT99o22*"[iV0ʹw.:*ʓGroytaNӥ**VΥ*dް2Ͻ (yUĿ!rF٨MOO_?79Tp3&xLUPUq"\YU=`Qq]?L*铹|G+k7GTCGUԘ|iuShMߚU|] {̟W'L\F?5ڠ-yoI5c/_Ym\W-=Vw9+Ul tYC1ɕL?DӾv!:H\8+銀nWaDzcn?=hSb.q{/MoLYGpԣdۗ~@a a08p R#]u(W q3ujx0 & `:q9farsam䝺E\/-~),y/'VJW!#g55Y#]F_}nan1`na]5o%rG~/~@άz}#̝<,f=}c\'Jq,pZj(󖾰|a2N4ׅA_$<y c_ ts K;j@YU< ~;.< Xi^ mHO~?HS/dg'YW+_kptÕ_݄[Mw.n9<]M;b؝Z3]=DȘ1O) ܿ ^”q[{'&LP 폴q%'CA3z`p/iq(Cfm,.w7 N7w#&&?Ad[5EgWKS/{,'0lvp\hG0>&7uba8XVFq&̄cqܚ2%F$-) mH_o ߒ+[R"kī.ݎOZRz#Mi!=ϴ=r,Q|<<.sR2 ޟ O2!yjinfʂϸ2e%]-LٰώlnkJ``hʩ'%L99\vKCrwmqI=%y!P҆ }. ?ݝGEb [^J@IRP@Y(TJP1ΪPͽQUwKR5SMro| 8F篿!msB=Ϋ@C5CcLMpo ͠;9kw5hgKh OY퇴! mڻ׭c'Ī#2N{gwgAي "x~F z"ʘMdnuCNVUx"#gH'_ǎ{wY 奧; =fgݣoSWCY_anR6v!,ⶫII<p<1kG9q$( c`,0~*!%c;DM7w5 s2L0 `6́0X`1, a7x7k`-Pzֹ{|{~eI0v 8f# 07VJCo W_7*(Kik6=ίvн<#%@={擨KO7@hɂ.`AgtQbA!d B:M v<Ǟ7o{IDq{t߻{ι&\7ϐ{wh3.] <t.DH B|aX1g {`ا`qt6DBX#p>k,:5hc`FҠTH =׮fl].<:Ø# ( !Ǝ6Z#PFɂ8,0.DI`XO 99L@eb"`p4_x1 x5:Xg^G]°Kχ>%x鄧 kp)A&V_@ Zzs#360ඈwy{]z2hO" _Hcc )d4y,uhп$XeMN\e8Ф]N`73ϩML&C(&, v= G AL$t=}f&$Ƌ; yQ:VNI?d}FA6D$Rci@"DNTI&%hd4&`1* s=N+8$R8W΁7%Ƥ^F1Ov:ѹtve?6Ur"7NQYÚ )zNP=PK sG 9 .B fZ=h(TQl VC:k]1 x_ uIx7v#)ˌhر@S4i;yTh8h&0HYV[i NM ϡe@JC$Ki̳quͭiw d(.W $-ffZhw !*8'p[hI=w=^X!MxV-A(&F[LV,xS={h84-O]~U1¸N}j < <0ʡǙ>Bwrg|!$<0?@EC>ADCCC=?cecmm%ihLkm/or lk;fhepn8qp?twkljokmrpTwv-npmuuJvx:xvEvx@|~vxRsur{xYvwuxye|}E~Az{g~M<y{xDUK4_}|"cOJmw&G]XaVQ@-y^tM9X3pTlW:EyaUrTAZb]F|ah_LZcn[hVpgq_f¿oʛsˡ{pԤـv֬{۱ݭ~RV}tRNS@fIDATx՗iTWYQQjUGJźUT\,JlV$xDsKM- ZQH-*Pq̔h!;&cM֛|w}vvu -tYi&IRuZ3 Emғ*RTΗ[+uYk.$ONZ#.,,R$9^sÁ56V#gpxhϑҚG%O:iZR6Yp7(xLv`Қuɶ %'2H .VeV,@Wg@0|_m}N]-.0ǘ1)E2=px~^a_$]7zu?J*%l]/ yz};u(*}ݥ^- W÷T$+r⍴BU(,Fݡ`i4ڙo0ZbbBG2tg}Q3?@m^ZIl8OsцN2W6+N@09L{C{\xgHwit~-tz`'/M Vp*"3.R]wQZ\oFe8abڟ?= f#_W0vjuw~6JXðx̀8'ʧi`ڀZN17!bPZa Lj4m|bsWa ,71Mb鍦3}OQPYWYV|.U {0+M$0G*Ο>}*;;L|?e쭞y=_u=OMMMK39 w #G Vڏ76,uVgU0;01&QJ ?bP(^!mCZںYj? zLoc}\qU0NÏĺ4ʊ^/;^:zzXЎ)\q1 P)""ϫC-kR@:v.!\~uU/[$8atq e=@0M/L.Xyl$YC1 0qBZV᪈yut1( v&t$ a/..+8,!BS'%0Yz&~{8i&*ffyLd-,ygeAq 8. Ș%=|}gK-+` L&GSӂXahPP< xlߧOTYœ K (v˳ Ծ,3L@ןb #K~'\axA)[sm*˸7f Հ Szaeɚl.O~78\} ^.Z#zԩM[`a?1>':60W\ѾӃgX=eAާ"Op7`FcX,GF}'LaJ"Sjw9X9keu #A+0d+c-SH_|>Se۸>,514?߶$Lx#\y|`&Y*2|ss6YdcJs&k}x M!d}_}v%ѮʁA|_߾lw c,IENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportpno.png0000644000000000000000000000013214771215054017000 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportpno.png0000644000175000001440000000026114771215054016767 0ustar00rncbcusersPNG  IHDRRPLTEpH@fvtRNS@fJIDATxc`5(͖e&C@r*DFM- "pTS&AJRD  5SRD@YjZ} kIENDB`qjackctl-1.0.4/src/images/PaxHeaders/mporto_64x64.png0000644000000000000000000000013214771215054017331 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/mporto_64x64.png0000644000175000001440000000337114771215054017325 0ustar00rncbcusersPNG  IHDR@@PLTE       # # #!' "#!*"#$"$%#3%%'%'(&()'/*++$+,*,+.+.",-+-/,01/7752'315130231689496342:8796A<A8)9:8@=@:4CBI> ;=;==6P>J<X;=?ICUB@B?a>CD2ACAJEMD$NB.VEDFCOE5OG,GHFRI(VJjEXH$TH4IKHOIClGOM0cNKMJNNFMOMSR:VQ@[[RTQnWUVTVXUbaY[XgY>[]Zk\B]_\mc#^`]dd:_a^`b_ac`}a&bdaib\scCkgDoh9ti)khJueEfheuo&mhgpikhlnk{r>npmnNvnhoqnvwvEqsprtqzsuruwtwyvxzwxly{xzy{}z}|]}f~}~rȇщGzՍj^{qitɵĐ¾ÿͱ|tRNS@fIDATxmEwv8ž^yHؘJNPRoԥ6\+ =DVF϶VSyP/=n) MIL7k7bci`%^ү'K>L]E}uui&wB>h޷a ldy;y 6&ִw<ȼ;ׯ|N4Ù=w|xę,4vóSBKhΞ ~쌣^3G^+̣{b_} J?۬b+ 'W/Z6=?C*P˯~2}ϞC_O~2Q>.?_ͯ61vWp?B*"ڥ8,٧ Xu&\NPg((&Kn=/ݵoU-R?x ! r%7˰q\/t?s5@iDaQd`­6`ی` $61j@ĠPZ2bEéd|6b_㌇WU4,‹񺕁y;ՈW:0 wmFMSՂo6?gZk 9?@?GihQl\şgAoŻ+lh2yר^0ؔ2,|fDc~²uf~ ~_(USj?M@X>eZnt[#_~UyC|K;* br#O8~㑑w^oݾ:U]9~M{#I^ȳOGʄ?CcحK|KJ v)<T?<ʹwSaIENDB`qjackctl-1.0.4/src/images/PaxHeaders/mporto.png0000644000000000000000000000013214771215054016456 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/mporto.png0000644000175000001440000000032514771215054016446 0ustar00rncbcusersPNG  IHDR(-S6PLTE222:::???LLLfffhhh}}}Q :tRNS@fMIDATx}I@@0 g]#U)8D'g Թψ¥`Âmbz[_ ?fc._sNkY\JIENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportpti.png0000644000000000000000000000013214771215054017000 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportpti.png0000644000175000001440000000031314771215054016765 0ustar00rncbcusersPNG  IHDRRPLTEpH6tRNS@fdIDATxc````K`$f a(*0(\CH5uM U0 IN3L]RUB Rl ] cD Č&Bf>$]9IENDB`qjackctl-1.0.4/src/images/PaxHeaders/forward1.png0000644000000000000000000000013214771215054016663 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/forward1.png0000644000175000001440000000041014771215054016646 0ustar00rncbcusersPNG  IHDRasRGBbKGD pHYs  tIME!4~8qIDAT8˭ 0C_o%$34t| mUԟmYaUj@v҈- 8`q ^ :q Hwo~HwӀ2<1+;y<1~&R7~*1sV[IENDB`qjackctl-1.0.4/src/images/PaxHeaders/messagesstatus1.png0000644000000000000000000000013214771215054020272 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/messagesstatus1.png0000644000175000001440000000135014771215054020261 0ustar00rncbcusersPNG  IHDRasRGBIDAT8˝RKHTa=gitD 󕨃`XIa%.DQТUˌZ(բTBT mRU:9ܙ{Ν 5%Y~w9*&:N=y]@ *ʁz#F`wӀsP=ڪɒC9z͉HBK+핷8( _ vLH18da b'N낮`^D`oiv+3Il$g/tĢBjvn+5˃'9{/!Ja6WbLo$dw[(k#OjmdNP*TS>򠹧jÎѽE0p3}ߊUߦꋪFž#HC_g6'~ ? gM7CWaU$UWX2?xC?[R~&OT˭H+}Dv)["t_"kiIENDB`qjackctl-1.0.4/src/images/PaxHeaders/aclienti_32x32.png0000644000000000000000000000013214771215054017567 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aclienti_32x32.png0000644000175000001440000000310614771215054017557 0ustar00rncbcusersPNG  IHDR DPLTE03'" ( - 27;?9 BEINP34.75)TM6:,X[<:.^<=;>=6?@.g#ACA e&m"j er&m#JL9v".a"w*6d })t/w+ ~"(r!KZK4m%*VUMTUSWXE/ZYR[\I1({6Yan}u{^'7)wuJAl{{;CGfJUEoP؈E, ؜R8I´Ŵڰșڲɭɳ5ͣɻX_F/uiҢҩKԱXخڶ}ؼqT۫ڷP9ߵuJjs:^(tRNS@fIDATxc` 8#07wț7O ^x(֭[N:rΝ;7eS}| d?uMىAVZJ@ #'!yXo߾=5o.θZ:} b•'=zˁ'%Y.5QW>vLM><|s]3Vu$##q o/zu{߼{nG{}kۡC@F?YܹxڴƊt_ ac&>=뗯xpGE}xx!~q+x}7a`*^4h1P]QQqԩSu+,..yLj ӯ7EQ<~…oΜtiiI`6)((@:::^\oWQ`y=j׾?typpή >UUc$mo;v$II;wez#||gN_v5]SS3| g{%tCCCLųej CnWv(r1` P{ngΝ#G5`P~ĉ:UUr5@PU;q`X,l5R UUUP( x(DRVtcǎ9FqڊE`cAh4A_sH`@ҵ`T<GEzȫݩrrfZ@l6u2ӿ&(l{ss<8 L&55j2Y _3 $+LddCfH'D,nZm{+++3LvkH&ZdLR[__EccѣQ͛_ȂvYjkk=l0Į.V[F"hwn||U#ܝrdܙ@[VWWrxI(Jru|KdlYZK@x/rSmT!vQ%᜘ VϪ4Sv˙: 47m ^'?j$AVvWѺV1?DMKojo|W'$m~wIENDB`qjackctl-1.0.4/src/images/PaxHeaders/reset1.png0000644000000000000000000000013214771215054016341 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/reset1.png0000644000175000001440000000107014771215054016327 0ustar00rncbcusersPNG  IHDRaIDATxڭ=hSa/Mbn+ VSեAD須֡C)]Rl&(Dj38 E61&71EгqD3UlkTywϲW9+t~@T-p+X- /  $7OOncg@iȐ%d0zmUj# hO | G)?02:`:īUziXy/`0r]6  X4({{8':@h""U5y,sI>_[l6u@TE`r)[J5+BI"*ǛTXz.x<Y :ۺ\˭D\|_IXt%729flC~&B*рѥRs|*5xٷʕwn`Jج‚N>z렿TCVc"dc/t$TIENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphZoomIn.png0000644000000000000000000000013214771215054017373 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphZoomIn.png0000644000175000001440000000260214771215054017363 0ustar00rncbcusersPNG  IHDRĴl;sBIT|d pHYs & &Q3tEXtSoftwarewww.inkscape.org<IDAT8]LSg紥eW) ̯L[RΏɜ^x1љd.lf1a7$l l3FVB#ȂT - ؞삃!dOzCM@.`D ~  B+V>x඲,-@ Hܿ5R VʻZ OŽNȑ/s_~-~&&&0ddd MMMUU?622r g#p;wL줹9*IAY弼\V{'&Պ$=8q{N<(6mߪg?ptuu{(B &nt+[n+{{{׮]Z,o+W6Mܺժy`Po߾mDBuvvt j4bV$uuΠbf-VBIIett 0hѢ_dggoQE$''ۭVr rF.]7 K"tccc!xgKnfp&`ժUv]Fo4Ln1677 /[EEњG}˗\@0jYKӉ7n)..`0DK_^wThQQQ۳Gҽ{pΝyrr@mKܕ-z^:::hoov˄LF#ZH$B oZ[[~D"U1eAMpw:vY,9륭ބ 7lذ8l6EQ#džB$~ @ul~XZZ}mŽ99ַPIn=̜jv"U?v*I]N57) ގ$IƁ}`v=ި^[^. 7n|T+W!otcYEMD|>P(s^9Bf'eiUl@MA2IENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphCenter.png0000644000000000000000000000013214771215054017400 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphCenter.png0000644000175000001440000000234714771215054017376 0ustar00rncbcusersPNG  IHDRĴl;sBIT|d pHYs & &Q3tEXtSoftwarewww.inkscape.org<dIDAT8_Lg|+t$ۂMBb!Ӵ,hVNӫaZb̔ M14fbt"&`@ii +_u}18Nޜs''<9:l:@@Hz dXzNj6M"ٚU@ :Q fzѸTQO@,;>oϬfy$_Kwޝrh4 0 hAl%I>}ONl~,,7D"###${ ɀ-_cnj2j۶m+EEEM`&p@v%fX<@`&9(xW};zsӉ'N{b2 0ogLp8Fv,^T8wɹy@ `0$ "0z\ce(X,M--W'&!`LuuuYkn;8Db4JtH"MjU8sxT@)7[tzdo!TzˇΐsӰ0DIENDB`qjackctl-1.0.4/src/images/PaxHeaders/qjackctl.svg0000644000000000000000000000013214771215054016745 xustar0030 mtime=1743067692.321636603 30 atime=1743067692.320636607 30 ctime=1743067692.321636603 qjackctl-1.0.4/src/images/qjackctl.svg0000644000175000001440000026046514771215054016752 0ustar00rncbcusers qjackctl-1.0.4/src/images/PaxHeaders/aportpti_32x32.png0000644000000000000000000000013214771215054017641 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportpti_32x32.png0000644000175000001440000000257714771215054017644 0ustar00rncbcusersPNG  IHDR DPLTE02/ %((' &('(&,-..*.!.-&-.,0013  5267 575524187463=<:7,685<=<<%9;8>=!DB>>'BA AA>@=FFCF#ACAJLGH IG+JJIH1IK(FJѺ\HY'۳O*2?޻v_ןW <-;E_9Iݻ-6?w~o.+`NIq/**rx{A`it \zBrdJ^.|ۯCsn8ynwHdd^g^xO#{K/$pu˗_ЫH9I;a.Л@%A) E]VoisL]2U-Flqضmx%=*??v8ftJ?<"'`>Z8waFRe_cl2ű)`˞0I`nЅe\'k¹-Jbո<>^>\Yzu|Qcx7?(B,IENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphRename.png0000644000000000000000000000013214771215054017367 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphRename.png0000644000175000001440000000146314771215054017363 0ustar00rncbcusersPNG  IHDRw=sBIT|d pHYs  tEXtSoftwarewww.inkscape.org<IDATHݕOa?4!{$ i5!)щ89p`Z5L$,XR%ҡ&r¡m\6H^SZ qys8LW&t + t:l!MӎJ"@ l@0:88l20_F3XEs&ڢw@0C$|qQT*E25]ׁp $IϽ^fRDxgi1&myy)* Ѐ'B#+u4c% 9ՋgbhQt0f:^o-Zb<; i(J@W䔦YYDpF0v3cǠ|Jǀy ШLpvB_>"@zrZ,yu9yTOsA4A,_HҪ^>SJ89D!PX\f͵Db5>|8m^yn!ɳg~S$:`1On*Kfx͓tЪ@?6]P^XV62ܟ98~( (}_'fHDpȒW]>ٴz(҆L"ë] ~H|Spϳ(Cq!Gb9ԫ@ |nPa?a/uIENDB`qjackctl-1.0.4/src/images/PaxHeaders/formRemove.png0000644000000000000000000000013214771215054017257 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/formRemove.png0000644000175000001440000000110114771215054017240 0ustar00rncbcusersPNG  IHDRasBIT|d pHYsu85tEXtSoftwarewww.inkscape.org<IDAT8ŐMkQLrcL246%tJI]TJ)])] bE\ B\ EJJ I|ndwq_898m IoC,ʝ_sڶ7<:{PԲyOM8{?Ra4*{ssi U.@~6,iB䵮*QZ.oJIM)k|2 yz0@dԨD2`rR 5INЬ]f3vNS)\HZDFI>z[7Mi}me!RT3|uqfg(\;Rf"Ppo--U6Af{uM,[͚@£E0E|oؤEIENDB`qjackctl-1.0.4/src/images/PaxHeaders/connect1.png0000644000000000000000000000013214771215054016650 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/connect1.png0000644000175000001440000000066414771215054016646 0ustar00rncbcusersPNG  IHDRa{IDATxœK(DaJlQl$EYBsY) IbEJp)$& ~1h8̌soL#_}_1+_dZ3wj&.Xݞ`r>>f] &cx~#S@Vlp@;p<"V@@&sb6.XR;9+o apj-SvFLZ`+Zg<'p<]#H/g3>^n-wXQ^ݹ4Mv8lCme/T$HEGm+`Ec-p6d.c]N nXQjutY A)P&h1(@ߧP'iW_s vCBt-V`YIENDB`qjackctl-1.0.4/src/images/PaxHeaders/itemReset.png0000644000000000000000000000013214771215054017077 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/itemReset.png0000644000175000001440000000110314771215054017062 0ustar00rncbcusersPNG  IHDRasBIT|d pHYsbb8ztEXtSoftwarewww.inkscape.org<IDAT8R`__] NHMP ]ڥCS'(tS7%O24bHi/5{clt{s? D$(M/Lr)˲|i .y'aE1'mq("( ԡ}eYf)q mE1;͒l6re}u=" ѨZUBl[c $۶ziVs !Kv;cEp΁R R4M$~;9?5 s~Z!g~Q20J)AG"H7Bay?m4J1LRT.v$"!`8(ur|V*c}q%N~3υri6MZ.:GixUs IENDB`qjackctl-1.0.4/src/images/PaxHeaders/asocketo.png0000644000000000000000000000013214771215054016746 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/asocketo.png0000644000175000001440000000136514771215054016743 0ustar00rncbcusersPNG  IHDR(-SPLTE#%;*+;.0;<8=9=:>:?;@AT5.Y:.Z:.DD=Z=,LNHG=IH=LK=ML=ON=QP=SQ=\[UT=VU=ZX=^[=gfa_=ggb_=iieb=fc=ngmnhf=nojg=pqli=ffftmnk=us pm=uvvvso=roItq=trI00ws=yu=MA{w=yvI}x:}x={wI}|4z= |=~=}I}I==H =:I==:ZLZK$E==IG==&:=I==U:===Y,:A-1iI:I:j1,:-I}-.|º)|Iľ+Ⱦ:kºhǿI¼jI:h¾I:3I?ÉAIlj:ˈ:ABtRNS@fIDATxc`q~N`iSz&u64i0L<),"'.SޟoWfaɊ W x7p`9&W,V?uL2OgicA2{pXC#1>H,`^l窢# 0fί 25 Xؚp[Xp 4Ue$Dx ZHM6rIENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphZoomOut.png0000644000000000000000000000013214771215054017574 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphZoomOut.png0000644000175000001440000000251614771215054017570 0ustar00rncbcusersPNG  IHDRĴl;sBIT|d pHYs & &Q3tEXtSoftwarewww.inkscape.org<IDAT8mLSgBQ2|a" ٤83!Dg6b6,q%3B2ݗ-!,QN0T"PLK}e! nNr|ssT* 0j@@pcK +GN:Us\>/ I< lwi)ik(tRٳ ^P(N#''Ahkk\SSS׀a`~%R ׿:x𠮷X__ߘuhh68zh4t%.\pmrr*0R _xqŋRM]ߚ ȵQQ-***n߶˕GE 3\j۶m6S>|KLǏWI$tu݋?d+Sx:<<7 mLi)ePr4~`jݺut:1He9) 2D"PmZ9͛24ͦ`H皜Y`l^FD"$Iay|||ĉFFFjZ0`iaatT*OR@$ ̔333LMMyS/&^oe{(>幼LAɓ' qCyyzrӃሙf֭[\Z-(F| lmm.6`AP/X,[Z 墻Ajv޽d2fei3DQ%<<>11p:ǭ@"p emUQQeSS|?P)vuJv"0Lϔ3kh,H8Nf<fI/,*Rr)lnr=Baox<(З $@t, z<@ `\6_[[].ePi˖6Z0*5U_PE3nIENDB`qjackctl-1.0.4/src/images/PaxHeaders/session1.png0000644000000000000000000000013214771215054016702 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/session1.png0000644000175000001440000000102014771215054016663 0ustar00rncbcusersPNG  IHDRasRGBIDAT8Œ?HQǿԄT(-t,8(ءcPnVD-AD,.mҡ! ڔjx;K.w~4!E>>|k+m-}"Yr_z7&I{A)̚mwm ~;_BLrLo@j}4W] #Y?PސxL`}/+^ FȒ i%% )7'SVfk5o'r!$_c-=' p2y50 T H_ =}D `1oMAIu@E}9bWnxD^vmB5tOEo6ƖAJw'+1.I1%bT܀Pvp (F p 6ZE<IENDB`qjackctl-1.0.4/src/images/PaxHeaders/mclienti.png0000644000000000000000000000013214771215054016742 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/mclienti.png0000644000175000001440000000037514771215054016737 0ustar00rncbcusersPNG  IHDR(-S?PLTE@@@LLLQQQYYY]]]```kkklllwwwxxx䞳tRNS@flIDATx]  QtV{A`Ÿ!]C#N0!7eej@…d"39(p(l.,Tk8d "^J}k} 5TIENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportpto_64x64.png0000644000000000000000000000013214771215054017661 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportpto_64x64.png0000644000175000001440000000373314771215054017657 0ustar00rncbcusersPNG  IHDR@@PLTE         #"+,"  !11"$!+)56 34&(%.,!+,*??==-/,CBDD<=14'231";9IHEE574NM981:;)6?0:<9USWZ@?8QP7BC>@==9u&Z8u(gw6n7q7΍u'H='8˽1Da ı3nA6kAb1q[A =e $ (9*8,^]Vpqː[ 3׭kW8dr>^E{1y[F}bgyEס)Ux[xP~]Rç pw#[哳EG<{)bW-wU?m;?uƊEDc.._? d "l82(n/IߤxO;BMJ֪ xJ]W#x_c-Pn0ۼ~ͤ_aeu}PQ?&.:i\n9HVG- DRkRbz"m"Qȅ%T ɷBNH3~(M`ƢSKD$+2ڢ᩶5:6znS6N7H%E!3)#eU( K{fx {;9=(ol ]/ ~CC/#wA:@ qsYr[mn 9;*AZs,%{4 eqUN "V":'8 >>@@@BB0AA>AAABBBEE3 ]]ddGGGHHHhh ff*YYiiQQ<%bbPPPkkSSSWW@P__V^^\\\]]\Tbb^^^aaG}}3qq___~~```bbbddVTiiffN6zzakkhhhVsslll9nqT)=7qqqvvWzzz{{{~~l6@_`dB;cbDegEOGSiKkEJyZzz\rsvxtaYz_~gíse˳ru|ljαpԼpշrغÐđˆ߃:|tRNS@fvIDATxc` k97k۞8jwٶk>.KصmQ[7mR۽sf d\6HGy{vLɯK._޺%iaXݠrlr+ O&/QX`;V=, 0D|e3Gg+='y֜U@3g`WK]W>nKV4Mf=gnjHw?x.:cIENDB`qjackctl-1.0.4/src/images/PaxHeaders/mporto_32x32.png0000644000000000000000000000013214771215054017317 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/mporto_32x32.png0000644000175000001440000000150714771215054017312 0ustar00rncbcusersPNG  IHDR DPLTEiii  '$ )  $" $" """###$$$)&%%%('/)1+,,,6/ ...70;3 222320333>5565777878888;;;>>=DA%DB)@@@AAAIH ODDDDEEEFFFQH#GGGNG8HHHIIIMI@JJJKKKNKGLLLXN%POJPOOWR6QQQSSSTTTUUUVVVbY,dX?\\\ha=```mc4dddseLpiBtfMhhhyiJmmmnnnoooqqqrrr{xDuuuvmyyy{{{pt~ÈpȰɱyMtRNS@fIDATxc`0*̈́O^NIbo mJS*ϑX6uvT@}m6y6'`gHjM"i]f{DeWO\`s?6e, Rbkvb;5Y ua,򳦤9˫Hb@ $_#8pX^q.` ẉx\D晉㖷l-S^?eR1Ny<3.Yrdw7#Ϡ"'۔zJ/tßiI2[([IENDB`qjackctl-1.0.4/src/images/PaxHeaders/rewind1.png0000644000000000000000000000013214771215054016507 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/rewind1.png0000644000175000001440000000040714771215054016500 0ustar00rncbcusersPNG  IHDRasRGBbKGD pHYs  tIME%:?rIDAT8˭ E_1Lcnw;S=&jPJ @ZMQmި[wHT{{CEyw@E :usXO@?nTxB P dO65dy`ؽC@`AO#LIENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphConnect.png0000644000000000000000000000013214771215054017551 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphConnect.png0000644000175000001440000000164114771215054017543 0ustar00rncbcusersPNG  IHDRĴl;sBIT|d pHYs & &Q3tEXtSoftwarewww.inkscape.org<IDAT8AL#U3vSZpvMp!L@=/pXLc$O$rd,'B8B%@]lȴ2,Б}{Tlty{OKifۅ x^Wˀ =('Η;|]0mYibC·CCC^˲B`YRppk.o"?Ͳ)Bz0M-7/FGGSt:-gff; ݑ*z}===&''B%d2?Q搦ދF{aTs\4MY(ryyY__!5:8.]!n׋a@pulUJ2'|_- Q.1MS Z0eE6}"ccc!r9|>p؏m2+br%ɢeY\.ffz/..~ԭ-DaeeQ"d2ū.x|@,ښn!.賻k K_4MR)955U BK66G]S)oE"7Ţxs%ɍǚOZo;@ pT*e{{;J~7y\駚y C @+@QӰ 1K ̨3õnnXHd)OIENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportpto.png0000644000000000000000000000013214771215054017006 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportpto.png0000644000175000001440000000046414771215054017002 0ustar00rncbcusersPNG  IHDR(-SiPLTE_@@000542@@@``0PPPPPUTR@`````5trjhd@@@@А` ,OgtRNS@fyIDATx] Db"A[RZ#hvd7om!aƀ?f=>6p̗ _Vp]}+H!ᕯyҋ >(=%qS 7^%IENDB`qjackctl-1.0.4/src/images/PaxHeaders/apply1.png0000644000000000000000000000013214771215054016344 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/apply1.png0000644000175000001440000000040714771215054016335 0ustar00rncbcusersPNG  IHDRasRGBbKGD pHYs  d_tIME|$:IDAT8͓ G6 Xee`6  '1n G۲o@KB0Fnfyz&յ\ۧ}Ǣ hq#gB*9[~p[ߍxj>;u+XG6IENDB`qjackctl-1.0.4/src/images/PaxHeaders/xstopped1.png0000644000000000000000000000013214771215054017065 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/xstopped1.png0000644000175000001440000000050314771215054017053 0ustar00rncbcusersPNG  IHDRĴl; IDATx1j@EV۸RwF'!+j)2Ai(ҫv,1sۆ.{>zZ[cn1N"2ZkG"2N "#.+ag?~p@J eY{_s"3WƘ?gc gMaf89\ls!\rĹ:0!j4jXq%U@DOI@Dck-Dy]]m?>Qw˕Cȍג/Ȟ*IENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportlno.png0000644000000000000000000000013214771215054016774 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportlno.png0000644000175000001440000000026114771215054016763 0ustar00rncbcusersPNG  IHDRRPLTEpH6tRNS@fJIDATxc`5(͖e&C@r*DFM- "pTS&AJRD  5SRD@YjZ} kIENDB`qjackctl-1.0.4/src/images/PaxHeaders/formOpen.png0000644000000000000000000000013214771215054016723 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/formOpen.png0000644000175000001440000000105214771215054016711 0ustar00rncbcusersPNG  IHDRasBIT|d pHYsu85tEXtSoftwarewww.inkscape.org<IDAT8?AGW# M!8V%} I!)m *hw,bac"ץHHsn&wy/!3B]Pǀ π@~_0 EF4j [52Q8o#JG;#dDWnt(z&3d%mCb QQD2b@+RUB{ )TVS!|/@hN +Bv^_LVbX -1B}4ebUcdPOnZfeL;?gf^efd /'^sf8EsrXqr^sqgkvkP`)/E,(}k3'N`lxAn}p9]Nez7H7Zo5xt CELm,BfxIV,Su~m Nu_9_Fd|j*.p6 |f}hÆ_HuYqr|Ẃ}˒AvѢқ=/ʪ#_³l>“(دMŭɦʡ\̝V\"޼hqBөǶ4Աsקڶ}پ3ݳ۸^upETkxas'+tRNS@fIDATxW{TDej! QJ Xr8֢ 27ňhV$VHa[1#r6 BL!x! _Hg;gg~s8>{1k ,\V^8B>7cD&u+}N7IZ(TjBN9645 j գ+Sj䝝m *4fkpx8`a4Bq$$RhJ`d۷Kfe=uk޽kX tx3'򛦇VX;H9+ݽŢ3Xt&C+| 1[?ϫWq b0YnSɎ66,>#ֲh|& P4kGP]0tYY~ 0O0T$ m堸~>mJm}oJe fR)I,9% @~s_4(,$$וޘ369?oN[ 5BV_pCYi7k@f_B!C`|Ʉ/f 05*~ֺʻ/k2NLڵK>GȀ%̄_Sk乚瑒eAQmu d&$sc~pZ\SR` yEy7l;vDG:B0h̯})^5TVWyyy9=ו=0>GGmڴΛG2#T(6 K,ll|TZ[[R{΍;=w]8t`ԗ7q矯[WB΁J-~^5A\{? D6۾q{榦FPp{/K~N7{G7lHD3SSf*! p9;//^gϦ7E`Br C*\.`!NvoU71ρȐ,!87S1xhL; l<p(L UzIR2-=#֮ޫ[^9AXOȥ]Q`&Ɔ|$R=eZY~}.0M'a ZZYBȀ@?B XkYk++ ,hɸ9>;'}L`ll4!L%Q0 RG@s2*Xr;aDА<с8fg` 1gg/~'ht 'KBf0o NA_8=h9̜H051 .O͂\tOn7kl)Bd=L@N`H;@7e7B4/:ŭa04>$q* $@G10ޫa|5}{{kk  &ey'Ss c4 QHg LLݭ? *74bA  -`b 0$qʁB!`1a4 ~5G0A7omeg6gGX?Lm@%s``H[ `߳g}SOT& śP uuËA J9($bX$UЄD "R fTHq|@ (29zŮWXllXPPPX@Pq۠!lȸHVj qTqP?66k XXX/<ᲑoJKO?|x[dd߇XzgD% _"9,;@ q_q[Vbb"!+WXn.rcSC8v3gRisSsFXxLN_02A=x a'4C<~cY'N?/E~111111B_{NN7'iĎ@LLLLo:0'eI`s@x4p gg=~vt vbbbbb~CgsN1f5*"0uHxZnuSO@|?nu ׀3{=N> &' 8'3:;11111Ag%SS'oP"JX'r {fZ vbbbbb~S'9'V ;+<.4MnH$ 0 Mu]3M <q}!!@JIoD5CGCps)#?x/i) M4]-۶s|0===;>>>;666a۶fB@𐵵5e^RJ_JٕRR0   z\!*"<.`pkf \.7fӓRdgff㙱1P(1z\.8B.RJl~n" @)U%j y_Q$'SSS|`zzD"MӨjy{dY._,rf~o6ͱlZpO) yRpr? ;)?*<5,Ii_*v|/X'i-%K  7WiܻwZ=~~WO@TQ{x%P0&&&&'"XN p41 !\xo-Z7|;wpE+W4gzzEIaÇj!Md2C:<:ݻܻwoJ($u]n{^/V0 J/ x|챓рӺ11111]y*pJ<Dc~rI˲JsENdayHG)52aVal69::޽{R)" ӑT_kٳg VE>|r hI ;CVspp0 ]yd2jZfBJ)!D{0iɪh:QL ?u}4pggzrL98 iZFJQJ0 !jRaWa:xHpӤcG &&&& #78sð& tjzfZ+JC=&tzпm1̳hu.O\FuRJZ-_KKK\v2 v ÐC*V=z.KLOO /&r{;Pu}2K$Z:Ndߟ 0PJu)Q:I aH3 ;c ;bbbbb~!8-/@?qL3 -[*gfgfL${{pyi=QD NR,xwh׾5x Μ9m۸۷Y{]ҙ ,--m#˲LT*Cfggmۃ6!(\C:߲,Z{{`^\.GTbzzQ^GѠjx7Cp5RQjΝ;<~Z6(0 C!0\5 Х" îR  6 Fيt@\(ƀg"O;iF"aV+kef9{,Z-avvr&d4uFJ~C@)PZ|ȇ|@>gm?wP}5\.7ZE|hV>zΟ?ϫ~l6G*"LivT*XE244j24 VV.W[evvv8*J%Ql6hZ4 i6$ fggm{TO0cb85PE,288ǧ^#~' cbbbb9S 躞6-k~fz:?33C>i,J{ʗ xbTG?'IX*R\|#!eBdyjҥloo3鏍aYfvB0%JAtӴ×z@ H5 FF.vww#'`k8?Efff( #`Iptt83aBpL'?yK=zHD)!07;WzEG"@i Phssg|G &&&&sqZ[T !0M ۶[4F8w,sssO~6NI/`YZnB b=2@!i\;2Rikb|饗W_}U+Jmzp֭ƭnDbXOK%YXX$ˍtь* jZ.T+UPd2J%rvvM\f{{zX%٬K)540Lj6&*ZRaWH \'Hx\CYNg AKy' Mt!iYV"왖6aTAs+YϯsKx!< F*md.BTAʗ"*OMM@Qgݻnsstk_o/^d///sE&&&FCǡvVg}}mp0d,ϣ)y嗙!֭[uz##۶1MqL&)e1 M)rP &t 46~w{D}Ď@LLL̿qωcB)e 0D7 ffg4h6jXE.'rtTF)2lnncZ++pj۷os-,dzz0^+T@Ӂ+@I>*Pi L!c 0dc}lllv699җp^YY1.\0 Ðn>A:Hb9X\Zŋ$Il&`&Bǡ\.{ﱱA^0;N$CG ðdFF)(AAYJ9 K"m?^#hią1111xi!Ma$8aDCvlZ-ē噜duuFKKdY>$I\ t %b'B)C()d]BׄЄw+\Ǭ9Z!5Tvqi9|%7334\Z:[K{G L,1\RB$΂hQz>>ݣViH$FuCA݃Fa9ci4MMƂ 8R6=YO  cbbbbⳔ?xkn&a r&nٙ Y{HR m\ffǷom'ۧlR5 !L ԅT&5]RHǓiCQOwTҩݭɩi/}L&32׸y>n+oH2ONfLOOٳgGPfu]:wassMݻ6R*,"H:aH:&NHDQ~O:l69MrM!ҾoH!)ɰ!E4#R|PyBKEvwT+|?@ӴQOP}_kiZ"z(:NDLlT&կ~U[YY!Nyj-ܹs2ib&lnp"|y5 *JY[[Ca,..2;;z(0 c״h(DúHu]~FqVPð:*<xH<[@Ib|4@xbGt>i:Aw2vLNNbYwݣ266$X}333,//fowI$hF IDATuH}W9n MGqtBA/ ^@vZݲ~q>f}1[[|8HE膉m&ܹs *]J BZZCvwwaaضM:D2 H@^<`o/,Dua6a~T*233Ci?}Wiw;$ Y;E"լK1`gߕN ٌe%+˰@uM3f;}m333C6p|[}Z.`r|L& ƶ:H)hݻwO/v:8!}EdT*@X_:KKKT*~m*~S>H)S|RH)+Wh|HQp~@ ӔN>AJH)j8Rs\!t^GVhrEgjGXڵkLSݣw/|d2k=GuupU~D*u=F@!gZN\m^(X>_L$H3rS~w7i6ꬭ=6PˏqY^|E\BT4M>.{lmmmG|]71- VVV8{H>81555 A@I7 /p}|ϋ"'uHy0g!y^OH$ <}ش{wDCN8-%p ,PԀ?M:&Fz׍l VEŲ,<^q\J"W.`&;;;j5L+/\!z zaX²ZӔ4uj{;iK&hٵ|6loﰿKquT*E&!͑d))._̅ m{4p<Vt**j5sN'*u&Pf0]i88ARaP;`hKGD?[ yyG_ !nK (DEnSV gY\\@o",/-111&q=+P(dkczhh%4IG@$Lk6=+#Jf"%!|)lSۛ^Ad26 OMMo|ba}~tⱱ"d$<55 /_fyy\./ VjTܹ}-vvvi6[kJQ(( !4mZ-.8ip]78NJQ `[J9OW yi6 &&&g(J@^~#(<%#,d29hL0?_ [[[Q:`z*?`wgb#676i;FBX@@h2 թ N LkZFP9 H Q|b&klormdI$q&''X,2>>>59ݣVQgkk q Π BV"A۶GvLBMӰm[7MS8vgQӴAE4`hX$( p6`tڀ_s ~8* C? C~T8|#!z#,q&{{{zSS4uiZ3^*Nަsc6LvMPF(~/eHOhv1'Fge(ѦwafRM"E0 yū\>7oIZCD¦P(0>>Ε+W׾ \ndǡRШU?[lmnFIA t:MP`jjj4e0^ӴQzpxxHZQ|`T*,+J1 Rnu`yZ;Y}n@#B24MR|@~!`YnMH$,w8<:bff3g)ܽszA2_dvvVM|HV\=13=m}񚭎N$R aF'/%J(-Diz20 #9 i$^7opuj5)Kx$e(oW^eqq4}#66ֹq>`g{F+}?u]td,0L  \z ( A0l^Re ^7mF v0$ XwNр ?J)}yjw:JhBDn<0',~&WV' }iΞ=i= 8w233 d2RCynܹ˻2 4u G`` s4@DI4`)38t:`v pG0 F)BCI*U*Rf49жmVVVH%4 H,111A|ăMg~fnPXUղZ~a?I155-ǵb1*[ZZ^`nnn4r}ߧAj(y&om~@.#NciMA<%8U˲,kz @)*D)"AGTDO bG &&&Wϊ  ~R~M3t:j$;!0 QJb q\9fhԛlon-կ||>GYgowvݐJqYS"+I)va/PHRg,JTH:Дr * p ϟ_&gϞ9:O6) )rjQZNu"yϑHd.PʑyFa8r DBs]wN n|yA,Gcq4 &&&WMD`8GRa㘮FUGD ,ˊ*2dlnEr `rbI2GGx^4@hjzgRojs=% 3N%Si45<PIz4-Hh @3l Ӣp> Aa˗9wKKK:wR.WJJ$),-/3114+++1>>TEݦRmT*T+hUﺀfF"255E24 J)R3`Tp!m[pV8& 8d*>9~R\pxM&!LvI$XVwhY&V¢\>booI&smj:`Pbrrb<^Ӫ8o=+J$T>T(UZݾjXr2i9ȍ+LM"D*DO8N$iSTB0>^Oϟ]tItheY[H&t:] r5SvC˲4s^RKA 4<yhC :>-2N rxd8E2V~;r. ,|9C0 )yJbYbpV"iR}]7H3ϓIxl6 |!9?78s ~zP CÖIfdl۞u]-Z&LI BE<ڝ@FFRkM`}rr d0SiKLNMk/R(Rl68<8doo >d{krJ^u{~W׍Ԕ?;;BA 133X^^fyyP`98}* 5a@{+:%"H Pv;B$*+ZrD)р_CYb@'R)X)e !~_F>D4 M,--eQRa&lqz()IS$sn{;jwAf3gP,xCsduAe7ɭ$m4̑3BF4$QBQ{)%cd{sVǡjthulllZ_uH"ឭ-ȏ6ӋvH&ɩ O\|9 LMM=b?⏆uiG|GHi'T5AP08%J}@ ,u xLJGbbbb~ xm"B2~tjb CJ{xOPX(uQ@ҶI6z#Ⅻ/ken}u +%1=5t=n; T*sζa@@!Bt: ?U:WΓp}H1+-vӅnuѵy.^׿u^JX$Htx7o捛᝻wzhW_RҲR°0L&&&KKKիWo`{{JBT녃: tn#\cPT0 LCBڝ xs>0 wxxJ`OO р_AN8Wt xH9NJ !lqRiOk6(H6&p>fNCYh4zΌYssš6[sp+{~9^HD:4(:HOu],Ze ,6Hبz (J|W^y9\ץ\.ow.~x+<8<^p~%NX"Q*311\ZZJ^zL&3Rt]FAӡnJܹݿOo`GAئRknai$Iv{޵^{{l`EH3P~O"!!8Da `gZ~CdVeݮ,-3#rwsǘRx {,,.PU'5έl)̎CGKBessùz nGȒH?hxUYS[[ Z"!ɵ0kAJRrK-H /hV@1!'۷os Ґ}yWo߾-oݺ%nܸ2PN^ǣG? >smΟ?~ccc… ܺuϋ-g}}ݙ%.NU<{uRz9MSbh]-%!'Ugj5t]W BcOe??̑orgg<*0sZkgVY_lLKRXk$Iz֚^GQl6IpD欯QTi%6Ν#Xy\zW_y9c8G)qf@( kK ]G(8nG)yaRv7 C\p{$+x2v=0/^GT$i/>/~ >#ҴLa;wnwcc~w7޸vzt?Eg==zÇȲu'RHvaE9%9uI'Gs>$Iց1汵UCJ>wξ~^c9‹Rg󜇦\1 'bcLGk lI)W'ҴJ#RJ:JyVBWRrtt( [[T'_}uW'i﹮h6xRŋ;vsssSj5RcȲNC}jۧ툣#qxp':M4ZkEV][Xh8HqI(Jɒ,HqbH<Ґ$p\!-2/iZ=c`2wf [k x0wq3O0wc9&)ٛYg@O?y?t)B8RJ$^f="lh4 pMΝÑ2E <:Q)5MQgSDHg /R3'l U )4Fi.a IDATX hxʠrU<\;=|;owy)E{_"Og>TG?,;;qpƍ7^}ښ"O=}|J?s3h$qTq2}kkK]tqlZN0Q !n~Q;b%6#A_yalBϭ8A9q!͌1%/`?5[@RRxH~S "#0sÁ)x%wS~Qu&@n^k8y^= F1Jc,Q3(򂥥%n޼ zm~$II G \twc`̆QBaioUW5 cC<(?(EG\hN;) 5Zsrr׮]ٙ(7OOF#y…M)eX .p Ν;'Β1z=vw_?އvw`ЬT7W^ިzZ\__ͦRH ]t,J) z nL9Aʃ~`\0[JҼbdZ<[%`xz4M{KNNZDIT|`4f{<7nܤ:9b8s*ŕ'](q08)G(qs]̠a)[ 0rݔE#~9F,իXk9=mq='?ߟ_~`|kW^}՗~wަle-sm'?z$~{KfnYR%u$srV T-+LsBۓ)熙'955M)%}mdY/_ig9) K ht5Ha9ĩtɥ~"!,eagqttxDQzUׯW_}-abLxa_$<F+(x}{{~ŋBMn )?LKJb2<̰,b1avP_Mؼ~F5bĹu<&4xt8NfNNalb &ÐgC/(ug7 Ns1NjmOΝF J(sS砰f$yqY `<.ߧu* Myvtd&S0,--8{Hq}4#3/]\x/.EqZ#4ڔ yB*$eν7(Ѻ -rQ;^ފl_ҥj{Z-,gaq_ot2z=}r|ݹigySW666J0 .T76ʊ+M ' |1yg={fB T%ppES;f, w>>aOzs"}9|Fĩ!7ZdښZ2kȵ#ky(?c:wc9f2 !?>~666޼vbVcyyʊV%&|ڵwiLy輦FD93$[k,6^I;"N 嗖=HT+ިQA cMLb3[|6L:s%~vup9_o&:35ƘAkJ%k!c 8.4!KKcHZ-8&isac+/h}ER:.ﰹy|'N֠P{iIOH.4QJ!=K?LM-( s6ƲOw}q-|'2ڧ=O>n}''ۯ+ *,/7YZ pG8!lUif.bf7f8IRp1e78*Ѹ0Qj|+yE/7=c>S>=sP,7`1s~Q$`6 S~ofacqHH)E%dYNQ{XY]}ÄhzHyKoq\C˼[\ }v J&Xc`qV},(Jm|j)OW(CF:j,ψO#lxă_ӿK{iפMw_zW/.//֮]\\ pvQ@Lk وt_7aVJ4hw#|?Ka$mQ_֥Kljw%CH!(#Q{_~嫷^K;^)חF}=[9=;$F-w6=d?]>0V<ݧ1X\\d{{%%~ӤW|&??x0֔)pAq%QcLr7Ie(rSR lej9-CӣqaYOS_44v}^ ̳t0cF$͈4tJ2JR9 MW fλG?oy睷wW?}RoҠ֤b()QB`GfThc {뺤Оy!jQ 1Ovb8ޟ| gʧŚ v($ )qNk7\q;xfͣ7LrWT+.nZ%$ ւH9%$iA2rÔ8)Qs2(tXn:DQHkkq1fNeJ'MIN/\;s1o%m `_E|^)WiUFƘ(M4 C'I՟'?/_Z^fii} Řz*++KzBHW9'A7nܠRi;dyNDӥޓ,B$ E!(L9P5SLqA~8 E1YN)F#X(WuRҵ5J"B W!|4*`AT36Sg2ta lbb3uJH)I-=IQvqB'aH9Z*QF^Zcmх?Liu$YAjD%h[) [ݛt&'w(?0st~!WGx(0$IeLOfr74uVDшNUpVWW8wnjpУ8;ۗɵ oIݯr|tO'Zm#'r/ Aa'ʀT?6V#yTCEt}"jd!qhcQFX*j,.2`( E?DmBCnhJ0(%@ ^u |Ik!4!`$xk+t`ӌf#(\4]1(Жn?5q$NBL:a 8ᲀ`1τ< kS<pv.ϝ9 :oS_S GZeբ(1ƩժAh81I3MV^~@>f ӓ.nؠVoBŋkEAGt=r IfIӔ8 \\`!)$Vʓ5m4Jv$ϓ\az(R"\2>ΐxB HSM8?0a\#+SJ. PӅH3FdFJr|P’A{Z@5*\W,b K4F ; z1>>7k4F4,O<9Г(iEռiC2+l$4_|Vs_7p,pĔ]kޙ~Z۳ֺƘ`Pð>B@e7,/}0 кl;q\З nGb0W G%}Ʌ ަurBv80V,|r5=.)r[jXkXR]`qS'%r\!pZdNT4oq$qRLHs.#"Deޯ$f!\=εˮ0` N2~iuy8EX#R7pJM+BU PP.қ@>BJAjBnAoՑހK ǧ1)Zݘ5Ɩ)B+e8!Bٌ_QFZg,9bFrzAs1o~-fQM#Kz$MS,vyG2y3DQBZܹsn~JOT\|}"!l. }tpP"'M3F1GHu2,En02hgӫ|}9f:Yp2b@I$Dݣ ņ`Q,.FiZP2 IarU!Ht8gyB>x( w\ՍX씵 @Ih\菳I:B+hH02RRsD큁әiR8|t ;s1o>7#J7f>cpT\2ph<})0Z#(Iry^ C`uu){$IF7\>$8.9 `BPV)@IAqd%$S`O&0=Y0sl8S>9PIӴq.r45YFeX KKK\p0 wOZ8J++8ixx?/+Zùsܺu |~JZ$EI/i!Td9T.UXSǥ )-dbf퍥\gX' Ҭ{"RR0p(᫇}|VCdQNIRmkIbaA Fee)I|6./ **&g g;N=x`rC&F gqni/!yZ=SzHeŅhcA d٦иX$2cyw)eEx/`v~ϝ97'\%7qNo7'4M7ݞΟߡZ=-&,Xr++˜AAyFR! GGGkumqhgey/ć~Io&hL2Gi4j+xMG)@ ,ch-mږxIn;Y僝`%K U]|t`a <ʢ;HOWݒXHQXtR$*.cfkb!]g39+y/l>feEx.Z\ plUoШy 6A֖,dy}EQ$ǯʀhD&XcQJ:EE1䅦%F$Ȟ[]>ȝϿ`}}SE8YeGRK!XiA*H|ڤĹF 6G=;mgxƒ[֥1ƲB[:f@%pX] q=p$+!VI maFKXHRI:'c\s|(g[.PYhR=ϰȨrf;;gyʢ,R;5Ǭ-ܾDoP:3yahwV @SclՓt@~L)J(GGIǨp|< 5*t)4. i'& 5$;K,ԫ,<;9;gߟML?380z&2@%qz,6|6ת?D^.4rM(RvYʧdj(dM4Ij9P~rdgg[(Ν975#ה!RqSJi9ij|r 뢔C&eUtl'NRj++ˢ^ F$IuÖe o޼^<ϸxRs|o޹YQ4F8R -Ȋ"Fa~^X+#JOl̚Ғ.rԤ_-8*\ ׆n?A)8*~^V!#%iL)v/^udj!b{8 V93dӡ:(gf3@/S<ۯlA/KNOO?8 M#lv8eqwDF,U+D.M13^8YBI,u%4AN ~Jqk{ÌmCn_[ZшK ꎤ0 \gbfUg})(,IuC0yS !q.oSFQ MP zgx" IZx_J%l-JB`cٌX-ǿiY̛1xQ^d-m:=`)%,.|@F<8tй*Su\YY[J?s!,̚n"K%\@Nv/a8Yjԫ.~Je]^h[v୷ݻwȉˋK^x֚K,կQszzd[MY͓q$oe:ceH"Ix:X;UH&81ԍnhVRPV+>~?x`lŒyů|鐓?}Qȃ!g+Ʊ isჾpt^Qǯ.1ؼKI/7׺*\W$j U$Z{xbA!J pqXkplpp BxU/et7].Ά6qۉ[-3 pqH ^o[kRONOe&^aVhXR(Ǽ#VϾuqP<~g傺YYdCg%?a8eA{)J  Ӓ2EIKd@,Au>]TK%ʏ"'vH8hv\|.Ui/kVEYl^@Hs>$mxeGO 7VEyun=&B[l/<~" tM[p]X9箬,F/_`Z[Ƙ;`Qx爢x!/`vuifo~u0|/l6rj;}{𜟞(%{=ٿ:6="!0E.+}/C/DvyAƛ9˘/k?y _;|_+wSˊ?Y0b_U1h( CDc.lewyUjo%/w`A $kq cT| V|K][C+ MeCYD kwE%TM佪ߕe?8Ml-?Gl&]pC 9wfٛfZJ9R(KY, Fk[ *DIEE{qhӜH+~K4ϿwR@aV~oFlb ElZ4,I x)>x!Fs:7/fNAP()A~@GGClްrzQ0DLbW5AIi&.bV^  ?!eMmjオ֞6My>Xzp45ySA0J2w*454BG1I&YkK;; Y Z8$I쑂h|[6vR`0k`k/NV]xєwIc*|l_"iYEID #M(eH"`Cwe~Io ?xܯ#$)Td{4䊼<7bKq=%q,0xȤLe7gmcV7$8m[|h_ 0 @Nh!kk2.(";V A s$HMCcQ:DE9ZGܿhj?ZƛD&_-8=~mj ??`7~0)16̞G$BYȰHlCiI{U^ ">x3R~WrM/j^P֖A)ʆyrN4aˈ<(- k)%:RD!G@I q ~:8d7?D/-9:)+dsGtѡl OO9G%WEmZbY*8cci1qqQXq1pp8-q-UT\KKYO`z׽n ILt[VWI֌)jՅ N ai)+-J*Fam(J%@$".&2`DZۗyC{=;^G+ɪH;)8"-kPTcXJ |SH)6WmW_f@Җ0w%?kFιw4DkY h,{{&RE"0!5b-~SK~~y֤Fc.BJyiH)%#BiBP6 U%bֺ%yuXk=H;ck _]")L&J&B$,2!B˼1!A IKv1}:oRr#w3 8=+*K^4hqN Gz IDATXkW(!X,Ƒe'g9/NW Rt&xdF*\Ɓ`=nQ"5"%я]iuG'' UT&^Πd;d6*s&j,*-,!׭Z{,V(sN2*.//ȋc,B1 u] $A6$xIƛ_x{_o?m_*۶U~/$an,e|(}Ch8q|2J߶/K%IPR%{; wwS˚?_4޻d0N; + I"t"΄. oq'Tso4HX3ܹ7b8NS<;MX (+K^68Y AL`5U!nj@0/ &BgO~[-gzG ܬNfZU ,IH:O>c\xk[¹`\Wq;]c?xoW7G?Q*[tn_ҿq$dE/*.g%+IֲusE +PK"^[J mA'C)0ֵ8\u0PB28ٙ<7b4(kKUYN 拊plNV<:[s,j+VG<A lxsEO 67GCcdx&ӌcYtM.JUe9,l]C+p Ҽ5!Hq>.?-؜تn Z6 /*@mo+zv&8)^ER|;;TuETx"!-X.fr!IS/3>ǣGDZu`#ePt>ʭ=ucCAdDkռj^4h @Jqan,C!̲eljgR qgw'EQǝ4Q\\E9ވ8fq :a!i!k7~k=}# wr8P)r֐ $ >ٝ&g˯ #,ZKQVzM"-hY$6<5w^_84m[3I~D.oN8Ml-犟u~8Bm O }n՚ !tQ;Mp~~1UEe<ҕባ`ې1i 9`1'ϼ%#h|(ΕHzň8ɩMbUu/!۬Gφʀ Vm Xu'r+8(M 89/xrIUYp|^ph#v' dHj{㬧,-YYP[;Dڻ |*+wwSva3o$x`H c84 &2 R?֒$eig<\DIY9-ʲ?%%W%Чut{fvsx|`qp[u'p8(C# ϟ-ْ첿3&$EaE4n odD 6mЍ7|P #&B[l?7-_`?,!O ,|Ϋ ik*,놺n0;("eEUn5ۖ!:h+B s5xvbMƘdqru Yf4Q AD+"-ߝkd pίYyPEi(JC^Vaj֊yPUg|W[ 2j|41R vS3RÑ8jeE+g9Z iբn,-g%RL/qy=w3IJB9 "& Ċ w~BMscxP !=8F'cD>9N/ ί4m饿gJ %W'J-D[v_ &[lO ' zzmB|$4ʹi(RJi(rsT tum+4Q0B6DU[D)hq0#RApQ*o87\T!qG:6*|WnEЁ$XDh A4N"vSxc_,wG48'յ15][w - w$p $B 6s:l-g&m˾0۟+19q cwEQruuI&H?b^vL)P?ߍv`=,qbp2~(XaMH:U^cco'p/%Eehr^Q)EX4(*CU; Ck.m+s+nheI^H' .*\*f0h?CJ|Y'+ m+[ D9Mr'7;][~JBc3K Yt'#vx;Ta4/*X1ǬE^lG/m@[eeB vYo# c%q[odl?4>S LKhnS{Os9Z$IbUUq||̣GYY}uw@kG$Z^k wq[o+GH/@>L(,H;M,oi(:3[m|[ Dg7lgE2oXg/40W"o(sCmQLk8_L2FGcDU#F #M@߇- B8dAc)ɛeU. y1΂ εUv7 T<:h/c#'hsr}rI[lJ4A {ι9w7h0PW8~;w+GS4MڒhǼYɺױEEżB+N4)4]Wj[R28Uȁei(f4(JDз%EZ⼻&pC[YlץqQVp1+p~{8ق݋I'Cbpg7)hEѐ!E!ۋa^ u XJ6NU-*t?NcJuM rv&1͝!1aķ߽18H(+b}(:(%J_5^0xeJHxR5b-%p# z?N~e}_J)ʲi% ;.x1E q=}~V#ܯ?1_~xG%;qBڵ}^9kk@IAINcÜ~JIX!hy_MIֶiBl}x׊͵@ (Xr‚qLs4h;W UC6PdØ$aqchY!F$ K~'7{}r*~g-A,'n$_rY@|/~Sk]; !!Jd%^k1ԕEOR{; X%ýiŬ1 &}f: R tUs~,jcu{;L:3&[l+M~BWn;k)`Râ(` "q"GU} "х u][)*eEYp7eoDyDGGu˖oPՖXZ8FЗ?)s!8Oc/KJvEQX&:&]Lqju5 "FM@iLV ge0ǩWѐ85wL' Ϟ.0ޣI($[T?(Q\ Ss|:ܞ$6IX+3g aB2Jyp$M{_xs8, ;0i!ݺ;D )( H[+B0 >[l#3l]_F(B,pEJI2eeJ^s+y+ aTngnN:VRM(Ø9um%a W3ɅUaysH+\¸`W^TݗnзEk=9 .eӗKHb{\Q)/ DWı Lơdyd8f@bйvB`5)q u~!V(Fi c")caiGTQ3J< x;*$;"BIŨαc? al?> 6UF <M[1ʲH)eذ.+#Hm1#Eƣ;{; Yo&7@^ TYZ@JdZV$V R0l+ :R8m%G5QOHl拺q Dk`dl%0ιK!Ļbԋ, @pg%Va u&A]vkt<S*H,M0ֱ( {;) U2oxvBP΋wX)VڐXM k썝£8u  C(Œ_ LUNXٙ&a42MK  nUk A.;&1jH wq'+>~:!{Zj,ER4Q U2!k-^j{#[e&\ڗϖ(ER$@?Q4"A$` P"@?Ls˾z.]dч}YY3a^l ^䋈"ckyrG쐀Ww.\/}_N|U+`\5O?c\ir3Unke(A @ƻPc$t뛎cZ S_iEE1}̈qO|k%.:Q4v k4YDI96r32Cv.|JJ?&?tx w2 8$T+7j}ZZ>s7_\+%.0et͛-kG6.66јܢȌ ]}zlAZ59b, '%U̦gprX0f]⪦̭Qi60LVL6ȲHW)&B>\)~JW!T}/sCef~ǝ\DJlx}`ul+O&BEњyBD{tj~F?{8}MDAtM빼iXmdf189.EFՍ\D lEn3MdB׻ & #:q8Z vYnY|Ś4fҴYan% 'xe#lZQ4SZ,:%^G/ٻ5>% *n'}u=wOؠEMD# t,fYi9{wc_c_mW~Q <O}D^_Vg)' !*EM'2]ܬZP^|j5Ɓ҈ORZHM@HUk b7if(<[`J׊tB^4!v|7Fyi kF'w*, dcx56rxNlEajriyhƴl*t<Ơڬam|Vj.~B<&T M}kU܉Z0"E= nb&Χ:d^)T8iUR<~?}8(ĔEuZF՞/?J *AŒܠx^f4m4h{e2Ԣ\}!%OF$M&hEyValզMrqu$3XxtΦL3=Q_V+ENtv9`P>q2ne0&7u ,\spRҭ[R3K.ky< _nS}@*I6iX+buc쐀 /G߿} E>6׮0o| ]+.:_]ζp6:%Ɂ+`D ; 8&%tE4sE.P'ـ*6o*7-,Xמ0. cmYWbd\t48y 1!y([ێ}EAv\N N n-Ei/rla| j0(01ɼGGDy|ռ淾.w^wcoODḛg1Lsɫ5uWWk<c-I8w9!lAY^bBMh,sw zM1u\|B|3r[7罉>gp'~Y+p bS1@|ۅsF, 6{nfӣyoȣ Wi׏V^g?FA AiEzQ&m 踼i1Za3tYl" mպnЎ4d;'bYHck {[Ǻ!xsYQb"ij]WWwBj^lA+b"bңXܥI&A㸻;G ЦmC4h2|Éf㣒o{G3>! y.jea !4}LB"2D9j;#$'COܮE>׶3T]?FV k\ UۺՅA\J:GgUK+J`l*O8|k2_/ジA" {A D`s8ϙF{r"ُ$QD=Y : &)݅MK8u:q(t#il*Ez$Ŕ= Dk!/uQz}>w@{_ƂDr|g]<{0%.4&1EFQZfӌ瘿;N>Q'FK5O#:H:X!&B7D1zl_coA|m 0EO9./ؾI0ShMVPYS+I?-}h@d .| VD!!(*X)slbV"7DV LKlbA$u2"qx!E9/X:O*.kLZ"|S=`ksA$> {`<6{[qpXF(יm&ϱY6UDekg7ܬ;NK꺣i:✧n}*T ۊ**Mֹ{.G;qGpKRZ{}_~)OG[`?uytVڢIjb# Afx'O >n7>*nRZ񶈏I<EEIQeRr书u tӌjq PՎg?wZ鮇s tͦi=UxsYC]{\ȴ·a<t Z)bHJFLپ򧉾Fc^A?QFf(k6hlnG3ʏpȈ!]W֒MR ,AkAN}馎D0@݄0 >dg"to`{}-oD beiشnUEniF=CҔM}"{uQ);'FfJnjX)ZSO_\9MkG];^޲\|??b6dY1 M Q}x(й;cq3jǦIfR:+AG)lbi;W-ea(r,ri'=Y`gO؉EYEv:%z065.U$㮎35F `}IN7"9 Ya 33 y~s?>gP>G+U 4Ȥ"mUExdJoRPvZ`_coM|c ?g+`p1~ lZ䓛'p#T,~38ZXB#1O;'mЕW 1*m-#Q !mXd`R<8v̦ZAs}+~|G|ǫ)X^VLx#9$]m@A[w0~3[Lhs3FPCg;)>]cuoZxs (F MV)/ ]P1DBAw^s7>E5 |x AR¦y}6+uT׉X*MAjH&@0cJ (ݞ?>"`4NOA!1TBI4C @iH?SB"㍊TmX)n=En?%LJg'ڀV<<*6\_<~z1_F h <QYƮF9{ pm$?NwH{¦ -y6L*&peCY"t.p|" əRt k{B)lTl'*dIdJGK~79/oh| R8[,.:k:o@_MJC_weH/^$U"b{ (V͠ Qh[V2_<)-G'$}'m\eW/Ű#)F}w*JQ$,DuUK K%VL6 i$jg7>stZЮZyEP9l-`ǡm>N՘^߆"x ݧɇ+VsptO?ްtq}Ӱ\-rgWx9:U<\6\^7(m8E=|9Պ{^3.v *|Sjh/o<#o.*9EaOQOK6ێv'a bkTW=1Scוzs9;^@o"T+z.Ə}kO!;@ ֫XF݅ IDATMl/bT.!m $¾T{^z% #lC튋Ѫ\| X2I" }6U'i]Ӷ4MhZA(TzuSRtUZ/WY's)L(tm PB]Iw(md˭qw?Bc0CE|Gѭ͆f ÷.k!u3$y1F V\4!d,3X+?zqZF<3o!kH41ը"U MoP|# U܅,._Fֈ,pu*LջEʯN*zS ZA"(r-4M/|~ծ\Ƶ޿G w ֨>.H^֝IJ8(~RV||"'όHt3MU;6U&dtH}kn,b}G?tI_{J}vSP/k|q͗=>Ĉo:fUW05bKNرk#ӓ{gbaCYѼqumxo\Zy2ipjSu僣WmrY,# ռ:xyeqDMko"#?ĵE>5olp'Kn (sNLߓ@vY}^[hZ/܈5*@H c{Px\+yeMȑؕU}q.wc`  fzu12ppգbPP90ίje>嚲s\S77WIicYFP,||rtɳG3=R7w2zg/ryELJ(rR՞ԙ1-e.n0*T#,E(oK` m& rMͺh\3}m -ߥz}&5P1%{i(NH((6(m1ZvW4x, ``.$fӑ!h;~}eAчiN hVFĹiɤ0xţ JIA1Z|ZQ`3M>Z<&By0>GBvK@#z UEʣ\ɉ M8>4-&3.nsBx,rѢ&Lntd?-aVMTtm{O改yzh]DmM83;؛cJ> D(}- "FNF"JL\v@VD ECJ7 2󆔣zk{D h%bBr|a}ډBi!OD$<o"ݴe Rޣ=0Q۔ҤB?R֏qTƄtQnKB7miiY<)~6Y^TLs~el8|8&ey+-q0ɶd! Р PX{1l5LfdF(`KA!2+7y!ZΧ-֊m%̺vPWaRZM 1 u_$(ʷ5q>r6?`3|_싀}kN| p_wIZ>WFM6VCHxM{Nrĕhub ws q! B%u9piJd}$vA)MVU*^BĢNRlu->maQҷ&:&tdC*T$*EՆ <:O4yzUaחy9Y '1Jt&"I?K.<%`^t/Qx:[0EkODryqcbZZ/F3?XZB.Dnl;,JղaRZN'>X_$}rx‹7[.0+7Q#KY癶ZE·(D)t !ףiM_x+ @+ O"o<"&#7IrwS9FVZBLnzZ o*$5vH}KVaǰ $/}Ѡ$vII0HL`m)+J:n-!4:ldjm8X57mQ7DqDӁ: 'EB#:*l߉a@bTCk"\b`tv2Ak~A΋79.@)N :!W:C*EX$ ߋ5 l+⺦]W(0Q ыҴ4tSyt:eӣkenȭA!LuV1(,;l`0zy:!=/^0h[Q܉Ӹ{_#h8+ȫr1U(ULB7BS6A돺wp1$7-i CYHa6ˇjKKtPuL"y]X8MEt[t^U^{!u~jʌDtO-LshAP*&283sɬp>°HCNEx BNCit6䔩,"@G슀&B}uK˾>~e)'qA1kJv!~VMREΓu媁9:VsIqWʹG v#ല w4&ns%q4YagF熼0X'%I$bq|X W7 J)΋aw}~amsZOs>}ebm9<(GL3/+sl57&3<8 Ey\O퀈6Պ"Lhl:ND7]Vg kw2?)-%YfX|yp/8'mˊqr\&b FJc˷-嚦|;G>rzT<_Q7j&pQX[s[fQ6*Q_У"">ě΅7!Ck$jmz눱webj8$#~Xݫ[I'&Ѭ} z8:B^ϻ3VZ;ȝa]-?Ff8t$,$&Zus"TS7֧'V6n_b2ػnBz6[rբbSu~eq5O,*:xr,x^9N-%0mW$>@1q>~D]N싀}W>J\ `?J)mEȐ42ۦ|/(k[]A3;}cզ[Tӵ!p}ӀT=W*x\*x¦{&*K[)nV-yRs!bB$h5H7$ŗQt.\<]YL3Bl7Ԣ#Y#c*v(vZ "8s^oYL39jс8h~*d@ȍtNG u3mtEӛW[V]lQd0l+G \w6@D `54#8 DUct \LW6bafDI uYq NJV.r9ciYm:kT YV:M=t.h\3!|`>ͨ}~Us|PpzTaq1F%Ͼ}uM#œ3f]kjMsdBչ#E{>拗}ueQ1ͦ(ooE*)x";2xpFUuD"'dorupl8yf{Olk닊 1ˊ"3&yM\|!qiQWZlkdbYrN:)[7-A&/fͦG~EЁ8gC@>*"C<2#> YWŗ PVU(δN<s-EN%iZ!*ŸP 5`oZI-W7rd=2q D@6Y],CFsq]ʵi=urCPu򵏸x ܆a/;MfD^5O>_S7,#4',f~Gx+ʉ0(YɋkN&T bYuM^XcQutW'3HyG>Pb\m;&S%4Y9A W7-ZSVk!?~0⺦i<2C%'զcR=\ێ륐(?R;J݊sx⤅gBY%UlG; R;S"{LC9/x ;&A}"Ko甏\uJ=-\P!Ho8Ȧrt,,4Χʪ:ҫ;vwΈTvA7$:"R[Z :U!F 1#h 38^f5J+OpjIi^Lrx/Q2j (tj}`/)y9>}Fxp<Ï,f?W[ET9/Q6<;"8{h+M"7|j(ʒUfd59|B$RTumț7\ÂÒWen8;ɥ0e\4]#g2/99,nh;) LJiIFN"$1q8M@՜**:5=7ۉw6E>+o]U}X{2GY>h:j2W&F1HRL'P52__'xj%d1mdfO".fG'Fz/(bת(dޞ̽lO!Xc\Lz"7&G)fۡV۪ù@\5^~N&m\"d4 g'%}pA3IKP~C]u(#_|x mɷprTtc3wY5|+=c,( ME/SG 0k R[ьƹ.Xo:֫uͪū Uß|th;O͘~у #/jmŊ.(rq Q&&p!YA,xjj E3s "<n/2&BǯH]8\(D&i7>U/Q1(Nmc4myK"Wt1+>nbO:%"*쒺V#@j0Br(_0),!D8Mf3b "q[yNk㳩!)ao+? qcj'Kw.P7^dn#\^7ĝ\6k.k0 WMA^vnGsIU%ƒÒ,W2ʷUr\ pvd( m؍ 7( ̇R K݈Ӄr <>>D'R8YO,=] %]'fKMY2\S憋Yr, ^ȟʴ=Frx7 G#&B{}W,2 [R󪎇:mF)Y훵0'%(!n6fQ˗(GZAC,H,;Iy}6 ,aiiu0\\גH{D83K0M˵mH|;[ª1?:bhX"zM7-}|E2o.*2 g/_ .Vu3%ֻpy]3f|[Gk?$"M|1?<wg7<7 ԶkjI87d0) }C1: 6! Z cֿ;s3f-QGN)&p[~fճQƈwB ZE|&'Š{a0JVaynvVv=nU?C {ЮA/ 64I! xSu|räyZU*dLn=Ѱi mo_|ϾX4-ON2|\m??]Iiyx.ONDKPL9=l1Vcsær\\T<~`Ruta3C[4651 m mGVY[.0?٬;6ãVq`J:>wKg.C`Ƈ'g3~5 .rs鸸yj͋7[/k2$T@?2 GѴk󶋟1W)ƯQYzzKx+3z$9ޗ{8K(V[t0׹V#1BgSa#2<4%I&AiE?0TZѫ~zN-GR &C8HꋊțˊE4' ]'|Ea͍.Zխs"2)C^L1h-X+"HFC顀+s6Z$X7k99.ViAxsD̂^]<e4T̞ufl;|ʌ&[ ީ{FGؙxk ;qb mKD!]D+"Ak~|611A'^5FIGL$hM0)F p^JԨov;`EQO^O~Z NZ8&2Lc',ļe[ IDAT\4.rybqzTP>MA:'1U0\Ktt5NK>F(жvT?Ϙ^7<}y]o;hZ|爳 g%˛[~3>tɧ7-jհX{|k6>8:Q+:QQ>[t*ZAB*,rك)=aRZ#+Vo=g.ٴG| /^o,oj=]<ϟش7떗[~k'<>\+^]lwϲAti鸸ysY꼢nqq]Sd-dZVJC5Wr|PPBFQN2ҵNZ;a0\dB*t4yiij2eT OΦdV͖Ã))1+&5ן_q~U"};` =(@߷}E~~7b+#VNQ0O{Ҳ +"i&tA`]% $|W s;(}h ? ݲlT4AP'>Ƙ\Eʶ >ͻ=NZ=@]Vlh%bC2*T#S] Pq̀Ui'7hCk@\E+N9\ JI4G7M51DV4zú%K"JMiBFn@Ak*sMEAYa޿ȭ?\`6(&9/= w jay&#Yf6ś-m+$E">sz?UJ!P;tt})H>{o#Yvr2#Z{.ݢ9$YIc$ll؀~o_ a@,y$%gåꮮ%+z9~qJV=#Rʌ{_~x%!p}q_h^M .=7}P 8x- 0K>.8В;=I#E>8^Վχ=N-~7n9pzEi/iڙBi?Xd^K5+f(T\JXӏ.}^h°l5αHk#WMiy[_zɬlůq?OIv9K9k~!I4 I'?>|0"oT%ÈGOȲϿ=YH{!5syPenӀ(L.3\-Ko<FDAёR LYL^ч o>bSHeLx`o',V&AMcylYRs-s ڸǵq߶w IۼFɁt Ԧ~>iTE6 .#|Xv7B+)AC~ay_nўiCB@kax=\iP2 ju-޺Ȋݽ8/u&4kYΑ.mp2+Ul41qw_fމC9:A6XIDZ0HG{ {'%;dw;NH"(,2CY>6a /g@0ފK<7ʺ!T TXK_ > i_ XrB4aQxe wl*C ~Q!@sfW(p<}|r^✗6EI1Z<1~*gN<"gLK͑Enaw\7pTs[ܨ>k Ԧ~OG/3M@Q5BH+!Bř%/ WץOk*V(%?,:yHnB@ p-V-֛Hѥ:IU l^yƼ+ D2^wJ_^?a0I{!KS%g9^û}/8>[isSS,1`'4-|Vb'lmŜkΛa #Dsb.%:TUV}\KL[[ezh A(*Kc,IRR Eox:""5yNv=gbpEV ɂE>4(i<#HGeMY9 !Mc x =`P?t2\nHL%:xu66Z"Oo~*$?c JZ<В^*{a V. ${)QİxH!?!nI~Dze,wSR] jqE;^-΂rQ _Xly_P`-9HSVwa:+9>[hG<}`Y*8, E2:#jrQ_PJłh8c[o' ?|mٷ/5LK_=do'G]spwE"7eak|} $_zɜ֒ "g:+yЇ&0P |t`%!XI*MF0TUPcT#u?RE˖4'3ӜaȤepvsbɒ!?pv̇O+~/oO?<~:(=:s=8998Y,P>eseƺvxu? x~v$`Sy׿1S7nݥ.]a"jj-7u7pwg^ Gis[uRE9Z;s%eu uНjAo7m!oQJz@KFÐAYaBUP7~P|Qۉ6נ}; {sB0[-tEb|ɜ$1ƳES/MHA* j[45C2@ F>B*lULb`v5.jk͚ڔD/TV6UI@V4+EM; MI+ɏE|񌷂!eDRt%tm q^(7MJ~!խīvk<~s,k^4;keǽn'ú_Lf6ﮍw?Uլ~n;6}'Ik\ tVzgmWR0~G\XX3ci@/+~jJ" 8!:({}>z:Yư;&;wytH^76MIF.eV׷/k,<d:PJ2ފJrހlQE YI(v77R uհ_D0ĽKa0 Gp(l],4gW,'3f@ i@Q5H [ȿ~d/]-QDU7,:o}9xxw@Ycٺv[È݄t#Nb1J|^)^RJI VC^Fڿݻ~a_D[[MmSl]?QnB=|lj B *%$w{l "H2DTiXj`$VڧtR5%-p͚ܯ=p ݬil;{c:ڮ-yo\TLrh%~@D1r0( T8 {6$+N/r4ıf+#/7X*g4N?|4a 8q|\"%b){O筁.s/xz`:k)qUr7Ν5?]X˒ 7u6 Qςo|{ro4xS8MCjJ`|{`FZPyƭR,{A_MG!pGqp7M: Z [EL'dn4utVCdZXG)zxZ:$ݔ PTc8[}è -\\Q%-+#gBH4`w`Eke$N@tGi5"i83r]if9}r񉁡mX)1Sׯ6J xBԭ@)-qxhhCaDa/|핕wl#RB(EP7DUNxxںzwmFg4^=]}v5MâܣqֺrY4՜/UpzsvS23,{UTl;ns^Z;_I 7~ Ŋ@۰*#ysD`/a^}|/r8Y!!G ThH#A?oҒ' Y݃_>=)o6jf?ŷ?{?c5)o>RUcvwwt%J {gL+^ɌYRqt3<;* ' V$i $;w\O &(BFk=FG)qM+Ss9/&9I B?; NU#,ja8(+"CwҀY0d6#R?H<B?^_?V+%@h;ȻlSM{ӛ.|'; !;v/tոtt'v-ĺF)%/gUm.kKYy!9s)L[4g9Ei#MѣAY Bp9)88>̼͘mpQx^Y YMiIc2_]:xSO*?pnL58+ ;Lcb>}y8:ZaukVt=ن簚n9-ϮKo ֲ+v;cN:(X7`WJJkBiEb`ivq/*.~7:W! ׳YɃ;} ݄wV)IxNf(څ[#}ݟV8l'l {7Y֜^<9^ɌiVQ(ZC#=q|PdVr"|GW\J~eO¯xwu~^=W^a|13>dF%_.71[,7xqqł{wXٜ0 GiÈ`^ rzqEuPI@Y[lZuyԵ#NC4DR0F4 Z=Q_V^T#q}@7%MG=Ӓ{=3{G}[1(놷IX,k=^;h/ew;f׫f|7Hem}!2_^:4M:36Mmk3 ȧK;N JZiQ$ ZоE;=QjiE~>Zo_kWRRm5ֽ 763aoF k;&S+G>zVNʚ~x~3 R(t0lImr5-(ʆ0x=N_rR4y!$L9뱻ƚ󫜪|=@ ~~uA%U %iK:[CT -\`8̠$J ΏG~lմM7jK]5VNY~Wyte׭o'G|s[kBi")ˆaH^.'9g9gdwK-b,첪]f4i8'RxcMj|ǧ!W0!L.k5EmV_˛vXy|Yef(f5w-Y=OD7V舀7݅7+Yv.Ch &GGOgewpGY5|tvD,ii o1f$K?~:#+j YaΫV" X.~*4$ˆXٜńj EbYpU;vlpmC&tL urNZI2u~Wm#(A6hʫ.l( ըs}D5U},0#/ 4p/pO 9^"{q(Z{Z{Jےw啣&?[?oMm3ԦQϟj~9~wc46\[i[ ?*ɜɬb-$ӜʝۙƏTKrܿYjI*SkhV]1S5 Ell"H %낼XQU?)5y5~EG E0_P84a z xq_vV}o}~;|}#t _9]2_V?8R<=!뒏L27r3fKƇ}eËd+&LLe! 5ue)ƛ#Ys"F,lo6VaH/Y^V;& Öџ5 1m]jZKɔXf>atMY6 z[Ý0$ %MQI$voZ#c~r Ƭ IDATLA?MfǬ X߉~QP>J+-hvX]o*{RM)vb$Rl2E$h%.*YͻoK5YaJK4;1u囯(D{G}Q 4OԳsЊ7XP ׆#ZZ=NAZP,k!!G8R5ce~Hm|O]\ıWi_7:Y2T4c/*1Ue9>[BLgU[YrzsuUD(kg+=㎹i;TotOWn}3Ԧ ,ca^7ݳ2_,]|Q1m/׳qAmI׶7OgXu/T›X5ewnBțܣV^:= ي9 XA+\+ERBU[1jx/@=(kz MX5 YFv7axሲjxlnBkN/2^/ƃ!pqUa>ao'ag/%j^2\8&cˆ5ߙ]h% #ʬ, N ?-y^TĶMGxsP[PyNGZh?K@Bw]a Ay?<H&ޕ I4o2ZĚAߧ v#(lۏ@mPP+8`]f.F>> _ c"#kW9BDx%B,E8 $%$Vġfo'YDϙEٿxI~4vއ]~6zV?wlŘ7_"gs<8sg4|{ya|+=QdF~`oUs>ܢ1 Ϟ̸{'I4(|3\~yV>s! Z⣓-e٠"E)O BMQFԒ3ƑeqUYnmIAVUNAT7[\['K@= 9$$E^.X֜_^d_\]](ln;mU=7 $`S4ʷu>n{q4 "k~6T& -Z{AKG,B3BZ\ko;gU~kN&tS =Ine D͢)RJw d]|deeS~_ycQDJ|eڒFˋ {oX5qv:1O#x1) ɰf; aXd5z0a 等Rkp=C8aw;O5ウwK>~:omϏrz=CN/sN|ɴ${s̎<gf5g:R/2%=3 "L qe}i񋽀2kSQH^޴r Hۖk*qέ~o]r+$Ywr-m4 !pԆlYrq9eu^PBXIAQZv#53/;DQ+U+29M9M8,]Yn/wا6o}Ӌ'/j=1=Hν omSTɴG}xq M{P^֒˜ $5XВnBUf9qҒ"7"Z{oiP"ijXZ=܂>(H1f2+%5Y^SV^^nI˼q`a`@5@)$Tp}G_q|djEFh,f6qո֮5֭ ]Ԧ>CmF?0ZߕR1xQ6 ¹;pa t:~=YN)uAh IxM֊Z߫V vxVs~A8Ar:kb6^/ lv @2@8!u~~PU4f†EVO|n)?X {6F#.vp=~".HiIU5pİpy]S짼Θ? /J;)|QqҲu/IIURBۚ4T4<3#Jx~6cn߹8/OUwRݱJ)V@!Y M& Vx;& % CԖɴbkqGQ&4%ġi /*. XRr=xr<'֦ǏL~G?⵻)}~{eR>j&i[p>)/q̗~eEfۆ7Qe{{=Hq^g8x9wzL% e(L&q0F( C R@Gru챋Ck^BIUx_ZWFK]7(%o\^ڊ.ȲPK$'%ftHkV4T'OrxM][[9E(jF3yrWƸq;Kކ7 "t;c3Ԧn9ֿ[y\W':(qgq'q64=>[T̖߫ibۦG  ֟eE[nX#u4AFDJ \l) eaZQ X{/kxkߙaH/ѫY "Pj8+W乡DK4 "/j*c=?(f5%^rr!ʍpؒጱ|r<Fh-esxv(I/ []䭣V^B du&E9JVrg2%.yDFA֡Iop}wƃ-<2>.1)'N89DJI7`7e$.Z xy{""t8aCI$16i~|lOms}F#OSt 1OY#99KN} [͎:35Ə=McIdV2W/yWj(K6OvO7N?Qt#5Ʒ $:s N' ^S0_G1㘦2-o>K0[l#z8b'9yis#4KL;)A"z-a<9DqBH)zG ?p£'3a4 #`^i%?|4_ vc}g|09ac5 E<~6g2-{,'K=$ $)pmY"Y)XR(2Cu^rz44  b>zI[ϟMIo|~r<31 #̏3Dݷ|1oPPFvPW}I$$_J o-I&`>&`ST`t[J8Z 8)é #hp2hGZI6HbM&3Z x$' ߩ:m\7:XmNێ@ G O<;YrzmuJRTCMPxaxqK5̼݃Y~s*D{u@y49xna@Y(f/\*h?%hwkG$?v3_|=ěTe {#/ ~H.(5I'k,J8|Z Q9r[J \霼Eo*a/`koG)A)IxwϪ#Z sy/[&Vx+11_}w{\| { CmSVxF}prdo/nW9sotR 9kK)zÈ|YDBi昪6`kO$6#pD:PWlMkds 45n aag; fGO]"6xy?榡 ~ =t̀[t +Z:@ ڻő>3)Nشp+OtzF=N>ز29>ks7n]V>^svIk!o#sp^e zi1ƏPJ|X T(8o-9WӒ=6_iIVFwM٬5,#/Sx ]p)#zx& |dy1eeqy}9i=Eѱ,۝?6FY6";އA$!zxJvR !4o{J dz)RZ$jiXdӲG^ ۴%%K^V@(%BK A;Y;xWf7!6Mi\5,bm1Ǥʀw^ծ kc`e[QT_?+ 7yOK7+V:/뒭nvgn'cuԕ!/ l >y.M:a?d878 I1c$^)v>MNkKCH{{HJv4ϤYϙpxR2rR`o'`7om(Kã'S>x<}]0_l"zy>p&g-1AlQq~Ţ_դ + WeC]6^%X$hT-  %0m`voaģ;[GD1*(@\%1o0 DOQGDhEEc1jɕo΀w=쓦*90obXj$x,(-D?că@Z57P⑳O ~8[?oSUzʼnF #`/Vb7 }%O"ًBZxCDp E A/ !IZDl[9 "Ien%J"E|3q( .% ^) z{Se{}˪ѓ)4`w;&Њg/=KNѓ)9>昬0\wz=kO5 PRrzq1)|/5歇C d8G3_pȲ0hu㏧ф7yݔ%-89xݭg 6`x`DW9i c $_8c%ԥ![(RJxsQDDƹB D4U\C#ۏ:u?; M . fZ2^__21WzS>X͉sSQ}_=xUCpvorcw쭅ac] ZkZihC|kY|-+_vmX9Vjnvݰmc1|s51z0iR»Ƒ!u+MGYZwSy{ JH35yiEfP/˜Efw{,s}%qm:^I~˒8?1U8GŤ ^ IDAT$ARV 4Z8hS mq8ih*n)o )@iID&#;8Ah b5=S{ѺC9 B"CM4Rx^IxqQQ?`2+q?EfE|̴΄JJi{$Y}ܟ~#ufUeh1rF8֌=?xih\.I,H3`Tʬœ΃iD0~fa2ċO~_K5+>ys n/ z;*C``PayQJO2ł`2+xz2嬗p1H^-d]oĿDoCda EQ2 gqbH*Z ұ/hW^q QFՍPaX໇Muɬ IKZ L9EWcqF-sA*~v^z71/V=po+&p%ynFC)Y/6R>z<⼗mϘLK-5gϧsڎ 3>|4Q*$u%1~Bj !Iyb ~rKH M( dU uZigs>(mDp4p՞ʰ>,P-@Php H}FL}E$K{8-N[{uvlu-smǿX zI;"r:ؖ)%yݫōu+`n=|Re8궃9 %IK^;hXDqt:yoט z9{1Q0h xӂOưrcΟ~Ϧx.ܫݵ{ǑđÍP~1Ш4ꖱW?9׾ɭqh!%|<%s67v4wQonWPۮbݭa2+8%vز(#_)IN2ݫ[IN[]&Jl"}/rEհ󹬄/⪲euȀ)1FQS>0?63z ;GCjtV0 XVp`q aW<5ҜyZ*s*nUu!Z\p<,'0e+mzeia4ItrOKM*Ɠ pf%I<)(*RYXU,]Ύ٢M%O;KInusaB Ҫ5j(qnXdV `iIF]BiAnN8k;fSU7Хވ.Z|4`C%|FRF7MJďlK"Mmw%RX*5P9 I}<@5/Sj2Rѻr-x1?]-p$2tqߊۭWS&V@=oEU^ !VWwW'Z$k`uš,N;|yЧ+xc=/)t=ebN+8J0T2\ 3y|tfpM)CQP Kk]΄Dʠ# 'J8A+8ߓo5m;l2#yvn+ ;6+Ls˿-~s8;g2g 6ʝ?{ Bw:(ex~͎u|tlol0g<}6cOOrWث?3et7"<%8[YGWix >^[-VJ0TT;.<l6ܹZ1a# ݊:Ãf5(t_\Ŗ""Yw$`xc{/(\_mX-x8t\GH#,L[aPm+Ah) +[Y@?۳u^|V%ώ\ sF)DXvAXam u-/|X ֍ojd⬗2K x .)'Yg9a4)C%p+wb/l,Y[xcM/V8` eH hcىKK`QZF J=NGa`mkmy%/,q j\hB,/MW-BXZ݁0pI+}(t?0# \u$?F; ydLQktᰪ^4jAJorcnu\*p ټ{v#B㹒;7Kʠ1=j >9Q8n}Mm1O z<~6!/5opx#Jmew6cIyNf5syح1e]̹Z5Ѡ{"UYڪb[ѵq5o]}zVˡ /x_!7Z8KxGJ3KUx⧅kJGkB鈚W.¥r\ϥxbg]Y_&h ,<bP=[+|aź,z$]Flu#̀Zn U*L(*Ғ4q(T`<  vg]\YB'$Io@)M ;'ߎ1"!/Qిmz I$c⭻2n˧BǺ nԨ׬RUs@@YžVh/[ [1a^F^W}ã17lw#Ҫm0m:0=fiRJvRirKX1as?j[ ᡸ rѫ8UC A9!$Hg9(hly''fl DfzDyuJ[;O))a9OҜb5 RkWj XJƺ%_B2:PnKAL,ͳRrfY.|J(c/ߺAGCw/>.Baz{JwjRrxۇ%=9"=x+CjQ<_$X9VYX<lA9=qױ%e>/,k,:^Xcd!_ϱowMR)@H(]Wr)Yd`VXyfvEEmY Υњ(弟-|ǹšGXSuKKe*`$]dVNn~V-/ ]+[N\iwY|*msy?%\jU491c'iF` ܰ<.be#oK!D( RAlfws]oo]X+k8F*u>+Azsž눝z$_ KWGi[j}Kcx3N.RzÜf#i5|3P$-솴~e*@UUpT?P\B1>dV wnZdVpVv6"ӜqmY gg\ R&7ZYOQ%f?&o56;?y݊ ࢟RS?@ %ga>ϻ 35|lloDX/A{GH[unI%?>"j:1^!A!) E5^`\v}j{e(c[8 w)c >:磟g{9:2KlYRKvVЀ%u٪k{jŪ,Hrc647?4yц{x p \ǫg?d_a1+IuY^3XߨʀPK#4QFM Roe}O{ E9p%qYPq Z^1XWC`]г'Tԥ|u+PmI^kBX¢fn?xotyrحU zvB퀸Dg8 #]%B1OmZWd`0W+W+ U˯@s]y.E0ƶm vGq0ұt/OHc0S;.Y rA +3^-W{0BNeu KduWK .w2e W,SP6@YiKil6z){g~+s6;')J)MH"8HH p!ew n5mDXQ ^lRu +p1+lEfcD $58bu3̕#dZP]V^B:69OKM>;u5P&V>з^zR=5%8dn! iZS Ot¶Bk( M)Dkv:c0Θ Ӝj`2JH)H4oA730+MwwkN3PP; vl1Lꠐϑ8!P pc5PHҶnX"W0u̕zbbw>iHGDL:IR4u e*}+"W_x| 5!!'p57 ZWJ:xE ]m\e @D_5FEiO_& @iۓ=sM NfQɌs&zGili곽ba6/rJuڑKBH.vXG4QJEOOqGX( }_5kON4j> vk Aʛw:ܽ$ ~~0pgwH^j~A⌽[ hçcIk7tZڰ5@Q IDATy_%|gJ?>4|͛ ?BNHM L4|R2J[hg42/Y aJEt}V qXVzjK`?& X>e1>ort.Ց._,t8`u&Y⃾D\i'bkF:ıxq<㫡m v)0Ɛ )|M$qtJ9/ s}V8 +C$'b:r o: . Q 9R\vݰR`R]Ak׬otҰD)Ų_o ld(QFlu#d;1+yFͣ {dZpOi5 ϱ48*^GQsW'rooϞJY E<}2&4AbNT,gETaA?q,߳x: ~e[ŘLHXpB0 Jg(; )PJXiYd-,j:'b=Ǯk +WGy=ń`2R9v1Ei΅ pl =ϕa1cei2MxHL#[op|:7n9ةqֳʄ0&Q'Svb5b7(&^Q%@โFͳm.B9v !~=,pݪ李e*I&wh.*+ўĔ,-s1RPd oSj( ՗'~Wxrj`uXIXPc" Dpz,8?uO I.qI+*I;\9Zk˅BAiڮNXE! x *ચjodk,:N^z{uW;OV`C"YtEj$7LK6;h]c0s͓Jܦi{  #\Gbo=WRDXS%kna3\:vH)iN)nx䴗0紛oxr2a299ݵx o.?^p[u5?~{hc8ܯ3ZVci8ou,) Jewv7 >Z5ͲԌ& Ow#Ƒm<`<)Z-HsDݩ6ʐXrUВ+ VG.k0: ֹ8<91KCK4VKzhYy~wY5|Cjھ.UsP}Et>jd`2źKu걫)qc ZS k/䀥4Wjx$I-KHA:5Q\(e:rJ=ՌKit*sZY6ʔ{K"c /q]$-ƶMV9*j9lu#&(E=+G̒ggtYQ%%yn%E%a2N&Ç|/? ºf5:sKt]Ri޹'+YΏ>g4{0e380d謨ZR)&We ܪs(\kbc,4$#td`؋C&3$s0G8>z>8.!8J) lTWe/x8#,#lj1z!zub=Ϯ +_@(hQ{zJ߹|0τRDDX:b t|R $y 3 [54qvg罄yZR(؁T'W^oѥuMr2M(-v``I )f6/S7#uۧ/G@4N;~шP?bNkmLvƨxdN2H2E>PF(MexZpXIc;UD5M<}IV a-)KmuN^jWj%mZuLC|}fHdX!KOy:do+fcu\hANHZ4h}je0rEL2r\0H&yZZ^-pdVXyD%Ph-thЬگs|ds֛jܽDkjܹ`/HsElP\ƳG^;hP&׶98hS5O>Gx&haJ@E J㹂Vcg+boRщ؈]PۭLro2>0Ok 4|gXv4} wr斋G-` HRH'C(q]<(0  ׵XuvB4R ./?O`yJ_ֱc  b*\ԊiAfsI5`,"Tgj&"s%أY-I2Ϸu)(ogql6'".o&^?)vfDZڱK8N,˘ϯuN~5jp /X9:pxQ#bkTq$6]"ӋRm Iÿvа;17j9A7opȃGOFc[^ `-KOrzÌww̛w|^ QugzN=Q(x3d!ю@16Uc'1FbD:yb\I aUII*6:eu+Kzr3`:V*T(c]Ri/Or$V/)bz0#/)8حm F٘;u:- /OM_{uÌ$Ulw#\~Ȳ4]%Fei %iAV(BZ޽7g41 F-89fcƳa ˛wZ<|:f4) wn4E.9ǧ3̀_s_,n^orfZ>b2Ny''sGVhKUϳQk퐼2Zַv`5|Ooi)&^Bnr7:YA[G.e2>l@Nؒe%`uh'1iL(=Bq]\}]exJiVlW RJ `4Ε )eMJY>tI|VX+W(>G VsZ:}Ke&$Bz4(FӜvçQst^e<9ຂNC-r2nf10!yO2pnEL%y͚U[[].XYAġK3K { [݈gb2LaU iZu͘~Jo yv$g8N[M16:!f͘4)a''3|ɀX%48!ղ2K4OJ. O*,p L2{ I4 S&(E<)TM,@;&_,vXA!lV#Mb,"K}p |إDx^1y5шh뺟xA\7h_\@u|b Z K0/KSH!B02 s B3eJ)NgxpASg3 QrkNiy.)JZunl^w>,3/҅qx%b Kʖpu"[c+QYmpf4""K?tN@!7knӒGGc9=b}*mTH!F#9RT WZٌ=[|<$J k/RdY>wᣏ>ɓ'L&;)/*+\뒀Ewxeb ^^\1/(D)3 n#iB4RA  'dگՍ%%GSnlu#AiCL9Q]V`;r .DZK̓ZS=gݍ8woո{'cONf',1m8r;x o񣟟v7{-hq֛l/#>MU6ج@6yZWHټ ]w)ݴ~EY ָI`ND%ʥ~AHs#+]G#4adU<# m_|^}o,#I,,˿_+-NR)VS5`_X'>(dW(0'4ѵz$=Yإ0UT k˛ɴd6/|^4%|+:lCb$GWZQ|JIs }X^,*F)JވHҒ^f;YfI;6(mD׹fÇ %]oQ(cLjɰ>.Lu|ic ~Ioo,[*U:r5Ku9ґH)X{$+f?\y;5ګP؁F7DYhYx-Ep_æF!Q2!}- zs?{oe K$'"#+/nnNfxdf3>Sȫ~ܜ^ ^3>6l[7O5pc^? co_>~RŘ wL z! Ej|r~ ' ݐ8tָ?e܎X:-Sk-ҩicY[iш)Nv)zw4<ܜPs{y~8w)dn/v}O"QS7.T^Wvp#1f{7i%n&L$uI04-O6x0$7|g2,yxS%6rvR)!QJ)xҤ?c ys5~k׮1 (H4MZ%QGjTˎ#y^{2%xIZ-eO3ZlٴXi-lj۱Io{,͇^k3 9._\Z'Ü?yz! ė;vi{hPF,-D$2IKC;RV)sGSʕT5qI3NB08&JvNTF\*g8XiqzN?>'VZuB.2 9ydǓnH{by>B˹S]R.Moqd=p)#M.퐵B[D tqAZ*R3 |O2NJo Bb P"OB{p<4 ,R!%R*!bi{LӔ->cܹ~1eY6?MS4kmY?[k1&xMYJ5foZqx^?4eQk§e X4kc`eB+U(kc;>;DA_UBANWTw,'pcAN@HhZ @ F#N΂gYvgf[K!6FđuH>)Im0,/ƴ[>B <%(KbD ϗ) CixDʶDnRbfbKҬ$%E (T F9{9,tPy$n' c! %$Z;O IDATG"DJTxQl\G??2 bJCedYZ,;X65\6ڧ6sf =foZ~zղByayg)8-PxRPJxxVyo;wYfu1 EyYVV8^(( ;uL7An!/ -mabbDH6LmάwNqqnr[9n½CZ&d4vG[-c,Vю=zaE]4ВBwւ"j @xhSҎ}^20sfx0s~ jCWZn ) G[Q-|ZDž=n)3NyEG;i> 4ܾ?vc2Z hR4D UYh ĄҐANI`mI,΅s.,̇,-D<~2>{0PU˝df-9]%)%QB7ߐ).`UZ/a$I'Y+R%L&9;{ /ܵQ25IDcZ0X^PG8Yy΃}6ׯ_gssPߕlc(4M)+ݶpR0:>U/puw;BO6Wv&ġbܾ7`{/RD\tc !if P956aR/2MSX9LR:YUG1.-LS*R /4rƓnu*:IR+H2v 9QG=–BxeQ>𔪺,RN61;;;|\v'O2rHvlm1`EQlWy,<'` k[P |鿧_~HKm▯Ii!-xMYZ&IɃck#>6d'Wx$y1ƲҢ{.Ӊ}$kc7W~a.Gb[~k,JS1I0 +1I,Gdfuj' ?bե1-IEX0Ѥ + /*EùN@^K^hTQ @;u'fd<)(d1u1Ld CKg>Rd2AJEH결 jGkMڵk|ᇇz4#_)|,F?b2Ƙ<)s~_EYJ4]3EQ4}QLz$9iK1*.8Whu̾g f K9GKG՟  a\b7",wNu47 .x5ƀ7(޲7xxR1K!R-'tƙݶnl(Ob#$icp)݉  HqRe%Q B0rX, `\N.MOYY!<\:6"Q5ZvoZP 1k)J€YeEʫ cz=|-nF|c8qk-[[[c8_yᯝ/?}Z[kMCah6` k0ópGkZ(hpjW\id|0] 8h&pgR{(KX"D%d%I5?.o/λtZ>Ü͝6Is0Pt>6FU:+~ֆեN9f+5NXI}*fU]$/ p޾T@ԑ30֢*WNWO~hR82\fX>'Ȳߗn;eSdA +q-{ 5c-YŞRr9Ξ=* C4E)E#_MzX֙u_i4Z;\gx^ `^[s8ǵ88 {AR6BBX/XRu체)S-LYY[9{Ky3v@qTV䱼?tCwsZn:pR AU6 u#x֮%yAHwdyޕR^Ӓr8}^;^F-l  >Va@vN@"%Q G)ӇH\8?Iwgo̩5'}'9}\@໾k+-"޺01Q0T:Mܑn c$chbATmlӊu~{ߓt[ |7{rF @ӪNn"x1/<4۳ƠuI Gcݥ( 1zfzq t:j~:EQ'Z"ivM8,9Sȵe O<q]93,S?vR 38N2+w={IRrѐ?W;k@6Ì$ 9B8Q';3n=ptnd0*H2AE=֊!{ DT{H%V ^(_)\'AQ:Y_%*pY0`}V"-v˧|LJavBˆ2S7B[, !P1Bcn0 XXX?c.^⋿T /_F)Gh0]5vZZB~QdIy:@m=#0k0KWK _L0vt@$fӒ(F7&ܾ?@K}>g4.qw>f0<cq!`8)N'IKFV#@UT,wƍhs;!`*}J@JA+qմ>w=OE9%'VZ.[սJKnT5ϩ/%_ B `ii|;|ʕ+qt6 `aa˗/#lH7oܹsQ:m.IP/Ӣ(U1K/8ϥ0D2;ʐ~jG:Z3)r{ֶO5WW?ҹ9Vڥ?_s!ۻ)7y"rN5NZѸ`s;!ļ8T& y~R;c^U}n3h.+޺щ ZB)7S PxJ2NJF9ɤ$(T,-Dbn'=êD vU BFdxIԤVw|2qJ*DQ9q TMu |MRsݐom,0\O^t9̉q{NhWw^ =ޞPKZ Tdw1)${Zw,P>~mأq%J %4IcՔ;1]SAJ.]byy+wE$ YqM:PJQeV1d]!Ě _^ǔߏ+ X[PBDX($)Ǵsg\q0WTڥE.X 8D%T%kF`ŗ4()I8 17q0,1pT7sFQC+˒,xY^^~*t:\x4Mn58uC u _[kkgg.ՌKN@7Pw 26ͥ Bx,rc4sO"{píCvpE{ݶ/?eD" v$JZ U߱p+ڽr# :AQMD!Xa8)sT 8;p쳛᠚{Sm2z0Xq l(o}\ie7~a9~/ g}oM-Td,!K+=%ݍ6da4)u!K1Id F%/-Ñ3b'j;G[ri'Ü4wzMOoא:q-y)\$6ڵՓhăxXX3d&$Ͻ˿ǹ7ާvyQ)ZVs3tF$ ~qDQRKqt~ENQJ$iyT%T% QRzBBZnq"4'ड़o ;f|jt&c|;Z %h^K)RB?OJz7< IDAT7I3;}G ϓwy(tu=$[ s!~g@wV8u?]oR5l~CX[m2Z+%* X&y^&g]stzK(g8Q%hm^%ӣw[h*}6~my{=ﳰz~(beewyM\EQm>a<;;WRyt3b%ߧ+2c A Gnu[JU RjG(ԉg1ֲ0qrũؚSkm"c EukcQZ:ZШ#gLC`kAT=::"s\%yaH/v{|5XZZ s>cN>MբjqJf͛7L&OԈV<;Aei-1OuP_vj 1uƬ0WW(0?L;F "mJȃ(,Ea'%ݎ\(JxR0K^?'Q}v3׎⠔KJuRLC-kkə6nxPiFIAjtVY96/. gJJROE!Ȳ$ͪz#Pz0ϴqmwGQx4M9nexSRQ<kRHPݔ(\3]{Oosoc/>zc,-ߗc,L!5ruԩBTF'de9`ks.c4V+ĩaq"Aɓ'ZiVe)2_s+>A4:rb[Gߵ`R]~5S.]DiV#N8Y__,FA0s>Z맴mFRʞyp6} y=efZb%gXj9Pk 㼰}KA(P )]\Pϟ2IJ:A 6zgŹ0NJ>1\7@6iؚGn+7rW:Xw]1:rzYuH6?I6zʩwX>>q+&vN.{+++|[jzoFk]Eq[yv,b:_>pיxÇ!}Ht]0lx/14M{1qI RkZ%xq ."#>i<T931sfӤ p7/CKD"-GTP`O9ý\7y\$մZ>+-̵y$ Qim*JG?8Z4kW Ei]?+1s/.z,\ ۧ]y[m°isoDjAu"SNבu]F8?D,ːR>vhP; v/3RJ߿ޱ $I$Ю2j 4ZN"أxP,0o3`_ ^A(H!i,% ǩ-մIh#wOVx<`$[Օ6:u|t\t7muPa;HS'w`0, IhE7X;}VOGwaq:.pM8ƧFI~53u]X!) !*= P棏>b4teGK_D=P)E… A@MIcyp hyĕO\@C93֘93jGq4 xwcI)^!o(ljYi)@Gc:-+-MF(T,ġW0 Fd_׸#NX[g'pS ҐIZ2N $ :-d[D.JJ9#>40{?ϸ}6Ʉ Z;p(z x2SvMYM>u_x#[ 1YZtcWxy^3Z[#8kRJRV] 'W]8'`eZakT <p?r\[lIsZB@ɪJnnORΟЉ=gf<)qAiڱGX8S9Q쁄j`*/AR v<פ#c3x?. c@m@ Y[v{{{h[꺼zjyQ1??~y`4cܹsxO 2Lj=c YGq޽F+( @d2BN%P瀿W܊G7x5sfxm0sfM߳c+pFR>''4AHקƲ?I3 8/I?~`3fYI(ڱO ,+ ]}W2U+R@F3ƐsP,xJ3v{,x0YMs5w7w 0Gq׮]kZ"[תJzyE,--1ׯs]},ulna\__G)EۥW^=TtwU:%p͸?0fN %f vZ,pvn@/IvH)%+?5L҂ݽR[F00ƓIyqcYm˘SixAn+)ppIZ$%iOs'Ri~!Npȃ0Ɛ$ y?ekmAABdq]TbAPJ☢(iwp# <g]gN 1~#x@q8`?eis)8 }IH ?ȹiE)A(`!, R Q~`Wlϲib0iIVhZQ9ֿMgn ? Ex̣ >#ܹ[M()`b$4 ,3sss;wz㘓'Ot'\~ͭCmC=Ȳ$iZj ̶8fyy7|8x<>V6m)7 qY~zL?O93'`_f Qƍ5=uH:%T'N;PJYg1&R.6tJP עz4<3'`_f q@-WޯWЖ.=)hbzݶB $$ $ei*{ 7X+677ɲ{uO1FS>BN2/Źsg*zr?՘d) '&m{uBMg@]Yb 8c,sX'@7Jx2P/\_WR爃ܮK~TE7If8pw[OA8 uVsNBf`PSrSr@e<~)4Z{-uD$A )K]͌sׄu̚q% )A 9 "Ա]O `I }Vz<)p$iaf F?c*v& c\.ǁ.D$%>8P^h3hm<+-#d>o`/P[?NKӔZq^̕+W6 7y 6 bP uF4!f_V8,'/ {2773<+޹sUUz=Gt\Zu(% ig=*J|b( @OC#I[?4s UzR:=uDJB"~QK1R# \ UISMZ#`FŦ4oiWU9f^ژG:nV'fD-[^^m߿&q]e5*MR;/\'T<Gјa׏ jug/!7od}}qSsߒ4` Rofuuu qun7f:B,3 !I% ($%>؇so!LR[NO_lքQ7ov^?$rħˣa6AqhubRe'*}^6}9\A#/!kkܼywﲾ1ְc a76AS7==éSVȺ*f)4HNMMqPZgﳱ:-z~ : Od,z:* PT8r>lN x 3֬,q2@t$If\$FY Lb}v~P%(c x C+RMW%:q׫Kim{jJS jŊN7AkAv7&A,'O5Flp~?[oÇs" u6NJ9S*%MR:>}SNy~>BRf;!(-{ Ȣr/[LJ8Inݻw ֵ.sĉ3(X[[8nL:Ktu݋BRMT;۬! ]}ol"TcCIJ|&!4`|y~5z IDAT>'ZC- n T"DV*hfcf^£.a \DݎÔ͝!~Nei,Rƽ46H)]Qs6kkk mEwz~7(;|333?GR@1 qv,FӧO_]\_0sߛӌ CY\\<n s9}'+$<.4 v8 A$+@IF1*7]')Z0z+K14Yޝn4p4[6TPHwxD"I")INLDbmFfå6:(|T&M c=cloov;O%rv:j?ŒUC:O?qq̮^b(l,,h6\z!+kk3VqxE="=ʳ>TJ)ıʂnq=_'N| v+݉q]3SbE&&i0覛lGQ5 ǎu}\q.au{}VVV[z$_o{,7"0JyW^駟fjZj6p_=5HNafz<BJ|ͼSAPL Y>iRT}@r.`ofyyyN@^n ð8Y8`DL5E[14,F (,c<$h$R)D#BjsE>H aBQ 8 $ġPYLyy =+yDHHB_1Wjt6!Tt,Z Miͺ릔Sd>IUBΝܽ{VEEC7*cވ _,//Vqy pвV |oboC' z/pnGܼy3lnnBA71֥߯rT#'sHS 3]s:|$I͛xcǨժ)Y^^w-W0[GQrDZ_34MTƂ=R`<}To4x|[o\{4M8,N{*w;Zkz8j8$Y*</`XHIJ%( #\Gt:]fg8rtבL.@mpEaPLcǎ/ssso8v,,,EQ^).prq|gff4Mqׯ$ En7<) HdKWKO19Pm{t,I@"JPshD(hU̿vք*I%9Zf,{t P48XYYڵk,/-*V8ȵyoY1g|looRTx8w,FT'F s"l?,$ LTȬLMOSO \«?3k?:VJCmRCs 7!L3gK/!<oWnG@JvzRHu{ 'ĺ;.nE3c@JV:g:&z4ess(2v0xfwo\t)E<fSfR)8 Wπ *I@$%>wBA0<]3̿g4%KFFT8 8o($yan˃ q3;; BJ:ERL-7Ζ8W_JZ;{C_ Z\Ȇ5{ws]y߸qc8ut|B0lA- AA.p]$ ֒$%>G(h } }/dT,$At4!O ~k?!:(uN<1̤km,-#e/~sRVprTZ fv σ y<˗t:5_ei֖DddjjJr@!2==O jOڍTeq%aZCf;S %frY,'}jJZekkvM$4]}=zo߭| *f$l)$"ꂋ@h;7; /?!ox{ CQ˿Xf̳y{bzzzj(p5(ڳ+2$ $IRl}RC( @=_^8Ӽ9$՛#XJ Q!N}}w_u<ϋR$ITr8FC b1wΝ;ƍ_~#|9P̨Tx>`BF2ǎ+l:..`,6p}ǡ_!pA[LOOO$K)|MfIݮ:BqĂRVşg8% ($%~+je'saHjq]2¦hfqǍX?o5fjY[[{t8kZJFl|mmNqGLI<<Gh .p̊*M@`$@PU9S9ͿW_gvvy`ow⽐RY]]MsusaI#Gxjs~_Bh4DO"I)RmV_b}S@IJ19B?ǐ/ X?ҚsR0** :o5g- vv;N;c DQ9Bv:.% "y7q_z9 PJؿB l҅2L[aTZX10??=֊ܻX}`g苋:xDۤ$Iv[[[A0q?!zn+Dž^EKJ) ;>C) $%(یqq{=aHRVB9*P;!R(1N4R*ujU*4Mlooג$!8B8mgp@g*/r)\0(0w@ YHBU J0M~?t$+++loﰽG6fss$I}? h4 O/oݺMRJ[P|")X?-&{&J[!w0ji\ڸ"v%''ZIA Ld3$% y xYJ71?WZkv"?-ZO1,--j;jZV`/(孍L@3*[M)0dZpYo2??__t=[EQNdl=R qrX3l6BPVyh4D4MV&+{@U2f|Qu=$`~\N-_,TojH*%iM7+Z*h|(Ų$J0 (ڬVommÔzׁc wvj]cp8}6EW^ѣxYc$!L 4$D9s41ZI T>B"UR(JjZ3W>5}mCIJ)!BTWkZ?YϮ=ֺihT־©VCcRb}}w}8M)9zqۙ?6wW[6jOF:$Idum08i="roDZ}yayLMMq…\ ccccDC!%[Ut$I42$ '[/R ,I%([v2{]Z`L'ъ!(JgBa*iuގx5MӍ4M[ZVKGC VIl8EQU!d}}nK^Ǒ,o6n?|S ,37hQZOw~KwoyCvG֭[}jZ'`SO=EZӟ{7cE~B42tU qC\lU9oz %JFvo? ,bO2 YunlֱKӴşa$}MM|uJki$r$kin)?V0n+^s<ΐ#"!B8iR]@iJ&") |*'4E[hO 5U֋ ~0HI>pov$AyxwqVT**J~2  R.L:eNSSBYp@韊f|~PzJcLb Tq8T o@tmT(ֺv~/|ߟg5@EQ3wZ@ R$I$ַ01'bOk݉8@t]W!F[f \p'Y9`aFH 5,@Γ bl45$RE!-nw4cXgg@7p]fXy/^[?ׯ_gcc$I<^&5\gֱyQ$+ivyn/(=[D ƆuчkqƒVk8^Z}?Ե^aǜm f[#UlcJnQJu}TUL\#BSCw]wVX _7m]FuggEY+m0(%MEJΞ9k:7ÇU8 Ð$I{n/R?VR @^ܹsy5*Y<)!D|_Jt,9^/ysI>( @Iv݉t Sp9{U洛8!B7MSi,=e.~G)NӴ)k6p/d@$< x#S*68r]wTI[t50>}ٹ9e}'WQHP lYT+$s(1x`o)բ7/X7[z IDAT 3Ƙ\Fu/JӴ 8N@NRq6d5r^1w0ƿ3/^ĖΈ8N4J}/^Aǹ4[TJ tZƙ3gH)%N' aIȒV5TShwNS '$KD G#Ɠ֘:'.i.&#0Γ4F?d|dzcGL>y0ji}OӴiwy5RRٹ(X!-).ab -#f{)@+(>R0 8OҔRxS0??'p>N8lr&qy-st%IRTo|C G>$3( (>s # bǀ@AuEE(k+PI@;$I !RNvqxw]:.͹sh6x7 Xc;# %h-QZs9~w5^7o'v8Y]]CiP!3v_r7X]]wΔy`~4M I^xZyF8be,&߁J;0T=)ި /{>h͝;wt:&EaJ{3N B>O?4sssO$ܺu+? YHEt:SB %yC:'$Dbb^Y8"P4(suAJ¶Ź?٦D֩g~S-Zw]p'}!H\Gty83WLos\ti?X;$ J)ZKKK8زCz4W\!MSweii@9FvBq{I1P O:% ̣$%Jbh'QP4<8ƅ&gz{]b&1! $ZGRu]~{GZe~~"N^ zx7@ A!vQ=BA^ KZܣa T*Ο?Jy$Ir^8 RJfnWQ֩zfXc(Ig%(Qx OhXY].9}t?%{)s4A|-s(>SnwW霅̰}G.J42O n@f(]d]TyPksqLj#8N<5fdTUΝ;L^` ~!QjNRjݜx #<*aJ@IJx L Ɂ=h&}}/8sG&I`{(Ycvh4æ<3IO~S{.ss5pL`1)34Ѧn"ɶ_X{Vg R$IF.dgt0MS&=V 套^s !h6njgRkN@#?)I%(Q1afHߍkkKGI8?=L֕R}!t]t:F{Ma׉ㄙ._ɓ' 6k4 EI_h4^iVVVޱNc2/$ CRCJÆ駟KjN<8sN]q ဒ|P%>$( ? ǑfOǬ{\a^/a 0*5Eu/V?tDkT+.q;v,k+"Jr`5YC IHq?8KܼyI]V-u<>oHA@Rɛ=.\+yȟlnn r*0() 1?zp|P%>"/`\hh>HL6`t^/"qal; iLּh[ Fxnظ Q oR ^~efjhf]Ő)2zs6 :;w}kYaK2oZkrb89vXwXdǏs$I7w޾yYNnkZSk@g Flja|P%>" y/.3fxI`A(3qq&ֺ$ɺ:ёvLxq&"&/>{ &c},(( q 0;3Ë/^$|I. \Aͽ6` :|O`c &\p\h`0fywc=z%( xhZJYd;v-~_SEL$v(`_B!1PjO(RԦRʶ 5ϐJ)EIJqHonO"0{u"M-_w1$HRiDU!JeXvJ)}wy0 k8l2~.0E8~7+-c.,$S( 1Lzk0nQP%.v80Iu!^wTժs}㕯җDsIE+{6/IE~vf[oX$I̫Sljzh`8f^x!I_G ]$d"RQg@xqB^| P%>A˓\c0A u Z4MײnwJJfۡ$I7oޤQSոtsBf|6ίK7i6=}G1^o_ $IT*y<<X $N:R u !kkkB;> T<C7^p`I~( @ p:}{3|"Ƒ+oY4c}޺qvK٠ZAvR5B#!ݗ8Y^+xO烅hZ&Yج|uML8&Z233X<Μ9,J)*?t:GBLa$IOEpd$"D &8Y>$`!?.l_`$́'ICffo_޽'?egիWixD&ScAdOF+  /^@ip{!?ކlmmq=z|vnꡫ8\ץ^/|!Ogܹ{8jBkGOi4Md xɔ$S()@a1}guÑ0a%#Jt˞Cml6I1874O<3Q ,چې LK VP?~8AiREEV +={6 ܤaʸ8Qu_J0 CN  { $DO!x>$WH`\b[Y8 RVtfDAm~m(&/^`jj [~mwm(e'E!pi^ykLM5XXX`kkK)mn߾MCƁ= u9qD~G =ju= ÓAQVJa81[Pg1='PO %(QS}a/?.F2<}4q(SGo HӔ-nݺE^'z*A%u^/ v'N0;;ǁ)t^)%?OX\\$M4jZkMywIQ pTO85ZM% ( @%>r< (L cI$K<Bv:g5^G&LsRvuQ*؎*S+%G::y j֍ܹ^@iVq+IDŽ(Qc!&xxp~KBOw:F;cNݻC^ȑTUH]Špnw1JVL@J9})%KKKaX,N2@ `B6LpXXOѣG|2ZnRE0DZW8@Jt:cp )_4wgH% P%J|8d( 0`f:϶mwjjʙdDt筷21pK_\љpqgz sA?MFC&niosk?eye^M+N~/'0i%!V!z}{"DQ׽Ns$+qh pwNJQ%J|8d)/@xpP)EтT:h4cYJÇyps=q2ҨjPZNm䒬@k.u=fgfx^}yvAP姩m+++I.zUp]7 : 8JK./ym 8Ngu BJE(څMgI$ϸ% xLD>dq?|i2MӮRjRjn4 _J`cۼxjY,gz  W N-C 3j5H?|\=$ջ"I0qb#6F,u]?*Dʃ])jNd$IV3swƓ|D( @%>1|Ⱦ@1GO 30 Sn5uqo\ݚ^zS'O4@i;/APȑ|GZessnKŇR X]]u](&cp1&jP W^EJIR//@:h4v=ye4M`4[FQ%(Q'JW=dQm](h!đZK-068aqq_5*'O8NFEGB?0Ef!H#?~8?n;Cz>Z)0X__GLu|/ H)sǁ '\p$IhZ\v-o]_2yV9v{&pl'˽P{&9Y[36qͤ)Ri>vO\;GnXNȖdHE $A;@CXfzʼTeuuOPH3յdVwCl Be н@t{c'ƦK)P*")`?2m3==`1 `vv @A.Kr\%50\.fqqW^yB\E֬ B|h.l>WCF6dȐ%{ł bDƸOBˣŋ޽{6;EK Rq A$%J t[nѣXŇ~lvNk e>c6$^<&099IXI4D M"~D pAk  X\c8 XȐ!}Mސ@45=ֺBH!VNXth55=M)˄aÇ#]IѺ'ߴ L^G۶(sJRE ˲,(&\RJYA̳3H mfd C o@?=p@8jZ|ߟߗz}[\3jJ!_`=eX"<0 i3h#W!d0 UH\b߾}XDk~Fp30+zNJe% r ?Oy׸q&!3Ǵ7 HypB }PJ=j)߃(ap5Iq}!Ȑ!}>$W _y>Rj}![Jcv+WZ.𢡄{144t L QwԄ(DIRX8c4=e.=֚K.1336J]JTT]#}O@ʕ+ۼ;,,,$Ciß602GpGxgIuԢRʨo`n!ƌ 2XE28NNx$m0*!Je!\5`6SSh> ]'NB]Z©@(  pAJr4q299 \-//~J7c9ܺu~'NpU\u7BO^yq$,Q.T*Àbat8`+Uُ0~I@F2dp_c ^`uo8uzk۾߉_ju\.kCX\\ߙsr۶R,ʀXqmL:I*\Zi u_+»˵kג΀kKT42&L`ꈔ־k HDp2=M3##2d`$t(AԵ !Z/J!FwF|b^ѷA۹ )Z#c aP,k.;˷IkhZܼye1::J.#z-x {=qh~"$>ٳ}jkv L>sNW#!ff˗yw8}4SSS(m+P COp!9{,>Vf@RJQ,Z6y^ RmpN+M= E2!Ce""fcaօ2h4d>k~cn߹,Fp])*WMY{OtHl7LhtdqW^a~~~Ŋ|=?۶T*I>q]^ʿ277GNiVLMmqzqܹ+;wZ)p@^}JP)n&7/ @ > /),!Z !r|~MvSN1:2J>#* $NH"&B&]u2 PJ#X,2>>O?繜<jubAFG)Xŭ[}6Qw̔7ܹs_~_~Ǐ}vlf֭<ض~3Ο?  !BZ&RR)N u7kN= A2!C,1 zQ8DH0\tCa{'@kCnܸ@>K<>m;$E&/N # {ul{ RruR?nokܹ}J7X^^J' R|GyxgٱcsP`޽yF-^ BQ,B mAXATN |:BdȐ3 ~i3SObff;eD6P2MRXFbёܸ܈ vTJB$?ꛤPJ779r+R޽{yٲe j?u !#DဖR*s\ C2!C$ #2d\`$OkzRAzz}TJYm[ Vŵkèρ}vIVt$RD 5Du4ow lwQ:.˕eR,//I0A6#{.3veYl߾gy{u=axx:/_Vyq8`n;8E~J1Pv߃d C WEV"_!r!ajhj`TY: !X^pH/^hZūai(U E2ƃ%dYC[xGĶmN8i\b3>3__O322®2<<7Mg^º:8fUg. pksO2!C z_.V ^2^ 2ϙ}mT5I@jR)ov_/D1V͛79}CGe֭dp<8m)(Y@]P.9p`?Qo€ifI++ll]aq=ʋ/K/؊k$ܹcǎw}FN ŢBVkyA0 8D/0 @ >WCoy&*+;V;Yu[JV\.Rʾ_^^ҥ4MJe˖$/|m IA, u=oB vK]an+{<J)|x?"c4M* ,//orP@jbOL8L3f;'Ȑ!4 k0 uReiY֚wKK4._T*nyg}ˊ ,ӳ5ԌLPyPehGy0~}DrRf [$R^6ضmǏ^GYkiN/e~pn޼BԢYq&TJ'"臨ބw&ݪ3M2!C%!z3$* <A,!lVrs!aH^˗q>FGFBv0+ @G ~-Ѿ1,KVJ6«DJgϜ\*GTO!lO''3Τ0A'rt) oVhJV]o.qٳZ-InC,sO,A}Yϙ3gXXXP8 ˡ݀' p)ۋDvkʐIn=1 2|A720ksljZ.J~$]#t0u]v-HKv$tyov 6KKKqBR׊>m!݌q\EϟOȁ8ɾ\uٹs'1==MP>`qqvN@>RR^؈kRy"b1?̑dȐ M^Sk0v[{z.J{Rtsss|Ө  @ 0A?'FAO-ب/uEp[TrV1B@={bD8x`zV063FB'@kEoSTy8yfffW}:o~0|S 011VT s3By_ۿ[~{mQL;]׵nH(QG5Nׯ<3A2!C/廮i#<_a`k۹ZV,'uQJ1==3gPZعs'r )x:13&?ɸG)}fr'O~˗~b?ieyqB'}Y< vׯ}عs'CCCLNNO;yBQT_5< 9@#=}&I@F2d]Z`z[t0 M|Z,+gk… LOMa6O?hcJgd0Vs%^ynݺE20 S$̠.?{ar]<6 Qr F3\Eko4D|; <%oDDw6@ mr1XwcȐ!C:P@ _1@ʀ W|į~k&&lc:S]@%|rrݛptR`=p]۶7(Lccc~yZVjpr\Vdq8BDaD@F2dH&*2:DV!ZK)|'uBHK6ƜHeZqI^}Un޼^D9] Jm6V֚EN>(jq]\.=^<3e ɓ\~}CŶmJ[VwI)]!j Pk}N#0/I@F2d]JӏDedHtBZf}=&!sss lfxx8jxcdĉ|I̿w[?*}(H)YXXl0׌׹}6m')%A088xf8p_~(rDFx-ضm XJeڲ,+C5<ݕ!I@F2d=zZ^^%BZmB:k,-"N:R-[pFz^RsE^{UnݺE\7+d6|{m۶>Νc$A_z07ҽotLVeY R2::W6FueRPTrv{(4%:CZd C K^ހ0e@DKo `AkhUZ:000PWeYI)ZI IDAT7x7x;}3Zg{Q?0mYx'7o~WzKWTU.\v'!lBb=Ǐ344뺜8qWn\.'I`v_ [뜲dȐ!Cul&&"O֭o$@RqJmvߤ4jy&oJ\ciisq)߸A)5 |ǶmO<α=|.>|iI4)ÍVE͛I(j%-[8x _<)%D  n !E.h訵"a C~#:2ߛ`F2dȐ!O@wN{D$OZJYVrٖRdo33lݺ&'dugCZS(8vǏljz~@٢ZnH+pA$ބ|>Lb佐s|\(Z٪8D0ܰ=uXې?IپB7Qo g C zp$`4~ITx(oWVJeYGJKKKJ):ssۭ8nt f3I>ܜW(eKKKtm{@?ϖ-[<,//'.a>JB<5p@;p si>!Ȑ!C5fQK20A\Z?XTFK#Sq&^ד8u?;!eGWl6җ022)騳[ ͰmG[lѣضgpƍ@DZ>yJ+HַExٳgT}ZQ!qI' ; 2dXl^r`?AZ-! Xz}KXtNJm4]h㇕HV oƓO穧bllW7q--B ,+J|iϥKIvVkƛX,nLxdhhrLRlru0L@i.ʎQ8:ZE`gHihdȐ!AzͣNHoiR/VXJ)&JKfeM~H+LIZg||?ַ8|;v<-olqػA 5nJ}nn帄Qb6glll}փI |'k׮177$ьoZBރN_Oh*ϧdȐ!q${* mbݞPJ)FֲlLL#CsA@?~ǟȑ#lނmGI~#1ZD=9H!AF%cddGrgvvf)U?3 D"cc=̵㏹z*Z-$7 %-:v0sH' kUd C 6{ k-](a֕RR~N)eƤӯ{WBD|(J?~'<α14^z! Q[, "C$VfZkfffPJ%RFހѤnanx"Ofjj uλZJ)=˲5uE)e\od C  !i4<&*7N5v{^Zdmc~=_>(;vXa@n!ck<Uz޽|.Q*ν%5B9uToή]<x9uccc(kǑ)q],EޭZ`!uh7IIFI@F2dȐa0MGDAzKZkI=,(ދNx"{Hs]FFFؿ?CCCQW<шT@D}εHFA>cttÇ#HJׂ! N@yl8@)2Ν_4M BJ؏TnK۶SYpe~_qifgg0H~+zR^^^.}m v)Vt>z{BF2dȐчu_~ `ϧ_&RsbYZ/}q/IY@VVni6l۾r9ɲ7zK$ h!. @ B#F 6ґA!_KKKܹs&Ɋ,ӷ߾} APT8qO¨fzD~DBJSVRj^)Պw=4v4Ȑ!CO}qBI  x*= K-rBa`ii>^}{hQj$9Б6$k!fAmv~>$W|DbːS§q(nn^OHD~ 2 cOKk-X*eYyzβ= &]InoGȐ!CwI> x<~yƤV> ˲VhִZ-&'9Tݻw%@ZdtVQ@i0T )r={PV W\utZq#=44D.# CΟ?ɓ'ywyfW~{z{s]a*v{]-uRn6eqE# X+WD$KmDzs9zkH"T*j[~&@T(" K5BH0TKZ/188; M~cƭoY,,,$جu~۶,뾬R[&<\x18X\  mlԒR* j 80$<Ȑ!CO됀40X+0x `VmXݬ'''9s rAv;PAO7:Zգ-4)̀=DH GƹP9r_oP`Ϟ=x wʕ+j5ldWfB8"ph}~i`;$/ƛ5gȐ!CFϏs8o<ԣJAp)Z7|߿fP׭RW^ܹs\tJBh $y^352N!$ J# ܳ'|lZӕsO8ɮ+7A PLVg旮0`ppps6O<,ar%W3bC{J)e QI10@PLؔ' #2dFIA?Qt(0\VJB|ٴv."Za~~˒(y9B%?@C"^G d< uGPS7^a jQ %kzmc?7U uٶm_9u]1A1Z@%0H 0XYPj,!C EAHB,QN@3}ֺv}h,Z^|SNqE:z& DTu$:;qeadBDr;vرPN[jJw yC&\066/wbhh#GwwK,//aBE70@@x3@ 2 vۜIG01&u]w5`\>:Q򞕨M?57LIMDT*1>>J)h6AfItVƭo{{`n<=/O=n˺zIJH[qkP%1=bᠸB P8ˡC>}kl6WzTBdD7 ~k_)NB˲k_<wy7qZ P:t>DzXI]gȪȐ!C6@t g&__빞 )J8 cŋd]v144;6\zZNX BF@F]hv [Dy*]JL6C 2X 8GD!)`! Z.;XVwJ%˶5[Z"p|ho@g{R;)5uX( ڭJJ$'n-}pf .^ hs_aVV[nq loK)VbpRu`+}"U~aMUF2dȐ>$77M"pj fy}juW\ 0<9y$Jqv%%&!/nPDb̀j;D>umk,D/B.8a255;#eYxmnJׯ' 9,jRضMM(W?m}I@F2dȐ>:5{SjaX}ju{T5V*Ο@Zرcl۶-i<7zFZn~\r'Or|_a{e{{ޞ&!fn!Pdz:u 5q!vܹd̰@RIضMT"F!RqVݞv_^ee;i$ #2dp +{.FA0 B\ZT*j_ u'0;; RJmۆmYhVI R[,..111 9wN\ H8TaHի4dU>88< z{e||[nq5Μ9I>bZ礔,˪!Nk /$dȐ! ޞпyP/~ \A)xX\Mg 8hÐ|>OXuH ]ahJM5LNNrY>#/BiCd@ʁNX IDATrr9\]5}~mIGR" ClfttQl&su^u~_j( +$ħAh4PH)=)eɲAuE):^$s!Ȑ!C$1QԵp!\tb_ pW^Ų,&A+h4ܼyK.qD7o碫/=veYK.[ LMMqIu?qyl\~) 6j8$7o[f˖-HiJWf}.]۷<۶WY."Lh "`Z" C.^HRX,8R )Hۄ\MGݦj%2LW8ZU,`QS%Vj, 0C >G-?ʩk5 @1BZ)5FSNQ9z(b@{1??OZu^d2=g)e6} 6(?Ans6?T* 1::J>9R5]Rh4ؾ};ZG(-6R! .՚%D #2d]b-Z7|ߟdpb>/@8C\fll,.h|*enݼŹvZr|O<ߞ7{㾗RnOk0VqU~_122 />B.p~(ˌbYavr!&4`x0A;tKV]^dȐ!gw M sD9rk0jZ>p@J%sW%Zk `rrzγ>KPT*]୷bzz'-`v 0Ft۶m033)3(N>۷ٶm۷oO 0۷g ÐvJzA5z{XE#3~tL$D #2dHjMa(@SOD_)}߿UB!ĨykM)[R?dzz1._G}bR/0P(0228;vSSS,,,$UL}y)|+_IZ-|q$p5 cY'Nٳ,..&zsaJ BLhjj˫{6$EǰocO,!޹5Irɬ>wyfg, DX|a Y>5FBa-K!B/L!KΩ]鋬ή鞝Y QUߛ1u"u+?~kX\\q,d4%@^3Ny)/_䄟<{jjjF||<|CڭXس,e:+k O~RN't:j2߭]+Um߿Bs%"`Y9;ֲK)9<Y;ה<@ sݐ\4LI!pq{&"n8{nyN 1Ŧ}Orկɕ.?ujNl;LRJ!~)?ONdYVO>AJd2>lmmq)t!~`@dcca'L|E) g-B7s1`Y x@-E@U9c9wǾĖ 755?Ia (lq\s6.{o>9_&'@EmܤQ%ϟԗR)Ǽ|tJ "(b6'0N |ѣGt]$Fhh4D{{{}1Ɣ(DQD^hh4܉ː0C` |_mnHc=)W 쁅(d7O]}1f(_(/)GL5Zu><h=#R$U1xLV[hiٳgrttijgܻwVYJٹw#Oj  o@,/j٭/Vt6c P*#Ij r445шpPIBV+C vRR($mz.(j5Ê{p8#:Ng>8.IJI$m4BTJ*UP +0̔RžZJQ!5NL&"_/..Xȕ!h]8ll0@\aZ7 5T 7rg}: y3$ ve٣}KDMV x@ BU9: R&Ipne5Y`vsFkwvDQ nj5i6$ZFU3#ۊ P'(#S }zٌ?vMࠌ4M ^JG@ Vs|-=l:1Z)unB$caVz^6m:[Qm64~nfI-qwI` "ϕ=`®UF!R~N XwvzNd2B!ZkY`+]P@`97nnlvqR*1Fj7]RKqa%Tn= vvv$NϺ&>7anTq)n_ J)t:e5^y Rʲb.qV= @ ܆[C'`ӽyq4;RJ] ;X+.߉< dYeUh e1mtW`F"0?on۬WJ1y)v ߅5t:.aUTi`1^i@ VrCpb[!\#2ƌ(RBXcCpϸKL8MFc!0s&I9lrzz:m?*DXwR )kyrg`2Yi_(]Cۥj-x1FE" E [WK#l8_)|X(K* 6b&} s?6ycZ:s{Gk=(L&t܉4MVZp[+0Nd:e3$۠NgA}j\@'@ n E@հ~M|xط OǷ*f"Lk,28^p;b:ryyY ms[n1N #.//˜4c;_:L&?^\N8iZt]K)e#`ZWo_o?k6MɆ;\(\v^ZmFTkl6c<h{2BʔzNtނiX5y^08;;fq(h8 gY\be@h+~AiQGݺGI oz5B]6}LSF]9;;0Nmrʕ ~ު῍Z)_~%z vwwjw, u9k\ T[ 2nr X[}Yҍo]¨]HsE'ryyYgY1TV\'`$Iڢll6VRm%kR5<A@R%W^9,g 'ؐ'g_ҧQYlfFc>xLe`nwm]S"cﲿ)ɄOVew(<4A@൸-7w!8"zx6XIf<Fe_ey!x_dqD?f3NNN8::j_~'HnpTJVlP@ ^[!Z@?f .N(jm.R 痗Lxw,oV`JE6N\'\'OE_ށHQ+UB@ j!U_TsOAX%,fYFe(oxJ ?/BkP>Ϟ=cccwﲹY v38ZyB@ *6ԯ7C`s 7(l}~%@)Zf@ w@}_8w[γn锳3>s:Vl\R8(?gE @ |uIDAT%@|ʲ=b c!DnQBeJ^ucE̽yY~O?}w@C.! rr DViػnE!_ /Z54{;Z;p,˨׫p-ㄍ1vpռ+?%6v811/t:t~Ih߂U  _)nL+90ޣ/|/<c!D+3S5.U*|eZsvvF^gkk$Ij:&K/ @ KbR׽oUo@5, |>Nn^DQs/jN4UX ([*1݁ đ엕B~ߧ`ш^xAlll0BdQ ߻ ,@ X"U{5X1{J1&h !lV i,d/օA^Y0xU<__2Tq-_y1 Qj8??4y sUt dnQ! OW(mQMjZ$ !BHT8yǢ6pNWJ-嵆y8Wsp0D U ϻcc ٌ#6w1hl/'{{@ ~B/3Φ*P_jLQRm)嚔iF,B(Dd[L Rjj\Q~AɃǏsfY>&Jy#xK$r!e]y@#Rh"<Bԥ1&"!DeY$p"BDQJ a5 P`z%`Y/ j}3zJtV=\&K  ,=˲\ <1fpup!b)e"I)BYlѽW T<U#'ހEo@UOZ Y.:(X%p! H)."_yI~~\_cWŕ-#x@ k__8a{~V5k\ [tlmPpsU ,e\́ ؕ*|V @ +5 Y.]̽ 'Wb8`;PlKCA@ׅj{ `pD\]׉ea k_{pe?^`]_b o<_yV*'`&< Ͷn8OS+*&%rgƿ+ @ :upS2׿E_~Sos.r@ + m.uL^UJ(I>r8IENDB`qjackctl-1.0.4/src/images/PaxHeaders/disconnectall1.png0000644000000000000000000000013214771215054020041 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/disconnectall1.png0000644000175000001440000000114614771215054020033 0ustar00rncbcusersPNG  IHDRa-IDATxœ[Hq?VNVNX5ӨXoz)#.!CQ!‚̔DL# /+/ͭ~=8=_ۤ@\ KsQID\ 4>A ]|;ZG@28uIr"7V((7aPyД%w."z krLrdj5 K: 8ca,ĸYeaK>G?Q$5<#tn0gN/a]! _b^4 Cv1nSIߵg-S (H\bu(,(_L uWKB?hOw0['9y.# "B0 I (|b۶mյwޝ=rl6w{{{3p?~X lE=u+0224$Av܅ ?:11qk2vÇ뺻q8 =4::_XXH fX]]x<=cccgk`=ٳgff^^||TUg@ pzǎ777=@EfggT*Cyll޼)CVoZVE" M-*H0??$IKh4VTzj0ER)J$NWLj"#CBd2\ N˙ENcƍ,JO|(F.d2\N-LOO3111:0=h GTV(%!AXY'N <{M$CkVsv6޵ˢ8yd-`^x$~oy<=/bU4@YYY!NΝ+25T*z֭'NA4} jjjN744>n޼imSt +ZlXZT*h,AV )㉒C>̳X,o<|;ƟfggAadXq㷪|ՅJf֭Bnn.(JbIGGGX,vqA.bZ EGgg'Rkk3 ۷oh,j5@`nq 6߫B2Hru"0A_^{5565777878888;;;>>=DA%DB)@@@AAAIH ODDDDEEEFFFQH#GGGNG8HHHIIIMI@JJJKKKNKGLLLXN%POJPOOWR6QQQSSSTTTUUUVVVbY,dX?\\\ha=```mc4dddseLpiBtfMhhhiiiyiJmmmnnnoooqqqrrr{xDuuuvmyyy{{{pt~ÈpȰɱyctRNS@f IDATxc` .$ѵ;*<)O ǣBƼcRK%ƝZ"2EI0-%*&eR$jV>ePN3TTqR( QΉCDv @*gVZT!\\ՔŁS]^O[~M.&AqݽU68|"fP4aj7)/7y E.bTQ*]UQ.+vIB,R 8➋?U$הgKѩĄ; Ι/'Dej3 [?OIENDB`qjackctl-1.0.4/src/images/PaxHeaders/mporti.png0000644000000000000000000000013214771215054016450 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/mporti.png0000644000175000001440000000032414771215054016437 0ustar00rncbcusersPNG  IHDR(-S6PLTE222:::???LLLfffhhh}}}Q :tRNS@fLIDATxmA bU*VTrܙd"f0Y2zPdYv^`'~gZKJłgUw$/Y$<IENDB`qjackctl-1.0.4/src/images/PaxHeaders/qtlogo1.png0000644000000000000000000000013214771215054016524 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/qtlogo1.png0000644000175000001440000000563414771215054016524 0ustar00rncbcusersPNG  IHDR szzzTXtRaw profile type exifx՗[(߽Y `9\#fdg]DWUytdp _$_?>׿jRrK>>5>b'~?0s_y]L?y_&}^z "Z=S?z~vs! Գ6 7$c*vfanj-({+ w+aSg6ld奫,[uwPy.vm׎|cv;j/TtB-H}W|{>APcɑsBKBAcbW,@wLz;v}\[rCKז? Ԗ;{T9 מj'9DcMN\B*!N<}Jzz՘5)x>>#\lG\Yl~V~W~C6Ȼw O(b/-+9lK~>S(έ fliT)~2$¨v7J^8N4CetCI'k"$['uW)cWIYV7(} إ#m6ߪldjw*dWwQheEe`L4++.܍Ig/FwƞgrtRQ [Y CgndVu],OhGGI;·9GNaX:s"5zY;U=Έ7#ű¾9H4=X;yd W/\Jc"Nɠډ]}COHOhZXVs/!=vyB1qǮG`ќ@t29:J+nV: Ch`lB8ݱ"0IQSIG-M(",uzJyzUz|>+s^ I?|NHۚ?ȚJ>}np.RuiuDKs6N;;e nF;V7$ƛT˽01 LeY(z*i;uP-5۩N&膊6^]^ĦThQ5-QYL>V \xMDC~,boM.ד ! -#P[,]gS-h$³Є fxݏ']PpwjvFl`CxY ԗef&(*"=H` 최Y=MqBNN牢%ӧ**J)$RH"W#=SҎ.%XWh9§-CPHZ)edeo2Xv:X*cֲY(EF.ub/ #rl+WK1\C>p=v3IF"0m󱿲f:ܪ6=>E2n"(YƆtSgxM>H_ϯ&8P]4}H 8aڹVϩr _dV/MT{blb6K6b~ufwnU#|¾N7g7?mv:WD!QvҝX䷁-H `;3Nz= BRtxpIENDB`qjackctl-1.0.4/src/images/PaxHeaders/patchbay1.png0000644000000000000000000000013214771215054017012 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/patchbay1.png0000644000175000001440000000117114771215054017002 0ustar00rncbcusersPNG  IHDRa@IDATxœMHqƟ)R,=£d:tj56EH_`ai$$a"!ꪑTd۴;ߥ{Nʰ?zĚc5PJF;f۠tT"ۨ #[F=ÖxiV5F0b—$; (5cȂi+9}fwzPܵ[V#T"bMCTJb+QPVXqL۬^-NgG=X9x[6n em_ |҈^tg3%2uŭ\"NFsʼnkX @ʲ۝'h`x;L\FƷ =HK.ջ%*ְCc =W~ 5( J/؝W2 l{Mu,{ Op:{g[V}/䥁`9V~}brMt~L-+ A28~IrkiG* C ͤ#IVYE&g_0 9woIENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportpno_32x32.png0000644000000000000000000000013214771215054017641 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportpno_32x32.png0000644000175000001440000000151414771215054017632 0ustar00rncbcusersPNG  IHDR DPLTEUL<        '".!& %, $- &.!!!"""&"###$$$-9&&&8:((()))*****+,,,2, ---)00...///000111333444666:63Jp9995=>;;;W]S}]aBBBDDD2LYFFF^fmIIIa#WrLLL gfkgt$^wQQQ ryt,ftYYYYZZ[[[i\@bbb7t}tfMhhh3yiJ"nlh=mB".'(u񋋋H%’+ӬĴƶŻ޹]c6tRNS@fIDATxc`Ʉj^lG^7bN\(ny/0:3LqUjꢄW~9uA|1 f9axRKfuᖗm?b|^Քz'N; ImS+B D°O]gmb̏C~d[f^dO!,`yGV6t{,byN"l3+ʳg9i">yy-,{frv!?&6IE3GR.Mg7oyH}F`^G<<9h^4<*%LIgw YU`3 IENDB`qjackctl-1.0.4/src/images/PaxHeaders/copy1.png0000644000000000000000000000013214771215054016171 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/copy1.png0000644000175000001440000000050514771215054016161 0ustar00rncbcusersPNG  IHDRasRGBbKGD pHYs  tIME9aJjIDAT8˭ 0Dߢh *pHlG-,8_#Y̬ ?BT抪z,j)6ZahfF2"pC!Ϗ4@B0KR*pYtEmۍF~8 DC{ f&3=i㐇0E^2%X8QP_ThtbIENDB`qjackctl-1.0.4/src/images/PaxHeaders/acliento_32x32.png0000644000000000000000000000013214771215054017575 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/acliento_32x32.png0000644000175000001440000000310314771215054017562 0ustar00rncbcusersPNG  IHDR DPLTE03')-36;!@9ILRWK#]L)a  g 34.75)m$6:,q'<:.f,x'==6<=;?@.|*s/~+*AAbHJL9;04|=<8VOI9F D]RHVUMTUSH){OEY[GhUG[ZRI^_LGtYHq^J}\GZCghUU _IdPqpWbK\` Z.eLht&f'wxdh~q`y/}^k3hlFq0xtr=w%|o}u45u~q~`x ƒ],uƉByş ˗7Ƒs˜1Ϩ8$ׯө8ПxԧRӥqϢٶҤ޻'ֲܿtԽBܻ?ײ578سAڵM+´ۻŴșHX?ɭɳ(ͣɻgeƷҢҩJB]԰*ֲ}׉ٯ۫پٶKovݹޗ@ٴ޼fߟ~srotRNS@fIDATxc` 8YKppp;ׯA%<~(;vy;} ? #ݭĕ%EDx\O)0W,Zgo``"+sX/~@@SCQVVQ /=kS'Ƨzhjq> 2W}x~ ~g4 pr=O~vؐ}+4T$Ņ8Ϝbe/8lӹʰ vI > Vbԩ/Nعis7UUdk r1)s}h5T#uf;ؑ?ݽiŒYK>^_Sɺ(ǬϯXxִ5֤ekps1vc;g|yRWJ4/7';`7Rsv4g5;#~L8mUFӹiFzf9 y6f}`GZ}%nlj@6Vfa7k6PQ:YXq/ oIkX v6ffP t vsqsqq0غw8U:<ܼy橓'u N<}3 ,,//,CI/۵vrCn.ao]Á!k׮k/_8}zwc\|@p3GO( D` tĘ[cIENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportpni_32x32.png0000644000000000000000000000013214771215054017633 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportpni_32x32.png0000644000175000001440000000152114771215054017622 0ustar00rncbcusersPNG  IHDR DPLTE        '".!& %, $- &.!!!"""&"###$$$-9&&&8:((()))*****+,,,2, ---)00...///000111333444666:63Jp9995=>;;;W]S}]aBBBDDD2LYFFF^fmIIIa#WrLLLUL<gfkgt$^wQQQ ryts,fYYYYZZ[[[i\@bbb7t}tfMhhh3yiJ"nlh=mB".'(u񋋋H%’+Ӭ ĴƶŻ޹^ӺYtRNS@f%IDATxc` //צWYi^CL --scťQoWӄު9*gOJPeD<*sS12+ bN5.a`3ı`w/ ْďGM*X'uDRcRZ_.CEcߌh5no$#D=rlh@P]|*V'Y׿"D fi=:T8kQ,?!&SefȢP2Tļp2X;IENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphDisconnect.png0000644000000000000000000000013214771215054020251 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphDisconnect.png0000644000175000001440000000221214771215054020236 0ustar00rncbcusersPNG  IHDRĴl;sBIT|d pHYs & &Q3tEXtSoftwarewww.inkscape.org<IDAT8MHgVt76kG@@i$Kk*ٖ^ZD"9xh7 n)E]BaխZҭhcT4L4S9/ 7ϼýzK̚P^25iO4a&C`dc$x(DxEjm BGڇL0L-``~~^ؘܼ XLqqE`"׀ꮮ/r999t:}DnޱvIk(F ` xX{MMM~cmm!5dRڈb?hGZ" 555J"Pߟ>|H$V$ Gjmb(nw^QQt:mf4>O8::J0\߁@:؎)UUn[ffesNNcffρ^AF}>v7prr[YC]\xJ[' .+Wł,?7ťuXX(%^Nd2DU`8 R (ʺ[\\\ Bc|岙;R4|V__088(.b\ ^jlllumllE 񇪪޼pEgvUTTԵFFF_677"x|]U[^7 &b\ H#VVVL&%M\>tWАD@ 0i=??_eYfuuH$IF)@KUUU I5f ؍bTꕝ=m煻M kϣ@@QI$Wgg7'A>Fc6oΛ eܼhД 8f2x i-˗OMFpAx`//M+VIENDB`qjackctl-1.0.4/src/images/PaxHeaders/refresh1.png0000644000000000000000000000013214771215054016655 xustar0030 mtime=1743067692.322636598 30 atime=1743067692.322636598 30 ctime=1743067692.322636598 qjackctl-1.0.4/src/images/refresh1.png0000644000175000001440000000112714771215054016646 0ustar00rncbcusersPNG  IHDRaIDATxڭ]HSm(ZB7Ѣ~"N!AJ Ih٢Ңd˥qqc3s8μxޏﵰ*"MՃ jh1g%ڼ jxiG o4>ʴ 4X;'xK( ÀzmO$иjfH Qg+a&_H`a i jsBZ@A H ΐ^GhJ@aGr"~ͣs[fPXփYUHB~b&@T=T Rxȥ#8|ǩ M@[2UW$XU{k~*j+`i7ꃨ18rS g!.Cr_5~ \6;wѹ0ͤ> pS S^wPUŬb v&Dc9݁"b+ d|= U,d4;s-oJfIENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportlti_64x64.png0000644000000000000000000000013214771215054017647 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportlti_64x64.png0000644000175000001440000000516514771215054017646 0ustar00rncbcusersPNG  IHDR@@PLTE &% $" *, '($#././ -*"$"3302*)))77 46100079+-+==A@(2375231BBGF?@#==EENL685DE5:< LK:;9USKLPO+FH$JK?@> PP9GG)OQce/PL2NO\Z%UUCHJ-SUgiHIG![Zkl*ZZ2XZLNKcamogjPQOITU0__>ZZvv8^`$igqrTVS;ac5dd/hg(lj;jj^\`\^[(tv[`bb^]2us@ooPhi`b_:rq^ceafh7zxEtt?wvfheTpq#C|zJyyokmlmk?2Sz{HO~~*[z|qrpLfyxSHvwt\3QL ez|yx}[j:}|X~}Rr`Oh7]Bsy`V?iRr`EVo|[sTdMai|\faYkgĪcɋmuȔqͯoԕxҸtٽʽ۞Ϥy~͊ɄݴϊӸضعݘg*tRNS@f,IDATx՗aTWA kmJ*B;@YZmq-$6-P %EH bTrָ8.e7DC|urN)m;I|x]'G0  |Aӡo?1JLT'ۀXUUQ꠮l$2;E8/O}fFq7rY]>ʈdEsrrD8I9/^o''&nqu̅6SH8+E ңKNԟ s\ ,#fPoE۶F`-W>qjj9x)]M0<<ım[W 42mr3;?~~.Hl"t[e#NB[,6i<.p'R M|@zb<1fv8i M0#J[ (AѭE'G. ):Rccc"OiJ8Oj[\jkk> |qG4o8rQ}SO9Г\Ъr-_>My! ;Pj~r%TfϞ 06&\^拤*A~穹SN% m:]TPޑ.U#x>DxS׭FR~6;'Uȕ_P?̈*+O"7o zsq+oTnPJ|c-tx"c:chlPH;|ZbRh #IENDB`qjackctl-1.0.4/src/images/PaxHeaders/mporti_64x64.png0000644000000000000000000000013214771215054017323 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/mporti_64x64.png0000644000175000001440000000335414771215054017320 0ustar00rncbcusersPNG  IHDR@@PLTE       # # #!' "#!*"#$"$%#3%%'%'(&()'/*++$+,*,+.+.",-+-/,01/7752'315130231689496342:8796A<A8)9:8@=@:4CBI> ;=;==6P>J<X;=?ICUB@B?a>CD2ACAJEMD$NB.VEDFCOE5OG,GHFRI(VJjEXH$TH4IKHOIClGOM0cNKMJNNFMOMSR:VQ@[[RTQnWUVTVXUbaY[XgY>[]Zk\B]_\mc#^`]dd:_a^`b_ac`}a&bdaib\scCkgDoh9ti)khJueEfheuo&mhgpikhlnk{r>npmnNvnhoqnvwvEqsprtqzsuruwtwyvxzwxly{xzy{}z}|]}f~}~rȇщGzՍj^{qitɵĐ¾ÿͱ|tRNS@fIDATxolEov R.bicN,2K&& GaSmiɘh)րSLD@(i^ʝѓ&l{kػ6qvvޛ7o:Y}j  >t@Nơch8Zz "#s KwuI>玦Wo(&b~.QUxlIvcRgw%Kx)ݏ/ :>7X !'GiǠCidU( wf1:(F40L=sTr$&yy"q b}_!`xáX(>2@,Hw(9 &l(61:IcR[1`98r >S,8T̞u=a:0ٗюu#{J * ԁhO w0"6<|",df;q*!-qj"0$X@ ʢpĥb)Kp3O8='bfBwU2!N0h4:LjQu9tF ԑ5p#$k&ճhPJXH_ap)Yk%SC"U*6vSB ֠þtӄpJho i?&Fm}aA(vӛ{}BrOvݾwpB+ϭ"7G( 罸oo>#l 'v^Xʫbˠ=aU/qBE_x뷟 C͹hΞo}{4K]!/J|[?Jb!K.uO͜g^[ ǿ,{-IENDB`qjackctl-1.0.4/src/images/PaxHeaders/aportlto_32x32.png0000644000000000000000000000013214771215054017643 xustar0030 mtime=1743067692.318636617 30 atime=1743067692.318636617 30 ctime=1743067692.318636617 qjackctl-1.0.4/src/images/aportlto_32x32.png0000644000175000001440000000206714771215054017640 0ustar00rncbcusersPNG  IHDR DmPLTE   ## !!!&&"""(('' ((%%%)) (*&))$,,//***!..00%33000'5511188666,;;777??==@@0BB===??3>>>3EE@@@>AAAAABBBGGGHHHQQSSzr@csv6txB;DSzOZKEG~JE\aÿY_ķsf|ureljppr݃߈jtRNS@fxIDATxc` ت7k_ll 5+.[5Wu+V-ۥ:kV./SƮ@nZͩ\2$VS-3Nt͢NOh(&2kc셱Nw̄/knv,93FG u-"CqCs8jwϞ=]^xo^y'oǪB?j>)ޓgA-:0YZ3AdYu3>5Y̚al*/D$+akhG.[8O,E^#?iN2_t5 As:cv(YX!" ӪG2 ]AP( !Yo=IENDB`qjackctl-1.0.4/src/images/PaxHeaders/graphZoomFit.png0000644000000000000000000000013214771215054017547 xustar0030 mtime=1743067692.319636612 30 atime=1743067692.319636612 30 ctime=1743067692.319636612 qjackctl-1.0.4/src/images/graphZoomFit.png0000644000175000001440000000265314771215054017545 0ustar00rncbcusersPNG  IHDRĴl;sBIT|d pHYs & &Q3tEXtSoftwarewww.inkscape.org<(IDAT8]lSe=l~lNd`|Š^8nt*w!`&jØfv.ng c[ctkO{NeNM|7{<: @ 8F1`Hi?uJ`5k^ݵkW͖-[V\a}?u\w8'X%hϞEQtpX,F2DErsshoo}g_OMM~?T>q8y;66L&ZQQv"ñIT{֭[R 8p̽K555IN\b hZv˪M:t(.‡@RjʎOOѺҵc=Obdd$Օ>uTPQQݕv8^`~8 xqӦM\ѣGmذ&bkT߯( Z sR~♙{HlNNNY[[Q84`Mss󻕕wckkWg-[Iab.,,`Pu:ϯZ8>>AϺUU5ꛚ^ BZb% 4M`xxXK$/NQdYfrrRKRNCUURTj4'& Hii-I\AAA*z}Ĭ,"{LMM+V[}}}m^~Eٳg߿J[gg;zŘU;z{ѨP__B$AE[cO[Nؽ{+^pXX,dD_{;30 ].lGQnww1d4ωq̙ĉ'];w&'ZgwHjlvR(ի?dbvvFko|d,SW^߾}n%_EѓMsvojWX)ȲLoo/GlO 1A4E!s wڎ @H`nRmqEe~t:YUUrrY "?R$Iq' 2cٍ7~|-_PIvYx0gWLt0nf|,Sk4bx #include // QRegularExpression exact match pattern wrapper. #if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) #define EXACT_PATTERN(s) ('^' + s + '$') #else #define EXACT_PATTERN(s) QRegularExpression::anchoredPattern(s) #endif //---------------------------------------------------------------------- // class qjackctlAliasItem -- Client/port item alias map. // Constructor. qjackctlAliasItem::qjackctlAliasItem ( const QString& sClientName, const QString& sClientAlias ) { if (sClientAlias.isEmpty()) { m_rxClientName.setPattern(EXACT_PATTERN(escapeRegExpDigits(sClientName))); m_sClientAlias = sClientName; } else { m_rxClientName.setPattern(EXACT_PATTERN(sClientName)); m_sClientAlias = sClientAlias; } } // Default destructor. qjackctlAliasItem::~qjackctlAliasItem (void) { m_ports.clear(); } // Client name method. QString qjackctlAliasItem::clientName (void) const { return m_rxClientName.pattern(); } // Client name matcher. bool qjackctlAliasItem::matchClientName ( const QString& sClientName ) const { return m_rxClientName.match(sClientName).hasMatch(); } // Client aliasing methods. const QString& qjackctlAliasItem::clientAlias (void) const { return m_sClientAlias; } void qjackctlAliasItem::setClientAlias ( const QString& sClientAlias ) { m_sClientAlias = sClientAlias; } // Port aliasing methods. QString qjackctlAliasItem::portAlias ( const QString& sPortName ) const { return m_ports.value(sPortName, sPortName); } void qjackctlAliasItem::setPortAlias ( const QString& sPortName, const QString& sPortAlias ) { if (sPortAlias.isEmpty()) m_ports.remove(sPortName); else m_ports.insert(sPortName, sPortAlias); } // Save client/port aliases definitions. void qjackctlAliasItem::saveSettings ( QSettings& settings, const QString& sClientKey ) { settings.beginGroup(sClientKey); settings.setValue("/Name", m_rxClientName.pattern()); settings.setValue("/Alias", m_sClientAlias); int iPort = 0; QMap::ConstIterator iter = m_ports.constBegin(); const QMap::ConstIterator& iter_end = m_ports.constEnd(); for ( ; iter != iter_end; ++iter) { const QString& sPortName = iter.key(); const QString& sPortAlias = iter.value(); if (!sPortName.isEmpty() && !sPortAlias.isEmpty()) { settings.beginGroup("/Port" + QString::number(++iPort)); settings.setValue("/Name", sPortName); settings.setValue("/Alias", sPortAlias); settings.endGroup(); } } settings.endGroup(); } // Escape and format a string as a regular expresion. QString qjackctlAliasItem::escapeRegExpDigits ( const QString& s, int iThreshold ) { const QString& sEscape = QRegularExpression::escape(s); QString sDigits; QString sResult; int iDigits = 0; for (int i = 0; i < sEscape.length(); i++) { const QChar& ch = sEscape.at(i); if (ch.isDigit()) { if (iDigits < iThreshold) sDigits += ch; else sDigits = "[0-9]+"; iDigits++; } else { if (iDigits > 0) { sResult += sDigits; sDigits.clear(); iDigits = 0; } sResult += ch; } } if (iDigits > 0) sResult += sDigits; return sResult; } // Need for generic sort. bool qjackctlAliasItem::operator< ( const qjackctlAliasItem& other ) { return (m_sClientAlias < other.clientAlias()); } //---------------------------------------------------------------------- // class qjackctlAliasList -- Client/port list alias map. // Constructor. qjackctlAliasList::qjackctlAliasList (void) { } // Default destructor. qjackctlAliasList::~qjackctlAliasList (void) { qDeleteAll(*this); clear(); } // Client finders. qjackctlAliasItem *qjackctlAliasList::findClientName ( const QString& sClientName ) { QListIterator iter(*this); while (iter.hasNext()) { qjackctlAliasItem *pClient = iter.next(); if (pClient->matchClientName(sClientName)) return pClient; } return nullptr; } // Client aliasing methods. void qjackctlAliasList::setClientAlias ( const QString& sClientName, const QString& sClientAlias ) { qjackctlAliasItem *pClient = findClientName(sClientName); if (pClient == nullptr) { pClient = new qjackctlAliasItem(sClientName); append(pClient); } pClient->setClientAlias(sClientAlias); } QString qjackctlAliasList::clientAlias ( const QString& sClientName ) { qjackctlAliasItem *pClient = findClientName(sClientName); if (pClient == nullptr) return sClientName; return pClient->clientAlias(); } // Client/port aliasing methods. void qjackctlAliasList::setPortAlias ( const QString& sClientName, const QString& sPortName, const QString& sPortAlias ) { qjackctlAliasItem *pClient = findClientName(sClientName); if (pClient == nullptr) { pClient = new qjackctlAliasItem(sClientName); append(pClient); } pClient->setPortAlias(sPortName, sPortAlias); } QString qjackctlAliasList::portAlias ( const QString& sClientName, const QString& sPortName ) { qjackctlAliasItem *pClient = findClientName(sClientName); if (pClient == nullptr) return sPortName; return pClient->portAlias(sPortName); } // Load/save aliases definitions. void qjackctlAliasList::loadSettings ( QSettings& settings, const QString& sAliasesKey ) { clear(); settings.beginGroup(sAliasesKey); QStringListIterator client_iter(settings.childGroups()); while (client_iter.hasNext()) { const QString& sClientKey = client_iter.next(); const QString& sClientName = settings.value(sClientKey + "/Name").toString(); const QString& sClientAlias = settings.value(sClientKey + "/Alias").toString(); if (!sClientName.isEmpty() && !sClientAlias.isEmpty()) { qjackctlAliasItem *pClient = new qjackctlAliasItem(sClientName, sClientAlias); append(pClient); settings.beginGroup(sClientKey); QStringListIterator port_iter(settings.childGroups()); while (port_iter.hasNext()) { const QString& sPortKey = port_iter.next(); const QString& sPortName = settings.value(sPortKey + "/Name").toString(); const QString& sPortAlias = settings.value(sPortKey + "/Alias").toString(); if (!sPortName.isEmpty() && !sPortAlias.isEmpty()) pClient->setPortAlias(sPortName, sPortAlias); } settings.endGroup(); } } settings.endGroup(); } void qjackctlAliasList::saveSettings ( QSettings& settings, const QString& sAliasesKey ) { std::sort(begin(), end()); settings.beginGroup(sAliasesKey); int iClient = 0; QListIterator iter(*this); while (iter.hasNext()) { (iter.next())->saveSettings(settings, "Client" + QString::number(++iClient)); } settings.endGroup(); } // end of qjackctlAliases.cpp qjackctl-1.0.4/src/PaxHeaders/qjackctlGraph.cpp0000644000000000000000000000013214771215054016445 xustar0030 mtime=1743067692.324636588 30 atime=1743067692.324636588 30 ctime=1743067692.324636588 qjackctl-1.0.4/src/qjackctlGraph.cpp0000644000175000001440000022564214771215054016450 0ustar00rncbcusers// qjackctlGraph.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAbout.h" #include "qjackctlGraph.h" #include "qjackctlGraphCommand.h" #include "qjackctlAliases.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //---------------------------------------------------------------------------- // qjackctlGraphItem -- Base graphics item. // Constructor. qjackctlGraphItem::qjackctlGraphItem ( QGraphicsItem *parent ) : QGraphicsPathItem(parent), m_marked(false), m_hilite(false) { const QPalette pal; m_foreground = pal.buttonText().color(); m_background = pal.button().color(); } // Basic color accessors. void qjackctlGraphItem::setForeground ( const QColor& color ) { m_foreground = color; } const QColor& qjackctlGraphItem::foreground (void) const { return m_foreground; } void qjackctlGraphItem::setBackground ( const QColor& color ) { m_background = color; } const QColor& qjackctlGraphItem::background (void) const { return m_background; } // Marking methods. void qjackctlGraphItem::setMarked ( bool marked ) { m_marked = marked; } bool qjackctlGraphItem::isMarked (void) const { return m_marked; } // Highlighting methods. void qjackctlGraphItem::setHighlight ( bool hilite ) { m_hilite = hilite; if (m_hilite) raise(); QGraphicsPathItem::update(); } bool qjackctlGraphItem::isHighlight (void) const { return m_hilite; } // Raise item z-value (dynamic always-on-top). void qjackctlGraphItem::raise (void) { static qreal s_zvalue = 0.0; switch (type()) { case qjackctlGraphPort::Type: { QGraphicsPathItem::setZValue(s_zvalue += 0.003); qjackctlGraphPort *port = static_cast (this); if (port) { qjackctlGraphNode *node = port->portNode(); if (node) node->setZValue(s_zvalue += 0.002); } break; } case qjackctlGraphConnect::Type: default: QGraphicsPathItem::setZValue(s_zvalue += 0.001); break; } } // Item-type hash (static) uint qjackctlGraphItem::itemType ( const QByteArray& type_name ) { return qHash(type_name); } // Rectangular editor extents (virtual) QRectF qjackctlGraphItem::editorRect (void) const { return QRectF(); } // Path and bounding rectangle override. void qjackctlGraphItem::setPath ( const QPainterPath& path ) { m_rect = path.controlPointRect(); QGraphicsPathItem::setPath(path); } // Bounding rectangle accessor. const QRectF& qjackctlGraphItem::itemRect (void) const { return m_rect; } //---------------------------------------------------------------------------- // qjackctlGraphPort -- Port graphics item. // Constructor. qjackctlGraphPort::qjackctlGraphPort ( qjackctlGraphNode *node, const QString& name, qjackctlGraphItem::Mode mode, uint type ) : qjackctlGraphItem(node), m_node(node), m_name(name), m_mode(mode), m_type(type), m_index(node->ports().count()), m_selectx(0), m_hilitex(0) { QGraphicsPathItem::setZValue(+1.0); const QPalette pal; setForeground(pal.buttonText().color()); setBackground(pal.button().color()); m_text = new QGraphicsTextItem(this); QGraphicsPathItem::setFlag(QGraphicsItem::ItemIsSelectable); QGraphicsPathItem::setFlag(QGraphicsItem::ItemSendsScenePositionChanges); QGraphicsPathItem::setAcceptHoverEvents(true); QGraphicsPathItem::setToolTip(m_name); setPortTitle(m_name); } // Destructor. qjackctlGraphPort::~qjackctlGraphPort (void) { removeConnects(); // No actual need to destroy any children here... // //delete m_text; } // Accessors. qjackctlGraphNode *qjackctlGraphPort::portNode (void) const { return m_node; } void qjackctlGraphPort::setPortName ( const QString& name ) { m_name = name; QGraphicsPathItem::setToolTip(m_name); } const QString& qjackctlGraphPort::portName (void) const { return m_name; } void qjackctlGraphPort::setPortMode ( qjackctlGraphItem::Mode mode ) { m_mode = mode; } qjackctlGraphItem::Mode qjackctlGraphPort::portMode (void) const { return m_mode; } bool qjackctlGraphPort::isInput (void) const { return (m_mode & Input); } bool qjackctlGraphPort::isOutput (void) const { return (m_mode & Output); } void qjackctlGraphPort::setPortType ( uint type ) { m_type = type; } uint qjackctlGraphPort::portType (void) const { return m_type; } void qjackctlGraphPort::setPortTitle ( const QString& title ) { m_title = (title.isEmpty() ? m_name : title); static const int MAX_TITLE_LENGTH = 29; static const QString ellipsis(3, '.'); QString text = m_title.simplified(); if (text.length() >= MAX_TITLE_LENGTH + ellipsis.length()) text = ellipsis + text.right(MAX_TITLE_LENGTH).trimmed(); m_text->setPlainText(text); QPainterPath path; const QRectF& rect = m_text->boundingRect().adjusted(0, +2, 0, -2); path.addRoundedRect(rect, 5, 5); /*QGraphicsPathItem::*/setPath(path); } const QString& qjackctlGraphPort::portTitle (void) const { return m_title; } void qjackctlGraphPort::setPortIndex ( int index ) { m_index = index; } int qjackctlGraphPort::portIndex (void) const { return m_index; } QPointF qjackctlGraphPort::portPos (void) const { QPointF pos = QGraphicsPathItem::scenePos(); const QRectF& rect = itemRect(); if (m_mode == Output) pos.setX(pos.x() + rect.width()); pos.setY(pos.y() + rect.height() / 2); return pos; } // Connection-list methods. void qjackctlGraphPort::appendConnect ( qjackctlGraphConnect *connect ) { m_connects.append(connect); } void qjackctlGraphPort::removeConnect ( qjackctlGraphConnect *connect ) { m_connects.removeAll(connect); } void qjackctlGraphPort::removeConnects (void) { foreach (qjackctlGraphConnect *connect, m_connects) { if (connect->port1() != this) connect->setPort1(nullptr); if (connect->port2() != this) connect->setPort2(nullptr); } // Do not delete connects here as they are owned elsewhere... // // qDeleteAll(m_connects); m_connects.clear(); } qjackctlGraphConnect *qjackctlGraphPort::findConnect ( qjackctlGraphPort *port ) const { foreach (qjackctlGraphConnect *connect, m_connects) { if (connect->port1() == port || connect->port2() == port) return connect; } return nullptr; } // Connect-list accessor. const QList& qjackctlGraphPort::connects (void) const { return m_connects; } void qjackctlGraphPort::paint ( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget */*widget*/ ) { const QPalette& pal = option->palette; const QRectF& port_rect = itemRect(); QLinearGradient port_grad(0, port_rect.top(), 0, port_rect.bottom()); QColor port_color; if (QGraphicsPathItem::isSelected()) { m_text->setDefaultTextColor(pal.highlightedText().color()); painter->setPen(pal.highlightedText().color()); port_color = pal.highlight().color(); } else { const QColor& foreground = qjackctlGraphItem::foreground(); const QColor& background = qjackctlGraphItem::background(); const bool is_dark = (background.value() < 128); m_text->setDefaultTextColor(is_dark ? foreground.lighter() : foreground.darker()); if (qjackctlGraphItem::isHighlight() || QGraphicsPathItem::isUnderMouse()) { painter->setPen(foreground.lighter()); port_color = background.lighter(); } else { painter->setPen(foreground); port_color = background; } } port_grad.setColorAt(0.0, port_color); port_grad.setColorAt(1.0, port_color.darker(120)); painter->setBrush(port_grad); painter->drawPath(QGraphicsPathItem::path()); } QVariant qjackctlGraphPort::itemChange ( GraphicsItemChange change, const QVariant& value ) { if (change == QGraphicsItem::ItemScenePositionHasChanged) { foreach (qjackctlGraphConnect *connect, m_connects) { connect->updatePath(); } } else if (change == QGraphicsItem::ItemSelectedHasChanged && m_selectx < 1) { const bool is_selected = value.toBool(); setHighlightEx(is_selected); foreach (qjackctlGraphConnect *connect, m_connects) connect->setSelectedEx(this, is_selected); } return value; } // Selection propagation method... void qjackctlGraphPort::setSelectedEx ( bool is_selected ) { if (!is_selected) { foreach (qjackctlGraphConnect *connect, m_connects) { if (connect->isSelected()) { setHighlightEx(true); return; } } } ++m_selectx; setHighlightEx(is_selected); if (QGraphicsPathItem::isSelected() != is_selected) QGraphicsPathItem::setSelected(is_selected); --m_selectx; } // Highlighting propagation method... void qjackctlGraphPort::setHighlightEx ( bool is_highlight ) { if (m_hilitex > 0) return; ++m_hilitex; qjackctlGraphItem::setHighlight(is_highlight); foreach (qjackctlGraphConnect *connect, m_connects) connect->setHighlightEx(this, is_highlight); --m_hilitex; } // Special port-type color business. void qjackctlGraphPort::updatePortTypeColors ( qjackctlGraphCanvas *canvas ) { if (canvas) { const QColor& color = canvas->portTypeColor(m_type); if (color.isValid()) { const bool is_dark = (color.value() < 128); qjackctlGraphItem::setForeground(is_dark ? color.lighter(180) : color.darker()); qjackctlGraphItem::setBackground(color); if (m_mode & Output) { foreach (qjackctlGraphConnect *connect, m_connects) { connect->updatePortTypeColors(); connect->update(); } } } } } // Port sorting type. qjackctlGraphPort::SortType qjackctlGraphPort::g_sort_type = qjackctlGraphPort::PortName; void qjackctlGraphPort::setSortType ( SortType sort_type ) { g_sort_type = sort_type; } qjackctlGraphPort::SortType qjackctlGraphPort::sortType (void) { return g_sort_type; } // Port sorting order. qjackctlGraphPort::SortOrder qjackctlGraphPort::g_sort_order = qjackctlGraphPort::Ascending; void qjackctlGraphPort::setSortOrder( SortOrder sort_order ) { g_sort_order = sort_order; } qjackctlGraphPort::SortOrder qjackctlGraphPort::sortOrder (void) { return g_sort_order; } // Natural decimal sorting comparator (static) bool qjackctlGraphPort::lessThan ( qjackctlGraphPort *port1, qjackctlGraphPort *port2 ) { const int port_type_diff = int(port1->portType()) - int(port2->portType()); if (port_type_diff) return (port_type_diff > 0); if (g_sort_order == Descending) { qjackctlGraphPort *port = port1; port1 = port2; port2 = port; } if (g_sort_type == PortIndex) { const int port_index_diff = port1->portIndex() - port2->portIndex(); if (port_index_diff) return (port_index_diff < 0); } switch (g_sort_type) { case PortTitle: return qjackctlGraphPort::lessThan(port1->portTitle(), port2->portTitle()); case PortName: default: return qjackctlGraphPort::lessThan(port1->portName(), port2->portName()); } } bool qjackctlGraphPort::lessThan ( const QString& s1, const QString& s2 ) { const int n1 = s1.length(); const int n2 = s2.length(); int i1, i2; for (i1 = i2 = 0; i1 < n1 && i2 < n2; ++i1, ++i2) { // Skip (white)spaces... while (s1.at(i1).isSpace()) ++i1; while (s2.at(i2).isSpace()) ++i2; // Normalize (to uppercase) the next characters... QChar c1 = s1.at(i1).toUpper(); QChar c2 = s2.at(i2).toUpper(); if (c1.isDigit() && c2.isDigit()) { // Find the whole length numbers... int j1 = i1++; while (i1 < n1 && s1.at(i1).isDigit()) ++i1; int j2 = i2++; while (i2 < n2 && s2.at(i2).isDigit()) ++i2; // Compare as natural decimal-numbers... j1 = s1.mid(j1, i1 - j1).toInt(); j2 = s2.mid(j2, i2 - j2).toInt(); if (j1 != j2) return (j1 < j2); // Never go out of bounds... if (i1 >= n1 || i2 >= n2) break; // Go on with this next char... c1 = s1.at(i1).toUpper(); c2 = s2.at(i2).toUpper(); } // Compare this char... if (c1 != c2) return (c1 < c2); } // Probable exact match. return false; } // Rectangular editor extents. QRectF qjackctlGraphPort::editorRect (void) const { return QGraphicsPathItem::sceneBoundingRect(); } //---------------------------------------------------------------------------- // qjackctlGraphNode -- Node graphics item. // Constructor. qjackctlGraphNode::qjackctlGraphNode ( const QString& name, qjackctlGraphItem::Mode mode, uint type ) : qjackctlGraphItem(nullptr), m_name(name), m_mode(mode), m_type(type) { QGraphicsPathItem::setZValue(0.0); const QPalette pal; const int base_value = pal.base().color().value(); const bool is_dark = (base_value < 128); const QColor& text_color = pal.text().color(); QColor foreground_color(is_dark ? text_color.darker() : text_color); qjackctlGraphItem::setForeground(foreground_color); const QColor& window_color = pal.window().color(); QColor background_color(is_dark ? window_color.lighter() : window_color); background_color.setAlpha(160); qjackctlGraphItem::setBackground(background_color); m_pixmap = new QGraphicsPixmapItem(this); m_text = new QGraphicsTextItem(this); QGraphicsPathItem::setFlag(QGraphicsItem::ItemIsMovable); QGraphicsPathItem::setFlag(QGraphicsItem::ItemIsSelectable); QGraphicsPathItem::setToolTip(m_name); setNodeTitle(m_name); const bool is_darkest = (base_value < 24); QColor shadow_color = (is_darkest ? Qt::white : Qt::black); shadow_color.setAlpha(180); QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect(); effect->setColor(shadow_color); effect->setBlurRadius(is_darkest ? 8 : 16); effect->setOffset(is_darkest ? 0 : 2); QGraphicsPathItem::setGraphicsEffect(effect); qjackctlGraphItem::raise(); } // Destructor. qjackctlGraphNode::~qjackctlGraphNode (void) { removePorts(); // No actual need to destroy any children here... // //QGraphicsPathItem::setGraphicsEffect(nullptr); // delete m_text; // delete m_pixmap; } // accessors. void qjackctlGraphNode::setNodeName ( const QString& name ) { m_name = name; QGraphicsPathItem::setToolTip(m_name); } const QString& qjackctlGraphNode::nodeName (void) const { return m_name; } void qjackctlGraphNode::setNodeMode ( qjackctlGraphItem::Mode mode ) { m_mode = mode; } qjackctlGraphItem::Mode qjackctlGraphNode::nodeMode (void) const { return m_mode; } void qjackctlGraphNode::setNodeType ( uint type ) { m_type = type; } uint qjackctlGraphNode::nodeType (void) const { return m_type; } void qjackctlGraphNode::setNodeIcon ( const QIcon& icon ) { m_icon = icon; m_pixmap->setPixmap(m_icon.pixmap(24, 24)); } const QIcon& qjackctlGraphNode::nodeIcon (void) const { return m_icon; } void qjackctlGraphNode::setNodeTitle ( const QString& title ) { const QFont& font = m_text->font(); m_text->setFont(QFont(font.family(), font.pointSize(), QFont::Bold)); m_title = (title.isEmpty() ? m_name : title); static const int MAX_TITLE_LENGTH = 29; static const QString ellipsis(3, '.'); QString text = m_title.simplified(); if (text.length() >= MAX_TITLE_LENGTH + ellipsis.length()) text = text.left(MAX_TITLE_LENGTH).trimmed() + ellipsis; m_text->setPlainText(text); } QString qjackctlGraphNode::nodeTitle (void) const { return m_title; // m_text->toPlainText(); } // Port-list methods. qjackctlGraphPort *qjackctlGraphNode::addPort ( const QString& name, qjackctlGraphItem::Mode mode, int type ) { qjackctlGraphPort *port = new qjackctlGraphPort(this, name, mode, type); m_ports.append(port); m_portkeys.insert(qjackctlGraphPort::PortKey(port), port); updatePath(); return port; } qjackctlGraphPort *qjackctlGraphNode::addInputPort ( const QString& name, int type ) { return addPort(name, qjackctlGraphItem::Input, type); } qjackctlGraphPort *qjackctlGraphNode::addOutputPort ( const QString& name, int type ) { return addPort(name, qjackctlGraphItem::Output, type); } void qjackctlGraphNode::removePort ( qjackctlGraphPort *port ) { m_portkeys.remove(qjackctlGraphPort::PortKey(port)); m_ports.removeAll(port); updatePath(); } void qjackctlGraphNode::removePorts (void) { foreach (qjackctlGraphPort *port, m_ports) port->removeConnects(); // Do not delete ports here as they are node's child items... // //qDeleteAll(m_ports); m_ports.clear(); m_portkeys.clear(); } // Port finder (by name, mode and type) qjackctlGraphPort *qjackctlGraphNode::findPort ( const QString& name, qjackctlGraphItem::Mode mode, uint type ) { return static_cast ( m_portkeys.value(qjackctlGraphPort::ItemKey(name, mode, type), nullptr)); } // Port-list accessor. const QList& qjackctlGraphNode::ports (void) const { return m_ports; } // Reset port markings, destroy if unmarked. void qjackctlGraphNode::resetMarkedPorts (void) { QList ports; foreach (qjackctlGraphPort *port, m_ports) { if (port->isMarked()) { port->setMarked(false); } else { ports.append(port); } } foreach (qjackctlGraphPort *port, ports) { port->removeConnects(); removePort(port); delete port; } } // Path/shape updater. void qjackctlGraphNode::updatePath (void) { const QRectF& rect = m_text->boundingRect(); int width = rect.width() / 2 + 24; int wi, wo; wi = wo = width; foreach (qjackctlGraphPort *port, m_ports) { const int w = port->itemRect().width(); if (port->isOutput()) { if (wo < w) wo = w; } else { if (wi < w) wi = w; } } width = 4 * ((wi + wo) / 4); std::sort(m_ports.begin(), m_ports.end(), qjackctlGraphPort::Compare()); int height = rect.height() + 2; int type = 0; int yi, yo; yi = yo = height; foreach (qjackctlGraphPort *port, m_ports) { const QRectF& port_rect = port->itemRect(); const int w = port_rect.width(); const int h = port_rect.height() + 1; if (type - port->portType()) { type = port->portType(); height += 2; yi = yo = height; } if (port->isOutput()) { port->setPos(width + 6 - w, yo); yo += h; if (height < yo) height = yo; } else { port->setPos(-6, yi); yi += h; if (height < yi) height = yi; } } QPainterPath path; path.addRoundedRect(0, 0, width, height + 6, 5, 5); /*QGraphicsPathItem::*/setPath(path); } void qjackctlGraphNode::paint ( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget */*widget*/ ) { const QPalette& pal = option->palette; const QRectF& node_rect = itemRect(); QLinearGradient node_grad(0, node_rect.top(), 0, node_rect.bottom()); QColor node_color; if (QGraphicsPathItem::isSelected()) { const QColor& hilitetext_color = pal.highlightedText().color(); m_text->setDefaultTextColor(hilitetext_color); painter->setPen(hilitetext_color); node_color = pal.highlight().color(); } else { const QColor& foreground = qjackctlGraphItem::foreground(); const QColor& background = qjackctlGraphItem::background(); const bool is_dark = (background.value() < 192); m_text->setDefaultTextColor(is_dark ? foreground.lighter() : foreground.darker()); painter->setPen(foreground); node_color = background; } node_color.setAlpha(180); node_grad.setColorAt(0.6, node_color); node_grad.setColorAt(1.0, node_color.darker(120)); painter->setBrush(node_grad); painter->drawPath(QGraphicsPathItem::path()); m_pixmap->setPos(node_rect.x() + 4, node_rect.y() + 4); const QRectF& text_rect = m_text->boundingRect(); const qreal w2 = (node_rect.width() - text_rect.width()) / 2; m_text->setPos(node_rect.x() + w2 + 4, node_rect.y() + 2); } QVariant qjackctlGraphNode::itemChange ( GraphicsItemChange change, const QVariant& value ) { if (change == QGraphicsItem::ItemSelectedHasChanged) { const bool is_selected = value.toBool(); foreach (qjackctlGraphPort *port, m_ports) port->setSelected(is_selected); } return value; } // Rectangular editor extents. QRectF qjackctlGraphNode::editorRect (void) const { return m_text->sceneBoundingRect(); } //---------------------------------------------------------------------------- // qjackctlGraphConnect -- Connection-line graphics item. // Constructor. qjackctlGraphConnect::qjackctlGraphConnect (void) : qjackctlGraphItem(nullptr), m_port1(nullptr), m_port2(nullptr) { QGraphicsPathItem::setZValue(-1.0); QGraphicsPathItem::setFlag(QGraphicsItem::ItemIsSelectable); qjackctlGraphItem::setBackground(qjackctlGraphItem::foreground()); #if 0//Disable drop-shadow effect... const QPalette pal; const bool is_darkest = (pal.base().color().value() < 24); QColor shadow_color = (is_darkest ? Qt::white : Qt::black); shadow_color.setAlpha(220); QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect(); effect->setColor(shadow_color); effect->setBlurRadius(is_darkest ? 4 : 8); effect->setOffset(is_darkest ? 0 : 1); QGraphicsPathItem::setGraphicsEffect(effect); #endif QGraphicsPathItem::setAcceptHoverEvents(true); qjackctlGraphItem::raise(); } // Destructor. qjackctlGraphConnect::~qjackctlGraphConnect (void) { // No actual need to destroy any children here... // //QGraphicsPathItem::setGraphicsEffect(nullptr); } // Accessors. void qjackctlGraphConnect::setPort1 ( qjackctlGraphPort *port ) { if (m_port1) m_port1->removeConnect(this); m_port1 = port; if (m_port1) m_port1->appendConnect(this); if (m_port1 && m_port1->isSelected()) setSelectedEx(m_port1, true); } qjackctlGraphPort *qjackctlGraphConnect::port1 (void) const { return m_port1; } void qjackctlGraphConnect::setPort2 ( qjackctlGraphPort *port ) { if (m_port2) m_port2->removeConnect(this); m_port2 = port; if (m_port2) m_port2->appendConnect(this); if (m_port2 && m_port2->isSelected()) setSelectedEx(m_port2, true); } qjackctlGraphPort *qjackctlGraphConnect::port2 (void) const { return m_port2; } // Active disconnection. void qjackctlGraphConnect::disconnect (void) { if (m_port1) { m_port1->removeConnect(this); m_port1 = nullptr; } if (m_port2) { m_port2->removeConnect(this); m_port2 = nullptr; } } // Path/shaper updaters. void qjackctlGraphConnect::updatePathTo ( const QPointF& pos ) { const bool is_out0 = m_port1->isOutput(); const QPointF pos0 = m_port1->portPos(); const QPointF d1(1.0, 0.0); const QPointF pos1 = (is_out0 ? pos0 + d1 : pos - d1); const QPointF pos4 = (is_out0 ? pos - d1 : pos0 + d1); const QPointF d2(2.0, 0.0); const QPointF pos1_2(is_out0 ? pos1 + d2 : pos1 - d2); const QPointF pos3_4(is_out0 ? pos4 - d2 : pos4 + d2); qjackctlGraphNode *node1 = m_port1->portNode(); const QRectF& rect1 = node1->itemRect(); const qreal h1 = 0.5 * rect1.height(); const qreal dh = pos0.y() - node1->scenePos().y() - h1; const qreal dx = pos3_4.x() - pos1_2.x(); const qreal x_max = rect1.width() + h1; const qreal x_min = qMin(x_max, qAbs(dx)); const qreal x_offset = (dx > 0.0 ? 0.5 : 1.0) * x_min; qreal y_offset = 0.0; if (g_connect_through_nodes) { // New "normal" connection line curves (inside/through nodes)... const qreal h2 = m_port1->itemRect().height(); const qreal dy = qAbs(pos3_4.y() - pos1_2.y()); y_offset = (dx > -h2 || dy > h2 ? 0.0 : (dh > 0.0 ? +h2 : -h2)); } else { // Old "weird" connection line curves (outside/around nodes)... y_offset = (dx > 0.0 ? 0.0 : (dh > 0.0 ? +x_min : -x_min)); } const QPointF pos2(pos1.x() + x_offset, pos1.y() + y_offset); const QPointF pos3(pos4.x() - x_offset, pos4.y() + y_offset); QPainterPath path; path.moveTo(pos1); path.lineTo(pos1_2); path.cubicTo(pos2, pos3, pos3_4); path.lineTo(pos4); const qreal arrow_angle = path.angleAtPercent(0.5) * M_PI / 180.0; const QPointF arrow_pos0 = path.pointAtPercent(0.5); const qreal arrow_size = 8.0; QVector arrow; arrow.append(arrow_pos0); arrow.append(arrow_pos0 - QPointF( ::sin(arrow_angle + M_PI / 2.25) * arrow_size, ::cos(arrow_angle + M_PI / 2.25) * arrow_size)); arrow.append(arrow_pos0 - QPointF( ::sin(arrow_angle + M_PI - M_PI / 2.25) * arrow_size, ::cos(arrow_angle + M_PI - M_PI / 2.25) * arrow_size)); arrow.append(arrow_pos0); path.addPolygon(QPolygonF(arrow)); /*QGraphicsPathItem::*/setPath(path); } void qjackctlGraphConnect::updatePath (void) { if (m_port2) updatePathTo(m_port2->portPos()); } void qjackctlGraphConnect::paint ( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget */*widget*/ ) { QColor color; if (QGraphicsPathItem::isSelected()) color = option->palette.highlight().color(); else if (qjackctlGraphItem::isHighlight() || QGraphicsPathItem::isUnderMouse()) color = qjackctlGraphItem::foreground().lighter(); else color = qjackctlGraphItem::foreground(); const QPalette pal; const bool is_darkest = (pal.base().color().value() < 24); QColor shadow_color = (is_darkest ? Qt::white : Qt::black); shadow_color.setAlpha(80); const QPainterPath& path = QGraphicsPathItem::path(); painter->setBrush(Qt::NoBrush); painter->setPen(QPen(shadow_color, 3)); painter->drawPath(path.translated(+1.0, +1.0)); painter->setPen(QPen(color, 2)); painter->drawPath(path); } QVariant qjackctlGraphConnect::itemChange ( GraphicsItemChange change, const QVariant& value ) { if (change == QGraphicsItem::ItemSelectedHasChanged) { const bool is_selected = value.toBool(); qjackctlGraphItem::setHighlight(is_selected); if (m_port1) m_port1->setSelectedEx(is_selected); if (m_port2) m_port2->setSelectedEx(is_selected); } return value; } QPainterPath qjackctlGraphConnect::shape (void) const { #if (QT_VERSION < QT_VERSION_CHECK(6, 1, 0)) && (__cplusplus < 201703L) return QGraphicsPathItem::shape(); #else const QPainterPathStroker stroker = QPainterPathStroker(QPen(QColor(), 2)); return stroker.createStroke(path()); #endif } // Selection propagation method... void qjackctlGraphConnect::setSelectedEx ( qjackctlGraphPort *port, bool is_selected ) { setHighlightEx(port, is_selected); if (QGraphicsPathItem::isSelected() != is_selected) { #if 0//OLD_SELECT_BEHAVIOR QGraphicsPathItem::setSelected(is_selected); if (is_selected) { if (m_port1 && m_port1 != port) m_port1->setSelectedEx(is_selected); if (m_port2 && m_port2 != port) m_port2->setSelectedEx(is_selected); } #else if (!is_selected || (m_port1 && m_port2 && m_port1->isSelected() && m_port2->isSelected())) { QGraphicsPathItem::setSelected(is_selected); } #endif } } // Highlighting propagation method... void qjackctlGraphConnect::setHighlightEx ( qjackctlGraphPort *port, bool is_highlight ) { qjackctlGraphItem::setHighlight(is_highlight); if (m_port1 && m_port1 != port) m_port1->setHighlight(is_highlight); if (m_port2 && m_port2 != port) m_port2->setHighlight(is_highlight); } // Special port-type color business. void qjackctlGraphConnect::updatePortTypeColors (void) { if (m_port1) { const QColor& color = m_port1->background().lighter(); qjackctlGraphItem::setForeground(color); qjackctlGraphItem::setBackground(color); } } // Connector curve draw style (through vs. around nodes) // bool qjackctlGraphConnect::g_connect_through_nodes = false; void qjackctlGraphConnect::setConnectThroughNodes ( bool on ) { g_connect_through_nodes = on; } bool qjackctlGraphConnect::isConnectThroughNodes (void) { return g_connect_through_nodes; } //---------------------------------------------------------------------------- // qjackctlGraphCanvas -- Canvas graphics scene/view. // Local constants. static const char *CanvasGroup = "/GraphCanvas"; static const char *CanvasRectKey = "/CanvasRect"; static const char *CanvasZoomKey = "/CanvasZoom"; static const char *NodePosGroup = "/GraphNodePos"; static const char *ColorsGroup = "/GraphColors"; // Constructor. qjackctlGraphCanvas::qjackctlGraphCanvas ( QWidget *parent ) : QGraphicsView(parent), m_state(DragNone), m_item(nullptr), m_connect(nullptr), m_rubberband(nullptr), m_zoom(1.0), m_zoomrange(false), m_gesture(false), m_commands(nullptr), m_settings(nullptr), m_selected_nodes(0), m_repel_overlapping_nodes(false), m_rename_item(nullptr), m_rename_editor(nullptr), m_renamed(0), m_search_editor(nullptr), m_aliases(nullptr) { m_scene = new QGraphicsScene(); m_commands = new QUndoStack(); QGraphicsView::setScene(m_scene); QGraphicsView::setRenderHint(QPainter::Antialiasing); QGraphicsView::setRenderHint(QPainter::SmoothPixmapTransform); QGraphicsView::setResizeAnchor(QGraphicsView::NoAnchor); QGraphicsView::setDragMode(QGraphicsView::NoDrag); updatePalette(); m_rename_editor = new QLineEdit(this); m_rename_editor->setFrame(false); m_rename_editor->setEnabled(false); m_rename_editor->hide(); QObject::connect(m_rename_editor, SIGNAL(textChanged(const QString&)), SLOT(renameTextChanged(const QString&))); QObject::connect(m_rename_editor, SIGNAL(editingFinished()), SLOT(renameEditingFinished())); QGraphicsView::grabGesture(Qt::PinchGesture); m_search_editor = new QLineEdit(this); m_search_editor->setClearButtonEnabled(true); m_search_editor->setEnabled(false); m_search_editor->hide(); QObject::connect(m_search_editor, SIGNAL(textChanged(const QString&)), SLOT(searchTextChanged(const QString&))); QObject::connect(m_search_editor, SIGNAL(editingFinished()), SLOT(searchEditingFinished())); } // Destructor. qjackctlGraphCanvas::~qjackctlGraphCanvas (void) { clear(); delete m_search_editor; delete m_rename_editor; delete m_commands; delete m_scene; } // Accessors. QGraphicsScene *qjackctlGraphCanvas::scene (void) const { return m_scene; } QUndoStack *qjackctlGraphCanvas::commands (void) const { return m_commands; } void qjackctlGraphCanvas::setSettings ( QSettings *settings ) { m_settings = settings; } QSettings *qjackctlGraphCanvas::settings (void) const { return m_settings; } // Canvas methods. void qjackctlGraphCanvas::addItem ( qjackctlGraphItem *item ) { m_scene->addItem(item); if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node) { m_nodes.append(node); m_nodekeys.insert(qjackctlGraphNode::NodeKey(node), node); if (restoreNode(node)) emit updated(node); else emit added(node); } } } void qjackctlGraphCanvas::removeItem ( qjackctlGraphItem *item ) { clearSelection(); if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node && saveNode(node)) { emit removed(node); node->removePorts(); m_nodekeys.remove(qjackctlGraphNode::NodeKey(node)); m_nodes.removeAll(node); } } // Do not remove items from the scene // as they shall be removed upon delete... // // m_scene->removeItem(item); } // Current item accessor. qjackctlGraphItem *qjackctlGraphCanvas::currentItem (void) const { qjackctlGraphItem *item = m_item; if (item && item->type() == qjackctlGraphConnect::Type) item = nullptr; if (item == nullptr) { foreach (QGraphicsItem *item2, m_scene->selectedItems()) { if (item2->type() == qjackctlGraphConnect::Type) continue; item = static_cast (item2); if (item2->type() == qjackctlGraphNode::Type) break; } } return item; } // Connection predicates. bool qjackctlGraphCanvas::canConnect (void) const { int nins = 0; int nouts = 0; foreach (QGraphicsItem *item, m_scene->selectedItems()) { if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node) { if (node->nodeMode() & qjackctlGraphItem::Input) ++nins; else // if (node->nodeMode() & qjackctlGraphItem::Output) ++nouts; } } else if (item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port = static_cast (item); if (port) { if (port->isInput()) ++nins; else // if (port->isOutput()) ++nouts; } } if (nins > 0 && nouts > 0) return true; } return false; } bool qjackctlGraphCanvas::canDisconnect (void) const { foreach (QGraphicsItem *item, m_scene->selectedItems()) { switch (item->type()) { case qjackctlGraphConnect::Type: return true; case qjackctlGraphNode::Type: { qjackctlGraphNode *node = static_cast (item); foreach (qjackctlGraphPort *port, node->ports()) { if (!port->connects().isEmpty()) return true; } // Fall thru... } default: break; } } return false; } // Edit predicates. bool qjackctlGraphCanvas::canRenameItem (void) const { qjackctlGraphItem *item = currentItem(); return (item && ( item->type() == qjackctlGraphNode::Type || item->type() == qjackctlGraphPort::Type)); } bool qjackctlGraphCanvas::canSearchItem (void) const { return !m_nodes.isEmpty(); } // Zooming methods. void qjackctlGraphCanvas::setZoom ( qreal zoom ) { if (zoom < 0.1) zoom = 0.1; else if (zoom > 1.9) zoom = 1.9; const qreal scale = zoom / m_zoom; QGraphicsView::scale(scale, scale); QFont font = m_rename_editor->font(); font.setPointSizeF(scale * font.pointSizeF()); m_rename_editor->setFont(font); updateRenameEditor(); m_zoom = zoom; emit changed(); } qreal qjackctlGraphCanvas::zoom (void) const { return m_zoom; } void qjackctlGraphCanvas::setZoomRange ( bool zoomrange ) { m_zoomrange = zoomrange; } bool qjackctlGraphCanvas::isZoomRange (void) const { return m_zoomrange; } // Clean-up all un-marked nodes... void qjackctlGraphCanvas::resetNodes ( uint node_type ) { QList nodes; foreach (qjackctlGraphNode *node, m_nodes) { if (node->nodeType() == node_type) { if (node->isMarked()) { node->resetMarkedPorts(); node->setMarked(false); } else { nodes.append(node); } } } foreach (qjackctlGraphNode *node, nodes) removeItem(node); qDeleteAll(nodes); } void qjackctlGraphCanvas::clearNodes ( uint node_type ) { QList nodes; foreach (qjackctlGraphNode *node, m_nodes) { if (node->nodeType() == node_type) nodes.append(node); } foreach (qjackctlGraphNode *node, nodes) { m_nodekeys.remove(qjackctlGraphNode::NodeKey(node)); m_nodes.removeAll(node); } qDeleteAll(nodes); } // Special node finder. qjackctlGraphNode *qjackctlGraphCanvas::findNode ( const QString& name, qjackctlGraphItem::Mode mode, uint type ) const { return static_cast ( m_nodekeys.value(qjackctlGraphNode::ItemKey(name, mode, type), nullptr)); } // Whether it's in the middle of something... bool qjackctlGraphCanvas::isBusy (void) const { return (m_state != DragNone || m_connect != nullptr || m_item != nullptr || m_rename_item != nullptr); } // Port (dis)connections notifiers. void qjackctlGraphCanvas::emitConnected ( qjackctlGraphPort *port1, qjackctlGraphPort *port2 ) { emit connected(port1, port2); } void qjackctlGraphCanvas::emitDisconnected ( qjackctlGraphPort *port1, qjackctlGraphPort *port2 ) { emit disconnected(port1, port2); } // Rename notifier. void qjackctlGraphCanvas::emitRenamed ( qjackctlGraphItem *item, const QString& name ) { emit renamed(item, name); } // Other generic notifier. void qjackctlGraphCanvas::emitChanged (void) { emit changed(); } // Item finder (internal). qjackctlGraphItem *qjackctlGraphCanvas::itemAt ( const QPointF& pos ) const { const QList& items = m_scene->items(QRectF(pos - QPointF(2, 2), QSizeF(5, 5))); foreach (QGraphicsItem *item, items) { if (item->type() >= QGraphicsItem::UserType) return static_cast (item); } return nullptr; } // Port (dis)connection command. void qjackctlGraphCanvas::connectPorts ( qjackctlGraphPort *port1, qjackctlGraphPort *port2, bool is_connect ) { #if 0 // Sure the sect will check to this instead...? const bool is_connected // already connected? = (port1->findConnect(port2) != nullptr); if (( is_connect && is_connected) || (!is_connect && !is_connected)) return; #endif if (port1->isOutput()) { m_commands->push( new qjackctlGraphConnectCommand(this, port1, port2, is_connect)); } else { m_commands->push( new qjackctlGraphConnectCommand(this, port2, port1, is_connect)); } } // Mouse event handlers. void qjackctlGraphCanvas::mousePressEvent ( QMouseEvent *event ) { if (m_gesture) return; m_state = DragNone; m_item = nullptr; m_pos = QGraphicsView::mapToScene(event->pos()); if (event->button() == Qt::LeftButton) { m_item = itemAt(m_pos); m_state = DragStart; } if (m_item == nullptr && (((event->button() == Qt::LeftButton) && (event->modifiers() & Qt::ControlModifier)) || (event->button() == Qt::MiddleButton))) { #if 1//NEW_DRAG_SCROLL_MODE // HACK: When about to drag-scroll, // always fake a left-button press... QGraphicsView::setDragMode(ScrollHandDrag); QMouseEvent event2(event->type(), #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) event->position(), event->globalPosition(), #else event->localPos(), event->globalPos(), #endif Qt::LeftButton, Qt::LeftButton, event->modifiers() | Qt::ControlModifier); QGraphicsView::mousePressEvent(&event2); #else QGraphicsView::setCursor(Qt::ClosedHandCursor) #endif m_state = DragScroll; } } void qjackctlGraphCanvas::mouseMoveEvent ( QMouseEvent *event ) { if (m_gesture) return; int nchanged = 0; QPointF pos = QGraphicsView::mapToScene(event->pos()); switch (m_state) { case DragStart: if ((pos - m_pos).manhattanLength() > 8.0) { m_state = DragMove; if (m_item) { // Start new connection line... if (m_item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port = static_cast (m_item); if (port) { QGraphicsView::setCursor(Qt::DragLinkCursor); m_selected_nodes = 0; m_scene->clearSelection(); m_connect = new qjackctlGraphConnect(); m_connect->setPort1(port); m_connect->setSelected(true); m_connect->raise(); m_scene->addItem(m_connect); m_item = nullptr; ++m_selected_nodes; ++nchanged; } } else // Start moving nodes around... if (m_item->type() == qjackctlGraphNode::Type) { QGraphicsView::setCursor(Qt::SizeAllCursor); if (!m_item->isSelected()) { if ((event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) { m_selected_nodes = 0; m_scene->clearSelection(); } m_item->setSelected(true); ++nchanged; } // Original node position (for move command)... m_pos1 = snapPos(m_pos); } else m_item = nullptr; } // Otherwise start lasso rubber-banding... if (m_rubberband == nullptr && m_item == nullptr && m_connect == nullptr) { QGraphicsView::setCursor(Qt::CrossCursor); m_rubberband = new QRubberBand(QRubberBand::Rectangle, this); } // Set allowed auto-scroll margins/limits... boundingRect(true); } break; case DragMove: // Allow auto-scroll only if within allowed margins/limits... boundingPos(pos); QGraphicsView::ensureVisible(QRectF(pos, QSizeF(2, 2)), 8, 8); // Move new connection line... if (m_connect) m_connect->updatePathTo(pos); // Move rubber-band lasso... if (m_rubberband) { const QRect rect( QGraphicsView::mapFromScene(m_pos), QGraphicsView::mapFromScene(pos)); m_rubberband->setGeometry(rect.normalized()); m_rubberband->show(); if (!m_zoomrange) { if (event->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier)) { foreach (QGraphicsItem *item, m_selected) { item->setSelected(!item->isSelected()); ++nchanged; } m_selected.clear(); } else { m_selected_nodes = 0; m_scene->clearSelection(); ++nchanged; } const QRectF range_rect(m_pos, pos); foreach (QGraphicsItem *item, m_scene->items(range_rect.normalized())) { if (item->type() >= QGraphicsItem::UserType) { if (item->type() != qjackctlGraphNode::Type) ++m_selected_nodes; else if (m_selected_nodes > 0) continue; const bool is_selected = item->isSelected(); if (event->modifiers() & Qt::ControlModifier) { m_selected.append(item); item->setSelected(!is_selected); } else if (!is_selected) { if (event->modifiers() & Qt::ShiftModifier) m_selected.append(item); item->setSelected(true); } ++nchanged; } } } } // Move current selected nodes... if (m_item && m_item->type() == qjackctlGraphNode::Type) { pos = snapPos(pos); const QPointF delta = (pos - m_pos); foreach (QGraphicsItem *item, m_scene->selectedItems()) { if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node) node->setPos(snapPos(node->pos() + delta)); } } m_pos = pos; } else if (m_connect) { // Hovering ports high-lighting... const qreal zval = m_connect->zValue(); m_connect->setZValue(-1.0); QGraphicsItem *item = itemAt(pos); if (item && item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port1 = m_connect->port1(); qjackctlGraphPort *port2 = static_cast (item); if (port1 && port2 && port1->portType() == port2->portType() && port1->portMode() != port2->portMode()) { port2->update(); } } m_connect->setZValue(zval); } break; case DragScroll: { #if 1//NEW_DRAG_SCROLL_MODE QGraphicsView::mouseMoveEvent(event); #else QScrollBar *hbar = QGraphicsView::horizontalScrollBar(); QScrollBar *vbar = QGraphicsView::verticalScrollBar(); const QPoint delta = (pos - m_pos).toPoint(); hbar->setValue(hbar->value() - delta.x()); vbar->setValue(vbar->value() - delta.y()); m_pos = pos; #endif break; } default: break; } if (nchanged > 0) emit changed(); } void qjackctlGraphCanvas::mouseReleaseEvent ( QMouseEvent *event ) { if (m_gesture) return; int nchanged = 0; switch (m_state) { case DragStart: // Make individual item (de)selections... if ((event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) { m_selected_nodes = 0; m_scene->clearSelection(); ++nchanged; } if (m_item) { bool is_selected = true; if (event->modifiers() & Qt::ControlModifier) is_selected = !m_item->isSelected(); m_item->setSelected(is_selected); if (m_item->type() != qjackctlGraphNode::Type && is_selected) ++m_selected_nodes; m_item = nullptr; // Not needed anymore! ++nchanged; } // Fall thru... case DragMove: // Close new connection line... if (m_connect) { m_connect->setZValue(-1.0); const QPointF& pos = QGraphicsView::mapToScene(event->pos()); qjackctlGraphItem *item = itemAt(pos); if (item && item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port1 = m_connect->port1(); qjackctlGraphPort *port2 = static_cast (item); if (port1 && port2 // && port1->portNode() != port2->portNode() && port1->portMode() != port2->portMode() && port1->portType() == port2->portType() && port1->findConnect(port2) == nullptr) { port2->setSelected(true); #if 1 // Sure the sect will commit to this instead...? m_connect->setPort2(port2); m_connect->updatePortTypeColors(); m_connect->updatePathTo(port2->portPos()); emit connected(m_connect); m_connect = nullptr; ++m_selected_nodes; #else // m_selected_nodes = 0; // m_scene->clearSelection(); #endif // Submit command; notify eventual observers... m_commands->beginMacro(tr("Connect")); connectPorts(port1, port2, true); m_commands->endMacro(); ++nchanged; } } // Done with the hovering connection... if (m_connect) { m_connect->disconnect(); delete m_connect; m_connect = nullptr; } } // Maybe some node(s) were moved... if (m_item && m_item->type() == qjackctlGraphNode::Type) { const QPointF& pos = QGraphicsView::mapToScene(event->pos()); QList nodes; foreach (QGraphicsItem *item, m_scene->selectedItems()) { if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node) nodes.append(node); } } m_commands->push( new qjackctlGraphMoveCommand(this, nodes, m_pos1, m_pos)); ++nchanged; } // Close rubber-band lasso... if (m_rubberband) { delete m_rubberband; m_rubberband = nullptr; m_selected.clear(); // Zooming in range?... if (m_zoomrange) { const QRectF range_rect(m_pos, QGraphicsView::mapToScene(event->pos())); zoomFitRange(range_rect); nchanged = 0; } } break; case DragScroll: default: break; } #if 1//NEW_DRAG_SCROLL_MODE if (QGraphicsView::dragMode() == ScrollHandDrag) { QGraphicsView::mouseReleaseEvent(event); QGraphicsView::setDragMode(NoDrag); } #endif m_state = DragNone; m_item = nullptr; // Reset cursor... QGraphicsView::setCursor(Qt::ArrowCursor); if (nchanged > 0) emit changed(); } void qjackctlGraphCanvas::mouseDoubleClickEvent ( QMouseEvent *event ) { m_pos = QGraphicsView::mapToScene(event->pos()); m_item = itemAt(m_pos); if (m_item && canRenameItem()) { renameItem(); } else { QGraphicsView::centerOn(m_pos); } } void qjackctlGraphCanvas::wheelEvent ( QWheelEvent *event ) { if (event->modifiers() & Qt::ControlModifier) { const int delta #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) = event->delta(); #else = event->angleDelta().y(); #endif setZoom(zoom() + qreal(delta) / 1200.0); } else QGraphicsView::wheelEvent(event); } // Keyboard event handler. void qjackctlGraphCanvas::keyPressEvent ( QKeyEvent *event ) { if (event->key() == Qt::Key_Escape) { m_scene->clearSelection(); m_search_editor->editingFinished(); clear(); emit changed(); } else if (!m_search_editor->isEnabled() && (event->modifiers() & Qt::ControlModifier) == 0 && !event->text().trimmed().isEmpty()) { startSearchEditor(event->text()); } } // Connect selected items. void qjackctlGraphCanvas::connectItems (void) { QList outs; QList ins; foreach (QGraphicsItem *item, m_scene->selectedItems()) { if (item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port = static_cast (item); if (port) { if (port->isOutput()) outs.append(port); else ins.append(port); } } } if (outs.isEmpty() || ins.isEmpty()) return; // m_selected_nodes = 0; // m_scene->clearSelection(); std::sort(outs.begin(), outs.end(), qjackctlGraphPort::ComparePos()); std::sort(ins.begin(), ins.end(), qjackctlGraphPort::ComparePos()); QListIterator iter1(outs); QListIterator iter2(ins); m_commands->beginMacro(tr("Connect")); const int nports = qMax(outs.count(), ins.count()); for (int n = 0; n < nports; ++n) { // Wrap a'round... if (!iter1.hasNext()) iter1.toFront(); if (!iter2.hasNext()) iter2.toFront(); qjackctlGraphPort *port1 = iter1.next(); qjackctlGraphPort *port2 = iter2.next(); // Skip over non-matching port-types... bool wrapped = false; while (port1 && port2 && port1->portType() != port2->portType()) { if (!iter2.hasNext()) { if (wrapped) break; iter2.toFront(); wrapped = true; } port2 = iter2.next(); } // Submit command; notify eventual observers... if (!wrapped && port1 && port2 && port1->portNode() != port2->portNode()) connectPorts(port1, port2, true); } m_commands->endMacro(); } // Disconnect selected items. void qjackctlGraphCanvas::disconnectItems (void) { QList connects; QList nodes; foreach (QGraphicsItem *item, m_scene->selectedItems()) { switch (item->type()) { case qjackctlGraphConnect::Type: { qjackctlGraphConnect *connect = static_cast (item); if (!connects.contains(connect)) connects.append(connect); break; } case qjackctlGraphNode::Type: nodes.append(static_cast (item)); // Fall thru... default: break; } } if (connects.isEmpty()) { foreach (qjackctlGraphNode *node, nodes) { foreach (qjackctlGraphPort *port, node->ports()) { foreach (qjackctlGraphConnect *connect, port->connects()) { if (!connects.contains(connect)) connects.append(connect); } } } } if (connects.isEmpty()) return; // m_selected_nodes = 0; // m_scene->clearSelection(); m_item = nullptr; m_commands->beginMacro(tr("Disconnect")); foreach (qjackctlGraphConnect *connect, connects) { // Submit command; notify eventual observers... qjackctlGraphPort *port1 = connect->port1(); qjackctlGraphPort *port2 = connect->port2(); if (port1 && port2) connectPorts(port1, port2, false); } m_commands->endMacro(); } // Select actions. void qjackctlGraphCanvas::selectAll (void) { foreach (QGraphicsItem *item, m_scene->items()) { if (item->type() == qjackctlGraphNode::Type) item->setSelected(true); else ++m_selected_nodes; } emit changed(); } void qjackctlGraphCanvas::selectNone (void) { m_selected_nodes = 0; m_scene->clearSelection(); emit changed(); } void qjackctlGraphCanvas::selectInvert (void) { foreach (QGraphicsItem *item, m_scene->items()) { if (item->type() == qjackctlGraphNode::Type) item->setSelected(!item->isSelected()); else ++m_selected_nodes; } emit changed(); } // Edit actions. void qjackctlGraphCanvas::renameItem (void) { qjackctlGraphItem *item = currentItem(); if (item && item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node) { QPalette pal; const QColor& foreground = node->foreground(); QColor background = node->background(); const bool is_dark = (background.value() < 192); pal.setColor(QPalette::Text, is_dark ? foreground.lighter() : foreground.darker()); background.setAlpha(255); pal.setColor(QPalette::Base, background); m_rename_editor->setPalette(pal); QFont font = m_rename_editor->font(); font.setBold(true); m_rename_editor->setFont(font); m_rename_editor->setPlaceholderText(node->nodeName()); m_rename_editor->setText(node->nodeTitle()); } } else if (item && item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port = static_cast (item); if (port) { QPalette pal; const QColor& foreground = port->foreground(); const QColor& background = port->background(); const bool is_dark = (background.value() < 128); pal.setColor(QPalette::Text, is_dark ? foreground.lighter() : foreground.darker()); pal.setColor(QPalette::Base, background.lighter()); m_rename_editor->setPalette(pal); QFont font = m_rename_editor->font(); font.setBold(false); m_rename_editor->setFont(font); m_rename_editor->setPlaceholderText(port->portName()); m_rename_editor->setText(port->portTitle()); } } else return; m_selected_nodes = 0; m_scene->clearSelection(); m_rename_editor->show(); m_rename_editor->setEnabled(true); m_rename_editor->selectAll(); m_rename_editor->setFocus(); m_renamed = 0; m_rename_item = item; updateRenameEditor(); } void qjackctlGraphCanvas::searchItem (void) { if (!m_search_editor->isEnabled()) startSearchEditor(); } // Update editors position and size. void qjackctlGraphCanvas::updateRenameEditor (void) { if (m_rename_item && m_rename_editor->isEnabled() && m_rename_editor->isVisible()) { const QRectF& rect = m_rename_item->editorRect().adjusted(+2.0, +2.0, -2.0, -2.0); const QPoint& pos1 = QGraphicsView::mapFromScene(rect.topLeft()); const QPoint& pos2 = QGraphicsView::mapFromScene(rect.bottomRight()); m_rename_editor->setGeometry( pos1.x(), pos1.y(), pos2.x() - pos1.x(), pos2.y() - pos1.y()); } } void qjackctlGraphCanvas::updateSearchEditor (void) { // Position the search editor to the bottom-right of the canvas... const QSize& size = QGraphicsView::viewport()->size(); const QSize& hint = m_search_editor->sizeHint(); const int w = hint.width() * 2; const int h = hint.height(); m_search_editor->setGeometry(size.width() - w, size.height() - h, w, h); } // Discrete zooming actions. void qjackctlGraphCanvas::zoomIn (void) { setZoom(zoom() + 0.1); } void qjackctlGraphCanvas::zoomOut (void) { setZoom(zoom() - 0.1); } void qjackctlGraphCanvas::zoomFit (void) { zoomFitRange(m_scene->itemsBoundingRect()); } void qjackctlGraphCanvas::zoomReset (void) { setZoom(1.0); } // Update all nodes. void qjackctlGraphCanvas::updateNodes (void) { foreach (QGraphicsItem *item, m_scene->items()) { if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node) node->updatePath(); } } } // Update all connectors. void qjackctlGraphCanvas::updateConnects (void) { foreach (QGraphicsItem *item, m_scene->items()) { if (item->type() == qjackctlGraphConnect::Type) { qjackctlGraphConnect *connect = static_cast (item); if (connect) connect->updatePath(); } } } // Zoom in rectangle range. void qjackctlGraphCanvas::zoomFitRange ( const QRectF& range_rect ) { QGraphicsView::fitInView( range_rect, Qt::KeepAspectRatio); const QTransform& transform = QGraphicsView::transform(); if (transform.isScaling()) { qreal zoom = transform.m11(); if (zoom < 0.1) { const qreal scale = 0.1 / zoom; QGraphicsView::scale(scale, scale); zoom = 0.1; } else if (zoom > 2.0) { const qreal scale = 2.0 / zoom; QGraphicsView::scale(scale, scale); zoom = 2.0; } m_zoom = zoom; } emit changed(); } // Graph node position methods. bool qjackctlGraphCanvas::restoreNode ( qjackctlGraphNode *node ) { if (m_settings == nullptr || node == nullptr) return false; m_settings->beginGroup(NodePosGroup); QPointF node_pos = m_settings->value('/' + nodeKey(node)).toPointF(); m_settings->endGroup(); if (node_pos.isNull()) return false; boundingPos(node_pos); node->setPos(node_pos); return true; } bool qjackctlGraphCanvas::saveNode ( qjackctlGraphNode *node ) const { if (m_settings == nullptr || node == nullptr) return false; m_settings->beginGroup(NodePosGroup); m_settings->setValue('/' + nodeKey(node), node->pos()); m_settings->endGroup(); return true; } bool qjackctlGraphCanvas::restoreState (void) { if (m_settings == nullptr) return false; m_settings->beginGroup(ColorsGroup); const QRegularExpression rx("^0x"); QStringListIterator key(m_settings->childKeys()); while (key.hasNext()) { const QString& sKey = key.next(); const QColor& color = QString(m_settings->value(sKey).toString()); if (color.isValid()) { QString sx(sKey); bool ok = false; const uint port_type = sx.remove(rx).toUInt(&ok, 16); if (ok) m_port_colors.insert(port_type, color); } } m_settings->endGroup(); m_settings->beginGroup(CanvasGroup); const QRectF& rect = m_settings->value(CanvasRectKey).toRectF(); const qreal zoom = m_settings->value(CanvasZoomKey, 1.0).toReal(); m_settings->endGroup(); if (rect.isValid()) m_rect1 = rect; // QGraphicsView::setSceneRect(m_rect1); setZoom(zoom); return true; } bool qjackctlGraphCanvas::saveState (void) const { if (m_settings == nullptr) return false; m_settings->beginGroup(NodePosGroup); const QList items(m_scene->items()); foreach (QGraphicsItem *item, items) { if (item->type() == qjackctlGraphNode::Type) { qjackctlGraphNode *node = static_cast (item); if (node) m_settings->setValue('/' + nodeKey(node), node->pos()); } } m_settings->endGroup(); m_settings->beginGroup(CanvasGroup); m_settings->setValue(CanvasZoomKey, zoom()); m_settings->setValue(CanvasRectKey, m_rect1); m_settings->endGroup(); m_settings->beginGroup(ColorsGroup); QStringListIterator key(m_settings->childKeys()); while (key.hasNext()) m_settings->remove(key.next()); QHash::ConstIterator iter = m_port_colors.constBegin(); const QHash::ConstIterator& iter_end = m_port_colors.constEnd(); for ( ; iter != iter_end; ++iter) { const uint port_type = iter.key(); const QColor& color = iter.value(); m_settings->setValue("0x" + QString::number(port_type, 16), color.name()); } m_settings->endGroup(); return true; } // Graph node key mangler. QString qjackctlGraphCanvas::nodeKey ( qjackctlGraphNode *node ) const { QString node_key = node->nodeName(); switch (node->nodeMode()) { case qjackctlGraphItem::Input: node_key += ":Input"; break; case qjackctlGraphItem::Output: node_key += ":Output"; break; default: break; } return node_key; } // Graph port colors management. void qjackctlGraphCanvas::setPortTypeColor ( uint port_type, const QColor& port_color ) { m_port_colors.insert(port_type, port_color); } const QColor& qjackctlGraphCanvas::portTypeColor ( uint port_type ) { return m_port_colors[port_type]; } void qjackctlGraphCanvas::updatePortTypeColors ( uint port_type ) { foreach (QGraphicsItem *item, m_scene->items()) { if (item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port = static_cast (item); if (port && (0 >= port_type || port->portType() == port_type)) { port->updatePortTypeColors(this); port->update(); } } } } void qjackctlGraphCanvas::clearPortTypeColors (void) { m_port_colors.clear(); } // Clear all selection. void qjackctlGraphCanvas::clearSelection (void) { m_item = nullptr; m_selected_nodes = 0; m_scene->clearSelection(); m_rename_item = nullptr; m_rename_editor->setEnabled(false); m_rename_editor->hide(); m_renamed = 0; } // Clear all state. void qjackctlGraphCanvas::clear (void) { m_selected_nodes = 0; if (m_rubberband) { delete m_rubberband; m_rubberband = nullptr; m_selected.clear(); } if (m_connect) { m_connect->disconnect(); delete m_connect; m_connect = nullptr; } if (m_state == DragScroll) QGraphicsView::setDragMode(QGraphicsView::NoDrag); m_state = DragNone; m_item = nullptr; m_rename_item = nullptr; m_rename_editor->setEnabled(false); m_rename_editor->hide(); m_renamed = 0; // Reset cursor... QGraphicsView::setCursor(Qt::ArrowCursor); } // Rename item slots. void qjackctlGraphCanvas::renameTextChanged ( const QString& /* text */) { if (m_rename_item && m_rename_editor->isEnabled() && m_rename_editor->isVisible()) ++m_renamed; } void qjackctlGraphCanvas::renameEditingFinished (void) { if (m_rename_item && m_rename_editor->isEnabled() && m_rename_editor->isVisible()) { // If changed then notify... if (m_renamed > 0) { m_commands->push( new qjackctlGraphRenameCommand(this, m_rename_item, m_rename_editor->text())); } // Reset all renaming stuff... m_rename_item = nullptr; m_rename_editor->setEnabled(false); m_rename_editor->hide(); m_renamed = 0; } } // Client/port aliases accessors. void qjackctlGraphCanvas::setAliases ( qjackctlAliases *aliases ) { m_aliases = aliases; } qjackctlAliases *qjackctlGraphCanvas::aliases (void) const { return m_aliases; } //---------------------------------------------------------------------------- // qjackctlGraphSect -- Generic graph driver // Constructor. qjackctlGraphSect::qjackctlGraphSect ( qjackctlGraphCanvas *canvas ) : m_canvas(canvas) { } // Accessors. qjackctlGraphCanvas *qjackctlGraphSect::canvas (void) const { return m_canvas; } // Generic sect/graph methods. void qjackctlGraphSect::addItem ( qjackctlGraphItem *item, bool is_new ) { if (is_new) m_canvas->addItem(item); if (item->type() == qjackctlGraphConnect::Type) { qjackctlGraphConnect *connect = static_cast (item); if (connect) m_connects.append(connect); } } void qjackctlGraphSect::removeItem ( qjackctlGraphItem *item ) { if (item->type() == qjackctlGraphConnect::Type) { qjackctlGraphConnect *connect = static_cast (item); if (connect) { connect->disconnect(); m_connects.removeAll(connect); } } m_canvas->removeItem(item); } // Clean-up all un-marked items... void qjackctlGraphSect::resetItems ( uint node_type ) { const QList connects(m_connects); foreach (qjackctlGraphConnect *connect, connects) { if (connect->isMarked()) { connect->setMarked(false); } else { removeItem(connect); delete connect; } } m_canvas->resetNodes(node_type); } void qjackctlGraphSect::clearItems ( uint node_type ) { qjackctlGraphSect::resetItems(node_type); // qDeleteAll(m_connects); m_connects.clear(); m_canvas->clearNodes(node_type); } // Special node finder. qjackctlGraphNode *qjackctlGraphSect::findNode ( const QString& name, qjackctlGraphItem::Mode mode, int type ) const { return m_canvas->findNode(name, mode, type); } // Client/port renaming method. void qjackctlGraphSect::renameItem ( qjackctlGraphItem *item, const QString& name ) { int nchanged = 0; qjackctlGraphNode *node = nullptr; if (item->type() == qjackctlGraphNode::Type) { node = static_cast (item); if (node) { node->setNodeTitle(name); const QString& node_title = node->nodeTitle(); foreach (qjackctlAliasList *node_aliases, item_aliases(item)) { node_aliases->setClientAlias(node->nodeName(), node_title); ++nchanged; } } } else if (item->type() == qjackctlGraphPort::Type) { qjackctlGraphPort *port = static_cast (item); if (port) node = port->portNode(); if (port && node) { port->setPortTitle(name); foreach (qjackctlAliasList *port_aliases, item_aliases(item)) { port_aliases->setPortAlias( node->nodeName(), port->portName(), name); ++nchanged; } } } if (node) node->updatePath(); if (nchanged > 0) { qjackctlAliases *aliases = nullptr; if (m_canvas) aliases = m_canvas->aliases(); if (aliases) aliases->dirty = true; } } // Search item slots. void qjackctlGraphCanvas::searchTextChanged ( const QString& text ) { clearSelection(); if (text.isEmpty()) return; const QRegularExpression& rx = QRegularExpression(text, QRegularExpression::CaseInsensitiveOption); if (!rx.isValid()) return; for (qjackctlGraphNode *node : m_nodes) { if (rx.match(node->nodeTitle()).hasMatch()) { node->setSelected(true); QGraphicsView::ensureVisible(node); } } } void qjackctlGraphCanvas::searchEditingFinished (void) { m_search_editor->setEnabled(false); m_search_editor->hide(); m_search_editor->clearFocus(); QGraphicsView::setFocus(); } // Start search editor... void qjackctlGraphCanvas::startSearchEditor ( const QString& text ) { m_search_editor->setEnabled(true); m_search_editor->setText(text); m_search_editor->raise(); m_search_editor->show(); m_search_editor->setFocus(); } void qjackctlGraphCanvas::resizeEvent( QResizeEvent *event ) { QGraphicsView::resizeEvent(event); updateSearchEditor(); } // Repel overlapping nodes... void qjackctlGraphCanvas::setRepelOverlappingNodes ( bool on ) { m_repel_overlapping_nodes = on; } bool qjackctlGraphCanvas::isRepelOverlappingNodes (void) const { return m_repel_overlapping_nodes; } void qjackctlGraphCanvas::repelOverlappingNodes ( qjackctlGraphNode *node, qjackctlGraphMoveCommand *move_command, const QPointF& delta ) { const qreal MIN_NODE_GAP = 8.0f; node->setMarked(true); QRectF rect1 = node->sceneBoundingRect(); rect1.adjust( -2.0 * MIN_NODE_GAP, -MIN_NODE_GAP, +2.0 * MIN_NODE_GAP, +MIN_NODE_GAP); foreach (qjackctlGraphNode *node2, m_nodes) { if (node2->isMarked()) continue; const QPointF& pos1 = node2->pos(); QPointF pos2 = pos1; const QRectF& rect2 = node2->sceneBoundingRect(); const QRectF& recti = rect2.intersected(rect1); if (!recti.isNull()) { const QPointF delta2 = (delta.isNull() ? rect2.center() - rect1.center() : delta); if (recti.width() < (1.5 * recti.height())) { qreal dx = recti.width(); if ((delta2.x() < 0.0 && recti.width() >= rect1.width()) || (delta2.x() > 0.0 && recti.width() >= rect2.width())) { dx += qAbs(rect2.right() - rect1.right()); } else if ((delta2.x() > 0.0 && recti.width() >= rect1.width()) || (delta2.x() < 0.0 && recti.width() >= rect2.width())) { dx += qAbs(rect2.left() - rect1.left()); } if (delta2.x() < 0.0) pos2.setX(pos1.x() - dx); else pos2.setX(pos1.x() + dx); } else { qreal dy = recti.height(); if ((delta2.y() < 0.0 && recti.height() >= rect1.height()) || (delta2.y() > 0.0 && recti.height() >= rect2.height())) { dy += qAbs(rect2.bottom() - rect1.bottom()); } else if ((delta2.y() > 0.0 && recti.height() >= rect1.height()) || (delta2.y() < 0.0 && recti.height() >= rect2.height())) { dy += qAbs(rect2.top() - rect1.top()); } if (delta2.y() < 0.0) pos2.setY(pos1.y() - dy); else pos2.setY(pos1.y() + dy); } // Repel this node... node2->setPos(pos2); // Add this node for undo/redo... if (move_command) move_command->addItem(node2, pos1, pos2); // Repel this node neighbors, if any... repelOverlappingNodes(node2, move_command, delta2); } } node->setMarked(false); } void qjackctlGraphCanvas::repelOverlappingNodesAll ( qjackctlGraphMoveCommand *move_command ) { foreach (qjackctlGraphNode *node, m_nodes) repelOverlappingNodes(node, move_command); } // Gesture event handlers. // bool qjackctlGraphCanvas::event ( QEvent *event ) { if (event->type() == QEvent::Gesture) return gestureEvent(static_cast (event)); else return QGraphicsView::event(event); } bool qjackctlGraphCanvas::gestureEvent ( QGestureEvent *event ) { if (QGesture *pinch = event->gesture(Qt::PinchGesture)) pinchGesture(static_cast (pinch)); return true; } void qjackctlGraphCanvas::pinchGesture ( QPinchGesture *pinch ) { switch (pinch->state()) { case Qt::GestureStarted: { const qreal scale_factor = zoom(); pinch->setScaleFactor(scale_factor); pinch->setLastScaleFactor(scale_factor); pinch->setTotalScaleFactor(scale_factor); m_gesture = true; break; } case Qt::GestureFinished: m_gesture = false; // Fall thru... case Qt::GestureUpdated: if (pinch->changeFlags() & QPinchGesture::ScaleFactorChanged) setZoom(pinch->totalScaleFactor()); // Fall thru... default: break; } } // Bounding margins/limits... // const QRectF& qjackctlGraphCanvas::boundingRect ( bool reset ) { if (!m_rect1.isValid() || reset) { const QRect& rect = QGraphicsView::rect(); const qreal mx = 0.33 * rect.width(); const qreal my = 0.33 * rect.height(); m_rect1 = m_scene->itemsBoundingRect() .marginsAdded(QMarginsF(mx, my, mx, my)); } return m_rect1; } void qjackctlGraphCanvas::boundingPos ( QPointF& pos ) { const QRectF& rect = boundingRect(); if (!rect.contains(pos)) { pos.setX(qBound(rect.left(), pos.x(), rect.right())); pos.setY(qBound(rect.top(), pos.y(), rect.bottom())); } } // Snap into position helpers. // QPointF qjackctlGraphCanvas::snapPos ( const QPointF& pos ) const { return QPointF( 4.0 * ::round(0.25 * pos.x()), 4.0 * ::round(0.25 * pos.y())); } //---------------------------------------------------------------------------- // qjackctlGraphThumb::View -- Thumb graphics scene/view. class qjackctlGraphThumb::View : public QGraphicsView { public: // Constructor. View(qjackctlGraphThumb *thumb) : QGraphicsView((thumb->canvas())->viewport()), m_thumb(thumb), m_drag_state(DragNone) { QGraphicsView::setInteractive(false); QGraphicsView::setRenderHints(QPainter::Antialiasing); QGraphicsView::setRenderHint(QPainter::SmoothPixmapTransform); QGraphicsView::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QGraphicsView::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); updatePalette(); QGraphicsView::setScene((thumb->canvas())->scene()); } void updatePalette() { qjackctlGraphCanvas *canvas = m_thumb->canvas(); QPalette pal = canvas->palette(); const QPalette::ColorRole role = canvas->backgroundRole(); const QColor& color = pal.color(role); pal.setColor(role, color.darker(120)); QGraphicsView::setPalette(pal); QGraphicsView::setBackgroundRole(role); } protected: // Compute the view(port) rectangle. QRect viewRect() const { qjackctlGraphCanvas *canvas = m_thumb->canvas(); const QRect& vrect = canvas->viewport()->rect(); const QRectF srect( canvas->mapToScene(vrect.topLeft()), canvas->mapToScene(vrect.bottomRight())); return QGraphicsView::viewport()->rect().intersected(QRect( QGraphicsView::mapFromScene(srect.topLeft()), QGraphicsView::mapFromScene(srect.bottomRight()))) .adjusted(0, 0, -1, -1); } // View paint method. void paintEvent(QPaintEvent *event) { QGraphicsView::paintEvent(event); QPainter painter(QGraphicsView::viewport()); // const QPalette& pal = QGraphicsView::palette(); // painter.setPen(pal.midlight().color()); const QRect& vrect = QGraphicsView::viewport()->rect(); const QRect& vrect2 = viewRect(); const QColor shade(0, 0, 0, 64); QRect rect; // top shade... rect.setTopLeft(vrect.topLeft()); rect.setBottomRight(QPoint(vrect.right(), vrect2.top() - 1)); if (rect.isValid()) painter.fillRect(rect, shade); // left shade... rect.setTopLeft(QPoint(vrect.left(), vrect2.top())); rect.setBottomRight(vrect2.bottomLeft()); if (rect.isValid()) painter.fillRect(rect, shade); // right shade... rect.setTopLeft(vrect2.topRight()); rect.setBottomRight(QPoint(vrect.right(), vrect2.bottom())); if (rect.isValid()) painter.fillRect(rect, shade); // bottom shade... rect.setTopLeft(QPoint(vrect.left(), vrect2.bottom() + 1)); rect.setBottomRight(vrect.bottomRight()); if (rect.isValid()) painter.fillRect(rect, shade); } // Handle mouse events. // void mousePressEvent(QMouseEvent *event) { QGraphicsView::mousePressEvent(event); if (event->button() == Qt::LeftButton) { m_drag_pos = event->pos(); m_drag_state = DragStart; QApplication::setOverrideCursor(QCursor(Qt::PointingHandCursor)); } } void mouseMoveEvent(QMouseEvent *event) { QGraphicsView::mouseMoveEvent(event); if (m_drag_state == DragStart && (event->pos() - m_drag_pos).manhattanLength() > QApplication::startDragDistance()) { m_drag_state = DragMove; QApplication::changeOverrideCursor(QCursor(Qt::DragMoveCursor)); } if (m_drag_state == DragMove) { const QRect& rect = QGraphicsView::rect(); if (!rect.contains(event->pos())) { const int mx = rect.width() + 4; const int my = rect.height() + 4; const Position position = m_thumb->position(); if (event->pos().x() < rect.left() - mx) { if (position == TopRight) m_thumb->requestPosition(TopLeft); else if (position == BottomRight) m_thumb->requestPosition(BottomLeft); } else if (event->pos().x() > rect.right() + mx) { if (position == TopLeft) m_thumb->requestPosition(TopRight); else if (position == BottomLeft) m_thumb->requestPosition(BottomRight); } else if (event->pos().y() < rect.top() - my) { if (position == BottomLeft) m_thumb->requestPosition(TopLeft); else if (position == BottomRight) m_thumb->requestPosition(TopRight); } else if (event->pos().y() > rect.bottom() + my) { if (position == TopLeft) m_thumb->requestPosition(BottomLeft); else if (position == TopRight) m_thumb->requestPosition(BottomRight); } } else if (event->modifiers() & Qt::ControlModifier) { m_thumb->canvas()->centerOn( QGraphicsView::mapToScene(event->pos())); } } } void mouseReleaseEvent(QMouseEvent *event) { QGraphicsView::mouseReleaseEvent(event); if (m_drag_state != DragNone) { if ((m_drag_state == DragStart) || (event->modifiers() & Qt::ControlModifier)) { m_thumb->canvas()->centerOn( QGraphicsView::mapToScene(event->pos())); } m_drag_state = DragNone; QApplication::restoreOverrideCursor(); } } void wheelEvent(QWheelEvent *) {} // Ignore wheel events. void contextMenuEvent(QContextMenuEvent *event) { m_thumb->requestContextMenu(event->globalPos()); } private: // Instance members. qjackctlGraphThumb *m_thumb; enum { DragNone = 0, DragStart, DragMove } m_drag_state; QPoint m_drag_pos; }; //---------------------------------------------------------------------------- // qjackctlGraphThumb -- Thumb graphics scene/view. // Constructor. qjackctlGraphThumb::qjackctlGraphThumb ( qjackctlGraphCanvas *canvas, Position position ) : QFrame(canvas), m_canvas(canvas), m_position(position), m_view(nullptr) { m_view = new View(this); QVBoxLayout *layout = new QVBoxLayout(); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(m_view); QFrame::setLayout(layout); QFrame::setFrameStyle(QFrame::Panel); QFrame::setForegroundRole(QPalette::Window); QObject::connect(m_canvas->horizontalScrollBar(), SIGNAL(valueChanged(int)), SLOT(updateView())); QObject::connect(m_canvas->verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(updateView())); } // Destructor. qjackctlGraphThumb::~qjackctlGraphThumb (void) { } // Accessors. qjackctlGraphCanvas *qjackctlGraphThumb::canvas (void) const { return m_canvas; } void qjackctlGraphThumb::setPosition ( Position position ) { m_position = position; updatePosition(); } qjackctlGraphThumb::Position qjackctlGraphThumb::position (void) const { return m_position; } // Request re-positioning. void qjackctlGraphThumb::requestPosition ( Position position ) { emit positionRequested(int(position)); } // Emit context-menu request. void qjackctlGraphThumb::requestContextMenu ( const QPoint& pos ) { emit contextMenuRequested(pos); } // Update view. void qjackctlGraphThumb::updatePosition (void) { const QRect& rect = m_canvas->viewport()->rect(); const int w = rect.width() / 4; const int h = rect.height() / 4; QFrame:setFixedSize(w + 1, h + 1); // 1px slack. switch (m_position) { case TopLeft: QFrame::move(0, 0); break; case TopRight: QFrame::move(rect.width() - w, 0); break; case BottomLeft: QFrame::move(0, rect.height() - h); break; case BottomRight: QFrame::move(rect.width() - w, rect.height() - h); break; case None: default: break; } QFrame::show(); } // Update view. void qjackctlGraphThumb::updateView (void) { updatePosition(); const qreal m = 24.0; m_view->fitInView( m_canvas->scene()->itemsBoundingRect() .marginsAdded(QMarginsF(m, m, m, m)), Qt::KeepAspectRatio); } // Update the thumb-view palette. void qjackctlGraphThumb::updatePalette (void) { m_view->updatePalette(); } // Search placeholder text accessors. void qjackctlGraphCanvas::setSearchPlaceholderText ( const QString& text ) { m_search_editor->setPlaceholderText(text); } QString qjackctlGraphCanvas::searchPlaceholderText (void) const { return m_search_editor->placeholderText(); } // Update the canvas palette. void qjackctlGraphCanvas::updatePalette (void) { QPalette pal;// = QGraphicsView::palette(); const QPalette::ColorRole role = QPalette::Window; const QColor& color = pal.color(role); pal.setColor(role, color.darker(120)); QGraphicsView::setPalette(pal); QGraphicsView::setBackgroundRole(role); } // end of qjackctlGraph.cpp qjackctl-1.0.4/src/PaxHeaders/translations0000644000000000000000000000013114771215054015626 xustar0030 mtime=1743067692.335636536 29 atime=1743067692.33063656 30 ctime=1743067692.335636536 qjackctl-1.0.4/src/translations/0000755000175000001440000000000014771215054015674 5ustar00rncbcusersqjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_uk.ts0000644000000000000000000000013214771215054020547 xustar0030 mtime=1743067692.336636532 30 atime=1743067692.335636536 30 ctime=1743067692.336636532 qjackctl-1.0.4/src/translations/qjackctl_uk.ts0000644000175000001440000070154214771215054020550 0ustar00rncbcusers PortAudioProber Probing... Зондуємо… Please wait, PortAudio is probing audio hardware. Будь ласка, зачекайте, PortAudio виконує зондування звукового обладнання. Warning Попередження Audio hardware probing timed out. Перевищено час очікування на завершення зондування звукового обладнання. QObject Move Пересунути Rename Перейменувати %1 (%2 frames) %1 (%2 кадрів) (default) (default) Usage: %1 [options] [command-and-args] Користування: %1 [параметри] [команда-і-аргументи] Options: Параметри: Start JACK audio server immediately. Запустити звуковий сервер JACK негайно. Set default settings preset name. Встановити назву набору типових параметрів. Set active patchbay definition file. Встановити активний файл визначення комутації. Set default JACK audio server name. Встановити типову назву звукового сервера JACK. Show help about command line options. Показати довідку щодо параметрів командного рядка. Show version information. Показати відомості щодо версії. Launch command with arguments. Запустити команду з аргументами. [command-and-args] [команда-з-аргументами] Option -p requires an argument (preset). Разом із параметром -p слід вказати аргумент (набір параметрів). Option -a requires an argument (path). Разом із параметром -a слід вказати аргумент (шлях). Option -n requires an argument (name). Разом із параметром -n слід вказати аргумент (назву). qjackctlAboutForm About Про програму &Close &Закрити About Qt Про Qt Debugging option enabled. Увімкнено параметр діагностики. System tray disabled. Вимкнено системний лоток. Transport status control disabled. Вимкнено керування станом передавання. Realtime status disabled. Вимкнено динамічне повідомлення щодо стану. XRUN delay status disabled. Стан затримки XRUN вимкнено. Maximum delay status disabled. Стан максимальної затримки вимкнено. JACK Port aliases support disabled. Підтримку альтернативних назв портів KACK вимкнено. JACK MIDI support disabled. Підтримку MIDI у JACK вимкнено. JACK Session support disabled. Підтримку сеансів JACK вимкнено. ALSA/MIDI sequencer support disabled. Підтримку синтезатора ALSA/MIDI вимкнено. D-Bus interface support disabled. Підтримку інтерфейсу D-Bus вимкнено. Version Версія Using: Qt %1 Використовуємо Qt %1 JACK %1 JACK %1 Website Сайт This program is free software; you can redistribute it and/or modify it Ця програма є вільним програмним забезпеченням, ви можете поширювати її і вносити до неї зміни under the terms of the GNU General Public License version 2 or later. за умов дотримання GNU General Public License версії 2 або новіших версій. qjackctlClientListView Readable Clients / Output Ports Придатні до читання порти клієнтів/виведення Writable Clients / Input Ports Придатні до запису клієнти та вхідні порти &Connect &З'єднати Alt+C Connect Alt+C &Disconnect Роз'є&днати Alt+D Disconnect Alt+D Disconnect &All Роз'є&днати все Alt+A Disconnect All Alt+A Re&name Пере&йменувати Alt+N Rename Alt+N &Refresh &Оновити Alt+R Refresh Alt+R qjackctlConnect Warning Попередження This will suspend sound processing from all client applications. Are you sure? У результаті буде призупинено обробку звуку в усіх клієнтських програмах. Ви хочете саме цього? qjackctlConnectionsForm Connections З'єднання Audio Звук Connect currently selected ports З'єднати поточні позначені порти &Connect &З'єднати Disconnect currently selected ports Роз'єднати поточні позначені порти &Disconnect &Роз'єднати Disconnect all currently connected ports Роз'єднати усі поточні з'єднані порти Disconnect &All Роз'є&днати все Expand all client ports Розгорнути усі порти клієнтів E&xpand All Роз&горнути всі Refresh current connections view Освіжити вміст панелі поточних з'єднань &Refresh &Оновити MIDI MIDI ALSA ALSA qjackctlConnectorView &Connect &З'єднати Alt+C Connect Alt+C &Disconnect &Роз'єднати Alt+D Disconnect Alt+D Disconnect &All Роз'є&днати все Alt+A Disconnect All Alt+A &Refresh &Оновити Alt+R Refresh Alt+R qjackctlGraphCanvas Connect З'єднати Disconnect Від’єднати qjackctlGraphForm Graph Граф &Graph &Граф &Edit З&міни &View П&ерегляд &Zoom Змінити &масштаб Co&lors &Кольори S&ort К&ритерій упорядкування &Help &Довідка &Connect &З'єднати Connect З'єднати Connect selected ports З'єднати позначені порти &Disconnect &Роз'єднати Disconnect Від’єднати Disconnect selected ports Роз'єднати позначені порти Ctrl+C Ctrl+C T&humbview Ctrl+D Ctrl+D Cl&ose З&акрити Close Закрити Close this application window Закрити це вікно програми Select &All Позна&чити все Select All Позначити все Ctrl+A Ctrl+A Select &None З&няти позначення Select None Зняти позначення Ctrl+Shift+A Ctrl+Shift+A Select &Invert &Інвертувати позначення Select Invert Інвертувати позначення Ctrl+I Ctrl+I &Rename... &Перейменувати… Rename item Перейменувати запис Rename Item Перейменувати запис F2 F2 &Find... Find Find nodes Ctrl+F &Menubar Панель &меню Menubar Панель меню Show/hide the main program window menubar Показати або приховати панель меню головного вікна програми Ctrl+M Ctrl+M &Toolbar Па&нель інструментів Toolbar Панель інструментів Show/hide main program window file toolbar Показати або приховати панель інструментів головного вікна програми &Statusbar С&мужка стану Statusbar Смужка стану Show/hide the main program window statusbar Показати або приховати смужку стану головного вікна програми &Top Left Top left Show the thumbnail overview on the top-left Top &Right Top right Show the thumbnail overview on the top-right Bottom &Left Bottom Left Bottom left Show the thumbnail overview on the bottom-left &Bottom Right Bottom right Show the thumbnail overview on the bottom-right &None None Немає Hide thumbview Hide the thumbnail overview Text Beside &Icons Текст поруч з пі&ктограмами Text beside icons Текст поруч зі значками Show/hide text beside icons Показати або приховати текст поруч із піктограмами &Center &Центрувати Center Центрувати Center view Центрування перегляду &Refresh &Оновити Refresh Оновити Refresh view Оновити перегляд F5 F5 Zoom &In З&більшити Zoom In Збільшити Ctrl++ Ctrl++ Zoom &Out З&меншити Zoom Out Зменшити Ctrl+- Ctrl+- Zoom &Fit Підібрати за роз&мірами Zoom Fit Підібрати за розмірами Ctrl+0 Ctrl+0 Zoom &Reset Відновити по&чатковий масштаб Zoom Reset Відновити початковий масштаб Ctrl+1 Ctrl+1 &Zoom Range &Масштабувати за діапазоном Zoom Range Масштабувати за діапазоном JACK &Audio... Зв&ук Jack… JACK Audio color Колір звуку JACK JACK &MIDI... JACK &MIDI… JACK MIDI JACK MIDI JACK MIDI color Колір MIDI JACK ALSA M&IDI... ALSA M&IDI... ALSA MIDI ALSA MIDI ALSA MIDI color Колір ALSA MIDI JACK &CV... JACK &CV… JACK CV color Колір JACK CV JACK &OSC... JACK &OSC… JACK OSC JACK OSC JACK OSC color Колір JACK OSC &Reset &Скинути Reset colors Відновити типові кольори Port &Name Назва &порту Port name Назва порту Sort by port name Упорядкувати за назвою порту Port &Title &Назва порту Port title Назва порту Sort by port title Упорядкувати за назвою порту Port &Index &Індекс порту Port index Індекс порту Sort by port index Упорядкувати за індексом порту &Ascending За з&ростанням Ascending За зростанням Ascending sort order Упорядкувати за зростанням &Descending &За спаданням Descending За спаданням Descending sort order Упорядкувати за спаданням Repel O&verlapping Nodes Від&кинути вузли з перекриттям Repel nodes Відкинути вузли Repel overlapping nodes Відкинути вузли з перекриттям Connect Thro&ugh Nodes З'єднати &через вузли Connect Through Nodes З'єднати через вузли Connect through nodes З'єднати через вузли Whether to draw connectors through or around nodes Визначає, слід малювати з'єднання через вузли чи навколо вузлів &About... П&ро програму… About... Про програму… About Про програму Show information about this application program Показати відомості щодо цієї програми About &Qt... П&ро Qt… About Qt... Про Qt… About Qt Про Qt Show information about the Qt toolkit Показати відомості щодо набору інструментів Qt &Undo &Вернути Undo last edit action Скасувати останню дію з редагування &Redo &Повторити Redo last edit action Повторити останню скасовану дію з редагування Zoom Масштаб Ready Готово Colors - %1 Кольори – %1 qjackctlMainForm Start the JACK server Запустити сервер JACK &Start З&апустити Stop the JACK server Зупинити роботу сервера JACK S&top &Зупинити JACK server state Стан сервера JACK JACK server mode Режим сервера JACK DSP Load Навантаження на ЦОС Sample rate Частота дискретизації XRUN Count (notifications) Лічильник XRUN (сповіщення) Time display Показ часу Transport state Стан передавання Transport BPM Частота передавання Transport time Час передавання Quit processing and exit Припинити обробку і вийти &Quit Ви&йти Show/hide the session management window Показати або приховати вікно керування сеансом S&ession С&еанс Show/hide the messages log/status window Показати або приховати вікно повідомлень журналу або стану &Messages П&овідомлення Show settings and options dialog Показати вікно параметрів та налаштувань Set&up... Н&алаштувати… Show/hide the graph window Показати або приховати вікно графу &Graph &Граф Show/hide the connections window Показати або приховати вікно з'єднань &Connect &З'єднати Show/hide the patchbay editor window Показати або приховати вікно редактора комутації &Patchbay &Комутація Rewind transport Перемотування передавання &Rewind Перемотати &назад Backward transport Перемотати передавання назад &Backward &Назад Start transport rolling Розпочати перемотування передавання &Play Від&творити Stop transport rolling Зупинити перемотування передавання Pa&use Па&уза Forward transport Прокрутити вперед &Forward В&перед Show information about this application Показати відомості щодо цієї програми Ab&out... П&ро програму… Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. Не вдалося відкрити синтезатор ALSA як клієнт. Ви не зможете скористатися комутацією ALSA MIDI. Information Інформація The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. Програма продовжить роботу у системному лотку. Щоб завершити роботу програми, будь ласка, виберіть пункт «Вийти» у контекстному меню піктограми системного лотка. Don't show this message again Не показувати надалі Warning Попередження JACK is currently running. Do you want to terminate the JACK audio server? Зараз запущено JACK. Хочете перервати роботу звукового сервера JACK? %1 is about to terminate. Are you sure? Зараз роботу %1 буде перервано. Ви впевнені, що хочете саме цього? Don't ask this again Більше не питати The preset aliases have been changed: "%1" Do you want to save the changes? Альтернативні назви наборів параметрів було змінено: «%1» Хочете зберегти внесені зміни? Server settings will be only effective after restarting the JACK audio server. Параметри сервера набудуть чинності лише після перезапуску звукового сервера JACK. Do you want to restart the JACK audio server? Хочете перезапустити звуковий сервер JACK? Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Деякі клієнтські звукові програми лишаються активними і з'єднаними. Хочете зупинити роботу звукового сервера JACK? successfully успішно with exit status=%1 зі станом виходу=%1 Could not start JACK. Maybe JACK audio server is already started. Не вдалося запустити JACK. Можливо, звуковий сервер JACK вже запущено. Could not load preset "%1". Retrying with default. Не вдалося завантажити набір параметрів «%1». Робимо повторну спробу із типовим набором. Could not load default preset. Sorry. Не вдалося завантажити типовий набір параметрів. Вибачте. Startup script... Скрипт запуску… Startup script terminated Роботу скрипту запуску перервано D-BUS: JACK server is starting... D-BUS: запускаємо сервер JACK… D-BUS: JACK server could not be started. Sorry D-BUS: не вдалося запустити сервер JACK. Вибачте JACK is starting... Запускаємо JACK… Shutdown script... Скрипт вимикання… Shutdown script terminated Роботу скрипту вимикання перервано JACK is stopping... Припиняємо роботу JACK… D-BUS: JACK server is stopping... D-BUS: припиняємо роботу сервера JACK… D-BUS: JACK server could not be stopped. Sorry D-BUS: не вдалося припинити роботу сервера JACK. Вибачте JACK was started with PID=%1. JACK було запущено із PID=%1. D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: сервер JACK запущено (%1 або jackdbus). JACK is being forced... Примусово керуємо JACK… JACK was stopped JACK зупинено D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: роботу сервера JACK зупинено (%1 або jackdbus). Post-shutdown script... Виконуємо скрипт після завершення роботи… Post-shutdown script terminated Роботу скрипту, запущеного після припинення роботи, перервано Error Помилка Transport BBT (bar.beat.ticks) Передавання BBT (bar.beat.ticks) Transport time code Часова позначка передавання Elapsed time since last reset Час з моменту останнього скидання Elapsed time since last XRUN Час з моменту останнього XRUN D-BUS: Service is available (%1 aka jackdbus). D-BUS: служба доступна (%1 або jackdbus). D-BUS: Service not available (%1 aka jackdbus). D-BUS: служба не доступна (%1 або jackdbus). Patchbay reset. Комутацію скинуто. Could not load active patchbay definition. "%1" Disabled. Не вдалося завантажити активне визначення комутації. «%1» Вимкнено. Patchbay activated. Комутацію активовано. Patchbay deactivated. Комутацію деактивовано. Statistics reset. Статистику скинуто. msec мс JACK connection graph change. Зміна графу з'єднань JACK. XRUN callback (%1). Зворотний виклик XRUN (%1). Buffer size change (%1). Зміна розміру буфера (%1). Shutdown notification. Сповіщення щодо вимикання. Freewheel started... Запущено вільний хід… Freewheel exited. Вихід з режиму вільного ходу. Could not start JACK. Sorry. Не вдалося запустити JACK. Вибачте. JACK has crashed. JACK завершив роботу у аварійному режимі. JACK timed out. Перевищено час очікування на запуск JACK. JACK write error. Помилка запису JACK. JACK read error. Помилка читання JACK. Unknown JACK error (%d). Невідома помилка JACK (%d). JACK property change. Зміна властивості JACK. ALSA connection graph change. Зміна графу з'єднань ALSA. JACK active patchbay scan Сканування активної комутації JACK ALSA active patchbay scan Сканування активної комутації ALSA JACK connection change. Зміна з'єднання JACK. ALSA connection change. Зміна з'єднання ALSA. checked позначено connected з'єднано disconnected роз'єднано failed помилка A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? Зараз активною є комутація, яка, ймовірно, повторно встановить це з'єднання: %1 -> %2 Хочете вилучити це комутаційне з'єднання? Overall operation failed. Помилка загальної операції. Invalid or unsupported option. Некоректний або непідтримуваний параметр. Client name not unique. Назва клієнта не є унікальною. Server is started. Сервер запущено. Unable to connect to server. Неможливо з'єднатися з сервером. Server communication error. Помилка обміну даними із сервером. Client does not exist. Клієнта не існує. Unable to load internal client. Не вдалося завантажити внутрішній клієнт. Unable to initialize client. Не вдалося ініціалізувати клієнт. Unable to access shared memory. Не вдалося отримати доступ до спільної пам'яті. Client protocol version mismatch. Невідповідність версії протоколу клієнта. Could not connect to JACK server as client. - %1 Please check the messages window for more info. Не вдалося встановити з'єднання із сервером JACK як клієнтом. - %1 Будь ласка, ознайомтеся із даними вікна повідомлень, щоб дізнатися більше. Server configuration saved to "%1". Налаштування сервера збережено до «%1». Client activated. Активовано клієнт. Post-startup script... Виконуємо скрипт після запуску… Post-startup script terminated Виконання скрипту після запуску перервано Command line argument... Аргумент командного рядка… Command line argument started Запущено аргумент командного рядка Client deactivated. Клієнт деактивовано. Transport rewind. Перемотування передавання назад до кінця. Transport backward. Перемотування передавання назад. Starting Запуск Transport start. Запуск передавання. Stopping Зупинення Transport stop. Зупинення передавання. Transport forward. Перемотування вперед до кінця. Stopped Зупинено %1 (%2%) %1 (%2%) %1 (%2%, %3 xruns) %1 (%2%, %3 xrun-ів) %1 % %1 % %1 Hz %1 Гц %1 frames %1 кадрів Yes Так No Ні FW ВХ RT РЧ Rolling Прокручування Looping Цикл %1 msec %1 мс XRUN callback (%1 skipped). Зворотний виклик XRUN (%1 пропущено). Started Запущено Active Активний Activating Активація Inactive Неактивний Mi&nimize Мін&імізувати Rest&ore Від&новити &Hide При&ховати S&how По&казати &Stop З&упинити &Reset &Скинути &Presets &Набори параметрів &Load... Заванта&жити… &Save... З&берегти… Save and &Quit... Зберегти та ви&йти… Save &Template... Зберегти &шаблон… &Versioning &Керування версіями Re&fresh О&новити St&atus С&тан &Connections З'&єднання Patch&bay &Комутація &Transport П&ередавання Some settings will be only effective the next time you start this program. Деякі з параметрів набудуть чинності лише після наступного запуску програми. D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS: GetParameterConstraint('%1'): %2. (%3) D-BUS: GetParameterConstraint('%1'): %2. (%3) qjackctlMessagesStatusForm Messages / Status Повідомлення/Стан &Messages &Повідомлення Messages log Журнал повідомлень Messages output log Журнал вихідних повідомлень &Status С&тан Status information Відомості щодо стану Statistics since last server startup Статистика з моменту останнього запуску сервера Description Опис Value Значення Reset XRUN statistic values Скинути значення статистики XRUN Re&set С&кинути Refresh XRUN statistic values Освіжити значення статистики XRUN &Refresh &Оновити Server name Назва сервера Server state Стан сервера DSP Load Завантаження ЦОС Sample Rate Частота дискретизації Buffer Size Розмір буфера Realtime Mode Режим реального часу Transport state Стан передавання Transport Timecode Часовий код передавання Transport BBT BBT передавання Transport BPM Ритм передавання XRUN count since last server startup Кількість XRUN з моменту останнього запуску сервера XRUN last time detected Останній зафіксований XRUN XRUN last Останній XRUN XRUN maximum Максимальна кількість XRUN XRUN minimum Мінімальна кількість XRUN XRUN average Середня кількість XRUN XRUN total Загальна кількість XRUN Maximum scheduling delay Максимальна затримка планування Time of last reset Час останнього скидання Logging stopped --- %1 --- Записування до журналу зупинено --- %1 --- Logging started --- %1 --- Розпочато записування до журналу --- %1 --- qjackctlPaletteForm Color Themes Теми кольорів Name Назва Current color palette name Назва поточної палітри кольорів Save current color palette name Зберегти назву поточної палітри кольорів Save Зберегти Delete current color palette name Вилучити назву поточної палітри кольорів Delete Вилучити Palette Палітра Current color palette Поточна палітра кольорів Generate: Створити: Base color to generate palette Базовий колір для створення палітри Reset all current palette colors Скинути усі кольори поточної палітри Reset Скинути Import a custom color theme (palette) from file Імпортувати нетипову тему кольорів (палітру) з файла Import... Імпортувати… Export a custom color theme (palette) to file Експортувати нетипову тему кольорів (палітру) до файла Export... Експортувати… Show Details Показати подробиці Import File - %1 Імпорт файла – %1 Palette files (*.%1) файли палітр (*.%1) Save Palette - %1 All files (*.*) усі файли (*.*) Warning - %1 Попередження – %1 Could not import from file: %1 Sorry. Не вдалося імпортувати дані з файла: %1 Вибачте. Export File - %1 Експорт файла – %1 Some settings have been changed. Do you want to discard the changes? Значення деяких параметрів було змінено. Хочете відкинути внесені зміни? Some settings have been changed: "%1". Do you want to save the changes? Деякі з параметрів було змінено: «%1». Хочете зберегти внесені зміни? qjackctlPaletteForm::PaletteModel Color Role Роль кольору Active Активний Inactive Неактивний Disabled Вимкнений qjackctlPatchbay Warning Попередження This will disconnect all sockets. Are you sure? У результаті буде роз'єднано усі сокети. Ви справді цього хочете? qjackctlPatchbayForm Patchbay Комутація Move currently selected output socket down one position Пересунути позначений вихідний сокет вниз на одну позицію Down Нижче Create a new output socket Створити вихідний сокет Add... Додати… Edit currently selected input socket properties Змінити властивості поточного позначеного вхідного сокета Edit... Змінити… Move currently selected output socket up one position Пересунути поточний позначений вихідний сокет вгору на одну позицію Up Вище Remove currently selected output socket Вилучити поточний позначений вихідний сокет Remove Вилучити Duplicate (copy) currently selected output socket Дублювати (копіювати) поточний позначений вихідний сокет Copy... Копіювати… Remove currently selected input socket Вилучити поточний позначених вхідний сокет Duplicate (copy) currently selected input socket Дублювати (копіювати) поточний позначений вхідний сокет Create a new input socket Створити вхідний сокет Edit currently selected output socket properties Змінити властивості поточного позначеного вихідного сокета Connect currently selected sockets З'єднати поточні позначені сокети &Connect &З'єднати Disconnect currently selected sockets Роз'єднати поточні позначені сокети &Disconnect Роз'&єднати Disconnect all currently connected sockets Роз'єднати усі з'єднані сокети Disconnect &All Роз'єд&нати все Expand all items Розгорнути усі пункти E&xpand All Роз&горнути все Refresh current patchbay view Освіжити поточний вміст панелі комутації &Refresh &Оновити Create a new patchbay profile Створити профіль комутації &New С&творити Load patchbay profile Завантажити профіль комутації &Load... З&авантажити… Save current patchbay profile Зберегти поточний профіль комутації &Save... З&берегти… Current (recent) patchbay profile(s) Поточні (нещодавні) профілі комутації Toggle activation of current patchbay profile Перемкнути активацію поточного профілю комутації Acti&vate А&ктивувати Warning Попередження The patchbay definition has been changed: "%1" Do you want to save the changes? Визначення комутації було змінено: «%1» Хочете зберегти внесені зміни? %1 [modified] %1 [змінено] Untitled%1 Без назви%1 Error Помилка Could not load patchbay definition file: "%1" Не вдалося завантажити файл визначення комутації: «%1» Could not save patchbay definition file: "%1" Не вдалося зберегти файл визначення комутації: «%1» New Patchbay definition Нове визначення комутації Create patchbay definition as a snapshot of all actual client connections? Створити визначення комутації як знімок усіх дійсних клієнтських з'єднань? Load Patchbay Definition Завантаження визначення комутації Patchbay Definition files файли визначень комутації Save Patchbay Definition Збереження визначення комутації active активний qjackctlPatchbayView Add... Додати… Edit... Змінити… Copy... Копіювати… Remove Вилучити Exclusive Виключний Forward Вперед (None) (Немає) Move Up Пересунути вище Move Down Пересунути нижче &Connect З'&єднати Alt+C Connect Alt+C &Disconnect Роз'є&днати Alt+D Disconnect Роз'єднати Disconnect &All Роз'єд&нати все Alt+A Disconnect All Alt+A &Refresh &Оновити Alt+R Refresh Alt+R qjackctlSessionForm Session Сеанс Load session Завантажити сеанс &Load... З&авантажити… Recent session Нещодавній сеанс &Recent Не&щодавні Save session Зберегти сеанс &Save З&берегти &Versioning &Керування версіями Update session Оновити сеанс Re&fresh О&новити Session clients / connections Клієнти та з'єднання сеансу Client / Ports Клієнт/Порти UUID UUID Command Команда Infra-clients / commands Клієнти та команди інфраструктури Infra-client Інфраклієнт Infra-command Інфракоманда Add infra-client Додати інфраклієнт &Add &Додати Edit infra-client Змінити інфраклієнт &Edit З&мінити Remove infra-client Вилучити інфраклієнт Re&move Ви&лучити &Save... З&берегти… Save and &Quit... Зберегти та ви&йти… Save &Template... Зберегти &шаблон… Load Session Завантажити сеанс Session directory Каталог сеансів Save Session Зберегти сеанс and Quit і вийти Template Шаблон &Clear Сп&орожнити Warning Попередження A session could not be found in this folder: "%1" Не вдалося знайти сеанс у цій теці: "%1" %1: loading session... %1: завантажуємо сеанс... %1: load session %2. %1:завантажити сеанс %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? У цій теці вже існує сеанс: «%1» Ви справді хочете перезаписати наявний сеанс? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Ця тека вже існує і містить дані: «%1» Ви справді хочете перезаписати вміст наявної теки? %1: saving session... %1: зберігаємо сеанс… %1: save session %2. %1: зберегти сеанс %2. New Client Новий клієнт qjackctlSessionInfraClientItemEditor Infra-command Інфракоманда qjackctlSessionSaveForm Session Сеанс &Name: &Назва: Session name &Directory: Session directory Каталог сеансів Browse for session directory ... ... Save session versioning Зберегти версію сеансу &Versioning &Керування версіями Warning Попередження Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Setup Налаштування Settings Параметри Preset &Name: &Назва набору параметрів: Settings preset name Назва набору параметрів (default) (типовий) Clear settings of current preset name Вилучити параметри набору із поточною назвою Clea&r О&чистити Save settings as current preset name Зберегти параметри із поточною назвою набору &Save З&берегти Delete current settings preset Вилучити поточний набір параметрів &Delete Ви&лучити Parameters Параметри Driv&er: Дра&йвер: The audio backend driver interface to use Інтерфейс драйвера модуля звукової системи, яким слід скористатися dummy dummy sun sun oss oss alsa alsa portaudio portaudio coreaudio coreaudio firewire firewire net net netone netone &Interface: &Інтерфейс: The PCM device name to use Назва пристрою PCM, якою слід скористатися hw:0 hw:0 plughw:0 plughw:0 /dev/audio /dev/audio /dev/dsp /dev/dsp MIDI Driv&er: Д&райвер MIDI: The ALSA MIDI backend driver to use Драйвер модуля MIDI ALSA, яким слід скористатися none немає raw raw seq синтезатор Use realtime scheduling Використовувати планування у режимі реального часу &Realtime &Реальний час Sample &Rate: &Частота дискретизації: Sample rate in frames per second Частота дискретизації у кадрах за секунду 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 192000 192000 &Frames/Period: &Кадрів/Період: Frames per period between process() calls Кількість кадрів за період між викликами process() 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Periods/&Buffer: Періодів/&Буфер: Number of periods in the hardware buffer Кількість періодів в апаратному буфері Whether to use server synchronous mode Чи слід використовувати синхронний режим сервера &Use server synchronous mode Син&хронний режим сервера Whether to give verbose output on messages Чи слід виводити докладні повідомлення &Verbose messages &Режим докладних повідомлень Latency: Латентність: Output latency in milliseconds, calculated based on the period, rate and buffer settings Виводити латентність у мілісекундах, обчислену на основі періоду, частоти та параметрів буфера 0 msecs 0 мс Advanced Додатково Please do not touch these settings unless you know what you are doing. Будь ласка, не змінюйте значення цих параметрів, якщо ви не певні. Server &Prefix: П&рефікс сервера: Server path (command line prefix) Шлях до сервера (префікс командного рядка) jackd jackd jackdmp jackdmp jackstart jackstart &Name: &Назва: The JACK Audio Connection Kit sound server name Назва звукового сервера набору інструментів звукових з'єднань JACK Do not attempt to lock memory, even if in realtime mode Не намагатися блокувати пам'ять, навіть якщо робота відбувається у режимі реального часу No Memory Loc&k Не &блокувати пам'ять Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) Розблокувати пам'ять типових бібліотек наборів інструментів (GTK+, QT, FLTK, Wine) &Unlock Memory &Розблокувати пам'ять Enable hardware metering on cards that support it Увімкнути апаратне вимірювання на картках, для яких передбачено його підтримку H/&W Meter &Апаратни вимірювач Provide output monitor ports Надати порти спостереження за виведенням &Monitor Сп&остерігати Ignore xruns reported by the backend driver Ігнорувати xrun-и, про які повідомляє драйвер модуля обробки So&ft Mode П&рограмний режим Force 16bit mode instead of failing over 32bit (default) Примусово встановити 16-бітовий режим замість типового 32-бітового Force &16bit Примусовий &16-бітовий Ignore hardware period/buffer size Ігнорувати апаратні розмір період/буфер &Ignore H/W &Ігнорувати апаратні Priorit&y: Пріори&тетність: Scheduler priority when running realtime Пріоритетність планувальника при роботі у режимі реального часу &Word Length: Дов&жина слова: Word length Довжина слова &Wait (usec): &Очікування (у мкс): Number of microseconds to wait between engine processes (dummy) Тривалість очікування у мікросекундаж між процесами рушія (фіктивними) 21333 21333 &Channels: &Канали: Maximum number of audio channels to allocate Максимальна кількість звукових каналів для резервування Port Ma&ximum: &Максимальна к-ть портів: Maximum number of ports the JACK server can manage Максимальна кількість портів, якими може керувати сервер JACK &Timeout (msec): &Час очікування (у мкс): Set client timeout limit in milliseconds Встановити граничний час очікування клієнта у мілісекундах 200 200 500 500 1000 1000 2000 2000 5000 5000 Cloc&k source: Д&жерело годинника: Clock source Джерело даних годинника &Audio: &Звук: Provide either audio capture, playback or both Надання даних для захоплення звуку, для відтворення звуку або обох типів Duplex Двобічний Capture Only Лише захоплення Playback Only Лише відтворення Dit&her: Під&мішування шуму: Set dither mode Встановити режим підмішування шуму None Немає Rectangular Прямокутне Shaped За формою Triangular Трикутна &Output Device: В&ихідний пристрій: Alternate output device for playback Змінити пристрій виведення для відтворення &Input Device: В&хідний пристрій: Alternate input device for capture Змінити вхідний пристрій для захоплення даних &Channels I/O: Ка&нали ВВ: Maximum input audio hardware channels to allocate Максимальна кількість вхідних апаратних звукових каналів для резервування Maximum output audio hardware channels to allocate Максимальна кількість вихідних апаратних звукових каналів для резервування &Latency I/O: &Латентність ВВ: External input latency (frames) Латентність зовнішнього входу (у кадрах) External output latency (frames) Латентність зовнішнього виходу (у кадрах) S&elf connect mode: Режим са&моз'єднання: Whether to restrict client self-connections Чи слід обмежувати самоз'єднання клієнтів Server Suffi&x: Су&фікс сервера: Extra driver options (command line suffix) Додаткові параметри драйвера (суфікс командного рядка) Start De&lay: Затримка за&пуску: Time in seconds that client is delayed after server startup Час у секундах затримки запуску клієнта після запуску сервера secs секунд Options Налаштування Scripting Скрипти Whether to execute a custom shell script before starting up the JACK audio server. Чи слід виконувати нетиповий скрипт оболонки перед запуском звукового сервера JACK. Execute script on Start&up: Виконати скрипт при зап&уску: Whether to execute a custom shell script after starting up the JACK audio server. Чи слід виконувати нетиповий скрипт оболонки після запуску звукового сервера JACK. Execute script after &Startup: Виконати скрипт після з&апуску: Whether to execute a custom shell script before shuting down the JACK audio server. Чи слід виконувати нетиповий скрипт оболонки до завершення роботи звукового сервера JACK. Execute script on Shut&down: Виконати с&крипт при вимиканні: Command line to be executed before starting up the JACK audio server Рядок команди, яку буде виконано перед запуском звукового сервера JACK Scripting argument meta-symbols Метасимволи аргументу скрипту > > Browse for script to be executed before starting up the JACK audio server Вибрати скрипт, який буде виконано перед запуском звукового сервера JACK ... ... Command line to be executed after starting up the JACK audio server Рядок команди, яку буде виконано після запуску звукового сервера JACK Browse for script to be executed after starting up the JACK audio server Вибрати скрипт, який буде виконано після запуску звукового сервера JACK Browse for script to be executed before shutting down the JACK audio server Вибрати скрипт, який буде виконано до вимикання звукового сервера JACK Command line to be executed before shutting down the JACK audio server Рядок команди, яку буде виконано перед вимиканням звукового сервера JACK Whether to execute a custom shell script after shuting down the JACK audio server. Чи слід виконувати нетиповий скрипт оболонки після завершення роботи звукового сервера JACK. Execute script after Shu&tdown: Виконати скрипт післ&я вимикання: Browse for script to be executed after shutting down the JACK audio server Вибрати скрипт, який буде виконано після вимикання звукового сервера JACK Command line to be executed after shutting down the JACK audio server Рядок команди, яку буде виконано після вимикання звукового сервера JACK Statistics Статистика Whether to capture standard output (stdout/stderr) into messages window Чи слід захоплювати дані зі стандартного виведення (stdout/stderr) до вікна повідомлень &Capture standard output За&хоплювати стандартне виведення &XRUN detection regex: &Формальний вираз для виявлення XRUN: Regular expression used to detect XRUNs on server output messages Формальний вираз, який буде використано для виявлення XRUN-ів серед виведених сервером повідомлень xrun of at least ([0-9|\.]+) msecs xrun of at least ([0-9|\.]+) msecs Connections З'єднання Whether to activate a patchbay definition for connection persistence profile. Чи слід активувати визначення комутації для постійного профілю з'єднання. Activate &Patchbay persistence: &Активувати сталу комутацію: Patchbay definition file to be activated as connection persistence profile Файл визначення комутації, який слід задіяти як постійний профіль з'єднання Browse for a patchbay definition file to be activated Вибрати файл визначення комутації, який має бути активовано Whether to reset all connections when a patchbay definition is activated. Чи слід скидати усі з'єднання при активації визначення комутації. &Reset all connections on patchbay activation С&кидати усі з'єднання при активації комутації Whether to issue a warning on active patchbay port disconnections. Чи слід попереджати при від'єднанні активних портів комутації. &Warn on active patchbay disconnections &Попереджати при активних з'єднаннях комутації Logging Журналювання Whether to activate a messages logging to file. Чи слід активувати журналювання повідомлень до файла. &Messages log file: Фа&йл журналу повідомлень: Messages log file Файл журналу повідомлень Browse for the messages log file location Вибрати розташування файла журналу повідомлень Display Дисплей Time Display Показ часу Transport &Time Code &Часова позначка передавання Transport &BBT (bar:beat.ticks) BBT п&ередавання (bar:beat.ticks) Elapsed time since last &Reset Час з моменту останн&ього скидання Elapsed time since last &XRUN Час з моменту останньо&го XRUN Sample front panel normal display font Зразок звичайного шрифту дисплея передньої панелі Sample big time display font Зразок шрифту показу великих символів часу Big Time display: Великий дисплей часу: Select font for front panel normal display Виберіть шрифт для звичайного дисплея передньої панелі &Font... &Шрифт… Select font for big time display Вибрати шрифт для показу великих символів часу Normal display: Звичайний дисплей: Whether to enable blinking (flashing) of the server mode (RT) indicator Чи слід вмикати блимання індикатор режиму сервера (РЧ) Blin&k server mode indicator &Блимати індикатором режиму сервера Custom Нетипове &Color palette theme: Тема палітри &кольорів: Custom color palette theme Нетипова тема палітри кольорів Wonton Soup Wonton Soup KXStudio KXStudio Manage custom color palette themes Керувати нетиповими темами палітри кольорів &Widget style theme: Тема стил&ю віджетів: Custom widget style theme Нетипова тема стилю віджетів Messages Window Вікно повідомлень Sample messages text font display Зразок показу шрифту тексту повідомлень Select font for the messages text display Вибрати шрифт для показу тексту повідомлень Whether to keep a maximum number of lines in the messages window Чи слід обмежувати максимальну кількість рядків у вікні повідомлень &Messages limit: Об&меження кількості повідомлень: The maximum number of message lines to keep in view Максимальна кількість рядків повідомлень, які слід зберігати на панелі перегляду 100 100 250 250 2500 2500 Connections Window Вікно з'єднань Sample connections view font Зразок шрифту панелі з'єднань Select font for the connections view Вибрати шрифт для панелі з'єднаь &Icon size: &Розмір піктограм: The icon size for each item of the connections view Розмір піктограм для пунктів панелі перегляду з'єднань 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 Whether to enable client/port name aliases on the connections window Чи слід вмикати альтернативні назви клієнтів/портів у вікні з'єднань E&nable client/port aliases &Увімкнути альтернативи клієнтів/портів &JACK client/port aliases: А&льтернативи клієнта/порту JACK: JACK client/port aliases display mode Режим показу альтернатив клієнта/порту JACK Default Типова First Перша Second Друга Whether to enable in-place client/port name editing (rename) Чи слід дозволяти редагування назви (перейменування) клієнта/порту Ena&ble client/port aliases editing (rename) Дозволити &редагування (перейменування) альтернатив клієнта/порту JACK client/port pretty-name (metadata) display mode Режим показу форматованих назв (метаданих) клієнта/порту JACK Enable JA&CK client/port pretty-names (metadata) Уві&мкнути форматовані назви (метадані) клієнта/порту JACK Misc Різне Other Інше Whether to start JACK audio server immediately on application startup Чи слід запускати звуковий сервер JACK одразу після запуску програми &Start JACK audio server on application startup За&пускати звуковий сервер JACK після запуску програми Whether to ask for confirmation on application exit Чи слід просити підтвердження виходу з програми &Confirm application close П&ідтверджувати вихід з програми Whether to ask for confirmation on JACK audio server shutdown and/or restart Чи слід просити підтвердження при вимиканні і/або перезапуску звукового сервера JACK Confirm server sh&utdown and/or restart Підтверд&жувати вимикання і/або перезапуск сервера Whether to keep all child windows on top of the main window Чи слід тримати усі дочірні вікна над головним вікном &Keep child windows always on top Завжди у&тримувати дочірні вікна нагорі Whether to enable the system tray icon Чи слід вмикати піктограму системного лотка &Enable system tray icon Ввімкнути пі&ктограму у системному лотку Whether to show system tray message on main window close Чи слід показувати повідомлення у системному лотку у відповідь на закриття головного вікна Sho&w system tray message on close Повід&омлення у системному лотку при закритті Whether to start minimized to system tray Чи слід запускати програму згорнутою до системного лотка Start minimi&zed to system tray Запускати з&горнутою до системного лотка Whether to save the JACK server command-line configuration into a local file (auto-start) Чи слід зберігати налаштування командного рядка сервера JACK до локального файла (автозапуск) S&ave JACK audio server configuration to: З&берігати налаштування звукового сервера JACK до: The server configuration local file name (auto-start) Назва локального файла налаштувань сервера (автозапуск) .jackdrc .jackdrc Whether to enable ALSA Sequencer (MIDI) support on startup Чи слід вмикати підтримку синтезатора ALSA (MIDI) під час запуску E&nable ALSA Sequencer support &Увімкнути підтримку синтезатора ALSA Whether to enable D-Bus interface Чи слід вмикати інтерфейс D-Bus &Enable D-Bus interface Увімк&нути інтерфейс D-Bus Whether to enable JACK D-Bus interface Чи слід увімкнути інтерфейс D-Bus JACK &Enable JACK D-Bus interface Увімк&унти інтерфейс D-Bus JACK Whether to stop JACK audio server on application exit Чи слід вимикати звуковий сервер JACK під час виходу з програми S&top JACK audio server on application exit Вими&кати звуковий сервер JACK при виході з програми Whether to restrict to one single application instance (X11) Чи слід обмежувати кількість екземплярів програми одним (X11) Single application &instance Один екземпл&яр програми Buttons Кнопки Whether to hide the left button group on the main window Чи слід ховати ліву групу кнопок у головному вікні Hide main window &Left buttons Ховати &ліві кнопки у головному вікні Whether to hide the right button group on the main window Чи слід ховати праву групу кнопок у головному вікні Hide main window &Right buttons Ховати &праві кнопки у головному вікні Whether to hide the transport button group on the main window Чи слід ховати групу кнопок передавання у головному вікні Hide main window &Transport buttons Ховати кнопки п&ередавання у головному вікні Whether to hide the text labels on the main window buttons Чи слід ховати текстові мітки на кнопках головного вікна Hide main window &button text labels Ховати текстові мітки на &кнопках головного вікна Whether to replace Connections with Graph button on the main window Чи слід замінити кнопку «З'єднання» у головному вікні на кнопку «Граф» Replace Connections with &Graph button Замінити кнопку «З'єднання» на кнопку «&Граф» Defaults Типові параметри &Base font size: &Основний розмір шрифту: Base application font size (pt.) Базовий розмір шрифту програми (у пунктах) 6 6 7 7 8 8 9 9 10 10 11 11 12 12 System Система Cycle Цикл HPET HPET Don't restrict self connect requests (default) Не обмежувати запити щодо самоз'єднання (типовий варіант) Fail self connect requests to external ports only Відмовляти у всіх запитах щодо самоз'єднання лише для зовнішніх портів Ignore self connect requests to external ports only Ігнорувати запити щодо самоз'єднання лише для зовнішніх портів Fail all self connect requests Відмовляти в усіх запитах щодо самоз'єднання Ignore all self connect requests Ігнорувати усі запити щодо самоз'єднання Warning Попередження Some settings have been changed: "%1" Do you want to save the changes? До деяких параметрів було внесено зміни: «%1» Хочете зберегти внесені зміни? Delete preset: "%1" Are you sure? Вилучення набору параметрів: «%1» Ви справді цього хочете? msec мс n/a н/д &Preset Name Назва н&абору параметрів &Server Name Назва с&ервера &Server Path &Шлях до сервера &Driver Д&райвер &Interface &Інтерфейс Sample &Rate &Частота дискретизації &Frames/Period &Кадри/Період Periods/&Buffer Періоди/&Буфер Startup Script Скрипт запуску Post-Startup Script Скрипт після запуску Shutdown Script Скрипт при вимиканні Post-Shutdown Script Скрипт після вимикання Active Patchbay Definition Активне визначення комутації Patchbay Definition files файли визначень комутацій Messages Log Журнал повідомлень Log files файли журналу Information Інформація Some settings may be only effective next time you start this application. Деякі параметри набудуть чинності лише після перезапуску програми. Some settings have been changed. Do you want to apply the changes? До деяких параметрів було внесено зміни. Хочете застосувати ці зміни? qjackctlSocketForm Socket Сокет &Socket С&окет &Name (alias): &Назва (псевдонім): Socket name (an alias for client name) Назва сокета (альтернатива назві клієнта) Client name (regular expression) Назва клієнта (формальний вираз) Add plug to socket plug list Додати втулку до списку втулок сокета Add P&lug Додати вт&улку &Plug: В&тулка: Port name (regular expression) Назва порту (формальний вираз) Socket plug list Список втулок сокета Socket Plugs / Ports Втулки/Порти сокета Edit currently selected plug Редагувати поточну позначену втулку &Edit З&мінити Remove currently selected plug from socket plug list Вилучити поточну позначену втулку зі списку втулок сокета &Remove Ви&лучити &Client: &Клієнт: Move down currently selected plug in socket plug list Пересунути поточну позначену втулку нижче у списку втулок сокета &Down &Вниз Move up current selected plug in socket plug list Пересунути поточну позначену втулку вище у списку втулок сокета &Up &Вище Enforce only one exclusive cable connection Примусово використовувати лише одне виключне з'єднання кабелю E&xclusive В&иключний &Forward: Пе&респрямування: Forward (clone) all connections from this socket Переспрямувати (клонувати) усі з'єднання з цього сокета Type Тип Audio socket type (JACK) Тип звукового сокета (JACK) &Audio Зв&уковий MIDI socket type (JACK) Тип сокета MIDI (JACK) &MIDI &MIDI MIDI socket type (ALSA) Тип сокета MIDI (ALSA) AL&SA AL&SA Plugs / Ports Втулки/Порти Error Помилка A socket named "%1" already exists. Сокет із назвою «%1» вже існує. Warning Попередження Some settings have been changed. Do you want to apply the changes? Деякі з параметрів було змінено. Хочете застосувати внесені зміни? Add Plug Додати втулку Edit Змінити Remove Вилучити Move Up Пересунути вище Move Down Пересунути нижче (None) (Немає) qjackctlSocketList Output Вихід Input Вхід Socket Сокет <New> - %1 <Новий> – %1 Warning Попередження %1 about to be removed: "%2" Are you sure? Зараз буде вилучено %1: «%2» Ви певні? %1 <Copy> - %2 %1 <Копія> – %2 qjackctlSocketListView Output Sockets / Plugs Вихідні сокети/втулки Input Sockets / Plugs Вхідні сокети/втулки qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_fr.ts0000644000000000000000000000013214771215054020537 xustar0030 mtime=1743067692.333636546 30 atime=1743067692.333636546 30 ctime=1743067692.333636546 qjackctl-1.0.4/src/translations/qjackctl_fr.ts0000644000175000001440000064642714771215054020552 0ustar00rncbcusers PortAudioProber Probing... Détection… Please wait, PortAudio is probing audio hardware. Merci de patienter, PortAudio détecte le matériel audio. Warning Attention Audio hardware probing timed out. La détection du matériel audio a échoué. QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Option -p requires an argument (preset). L'option -p nécessite un argument (préréglage). Usage: %1 [options] [command-and-args] Utilisation : %1 [options] [commandes-et-args] Options: Options : Start JACK audio server immediately. Démarrez le serveur audio JACK immédiatement. Set default settings preset name. Définir le nom de la présélection des paramètres par défaut. Set active patchbay definition file. Paramètre le fichier de définition de patchbay actif. Set default JACK audio server name. Paramètre le fichier de définition de baie de brassage active. Show help about command line options. Affiche l'aide à propos des options en ligne de commande. Show version information. Afficher les informations de version. Launch command with arguments. Lancer la commande avec des arguments. [command-and-args] [commande-et-arguments] Option -a requires an argument (path). L'option -a nécessite un argument (chemin). Option -n requires an argument (name). L'option -n nécessite un argument (nom). %1 (%2 frames) %1 (%2 échantillons) Move Déplacer Rename Renommer qjackctlAboutForm About À propos About Qt À propos de Qt &Close &Fermer Version Version Debugging option enabled. Option de débogage activée. System tray disabled. Zone de notification système désactivée. Transport status control disabled. Contrôle du statut du déplacement désactivé. Realtime status disabled. Statut temps réel désactivé. XRUN delay status disabled. Statut du délai de désynchronisation (XRUN) désactivé. Maximum delay status disabled. Statut du délai maximal désactivé. JACK Session support disabled. Prise en charge de session JACK désactivée. ALSA/MIDI sequencer support disabled. Prise en charge du séquenceur ALSA/MIDI désactivée. Using: Qt %1 Utilisant : Qt %1 JACK %1 JACK %1 Website Site ouèbe This program is free software; you can redistribute it and/or modify it Ce programme est libre; vous pouvez le redistribuer et/ou le modifier under the terms of the GNU General Public License version 2 or later. selon les termes de la Licence Publique Générale GNU version 2 ou ultérieure. JACK MIDI support disabled. Prise en charge de JACK MIDI désactivée. JACK Port aliases support disabled. Prise en charge des alias de port JACK désactivée. D-Bus interface support disabled. Prise en charge de l'interface D-Bus désactivée. qjackctlClientListView &Connect &Connecter Alt+C Connect Alt+C &Disconnect &Déconnecter Alt+D Disconnect Alt+D Disconnect &All &Tout déconnecter Alt+A Disconnect All Alt+T Re&name Re&nommer Alt+N Rename Alt+N &Refresh &Rafraîchir Alt+R Refresh Alt+R Readable Clients / Output Ports Clients en lecture / Ports de sortie Writable Clients / Input Ports Clients en écriture / Ports d'entrée qjackctlConnect Warning Attention This will suspend sound processing from all client applications. Are you sure? Cela va suspendre le traitement du son de toutes les applications clientes. Êtes-vous certain ? qjackctlConnectionsForm Audio Audio &Connect &Connecter Connect currently selected ports Connecter les ports actuellement sélectionnés &Disconnect &Déconnecter Disconnect currently selected ports Déconnecter les ports actuellement sélectionnés Disconnect &All &Tout déconnecter Disconnect all currently connected ports Déconnecter tous les ports actuellement connectés Connections Connexions Expand all client ports Afficher tous les ports clients E&xpand All &Afficher tout &Refresh &Rafraîchir Refresh current connections view Rafraîchir la vue actuelle des connexions MIDI MIDI ALSA ALSA qjackctlConnectorView &Connect &Connecter Alt+C Connect Alt+C &Disconnect &Déconnecter Alt+D Disconnect Alt+D Disconnect &All &Tout déconnecter Alt+A Disconnect All Alt+T &Refresh &Rafraîchir Alt+R Refresh Alt+R qjackctlGraphCanvas Connect Connecter Disconnect Déconnecter qjackctlGraphForm Graph Graphe &Graph &Graphe &Edit É&dition &View &Affichage &Zoom &Zoom Co&lors Cou&leurs S&ort &Trier &Help &Aide &Connect &Connecter Connect Connecter Connect selected ports Connecter les ports sélectionnés &Disconnect &Déconnecter Disconnect Déconnecter Disconnect selected ports Déconnecter les ports sélectionnés Ctrl+C T&humbview &Vue d'ensemble Ctrl+D Cl&ose &Fermer Close Fermer Close this application window Fermer cette fenêtre d'application Select &All &Tout sélectionner Select All Tout sélectionner Ctrl+A Ctrl+A Select &None Ne &rien sélectionner Select None Ne rien sélectionner Ctrl+Shift+A Ctrl+Shift+A Select &Invert Sélection &inversée Select Invert Sélection inversée Ctrl+I Ctrl+I &Rename... &Renommer… Rename item Renommer l'élément Rename Item Renommer l'élément F2 F2 &Find... &Chercher... Find Chercher Find nodes Chercher les nœuds Ctrl+F &Menubar Barre de &menu Menubar Barre de menu Show/hide the main program window menubar Afficher/cacher la barre de menu de la fenêtre principale du programme Ctrl+M Ctrl+M &Toolbar Barre d'ou&tils Toolbar Barre d'outils Show/hide main program window file toolbar Afficher/cacher la barre d''outils du fichier de la fenêtre principale du programme &Statusbar Barre de &status Statusbar Barre de status Show/hide the main program window statusbar Afficher/cacher la barre de status de la fenêtre principale du programme &Top Left Hau&t gauche Top left Haut gauche Show the thumbnail overview on the top-left Afficher l'aperçu des vignettes en haut à gauche Top &Right Haut d&roit Top right Haut droit Show the thumbnail overview on the top-right Afficher l'aperçu des vignettes en haut à droite Bottom &Left Bas gauc&he Bottom Left Bas gauche Bottom left Bas gauche Show the thumbnail overview on the bottom-left Afficher l'aperçu des vignettes en bas à gauche &Bottom Right &Bas droite Bottom right Bas droite Show the thumbnail overview on the bottom-right Afficher l'aperçu des vignettes en bas à droite &None Aucu&n None Aucun Hide thumbview Cacher l'affichage des vignettes Hide the thumbnail overview Masquer l'aperçu des vignettes Text Beside &Icons Texte derrière les &icônes Text beside icons Texte derrière les icônes Show/hide text beside icons Afficher/cacher le texte derrière les icônes &Center &Centre Center Centre Center view Affichage centré &Refresh &Rafraîchir Refresh Rafraîchir Refresh view Rafraîchir l'affichage F5 F5 Zoom &In Zoom a&vant Zoom In Zoom avant Ctrl++ Ctrl++ Zoom &Out Zoom a&rrière Zoom Out Zoom arrière Ctrl+- Ctrl+- Zoom &Fit Zoom &ajusté Zoom Fit Zoom ajusté Ctrl+0 Ctrl+0 Zoom &Reset &Réinitialiser le zoom Zoom Reset Réinitialiser le zoom Ctrl+1 Ctrl+1 &Zoom Range Gamme de &zoom Zoom Range Gamme de zoom JACK &Audio... JACK &audio… JACK Audio color Couleur JACK audio JACK &MIDI... JACK &MIDI… JACK MIDI JACK MIDI JACK MIDI color Couleur JACK MIDI ALSA M&IDI... ALSA M&IDI... ALSA MIDI ALSA MIDI ALSA MIDI color Couleur ALSA MIDI JACK &CV... JACK &CV... JACK CV color Couleur JACK CV JACK &OSC... JACK &OSC... JACK OSC JACK OSC JACK OSC color Couleur JACK OSC &Reset &Réinitialiser Reset colors Réinitialiser les couleurs Port &Name &Nom de port Port name Nom de port Sort by port name Trier par nom de port Port &Title &Titre de port Port title Titre de port Sort by port title Trier par titre de port Port &Index &Index de port Port index Index de port Sort by port index Trier par index de port &Ascending &Ascendant Ascending Ascendant Ascending sort order Ordre de tri ascendant &Descending &Descendant Descending Descendant Descending sort order Ordre de tri descendant Repel O&verlapping Nodes Repousser les nœuds qui se che&vauchent Repel nodes Repousser les nœuds Repel overlapping nodes Repousser les nœuds qui se chevauchent Connect Thro&ugh Nodes Connexion par les nœ&uds Connect Through Nodes Connexion par les nœuds Connect through nodes Connexion par les nœuds Whether to draw connectors through or around nodes Si les connecteurs doivent être dessinés à travers ou autour des nœuds &About... À &propos… About... À propos… About À propos Show information about this application program Afficher les informations à propos de ce programme applicatif About &Qt... À propos de &Qt… About Qt... À propos de Qt… About Qt À propos de Qt Show information about the Qt toolkit Afficher les informations à propos de la boîte à outils Qt &Undo &Défaire &Redo &Refaire Undo last edit action Défaire la dernière action d'édition Redo last edit action Refaire la dernière action d'édition Zoom Zoom Ready Prêt Colors - %1 Couleurs - %1 qjackctlMainForm &Quit &Quitter Quit processing and exit Quitter le traitement et sortir &Start &Démarrer Start the JACK server Démarrer le serveur JACK S&top &Arrêter Stop the JACK server Arrêter le serveur JACK St&atus S&tatut Ab&out... À pr&opos… Show information about this application Montrer des informations à propos de cette application Show settings and options dialog Montrer la fenêtre d'options et de paramètres &Messages &Messages &Patchbay &Baie de brassage Show/hide the patchbay editor window Montrer/cacher la fenêtre de l'éditeur de baie de brassage &Connect &Connecter Set&up... R&églages… JACK server state État du serveur JACK JACK server mode Mode du serveur JACK Sample rate Fréquence d'échantillonnage Time display Horloge Transport state État du déplacement Transport BPM BPM du déplacement Transport time Horaire du déplacement Show/hide the session management window Montrer/cacher la fenêtre de gestion de session Show/hide the messages log/status window Montrer/cacher la fenêtre de journal/statut Show/hide the graph window Afficher/cacher la fenêtre de graphe Show/hide the connections window Afficher/cacher la fenêtre des connexions &Backward A&rrière Backward transport Déplacer en arrière &Forward A&vant Forward transport Déplacer en avant &Rewind Remb&obiner Rewind transport Rembobiner Pa&use Pa&use Stop transport rolling Arrêter le déplacement &Play &Lecture Start transport rolling Démarrer le déplacement Warning Attention successfully avec succès with exit status=%1 avec statut de sortie=%1 Could not load preset "%1". Retrying with default. Impossible de charger le préréglage « %1 ». Nouvel essai avec celui par défaut. Could not load default preset. Sorry. Impossible de charger le préréglage par défaut. Désolé. Startup script... Script de démarrage… Startup script terminated Script de démarrage terminé JACK is starting... JACK démarre… Could not start JACK. Sorry. Impossible de démarrer JACK. Désolé. JACK is stopping... JACK s'arrête… Shutdown script... Script d'extinction… Don't ask this again Ne pas redemander Shutdown script terminated Script d'extinction terminé Post-shutdown script... Script post-extinction… Post-shutdown script terminated Script post-extinction terminé JACK was stopped JACK a été arrêté The preset aliases have been changed: "%1" Do you want to save the changes? Les alias de préréglage ont été changés : "%1" Voulez-vous sauvegarder les changements ? Error Erreur Transport time code Code temporel (Timecode) du déplacement Elapsed time since last reset Temps écoulé depuis la dernière réinitialisation Elapsed time since last XRUN Temps écoulé depuis la dernière désynchronisation (XRUN) Patchbay activated. Baie de brassage activée. Patchbay deactivated. Baie de brassage désactivée. Statistics reset. Réinitialisation des statistiques. msec ms XRUN callback (%1). Récupération désynchronisation (XRUN) (%1). Buffer size change (%1). Changement de la taille du tampon (%1). Shutdown notification. Notification d'extinction. Freewheel started... Roue libre démarrée… Freewheel exited. Roue libre quittée. checked vérifié connected connecté disconnected déconnecté failed échoué Server configuration saved to "%1". Configuration du serveur sauvegardée dans "%1". Client activated. Client activé. Post-startup script... Script post-démarrage… Post-startup script terminated Script post-démarrage terminé Command line argument... Argument de ligne de commande… Command line argument started Argument de ligne de commande démarré Client deactivated. Client désactivé. Transport rewind. Déplacement en rembobinage. Transport backward. Déplacement en marche arrière. Starting Démarre Transport start. Déplacement démarré. Stopping S'arrête Transport stop. Déplacement arrêté. Transport forward. Déplacement en marche avant. Stopped Arrêté Yes Oui No Non FW RL RT TR Rolling Défile Looping Boucle XRUN callback (%1 skipped). Récupération de désynchronisation (XRUN) (%1 sauté). Started Démarré Active Actif Activating Activation Inactive Inactif &Hide Cac&her D-BUS: GetParameterConstraint('%1'): %2. (%3) D-BUS : GetParameterConstraint('%1') : %2. (%3) Mi&nimize Mi&nimiser S&how M&ontrer Rest&ore R&estaurer &Stop &Arrêter &Reset Ré&initialiser &Presets &Préréglages &Versioning Gestion de ré&visions Re&fresh Ra&fraîchir &Connections &Connexions Patch&bay &Baie de brassage &Graph &Graphe &Transport Déplacemen&t Server settings will be only effective after restarting the JACK audio server. Les paramètres du serveur ne seront effectifs qu'après avoir redémarré le serveur audio JACK. Information Information Some settings will be only effective the next time you start this program. Certains paramètres ne seront effectifs qu'au prochain démarrage de ce programme. DSP Load Charge DSP XRUN Count (notifications) Décompte des désynchronisations (notifications XRUN) JACK connection graph change. Changement du graphe des connexions JACK. ALSA connection graph change. Changement du graphe des connexions ALSA. JACK connection change. Changement des connexions JACK. ALSA connection change. Changement des connexions ALSA. JACK is currently running. Do you want to terminate the JACK audio server? JACK fonctionne actuellement. Voulez-vous arrêter le serveur audio JACK ? D-BUS: Service is available (%1 aka jackdbus). DBUS : le service est disponible (%1 soit jackdbus). D-BUS: Service not available (%1 aka jackdbus). DBUS : le service n'est pas disponible (%1 soit jackdbus). The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. Le programme continuera de s'exécuter dans la zone de notification système. Pour terminer le programme, merci de choisir « Quitter » dans le menu contextuel de l'icône de la zone de notification système. Don't show this message again Ne pas montrer ce message à nouveau Could not start JACK. Maybe JACK audio server is already started. Impossible de démarrer JACK. Peut-être que le serveur audio JACK est déjà démarré. D-BUS: JACK server is starting... DBUS : le serveur JACK démarre… D-BUS: JACK server could not be started. Sorry DBUS : impossible de démarrer le serveur JACK. Désolé Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Certaines applications audio clientes sont encore actives et connectées. Voulez-vous arrêter le serveur audio JACK ? %1 is about to terminate. Are you sure? %1 est sur le point de se terminer. Êtes-vous certain ? D-BUS: JACK server is stopping... DBUS : le serveur JACK s'arrête… D-BUS: JACK server could not be stopped. Sorry DBUS : impossible d'arrêter le serveur JACK. Désolé JACK was started with PID=%1. JACK a été démarré avec le PID=%1. D-BUS: JACK server was started (%1 aka jackdbus). DBUS : le serveur JACK a été démarré (%1 soit jackdbus). JACK is being forced... JACK est forcé… D-BUS: JACK server was stopped (%1 aka jackdbus). DBUS : le serveur JACK a été arrêté (%1 soit jackdbus). Transport BBT (bar.beat.ticks) Transport MTB (mesure temps battement) Patchbay reset. Réinitialisation de la baie de brassage. Could not load active patchbay definition. "%1" Disabled. Impossible de charger la définition de baie de brassage active. "%1" Désactivé. JACK has crashed. JACK a planté. JACK timed out. JACK n'a pas répondu à temps. JACK write error. Erreur d'écriture JACK. JACK read error. Erreur de lecture JACK. Unknown JACK error (%d). Erreur JACK inconnue (%d). JACK property change. Changement d'une propriété de JACK. Overall operation failed. L'opération a échoué. Invalid or unsupported option. Option invalide ou non prise en charge. Client name not unique. Nom de client non unique. Server is started. Le serveur est démarré. Unable to connect to server. Incapable de se connecter au serveur. Server communication error. Erreur de communication serveur. Client does not exist. Le client n'existe pas. Unable to load internal client. Incapable de charger le client interne. Unable to initialize client. Incapable d'initialiser le client. Unable to access shared memory. Incapable d'accéder à la mémoire partagée. Client protocol version mismatch. Mauvaise version du protocole client. Could not connect to JACK server as client. - %1 Please check the messages window for more info. Impossible de connecter le serveur JACK comme client. - %1 Veuillez consulter la fenêtre des messages pour plus d'informations. %1 (%2%) %1 (%2%) %1 (%2%, %3 xruns) %1 (%2%, %3 xruns) %1 % %1 % %1 Hz %1 Hz %1 frames %1 échantillons %1 msec %1 ms S&ession S&ession &Load... &Charger… &Save... &Sauvegarder… Save and &Quit... Sauvegarder et &Quitter… Save &Template... Sauvegarder &modèle… Do you want to restart the JACK audio server? Voulez-vous redémarrer le serveur audio JACK ? D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS : SetParameterValue('%1', '%2') : %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS : ResetParameterValue('%1') : %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS : GetParameterValue('%1') : %2. (%3) Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. Impossible d'ouvrir le sequenceur ALSA comme client. La baie de brassage ALSA MIDI ne sera pas disponible. JACK active patchbay scan Balayage de la baie de brassage JACK active ALSA active patchbay scan Balayage de la baie de brassage ALSA active A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? Une définition de baie de brassage est actuellement active, il est probable que cela refasse cette connexion : %1 -> %2 Voulez-vous enlever la connexion de la baie de brassage ? qjackctlMessagesStatusForm Messages / Status Messages / status &Messages &Messages Messages log Journal des messages Messages output log Journal des messages de sortie &Status &Statut Status information Information de statut Statistics since last server startup Statistiques depuis le dernier démarrage du serveur Description Description Value Valeur Reset XRUN statistic values Réinitialiser les valeurs statistiques des désynchronisations (XRUN) Re&set Réinitiali&ser Refresh XRUN statistic values Rafraîchir les valeurs statistiques des désynchronisations (XRUN) &Refresh &Rafraîchir Server name Nom du serveur Server state État du serveur DSP Load Charge DSP Sample Rate Fréquence d'échantillonnage Buffer Size Taille du tampon Realtime Mode Mode temps réel Transport state État du déplacement Transport Timecode Code temporel (Timecode) du déplacement Transport BBT MTB du déplacement Transport BPM BPM du déplacement XRUN count since last server startup Décompte des désynchronisations (XRUN) depuis le dernier démarrage du serveur XRUN last time detected Horaire de la dernière désynchronisation (XRUN) détectée XRUN last Dernière désynchronisation (XRUN) XRUN maximum Nombre maximal de désynchronisation (XRUN) XRUN minimum Nombre minimal de désynchronisation (XRUN) XRUN average Moyenne de désynchronisation (XRUN) XRUN total Nombre total de désynchronisation (XRUN) Maximum scheduling delay Délai d'ordonnancement maximal Time of last reset Temps depuis la dernière réinitialisation Logging stopped --- %1 --- Journalisation arrêtée --- %1 --- Logging started --- %1 --- Journalisation démarrée --- %1 --- qjackctlPaletteForm Color Themes Thèmes de couleur Name Nom Current color palette name Nom de la palette de couleur actuelle Save current color palette name Sauvegarder le nom de la palette de couleur actuelle Save Sauvegarder Delete current color palette name Effacer le nom de la palette de couleur actuelle Delete Effacer Palette Palette Current color palette Palette de couleur actuelle Generate: Générer : Base color to generate palette Couleur de base pour générer la palette Reset all current palette colors Réinitialiser toutes les couleurs de la palette actuelle Reset Réinitialiser Import a custom color theme (palette) from file Importer un thème (palette) de couleur personnalisé depuis un fichier Import... Importer... Export a custom color theme (palette) to file Exporter un thème (palette) de couleur personnalisé vers un fichier Export... Exporter... Show Details Afficher les détails Import File - %1 Importer le fichier - %1 Palette files (*.%1) Fichiers de palette (*.%1) Save Palette - %1 Sauvegarder la palette - %1 All files (*.*) Tous les fichiers (*.*) Warning - %1 Attention - %1 Could not import from file: %1 Sorry. Impossible d'importer depuis le fichier : %1 Navré. Export File - %1 Exporter le fichier - %1 Some settings have been changed. Do you want to discard the changes? Certains paramètres ont été modifié. Souhaitez-vous abandonner les modifications ? Some settings have been changed: "%1". Do you want to save the changes? Certains paramètres ont été modifié. "%1". Souhaitez-vous sauvegarder les modifications ? qjackctlPaletteForm::PaletteModel Color Role Role de couleur Active Actif Inactive Inactif Disabled Désactivé qjackctlPatchbay Warning Attention This will disconnect all sockets. Are you sure? Cela va déconnecter toutes les prises. Êtes-vous certain ? qjackctlPatchbayForm &New &Nouveau Create a new patchbay profile Créer un nouveau profil de baie de brassage &Load... &Charger… Load patchbay profile Charger un profil de baie de brassage &Save... &Sauvegarder… Save current patchbay profile Sauvegarder le profil actuel de la baie de brassage Patchbay Baie de brassage Expand all items Afficher tous les éléments E&xpand All &Afficher tout Current (recent) patchbay profile(s) Profil(s) actuel(s) (récent(s)) de la baie de brassage Acti&vate Acti&ver Toggle activation of current patchbay profile Basculer l'activation du profil actuel de baie de brassage &Connect &Connecter Connect currently selected sockets Connecter les prises actuellement sélectionnées &Disconnect &Déconnecter Disconnect currently selected sockets Déconnecter les prises actuellement sélectionnées Disconnect &All &Tout déconnecter Disconnect all currently connected sockets Déconnecter les prises actuellement connectées &Refresh &Rafraîchir Refresh current patchbay view Rafraîchir la vue actuelle de la baie de brassage Down Vers le bas Move currently selected output socket down one position Déplacer d'une position vers le bas la prise de sortie actuellement sélectionnée Add... Ajouter… Create a new output socket Créer une nouvelle prise de sortie Edit... Éditer… Edit currently selected input socket properties Éditer les propriétés de la prise d'entrée actuellement sélectionnée Up Vers le haut Move currently selected output socket up one position Déplacer d'une position vers le haut la prise de sortie actuellement sélectionnée Remove Enlever Remove currently selected output socket Enlever la prise de sortie actuellement sélectionnée Copy... Copier… Duplicate (copy) currently selected output socket Dupliquer (copier) la prise de sortie actuellement sélectionnée Remove currently selected input socket Enlever la prise d'entrée actuellement sélectionnée Duplicate (copy) currently selected input socket Dupliquer (copier) la prise d'entrée actuellement sélectionnée Create a new input socket Créer une nouvelle prise d'entrée Edit currently selected output socket properties Éditer les propriétés de la prise de sortie actuellement sélectionnée Warning Attention Error Erreur New Patchbay definition Nouvelle définition de baie de brassage Patchbay Definition files Fichiers de définition de baie de brassage Load Patchbay Definition Charger une définition de baie de brassage Save Patchbay Definition Sauvegarder la définition de baie de brassage active actif The patchbay definition has been changed: "%1" Do you want to save the changes? La définition de baie de brassage a été changée : « %1 » Voulez-vous sauvegarder les changements ? %1 [modified] %1 [modifié] Untitled%1 SansTitre%1 Could not load patchbay definition file: "%1" Impossible de charger le fichier de définition de baie de brassage : « %1 » Could not save patchbay definition file: "%1" Impossible de sauvegarder le fichier de définition de baie de brassage : « %1 » Create patchbay definition as a snapshot of all actual client connections? Prendre un cliché de toutes les connexions clientes actuelles pour créer une définition de baie de brassage ? qjackctlPatchbayView Add... Ajouter… Edit... Éditer… Copy... Copier… Remove Enlever Exclusive Exclusif (None) (Aucun) Forward Renvoi Move Up Vers le haut Move Down Vers le bas &Connect &Connecter Alt+C Connect Alt+C &Disconnect &Déconnecter Alt+D Disconnect Alt+D Disconnect &All &Tout déconnecter Alt+A Disconnect All Alt+T &Refresh &Rafraîchir Alt+R Refresh Alt+R qjackctlSessionForm Session Session Load session Charger session &Load... &Charger… Recent session Session récente &Recent &Récente Save session Sauvegarder session &Versioning Gestion de ré&visions Re&fresh Ra&fraîchir Session clients / connections Clients / connexions de la session Infra-clients / commands Commandes / clients-infra Infra-client Client-infra Infra-command Commande-infra Add infra-client Ajouter un client-infra &Add &Ajouter Edit infra-client Modifier un client-infra &Edit Modifi&er Remove infra-client Supprimer un client-infra Re&move Suppri&mer &Save... &Sauvegarder… Update session Mettre à jour la session Client / Ports Clients / Ports UUID UUID Command Commande &Save &Sauvegarder Load Session Charger session Session directory Répertoire de session Save Session Sauvegarder session and Quit et quitter Template Modèle &Clear &Effacer Warning Attention A session could not be found in this folder: "%1" Impossible de trouver une session dans ce dossier : « %1 » %1: loading session... %1 : chargement de la session… %1: load session %2. %1 : charger session %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? Il existe déjà une session dans ce dossier : « %1 » Êtes-vous certain de vouloir remlplacer la session existante ? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Ce dossier existe déjà et n'est pas vide : « %1 » Êtes-vous certain de vouloir remplacer le dossier existant ? %1: saving session... %1 : sauvegarde de la session… %1: save session %2. %1 : sauvegarder session %2. New Client Nouveau client Save and &Quit... Sauvegarder et &Quitter… Save &Template... Sauvegarder &modèle… qjackctlSessionInfraClientItemEditor Infra-command Commande-infra qjackctlSessionSaveForm Session Session &Name: &Nom : Session name &Directory: Session directory Répertoire de session Browse for session directory ... Save session versioning Sauvegarder la session avec gestion de révisions &Versioning Gestion de ré&visions Warning Attention Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings Paramètres Preset &Name: &Nom du préréglage : (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Settings preset name Nom du préréglage des paramètres &Save &Sauvegarder Save settings as current preset name Sauvegarder les paramètres sous le nom du préréglage actuel &Delete E&ffacer Delete current settings preset Effacer le préréglage des paramètres actuel jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE Driv&er: Pilot&e : dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters Paramètres Number of periods in the hardware buffer Nombre de périodes dans le tampon matériel Priorit&y: Pri&orité : &Frames/Period: &Échantillons/Période : 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Frames per period between process() calls Échantillons par période entre appels de process() Port Ma&ximum: Nombre de port ma&ximal : 21333 21333 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 192000 192000 Sample rate in frames per second Fréquence d'échantillonage en échantillons par seconde Scheduler priority when running realtime Priorité de l'ordonnanceur quand fonctionne en temps réel &Word Length: &Résolution (bit) : Periods/&Buffer: Périodes/&Tampon : Word length Résolution Maximum number of ports the JACK server can manage Nombre maximal de ports que peut gérer le serveur JACK &Wait (usec): &Attente (en µs) : Sample &Rate: &Fréquence d'échantillonnage (Hz) : &Timeout (msec): &Décompte (en ms) : 200 200 500 500 1000 1000 2000 2000 5000 5000 Set client timeout limit in milliseconds Régler le limite du décompte client en millisecondes &Realtime Temps &réel Use realtime scheduling Utiliser ordonnancement temps réel No Memory Loc&k P&as de verrouillage mémoire Do not attempt to lock memory, even if in realtime mode Ne pas essayer de verrouiller la mémoire même en mode temps-réel &Unlock Memory &Déverrouiller la mémoire Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) Déverrouiller la mémoire des bibliothèques d'interface communes (GTK+, QT, FLTK, Wine) So&ft Mode Mode &logiciel Ignore xruns reported by the backend driver Ignorer les désynchronisations (XRUN) rapportées par le pilote principal &Monitor &Écoute de contrôle Provide output monitor ports Fournir des ports de sortie d'écoute de contrôle Force &16bit Forcer &16bit Force 16bit mode instead of failing over 32bit (default) Forcer mode 16bit au lieu d'échouer sur 32bit (par défaut) H/&W Meter Mes&ure matérielle Enable hardware metering on cards that support it Activer la mesure matérielle sur les cartes qui la prennent en charge &Ignore H/W &Ignorer matériel Ignore hardware period/buffer size Ignore la taille des période/tampon matériels &Output Device: Périphérique de s&ortie : &Interface: &Interface : Maximum input audio hardware channels to allocate Nombre maximal de canaux d'entrée audio matériels à allouer &Audio: &Audio : Dit&her: Bruit de dispertion (dit&her) : External output latency (frames) Latence de sortie externe (en échantillons) &Input Device: Pér&iphérique d'entrée : Duplex Duplex Capture Only Capture seulement Playback Only Reproduction seulement Provide either audio capture, playback or both Fournir la capture audio, la reproduction audio ou les deux hw:0 hw:0 The PCM device name to use Nom du périphérique PCM à utiliser > > &Name: &Nom : The JACK Audio Connection Kit sound server name Le nom du serveur de son du Kit de Connexion Audio JACK /dev/dsp /dev/dsp Alternate input device for capture Périphérique d'entrée alternatif pour la capture Maximum output audio hardware channels to allocate Nombre maximal de canaux de sortie audio matériels à allouer Alternate output device for playback Périphérique de sortie alternatif pour la reproduction External input latency (frames) Latence d'entrée externe (en échantillons) None Aucun Rectangular Rectangulaire Shaped Sinusoïdal Triangular Triangulaire Set dither mode Régler le mode du bruit de dispersion (dither) Whether to give verbose output on messages Donner une sortie bavarde sur les messages Time in seconds that client is delayed after server startup Temps en secondes dont le client est retardé après le démarrage du serveur Latency: Latence : Output latency in milliseconds, calculated based on the period, rate and buffer settings Latence de sortie en millisecondes calculée à partir des réglages de la période, de la fréquence d'échantillonnage et du tampon Options Options Scripting Scripts Execute script on Start&up: Exéc&uter un script au démarrage : Whether to execute a custom shell script before starting up the JACK audio server. Exécuter un script de commande personnalisé avant de démarrer le serveur audio JACK. Execute script after &Startup: Exécuter un &script après le démarrage : Whether to execute a custom shell script after starting up the JACK audio server. Exécuter un script de commande personnalisé après avoir démarré le serveur audio JACK. Execute script on Shut&down: Exécuter un script à l'extinctio&n : Whether to execute a custom shell script before shuting down the JACK audio server. Exécuter un script de commande personnalisé avant d'éteindre le serveur audio JACK. Command line to be executed before starting up the JACK audio server Ligne de commande à exécuter avant de démarrer le serveur audio JACK Scripting argument meta-symbols Méta-symboles des arguments de script ... Browse for script to be executed before starting up the JACK audio server Pointer sur le script à exécuter avant de démarrer le serveur audio JACK Command line to be executed after starting up the JACK audio server Ligne de commande à exécuter après avoir démarré le serveur audio JACK Browse for script to be executed after starting up the JACK audio server Pointer sur le script à exécuter après avoir démarré le serveur audio JACK Browse for script to be executed before shutting down the JACK audio server Pointer sur le script à exécuter avant d'éteindre le serveur audio JACK Command line to be executed before shutting down the JACK audio server Ligne de commande à exécuter avant d'éteindre le serveur audio JACK Execute script after Shu&tdown: Exécuter un script après l'ex&tinction : Whether to execute a custom shell script after shuting down the JACK audio server. Exécuter un script de commande personnalisé après avoir éteint le serveur audio JACK. Browse for script to be executed after shutting down the JACK audio server Pointer sur le script à exécuter après avoir éteint le serveur audio JACK Command line to be executed after shutting down the JACK audio server Ligne de commande à exécuter après avoir éteint le serveur audio JACK Statistics Statistiques &Capture standard output &Capturer la sortie standard Whether to capture standard output (stdout/stderr) into messages window Capturer la sortie standard (stdout/stderr) dans la fenêtre de messages &XRUN detection regex: Regex de détection des désynchronisations (&XRUN) : xrun of at least ([0-9|\.]+) msecs désynchronisation (XRUN) d'au moins ([0-9|\.]+) ms Regular expression used to detect XRUNs on server output messages Expression régulière utilisée pour détecter les désynchronisations (XRUN) dans les messages de sortie du serveur Connections Connexions 10 10 Patchbay definition file to be activated as connection persistence profile Fichier de définition de baie de brassage à activer comme profil de persistance de connexion Browse for a patchbay definition file to be activated Pointer sur un fichier de définition de baie de brassage à activer Activate &Patchbay persistence: Activer la &persistance de baie de brassage : Whether to activate a patchbay definition for connection persistence profile. Activer une définition de baie de brassage pour le profil de persistance de connexion. Display Affichage Time Display Horloge Server Suffi&x: Suffi&xe Serveur : Transport &Time Code Code &temporel (Timecode) du déplacement Transport &BBT (bar:beat.ticks) MT&B (mesure:temps.battement) du déplacement Elapsed time since last &Reset Temps écoulé depuis la dernière &réinitialisation Elapsed time since last &XRUN Temps écoulé depuis la dernière désynchronisation (&XRUN) Sample front panel normal display font Aperçu de l'affichage normal Sample big time display font Aperçu de la grande horloge Big Time display: Grande horloge : &Font... &Police… Select font for front panel normal display Sélectionner la police pour l'affichage normal Select font for big time display Sélectionner la police pour la grande horloge Normal display: Affichage normal : Messages Window Fenêtre de messages Sample messages text font display Aperçu de la police du texte des messages Select font for the messages text display Sélectionner la police pour le texte des messages &Messages limit: Limite des &messages : Whether to keep a maximum number of lines in the messages window Garder un nombre maximal de lignes dans la fenêtre de messages 100 100 250 250 2500 2500 The maximum number of message lines to keep in view Nombre maximal de ligne de messages à garder visibles Connections Window Fenêtre de connexions Sample connections view font Aperçu de la police de la vue des connexions Select font for the connections view Sélectionner la police pour la vue des connexions &Icon size: Taille des &icônes : 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 The icon size for each item of the connections view Taille de l'icône pour chaque élément de la vue des connexions Ena&ble client/port aliases editing (rename) Activer l'é&dition (renommage) des aliases de client/port Whether to enable in-place client/port name editing (rename) Activer l'édition (renommage) en place des aliases de client/port E&nable client/port aliases Activer les aliases de client/p&ort Whether to enable client/port name aliases on the connections window Activer les aliases de client/port dans la fenêtre de connexions Misc Divers Other Autres &Start JACK audio server on application startup &Démarrer le serveur audio JACK au démarrage de l'application Whether to start JACK audio server immediately on application startup Démarrer le serveur audio JACK immédiatement au démarrage de l'application &Confirm application close &Confirmer la fermeture de l'application Whether to ask for confirmation on application exit Demander une confirmation lors de la sortie de l'application &Keep child windows always on top &Garder les fenêtres filles au premier plan Whether to keep all child windows on top of the main window Garder les fenêtres filles au dessus de la fenêtre principale &Enable system tray icon Activ&er l'icône de notification système Whether to enable the system tray icon Activer l'icône de notification système S&ave JACK audio server configuration to: &Sauvegarder la configuration du serveur audio JACK dans : Whether to save the JACK server command-line configuration into a local file (auto-start) Sauvegarder la configuration en ligne de commande du serveur JACK dans un fichier local (démarrage automatique) .jackdrc .jackdrc The server configuration local file name (auto-start) Nom du fichier local de configuration du serveur (démarrage automatique) Buttons Boutons Hide main window &Left buttons Cacher les boutons de &gauche de la fenêtre principale Whether to hide the left button group on the main window Cacher le groupe de bouton de gauche sur la fenêtre principale Hide main window &Right buttons Cacher les boutons de &droite de la fenêtre principale Whether to hide the right button group on the main window Cacher le groupe de bouton de droite sur la fenêtre principale Hide main window &Transport buttons Cacher les boutons de &déplacement de la fenêtre principale Whether to hide the transport button group on the main window Cacher le groupe de bouton de déplacement sur la fenêtre principale Hide main window &button text labels Cacher le texte des &boutons de la fenêtre principale Whether to hide the text labels on the main window buttons Cacher le texte des boutons sur la fenêtre principale Warning Attention msec ms n/a n/a &Preset Name &Nom du préréglage &Server Name Nom du &serveur &Server Path &Chemin du serveur &Driver Pilot&e &Interface &Interface Sample &Rate &Fréquence d'échantillonnage &Frames/Period &Échantillons/Période Periods/&Buffer Périodes/&Tampon Startup Script Script de démarrage Post-Startup Script Script post-démarrage Shutdown Script Script d'extinction Post-Shutdown Script Script post-extinction Patchbay Definition files Fichiers de définition de baie de brassage Active Patchbay Definition Définition de baie de brassage à activer The audio backend driver interface to use Le pilote d'interface audio à utiliser &Verbose messages Messages ba&vards MIDI Driv&er: Pilot&e MIDI : none aucun raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 The ALSA MIDI backend driver to use Le pilote ALSA MIDI à utiliser plughw:0 plughw:0 Some settings have been changed: "%1" Do you want to save the changes? Des paramètres ont été modifiés : « %1 » Voulez-vous sauvegarder les changements ? Delete preset: "%1" Are you sure? Effacer le préréglage : « %1 » Êtes-vous certain ? Information Informations Some settings may be only effective next time you start this application. Certains paramètres peuvent n'être effectifs qu'après le prochain démarrage de cette application. Some settings have been changed. Do you want to apply the changes? Des paramètres ont été modifiés. Voulez-vous appliquer les changements ? Messages Log Journal des messages System Système Cycle Cycle HPET HPET Don't restrict self connect requests (default) Ne pas restreindre les demandes de connexion automatique (défaut) Fail self connect requests to external ports only Empêche les demandes d'auto-connexion aux ports externes uniquement Ignore self connect requests to external ports only Ignorer les demandes d'auto-connexion aux ports externes uniquement Fail all self connect requests Empêche toutes les demandes d'auto-connexion Ignore all self connect requests Ignorer toutes les demandes d'auto-connexion Log files Fichiers du journal netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 /dev/audio /dev/audio &Channels: &Canaux : Server path (command line prefix) Chemin serveur (préfixe de ligne de commande) Maximum number of audio channels to allocate Nombre maximal de canaux audio à allouer &Channels I/O: &Canaux E/S : &Latency I/O: &Latence E/S : Logging Journalisation Messages log file Fichier de journal des messages Browse for the messages log file location Pointer sur l'emplacement du fichier de journal des messages Whether to activate a messages logging to file. Activer la journalisation des messages dans un fichier. Server &Prefix: &Préfixe Serveur : Extra driver options (command line suffix) Options supplémentaires du pilote (Suffixe de ligne de commande) Start De&lay: &Retard du démarrage : secs s 0 msecs 0 ms Please do not touch these settings unless you know what you are doing. Veuillez ne pas toucher ces réglages si vous ne savez pas ce que vous faites. &Messages log file: Fichier de journal des &messages : Whether to enable blinking (flashing) of the server mode (RT) indicator Activer le clignotement de l'indicateur de mode serveur (TR) Blin&k server mode indicator &Clignotement de l'indicateur de mode serveur &JACK client/port aliases: Alias de client/port &JACK : JACK client/port aliases display mode Mode d'affichage des alias de client/port JACK Default Par défaut First Premier Second Deuxième Whether to start minimized to system tray Démarrer minimisé dans la zone de notification système JACK client/port pretty-name (metadata) display mode Activer le mode d'affichage « joli-nom » (métadonnées) de client/port JACK Advanced Avancé Whether to reset all connections when a patchbay definition is activated. Réinitialiser ou non toutes les connexions quand une définition de baie de brassage est activée. &Reset all connections on patchbay activation &Réinitialiser toutes les connections à l'activation d'une baie de brassage Whether to issue a warning on active patchbay port disconnections. Afficher ou non une alerte lors des déconnexions de port faisant partie d'une baie de brassage active. &Warn on active patchbay disconnections A&lerter lors des déconnexions sur la baie de brassage active Enable JA&CK client/port pretty-names (metadata) Activer les « jolis-noms » (métadonnées) de client/port JA&CK Whether to ask for confirmation on JACK audio server shutdown and/or restart S'il faut demander la confirmation de l'arrêt et/ou du redémarrage du serveur audio de JACK Confirm server sh&utdown and/or restart Confirmer l'arrêt et/ou redémarrage d&u serveur Whether to show system tray message on main window close Afficher on non les messages de la zone de notification système lors de la fermeture de la fenêtre principale Sho&w system tray message on close A&fficher les messages de la zone de notification lors de la fermeture de la fenêtre Start minimi&zed to system tray Démarrer minimisé dans la &zone de notifications Whether to restrict to one single application instance (X11) Restreindre à une seule instance de l'application (X11) Single application &instance &Instance d'application unique Whether to enable ALSA Sequencer (MIDI) support on startup Activer la prise en charge du séquenceur ALSA (MIDI) au démarrage Setup Configuration Whether to restrict client self-connections S'il faut limiter les auto-connexions des clients Whether to use server synchronous mode Si l'on utilise le mode synchrone de serveur Clear settings of current preset name Effacer les paramètres du nom du préréglage actuel Clea&r Efface&r &Use server synchronous mode &Utiliser le mode synchrone de serveur Cloc&k source: Source d'&horloge : Clock source Source d'horloge S&elf connect mode: Mode d'auto-conn&exion Custom Personnalisé &Color palette theme: Thème de palette de &couleur : Custom color palette theme Theme de palette de couleur personnalisé Wonton Soup DO NOT TRANSLATE KXStudio DO NOT TRANSLATE Manage custom color palette themes Gérer les thèmes de palette de couleur personnalisés &Widget style theme: Thème de style de &widget : Custom widget style theme Thème de style de widget personnalisé : E&nable ALSA Sequencer support Activer la prise e&n charge du séquenceur ALSA Whether to enable JACK D-Bus interface Activation ou non de l'interface JACK D-Bus &Enable JACK D-Bus interface Activ&er l'interface JACK D-Bus Whether to stop JACK audio server on application exit Arrêter le serveur audio JACK lors de la sortie de l'application S&top JACK audio server on application exit Arrêter le &serveur audio JACK lors de la sortie de l'application Whether to replace Connections with Graph button on the main window Si on remplace les connexions avec un bouton de graphe dans la fenêtre principale Replace Connections with &Graph button Remplacer les connexions par un bouton de graphe Defaults Par défaut &Base font size: Taille de police de &base : Base application font size (pt.) Taille de base de police de l'application (pt.) 6 6 7 7 8 8 9 9 11 11 12 12 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to enable D-Bus interface Activer l'interface D-Bus &Enable D-Bus interface Activ&er l'interface D-Bus Number of microseconds to wait between engine processes (dummy) Nombre de microsecondes à attendre entre les traitements du moteur (factice) qjackctlSocketForm &Socket &Prise &Name (alias): &Nom (alias) : Socket name (an alias for client name) Nom de la prise (un alias pour le nom du client) Client name (regular expression) Nom du client (expression régulière) Add P&lug Ajouter une &fiche Add plug to socket plug list Ajouter la fiche à la liste des prises &Plug: &Fiche : Port name (regular expression) Nom du port (expression régulière) Socket Plugs / Ports Prises / Ports Socket plug list Liste des prises &Edit &Éditer &Remove Enleve&r Remove currently selected plug from socket plug list Enlever la fiche actuellement sélectionnée de la liste des prises Socket Socket &Client: &Client : &Down Vers le &bas &Up Vers le &haut E&xclusive E&xclusif Enforce only one exclusive cable connection S'assurer de l'utilisation d'une seule connexion cablée exclusive &Forward: Renvo&i : Forward (clone) all connections from this socket Renvoyer (cloner) toutes les connexions depuis cette prise Type Type &Audio &Audio Audio socket type (JACK) Type de prise audio (JACK) &MIDI &MIDI MIDI socket type (ALSA) Type de prise MIDI (ALSA) Plugs / Ports Fiches / Ports Add Plug Ajouter une Fiche Remove Enlever Edit Éditer Error Erreur A socket named "%1" already exists. Une prise nommée « %1 » existe déjà. Move Up Vers le haut Move Down Vers le bas (None) (Aucun) Edit currently selected plug Éditer la fiche actuellement sélectionnée Move down currently selected plug in socket plug list Déplacer vers le bas la fiche actuellement sélectionnée dans la liste des prises Move up current selected plug in socket plug list Déplacer vers le haut la fiche actuellement sélectionnée dans la liste des prises Warning Attention Some settings have been changed. Do you want to apply the changes? Des paramètres ont été modifiés. Voulez-vous appliquer les changements ? MIDI socket type (JACK) Type de prise MIDI (JACK) AL&SA AL&SA qjackctlSocketList Output Sortie Input Entrée Socket Prise Warning Attention <New> - %1 <Nouvelle> - %1 %1 about to be removed: "%2" Are you sure? %1 est sur le point d'être enlevée : « %2 » Êtes-vous certain ? %1 <Copy> - %2 %1 <Copie> - %2 qjackctlSocketListView Output Sockets / Plugs Prises/fiches de sortie Input Sockets / Plugs Prises/fiches d'entrée qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_ko.ts0000644000000000000000000000013214771215054020541 xustar0030 mtime=1743067692.334636541 30 atime=1743067692.334636541 30 ctime=1743067692.334636541 qjackctl-1.0.4/src/translations/qjackctl_ko.ts0000644000175000001440000064262714771215054020552 0ustar00rncbcusers PortAudioProber Probing... 검색 중... Please wait, PortAudio is probing audio hardware. 잠시 기다려 주십시오. PortAudio가 오디오 하드웨어를 검색하는 중입니다. Warning 경고 Audio hardware probing timed out. 오디오 하드웨어 검색하는 시간이 초과되었습니다. QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Usage: %1 [options] [command-and-args] 사용법: %1 [옵션] [명령-및-인수] Options: 옵션: Start JACK audio server immediately. Set default settings preset name. Set active patchbay definition file. Set default JACK audio server name. Show help about command line options. Show version information. Launch command with arguments. [command-and-args] Option -p requires an argument (preset). 옵션 -p에는 인수(사전설정)가 필요합니다. Option -a requires an argument (path). 옵션 -a에는 인수(경로)가 필요합니다. Option -n requires an argument (name). 옵션 -n에는 인수(이름)가 필요합니다. %1 (%2 frames) %1 (%2 프레임) Move 이동 Rename 이름변경 qjackctlAboutForm About 정보 &Close 닫기(&C) About Qt Qt 정보 Version 버전 Debugging option enabled. 디버깅 옵션이 활성화되었습니다. System tray disabled. 시스템 트레이가 비활성화되었습니다. Transport status control disabled. 트랜스포트 상태 컨트롤이 비활성화되었습니다. Realtime status disabled. 실시간 상태가 비활성화되었습니다. XRUN delay status disabled. XRUN 지연 상태가 비활성화되었습니다. Maximum delay status disabled. 최대 지연 상태가 비활성화되었습니다. JACK Port aliases support disabled. JACK 포트 별칭 지원이 비활성화되었습니다. JACK MIDI support disabled. JACK MIDI 지원이 비활성화되었습니다. JACK Session support disabled. JACK 세션 지원이 비활성화되었습니다. ALSA/MIDI sequencer support disabled. ALSA/MIDI 시퀀서 지원이 비활성화되었습니다. D-Bus interface support disabled. D-Bus 인터페이스 지원이 비활성화되었습니다. Using: Qt %1 사용중: Qt %1 JACK %1 JACK %1 Website 웹사이트 This program is free software; you can redistribute it and/or modify it 이 프로그램은 자유 소프트웨어이므로 GNU General Public License under the terms of the GNU General Public License version 2 or later. 버전 2 이상의 조건에 따라 재분배 및/또는 수정할 수 있습니다.<br><br>한국어 번역: 이정희 &lt;daemul72@gmail.com&gt;. qjackctlClientListView Readable Clients / Output Ports 읽기 가능한 클라이언트 / 출력 포트 Writable Clients / Input Ports 쓰기 가능한 클라이언트 / 입력 포트 &Connect 연결(&C) Alt+C Connect Alt+C &Disconnect 연결 해제(&D) Alt+D Disconnect Alt+D Disconnect &All 모두 연결 해제(&A) Alt+A Disconnect All Alt+A Re&name 이름변경(&N) Alt+N Rename Alt+N &Refresh 새로 고침(&R) Alt+R Refresh Alt+R qjackctlConnect Warning 경고 This will suspend sound processing from all client applications. Are you sure? 이렇게 하면 모든 클라이언트 응용프로그램에서 사운드 프로세싱이 일시 중단됩니다. 확실하신가요? qjackctlConnectionsForm Connections 연결 Audio 오디오 Connect currently selected ports 현재 선택된 포트 연결하기 &Connect 연결하기(&C) Disconnect currently selected ports 현재 선택된 포트 연결해제 &Disconnect 연결해제(&D) Disconnect all currently connected ports 현재 연결된 모든 포트 연결해제 Disconnect &All 모두 연결해제(&A) Expand all client ports 모든 클라이언트 포트 확장 E&xpand All 모두 확장(&X) Refresh current connections view 현재 연결 보기 새로 고침 &Refresh 새로 고침(&R) MIDI MIDI ALSA ALSA qjackctlConnectorView &Connect 연결하기(&C) Alt+C Connect Alt+C &Disconnect 연결해제(&D) Alt+D Disconnect Alt+D Disconnect &All 모두 연결해제(&A) Alt+A Disconnect All Alt+A &Refresh 새로 고침(&R) Alt+R Refresh Alt+R qjackctlGraphCanvas Connect 연결하기 Disconnect 연결해제 qjackctlGraphForm Graph 그래프 &Graph 그래프(&G) &Edit 편집(&E) &View 보기(&V) &Zoom 확대/축소(&Z) Co&lors 색상(&L) S&ort 정렬(&O) &Help 도움말(&H) &Connect 연결하기(&C) Connect 연결하기 Connect selected ports 선택한 포트 연결하기 &Disconnect 연결해제(&D) Disconnect 연결해제 Disconnect selected ports 선택한 포트 연결해제 Ctrl+C T&humbview Ctrl+D Cl&ose 닫기(&O) Close 닫기 Close this application window 이 응용프로그램 창 닫기 Select &All 모두 선택(&A) Select All 모두 선택 Ctrl+A Ctrl+A Select &None 없음 선택(&N) Select None 없음 선택 Ctrl+Shift+A Ctrl+Shift+A Select &Invert 반전 선택(&I) Select Invert 반전 선택 Ctrl+I Ctrl+I &Rename... 이름변경(&R)... Rename item 항목 이름변경 Rename Item 항목 이름변경 F2 F2 &Find... Find Find nodes Ctrl+F &Menubar 메뉴모음(&M) Menubar 메뉴모음 Show/hide the main program window menubar 기본 프로그램 창 메뉴모음 표시/숨김 Ctrl+M Ctrl+M &Toolbar 도구모음(&T) Toolbar 도구모음 Show/hide main program window file toolbar 기본 프로그램 창 파일 도구모음 표시/숨김 &Statusbar 상태 표시줄(&S) Statusbar 상태 표시줄 Show/hide the main program window statusbar 기본 프로그램 창 상태 표시줄 표시/숨김 &Top Left Top left Show the thumbnail overview on the top-left Top &Right Top right Show the thumbnail overview on the top-right Bottom &Left Bottom Left Bottom left Show the thumbnail overview on the bottom-left &Bottom Right Bottom right Show the thumbnail overview on the bottom-right &None None 없음 Hide thumbview Hide the thumbnail overview Text Beside &Icons 아이콘 옆에 텍스트(&I) Text beside icons 아이콘 옆에 텍스트 Show/hide text beside icons 아이콘 옆에 텍스트 표시/숨김 &Center 중앙(&C) Center 중앙 Center view 중앙 보기 &Refresh 새로 고침(&R) Refresh 새로 고침 Refresh view 보기 새로 고침 F5 F5 Zoom &In 확대(&I) Zoom In 확대 Ctrl++ Ctrl++ Zoom &Out 축소(&O) Zoom Out 축소 Ctrl+- Ctrl+- Zoom &Fit 창에 맞춤(&F) Zoom Fit 창에 맞춤 Ctrl+0 Ctrl+0 Zoom &Reset 확대/축소 재설정(&R) Zoom Reset 확대/축소 재설정 Ctrl+1 Ctrl+1 &Zoom Range 확대/축소 범위(&Z) Zoom Range 확대/축소 범위 JACK &Audio... JACK Audio(&A)... JACK Audio color JACK 오디오 색상 JACK &MIDI... JACK MIDI(&M)... JACK MIDI JACK MIDI JACK MIDI color JACK MIDI 색상 ALSA M&IDI... ALSA MIDI ALSA MIDI ALSA MIDI color ALSA MIDI 색상 JACK &CV... JACK CV(&C)... JACK CV color JACK CV 색상 JACK &OSC... JACK OSC(&O)... JACK OSC JACK OSC JACK OSC color JACK OSC 색상 &Reset 재설정(&R) Reset colors 색상 재설정 Port &Name 포트 이름(&N) Port name 포트 이름 Sort by port name 포트 이름으로 정렬 Port &Title 포트 제목(&T) Port title 포트 제목 Sort by port title 포트 제목으로 정렬 Port &Index 포트 인덱스(&I) Port index 포트 인덱스 Sort by port index 포트 인덱스로 정렬 &Ascending 오름차순(&A) Ascending 오름차순 Ascending sort order 오름차순 정렬 &Descending 내림차순(&D) Descending 내림차순 Descending sort order 내림차순 정렬 Repel O&verlapping Nodes Repel nodes Repel overlapping nodes Connect Thro&ugh Nodes Connect Through Nodes Connect through nodes Whether to draw connectors through or around nodes &About... QjackCtl 정보(&A)... About... QjackCtl 정보... About QjackCtl 정보 Show information about this application program 이 응용프로그램에 대한 정보 표시 About &Qt... Qt 정보(&Q)... About Qt... Qt 정보... About Qt Qt 정보 Show information about the Qt toolkit Qt 툴킷에 대한 정보 표시 &Undo 실행 취소(&U) &Redo 다시 실행(&R) Undo last edit action 마지막 편집 작업 실행 취소 Redo last edit action 마지막 편집 작업 다시 실행 Zoom 확대/축소 Ready 준비 완료 Colors - %1 색상 - %1 qjackctlMainForm Start the JACK server JACK 서버 시작 &Start 시작(&S) Stop the JACK server JACK 서버 중지 S&top 중지(&T) JACK server state JACK 서버 상태 JACK server mode JACK 서버 모드 DSP Load DSP 불러오기 Sample rate 샘플 레이트 XRUN Count (notifications) XRUN 카운트 (알림) Time display 시간 화면표시 Transport state 트랜스포트 상태 Transport BPM 트랜스포트 BPM Transport time 트랜스포트 시간 Quit processing and exit 프로세싱 종료 후 끝내기 &Quit 종료(&Q) Show/hide the session management window 세션 관리 창 표시/숨김 S&ession 세션(&E) Show/hide the messages log/status window 메시지 로그/상태 창 표시/숨김 &Messages 메시지(&M) Show settings and options dialog 설정 및 옵션 대화상자 표시 Set&up... 설정(&U)... Show/hide the graph window 그래프 창 표시/숨김 Show/hide the connections window 연결 창 표시/숨김 &Connect 연결하기(&C) Show/hide the patchbay editor window 패치베이 편집기 창 표시/숨김 &Patchbay 패치베이(&P) Rewind transport 트랜스포트 되감기 &Rewind 되감기(&R) Backward transport 역방향 트랜스포트 &Backward 역방향(&B) Start transport rolling 트랜스포트 롤링 시작 &Play 재생하기(&P) Stop transport rolling 트랜스포트 롤링 중지 Pa&use 일시 중지(&U) Forward transport 정방향 트랜스포트 &Forward 정방향(&F) Show information about this application 이 응용프로그램에 대한 정보 표시 Ab&out... 정보(&O)... Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. ALSA 시퀀서를 클라이언트로 열 수 없습니다. ALSA MIDI 패치베이는 사용할 수 없습니다. D-BUS: Service is available (%1 aka jackdbus). D-BUS: 서비스를 사용할 수 있습니다(%1 또는 jackdbus). D-BUS: Service not available (%1 aka jackdbus). D-BUS: 서비스를 사용할 수 없습니다(%1 또는 jackdbus). Information 정보 The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. 프로그램은 시스템 트레이에서 계속 실행됩니다. 프로그램을 끝마치려면 시스템 트레이 아이콘의 컨텍스트 메뉴에서 "종료"를 선택하십시오. Don't show this message again 이 메시지를 다시 표시하지 않음 Warning 경고 JACK is currently running. Do you want to terminate the JACK audio server? JACK이 현재 실행 중입니다. JACK 오디오 서버를 종료하시겠습니까? %1 is about to terminate. Are you sure? %1이(가) 종료되려고 합니다. 확실하신가요? successfully 성공적으로 with exit status=%1 종료 상태=%1 Could not start JACK. Maybe JACK audio server is already started. JACK을 시작할 수 없습니다. JACK 오디오 서버가 이미 시작되었을 수 있습니다. Could not load preset "%1". Retrying with default. "%1" 사전설정을 불러올 수 없습니다. 기본값으로 다시 시도합니다. Could not load default preset. Sorry. 기본 사전설정을 불러올 수 없습니다. 죄송합니다. Startup script... 스타트업 스크립트... Startup script terminated 스타트업 스크립트 종료됨 D-BUS: JACK server is starting... D-BUS: JACK 서버 시작하는 중... D-BUS: JACK server could not be started. Sorry D-BUS: JACK 서버를 시작할 수 없습니다. 죄송합니다 JACK is starting... JACK이 시작하는 중입니다... Some client audio applications are still active and connected. Do you want to stop the JACK audio server? 일부 클라이언트 오디오 응용 프로그램은 여전히 활성 상태이며 연결되어 있습니다. JACK 오디오 서버를 중지하시겠습니까? Shutdown script... 일시종료 스크립트... Shutdown script terminated 일시종료 스크립트 종료됨 JACK is stopping... JACK이 중지하는 중입니다... D-BUS: JACK server is stopping... D-BUS: JACK 서버가 중지하는 중입니다... D-BUS: JACK server could not be stopped. Sorry D-BUS: JACK 서버를 중지할 수 없습니다. 죄송합니다 JACK was started with PID=%1. JACK이 PID=%1로 시작되었습니다. D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: JACK 서버가 시작되었습니다(%1 또는 jackdbus). JACK is being forced... JACK이 강제 종료됩니다... JACK was stopped JACK이 중지됨 D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: JACK 서버가 중지되었습니다(%1 또는 jackdbus). Post-shutdown script... 일시종료 후 스크립트... Post-shutdown script terminated 일시종료 후 스크립트가 종료됨 Error 오류 Don't ask this again 다시 묻지 않음 The preset aliases have been changed: "%1" Do you want to save the changes? 사전 설정 별칭이 변경되었습니다. "%1" 변경 사항을 저장하시겠습니까? Transport BBT (bar.beat.ticks) 트랜스포트 BBT (마디.박자.틱) Transport time code 트랜스포트 시간 코드 Elapsed time since last reset 마지막 재설정 이후 경과된 시간 Elapsed time since last XRUN 마지막 XRUN 이후 경과 시간 Patchbay reset. 패치베이 재설정. Could not load active patchbay definition. "%1" Disabled. 활성 패치베이 정의를 불러올 수 없습니다. "%1" 비활성화됨. Patchbay activated. 패치베이가 활성화되었습니다. Patchbay deactivated. 패치베이가 비활성화되었습니다. Statistics reset. 통계 재설정. msec ms JACK connection graph change. JACK 연결 그래프 변경. XRUN callback (%1). XRUN 콜백 (%1). Buffer size change (%1). 버퍼 크기 변경 (%1). Shutdown notification. 일시종료 알림. Freewheel started... 프리휠 시작됨... Freewheel exited. 프리휠이 종료되었습니다. Could not start JACK. Sorry. JACK을 시작할 수 없습니다. 죄송합니다. JACK has crashed. JACK이 충돌했습니다. JACK timed out. JACK 시간이 초과되었습니다. JACK write error. JACK 쓰기 오류입니다. JACK read error. JACK 읽기 오류입니다. Unknown JACK error (%d). 알 수 없는 JACK 오류 (%d). JACK property change. JACK 속성이 변경되었습니다. ALSA connection graph change. ALSA 연결 그래프가 변경되었습니다. JACK active patchbay scan JACK 활성 패치베이 스캔 ALSA active patchbay scan ALSA 활성 패치베이 스캔 JACK connection change. JACK 연결이 변경되었습니다. ALSA connection change. ALSA 연결이 변경되었습니다. checked 확인함 connected 연결됨 disconnected 연결해제됨 failed 실패함 A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? 패치베이 정의가 현재 활성화되어 있습니다. 이 연결을 다시 실행할 가능성이 있음: %1 -> %2 패치베이 연결을 제거하시겠습니까? Overall operation failed. 전체 작업이 실패했습니다. Invalid or unsupported option. 유효하지 않거나 지원되지 않는 옵션입니다. Client name not unique. 클라이언트 이름이 고유하지 않습니다. Server is started. 서버가 시작되었습니다. Unable to connect to server. 서버에 연결할 수 없습니다. Server communication error. 서버 통신 오류입니다. Client does not exist. 클라이언트가 존재하지 않습니다. Unable to load internal client. 내부 클라이언트를 불러올 수 없습니다. Unable to initialize client. 클라이언트를 초기화할 수 없습니다. Unable to access shared memory. 공유 메모리에 액세스할 수 없습니다. Client protocol version mismatch. 클라이언트 프로토콜 버전이 일치하지 않습니다. Could not connect to JACK server as client. - %1 Please check the messages window for more info. JACK 서버에 클라이언트로 연결할 수 없습니다. - %1 자세한 내용은 메시지 창을 확인하세요. Server configuration saved to "%1". 서버 구성이 "%1"에 저장되었습니다. Client activated. 클라이언트가 활성화되었습니다. Post-startup script... 스타트업 후 스크립트... Post-startup script terminated 스타트업 후 스크립트 종료됨 Command line argument... 명령줄 인수... Command line argument started 명령줄 인수 시작됨 Client deactivated. 클라이언트가 비활성화되었습니다. Transport rewind. 트랜스포트 되감기. Transport backward. 트랜스포트 역방향. Starting 시작하는 중 Transport start. 트랜스포트 시작. Stopping 중지하는 중 Transport stop. 트랜스포트 정지. Transport forward. 트랜스포트 정방향. Stopped 중지됨 %1 (%2%) %1 (%2%) %1 (%2%, %3 xruns) %1 (%2%, %3 xruns) %1 % %1 % %1 Hz %1 Hz %1 frames %1 프레임 Yes No 아니오 FW FW RT RT Rolling 롤링 Looping 루핑 %1 msec %1 ms XRUN callback (%1 skipped). XRUN 콜백 (%1 건너뜀). Started 시작됨 Active 활성 Activating 활성 상태 Inactive 비활성 &Hide 숨김(&H) D-BUS: GetParameterConstraint('%1'): %2. (%3) D-BUS: GetParameterConstraint('%1'): %2. (%3) Mi&nimize 최소화(&N) S&how 표시(&H) Rest&ore 복원(&O) &Stop 중지(&S) &Reset 재설정(&R) &Presets 사전설정(&P) &Load... 불러오기(&L)... &Save... 저장(&S)... Save and &Quit... 저장 후 종료(&Q)... Save &Template... 탬플릿 저장(&T)... &Versioning 버전 관리(&V) Re&fresh 새로 고침(&F) St&atus 상태(&A) &Connections 연결(&C) Patch&bay 패치베이(&B) &Graph 그래프(&G) &Transport 트랜스포트(&T) Server settings will be only effective after restarting the JACK audio server. 서버 설정은 JACK 오디오 서버를 다시 시작한 후에만 적용됩니다. Do you want to restart the JACK audio server? JACK 오디오 서버를 다시 시작하시겠습니까? Some settings will be only effective the next time you start this program. 일부 설정은 다음에 이 프로그램을 시작할 때만 유효합니다. D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) qjackctlMessagesStatusForm Messages / Status 메시지 / 상태 &Messages 메시지(&M) Messages log 메시지 로그 Messages output log 메시지 출력 로그 &Status 상태(&S) Status information 상태 정보 Statistics since last server startup 마지막 서버 시작 이후 통계 Description 설명 Value Reset XRUN statistic values XRUN 통계 값 재설정 Re&set 재설정(&S) Refresh XRUN statistic values XRUN 통계 값 새로 고침 &Refresh 새로 고침(&R) Server name 서버 이름 Server state 서버 상태 DSP Load DSP 불러오기 Sample Rate 샘플 레이트 Buffer Size 버퍼 크기 Realtime Mode 실시간 모드 Transport state 트랜스포트 상태 Transport Timecode 트랜스포트 타임코드 Transport BBT 트랜스포트 BBT Transport BPM 트랜스포트 BPM XRUN count since last server startup 마지막 서버 시작 이후 XRUN 수 XRUN last time detected XRUN이 마지막으로 감지됨 XRUN last 마지막 XRUN XRUN maximum XRUN 최댓값 XRUN minimum XRUN 최솟값 XRUN average XRUN 평균 XRUN total XRUN 합계 Maximum scheduling delay 최대 스케줄링 지연 Time of last reset 마지막 재설정 시간 Logging stopped --- %1 --- 로깅 중지됨 --- %1 --- Logging started --- %1 --- 로깅 시작됨 --- %1 --- qjackctlPaletteForm Color Themes 색상 테마 Name 이름 Current color palette name 현재 색상 팔레트 이름 Save current color palette name 현재 색상 팔레트 이름 저장 Save 저장 Delete current color palette name 현재 색상 팔레트 이름 삭제 Delete 삭제 Palette 팔레트 Current color palette 현재 색상 팔레트 Generate: 생성: Base color to generate palette 팔레트 생성을 위한 기본 색상 Reset all current palette colors 모든 현재 팔레트 색상 재설정 Reset 재설정 Import a custom color theme (palette) from file 파일에서 사용자 지정 색상 테마(팔레트) 가져오기 Import... 가져오기... Export a custom color theme (palette) to file 사용자 지정 색상 테마(팔레트)를 파일로 내보내기 Export... 내보내기... Show Details 세부 정보 표시 Import File - %1 파일 가져오기 - %1 Palette files (*.%1) 팔레트 파일 (*.%1) Save Palette - %1 All files (*.*) 모든 파일 (*.*) Warning - %1 경고 - %1 Could not import from file: %1 Sorry. 파일에서 가져올 수 없음: %1 죄송합니다. Export File - %1 파일 내보내기 - %1 Some settings have been changed. Do you want to discard the changes? 일부 설정이 변경되었습니다. 변경 내용을 취소하시겠습니까? Some settings have been changed: "%1". Do you want to save the changes? 일부 설정이 변경되었습니다. "%1". 변경 내용을 저장하시겠습니까? qjackctlPaletteForm::PaletteModel Color Role 색상 역할 Active 활성 Inactive 비활성 Disabled 비활성화됨 qjackctlPatchbay Warning 경고 This will disconnect all sockets. Are you sure? 모든 소켓의 연결이 끊어집니다. 확실하신가요? qjackctlPatchbayForm Patchbay 패치베이 Move currently selected output socket down one position 현재 선택된 출력 소켓을 한 위치 아래로 이동 Down 아래로 Create a new output socket 새 출력 소켓 만들기 Add... 추가... Edit currently selected input socket properties 현재 선택된 입력 소켓 속성 편집 Edit... 편집... Move currently selected output socket up one position 현재 선택된 출력 소켓을 한 위치 위로 이동 Up 위로 Remove currently selected output socket 현재 선택된 출력 소켓 제거 Remove 제거 Duplicate (copy) currently selected output socket 현재 선택된 출력 소켓 복제 (복사) Copy... 복사... Remove currently selected input socket 현재 선택된 입력 소켓 제거 Duplicate (copy) currently selected input socket 현재 선택된 입력 소켓 복제 (복사) Create a new input socket 새 입력 소켓 만들기 Edit currently selected output socket properties 현재 선택한 출력 소켓 속성 편집 Connect currently selected sockets 현재 선택된 소켓 연결 &Connect 연결하기(&C) Disconnect currently selected sockets 현재 선택된 소켓 연결해제 &Disconnect 연결해제(&D) Disconnect all currently connected sockets 현재 연결된 모든 소켓 연결해제 Disconnect &All 모두 연결해제(&A) Expand all items 모든 항목 확장 E&xpand All 모두 확장(&X) Refresh current patchbay view 현재 패치베이 보기 새로 고침 &Refresh 새로 고침(&R) Create a new patchbay profile 새 패치베이 프로필 생성 &New 새로 만들기(&N) Load patchbay profile 패치베이 프로필 불러오기 &Load... 불러오기(&L)... Save current patchbay profile 현재 패치베이 프로필 저장 &Save... 저장(&S)... Current (recent) patchbay profile(s) 현재(최근) 패치베이 프로필 Toggle activation of current patchbay profile 현재 패치베이 프로필 활성화 전환 Acti&vate 활성화(&V) Warning 경고 The patchbay definition has been changed: "%1" Do you want to save the changes? 패치베이 정의가 변경되었음: "%1" 변경 사항을 저장하시겠습니까? %1 [modified] %1 [수정됨] Untitled%1 제목없음-%1 Error 오류 Could not load patchbay definition file: "%1" 패치베이 정의 파일을 불러올 수 없음: "%1" Could not save patchbay definition file: "%1" 패치베이 정의 파일을 저장할 수 없음: "%1" New Patchbay definition 새 패치베이 정의 Create patchbay definition as a snapshot of all actual client connections? 모든 실제 클라이언트 연결의 스냅샷으로 패치베이 정의를 만드시겠습니까? Load Patchbay Definition 패치베이 정의 불러오기 Patchbay Definition files 패치베이 정의 파일 Save Patchbay Definition 패치베이 정의 저장 active 활성 qjackctlPatchbayView Add... 추가... Edit... 편집... Copy... 복사... Remove 제거 Exclusive 전용 Forward 앞으로 (None) (없음) Move Up 위로 이동 Move Down 아래로 이동 &Connect 연결하기(&C) Alt+C Connect 연결 Alt+C &Disconnect 연결해제(&D) Alt+D Disconnect 연결 해제 Alt+D Disconnect &All 모두 연결해제(&A) Alt+A Disconnect All 모두 연결 해제 Alt+A &Refresh 새로 고침(&R) Alt+R Refresh 새로 고침 Alt+R qjackctlSessionForm Session 세션 Load session 세션 불러오기 &Load... 불러오기(&L)... Recent session 최근 세션 &Recent 최근 세션(&R) Save session 세션 저장 &Save 저장(&S) &Versioning 버전 관리(&V) Update session 세션 업데이트 Re&fresh 새로 고침(&F) Session clients / connections 세션 클라이언트 / 연결 Client / Ports 클라이언트 / 포트 UUID UUID Command 명령 Infra-clients / commands 인프라 클라이언트 / 명령 Infra-client 인프라 클라이언트 Infra-command 인프라 명령 Add infra-client 인프라 클라이언트 추가 &Add 추가(&A) Edit infra-client 인프라 클라이언트 편집 &Edit 편집(&E) Remove infra-client 인프라 클라이언트 제거 Re&move 제거(&M) &Save... 저장(&S)... Save and &Quit... 저장 후 종료(&Q)... Save &Template... 템플릿 저장(&T)... Load Session 세션 불러오기 Session directory 세션 디렉토리 Save Session 세션 저장 and Quit 및 종료 Template 템플릿 &Clear 비우기(&C) Warning 경고 A session could not be found in this folder: "%1" 다음 폴더에서 세션을 찾을 수 없음: "%1" %1: loading session... %1: 세션을 불러오는 중... %1: load session %2. %1: %2 세션을 불러옵니다. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? 다음 폴더에 세션이 이미 있음: "%1" 기존 세션을 덮어쓰시겠습니까? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? 이 폴더는 이미 있으며 비어 있지 않음: "%1" 기존 폴더를 덮어쓰시겠습니까? %1: saving session... %1: 세션 저장 중... %1: save session %2. %1: %2 세션을 저장합니다. New Client 새 클라이언트 qjackctlSessionInfraClientItemEditor Infra-command 인프라 명령 qjackctlSessionSaveForm Session 세션 &Name: 이름(&N): Session name &Directory: Session directory 세션 디렉토리 Browse for session directory ... ... Save session versioning 세션 버전 관리 저장 &Versioning 버전 관리(&V) Warning 경고 Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings 설정 Preset &Name: 사전설정 이름(&N): Settings preset name 사전설정 이름 설정 (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Save settings as current preset name 현재 사전설정 이름으로 설정 저장 &Save 저장(&S) Delete current settings preset 현재 설정 사전설정 삭제 &Delete 삭제(&D) jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE &Name: 이름(&N): The JACK Audio Connection Kit sound server name JACK 오디오 연결 키트 사운드 서버 이름 Driv&er: 드라이버(&E): The audio backend driver interface to use 사용할 오디오 백엔드 드라이버 인터페이스 dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters 매개변수 MIDI Driv&er: MIDI 드라이버(&E): The ALSA MIDI backend driver to use 사용할 ALSA MIDI 백엔드 드라이버 none 없음 raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Time in seconds that client is delayed after server startup 서버 시작 후 클라이언트가 지연되는 시간(초) Latency: 지연시간: Output latency in milliseconds, calculated based on the period, rate and buffer settings 기간, 속도 및 버퍼 설정을 기반으로 계산된 출력 지연시간 (밀리초) Use realtime scheduling 실시간 스케줄링 사용 &Realtime 실시간(&R) Do not attempt to lock memory, even if in realtime mode 실시간 모드인 경우에도 메모리 잠금을 시도하지 마십시오 No Memory Loc&k 메모리 잠금 없음(&K) Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) 공통 툴킷 라이브러리의 메모리 잠금 해제 (GTK+, QT, FLTK, Wine) &Unlock Memory 메모리 잠금 해제(&U) Ignore xruns reported by the backend driver 백엔드 드라이버에서 보고한 xrun 무시 So&ft Mode 안전 모드(&F) Provide output monitor ports 출력 모니터 포트 제공 &Monitor 모니터(&M) Force 16bit mode instead of failing over 32bit (default) 32비트를 초과하는 대신 16비트 모드 강제 적용 (기본값) Force &16bit 16비트 강제 적용(&1) Enable hardware metering on cards that support it 지원하는 카드에서 하드웨어 미터링 실행 H/&W Meter H/W 미터(&W) Ignore hardware period/buffer size 하드웨어 기간/버퍼 크기 무시 &Ignore H/W H/W 무시(&I) Whether to give verbose output on messages 메시지에 대한 자세한 출력을 제공할지 여부 &Verbose messages 상세 메시지(&V) &Output Device: 출력 장치(&O): &Interface: 인터페이스(&I): Maximum input audio hardware channels to allocate 할당할 최대 입력 오디오 하드웨어 채널 &Audio: 오디오(&A): Dit&her: 디더(&H): External output latency (frames) 외부 출력 지연시간 (프레임) &Input Device: 입력 장치(&I): Provide either audio capture, playback or both 오디오 캡처, 재생 또는 둘 다 제공 Duplex 입출력 Capture Only 입력 만 Playback Only 출력 만 The PCM device name to use 사용할 PCM 장치 이름 hw:0 hw:0 plughw:0 plughw:0 /dev/audio /dev/audio /dev/dsp /dev/dsp > > Alternate input device for capture 캡처를 위한 대체 입력 장치 Maximum output audio hardware channels to allocate 할당할 최대 출력 오디오 하드웨어 채널 Alternate output device for playback 재생을 위한 대체 출력 장치 External input latency (frames) 외부 입력 지연시간 (프레임) Set dither mode 디더 모드 지정 None 없음 Rectangular 사각형 Shaped 모양 Triangular 삼각형 Number of periods in the hardware buffer 하드웨어 버퍼의 기간 수 Priorit&y: 속성(&Y): &Frames/Period: 프레임/기간(&F): Frames per period between process() calls process() 호출 사이의 기간당 프레임 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Port Ma&ximum: 최대 포트(&X): &Channels: 채널 수(&C): Number of microseconds to wait between engine processes (dummy) 엔진 프로세스 사이에서 대기하는 마이크로초 수 (더미) 21333 21333 Sample rate in frames per second 초당 프레임의 샘플 레이트 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 192000 192000 Scheduler priority when running realtime 실시간 실행 시 스케줄러 우선 순위 &Word Length: 단어 길이(&W): Periods/&Buffer: 기간/버퍼(&B): Word length 단어 길이 Maximum number of ports the JACK server can manage JACK 서버가 관리할 수 있는 최대 포트 수 &Wait (usec): 대기시간 (μs)(&W): Sample &Rate: 샘플 레이트(&R): Maximum number of audio channels to allocate 할당할 최대 오디오 채널 수 &Timeout (msec): 시간초과 (ms)(&T): Set client timeout limit in milliseconds 클라이언트 시간 제한 지정 (ms) Setup 설정 Whether to restrict client self-connections 클라이언트 자체 연결 제한 여부 Whether to use server synchronous mode 서버 동기 모드 사용 여부 &Use server synchronous mode 서버 동기 모드 사용(&U) Please do not touch these settings unless you know what you are doing. 무엇을 하고 있는지 모르는 경우 이 설정을 만지지 마십시오. 200 200 500 500 1000 1000 2000 2000 5000 5000 Cloc&k source: 클럭 소스(&K): Clock source 클럭 소스 S&elf connect mode: 자체 연결하기 모드(&E): Options 옵션 Scripting 스크립팅 Whether to execute a custom shell script before starting up the JACK audio server. JACK 오디오 서버를 시작하기 전에 사용자 정의 셸 스크립트를 실행할지 여부입니다. Execute script on Start&up: 스타트업 시 스크립트 실행(&U): Whether to execute a custom shell script after starting up the JACK audio server. JACK 오디오 서버를 시작한 후 사용자 정의 셸 스크립트를 실행할지 여부입니다. Execute script after &Startup: 스타트업 후 스크립트 실행:(&S): Whether to execute a custom shell script before shuting down the JACK audio server. JACK 오디오 서버를 종료하기 전에 사용자 정의 셸 스크립트를 실행할지 여부입니다. Execute script on Shut&down: 일시종료 시 스크립트 실행: Command line to be executed before starting up the JACK audio server JACK 오디오 서버를 시작하기 전에 실행할 명령줄 Scripting argument meta-symbols 스크립팅 인수 메타 기호 Browse for script to be executed before starting up the JACK audio server JACK 오디오 서버를 시작하기 전에 실행할 스크립트 찾아보기 ... ... Command line to be executed after starting up the JACK audio server JACK 오디오 서버를 시작한 후 실행할 명령줄 Browse for script to be executed after starting up the JACK audio server JACK 오디오 서버를 시작한 후 실행할 스크립트 찾아보기 Browse for script to be executed before shutting down the JACK audio server JACK 오디오 서버를 종료하기 전에 실행할 스크립트 찾아보기 Command line to be executed before shutting down the JACK audio server JACK 오디오 서버를 종료하기 전에 실행할 명령줄 Whether to execute a custom shell script after shuting down the JACK audio server. JACK 오디오 서버를 종료한 후 사용자 지정 셸 스크립트를 실행할지 여부입니다. Execute script after Shu&tdown: 일시종료 후 스크립트 실행(&T): Browse for script to be executed after shutting down the JACK audio server JACK 오디오 서버를 종료한 후 실행할 스크립트 찾아보기 Command line to be executed after shutting down the JACK audio server JACK 오디오 서버를 종료한 후 실행할 명령줄 Statistics 통계 Whether to capture standard output (stdout/stderr) into messages window 표준 출력(stdout/stderr)을 메시지 창에 캡처할지 여부 &Capture standard output 표준 출력 캡처(&C) &XRUN detection regex: XRUN 감지 정규식(&X): Regular expression used to detect XRUNs on server output messages 서버 출력 메시지에서 XRUN을 감지하는 데 사용되는 정규식 xrun of at least ([0-9|\.]+) msecs Connections 연결 Whether to reset all connections when a patchbay definition is activated. 패치베이 정의가 활성화될 때 모든 연결을 재설정할지 여부. &Reset all connections on patchbay activation 패치베이 활성화 시 모든 연결 재설정(&R) Whether to issue a warning on active patchbay port disconnections. 활성 패치베이 포트 연결끊김에 대한 경고 발생 여부. &Warn on active patchbay disconnections 활성 패치베이 연결해제 시 경고(&W) Custom 사용자 지정 &Color palette theme: 색상 팔레트 테마(&C): Custom color palette theme 사용자 지정 색상 팔레트 테마 Wonton Soup DO NOT TRANSLATE KXStudio DO NOT TRANSLATE Manage custom color palette themes 사용자 지정 색상 팔레트 테마 관리 &Widget style theme: 위젯 스타일 테마(&W): Custom widget style theme 사용자 지정 위젯 스타일 테마 Whether to enable JACK D-Bus interface JACK D-Bus 인터페이스 활성화 여부 &Enable JACK D-Bus interface JACK D-Bus 인터페이스 활성화(&E) Whether to replace Connections with Graph button on the main window 기본 창에서 연결을 그래프 버튼으로 대체할지 여부 Replace Connections with &Graph button 연결을 그래프 버튼으로 바꾸기(&G) 10 10 Patchbay definition file to be activated as connection persistence profile 연결 지속성 프로필로 활성화할 패치베이 정의 파일 Browse for a patchbay definition file to be activated 활성화할 패치베이 정의 파일 찾아보기 Whether to activate a patchbay definition for connection persistence profile. 연결 지속성 프로필에 대한 패치베이 정의를 활성화할지 여부. Activate &Patchbay persistence: 패치베이 지속성 활성화(&P): Logging 로깅 Messages log file 메시지 로그 파일 Browse for the messages log file location 메시지 로그 파일 위치 찾아보기 Whether to activate a messages logging to file. 파일에 로깅하는 메시지를 활성화할지 여부입니다. Server &Prefix: 서버 접두사(&P): Server path (command line prefix) 서버 경로 (명령줄 접두사) &Channels I/O: I/O 채널(&C): &Latency I/O: I/O 지연시간(&L): Server Suffi&x: 서버 접미사(&X): Extra driver options (command line suffix) 추가 드라이버 옵션 (명령줄 접미사) Start De&lay: 시작 지연(&L): secs 0 msecs 0 ms Clear settings of current preset name 현재 사전설정 이름의 설정 비우기 Clea&r 비우기(&R) &Messages log file: 메시지 로그 파일(&M): Display 화면표시 Time Display 시간 화면표시 Transport &Time Code 트랜스포트 타임 코드(&T) Transport &BBT (bar:beat.ticks) 트랜스포트 BBT(마디:박자.틱)(&B) Elapsed time since last &Reset 마지막 재설정 이후 경과 시간(&R) Elapsed time since last &XRUN 마지막 XRUN 이후 경과 시간(&X) Sample front panel normal display font 샘플 전면 패널 일반 화면표시 글꼴 Sample big time display font 샘플 큰 시간 화면표시 글꼴 Big Time display: 큰 시간 화면표시: Select font for front panel normal display 전면 패널 일반 화면표시의 글꼴 선택 &Font... 글꼴(&F)... Select font for big time display 큰 시간 화면표시에 사용할 글꼴 Normal display: 일반 화면표시: Whether to enable blinking (flashing) of the server mode (RT) indicator 서버 모드(RT) 지시자의 깜박임(깜박임) 사용 여부 Blin&k server mode indicator 서버 모드 지시자 깜박임(&K) Messages Window 메시지 창 Sample messages text font display 샘플 메시지 텍스트 글꼴 화면표시 Select font for the messages text display 메시지 텍스트 화면표시의 글꼴 선택 Whether to keep a maximum number of lines in the messages window 메시지 창의 최대 줄 수 유지 여부 &Messages limit: 메시지 제한(&M): The maximum number of message lines to keep in view 표시할 최대 메시지 줄 수 100 100 250 250 2500 2500 Connections Window 연결 창 Sample connections view font 샘플 연결 보기 글꼴 Select font for the connections view 연결 보기의 글꼴 선택 &Icon size: 아이콘 크기(&I): The icon size for each item of the connections view 연결 보기의 각 항목에 대한 아이콘 크기 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 Whether to enable client/port name aliases on the connections window 연결 창에서 클라이언트/포트 이름 별칭을 활성화할지 여부 E&nable client/port aliases 클라이언트/포트 별칭 활성화(&N) Whether to enable in-place client/port name editing (rename) 인플레이스 클라이언트/포트 이름 편집 활성화 여부(이름 변경) Ena&ble client/port aliases editing (rename) 클라이언트/포트 별칭 편집 활성화 (이름 변경)(&B) &JACK client/port aliases: JACK 클라이언트/포트 별칭(&J): Advanced 고급 JACK client/port aliases display mode JACK 클라이언트/포트 별칭 화면표시 모드 Default 기본값 First 첫 번째 Second 두 번째 JACK client/port pretty-name (metadata) display mode JACK 클라이언트/포트 예쁜 이름(메타데이터) 화면표시 모드 Enable JA&CK client/port pretty-names (metadata) JA&CK 클라이언트/포트 예쁜 이름(메타데이터) 활성화(&C) Misc 기타 Other 다른 Whether to start JACK audio server immediately on application startup 응용프로그램 시작 시 JACK 오디오 서버를 즉시 시작할지 여부 &Start JACK audio server on application startup 응용프로그램 시작 시 JACK 오디오 서버 시작(&S) Whether to ask for confirmation on application exit 응용프로그램 종료 시 확인 요청 여부 &Confirm application close 응용프로그램 닫기 확인(&C) Whether to keep all child windows on top of the main window 모든 하위 창을 기본 창 맨 위에 둘지 여부 &Keep child windows always on top 하위 창을 항상 맨 위로 유지(&K) Whether to enable the system tray icon 시스템 트레이 아이콘 활성화 여부 &Enable system tray icon 시스템 트레이 아이콘 활성화(&E) Whether to show system tray message on main window close 기본 창을 닫을 때 시스템 트레이 메시지를 표시할지 여부 Sho&w system tray message on close 닫을 때 시스템 트레이 메시지 표시(&W) Whether to start minimized to system tray 시스템 트레이로 최소화할지 여부 Start minimi&zed to system tray 시스템 트레이에 최소화된 시작(&Z) Whether to restrict to one single application instance (X11) 단일 응용프로그램 인스턴스로 제한할지 여부 (X11) Single application &instance 단일 응용프로그램 인스턴스(&I) Whether to save the JACK server command-line configuration into a local file (auto-start) JACK 서버 명령줄 구성을 로컬 파일에 저장할지 여부 (자동 시작) Whether to ask for confirmation on JACK audio server shutdown and/or restart JACK 오디오 서버 일시종료 및/또는 다시 시작 시 확인을 요청할지 여부 Confirm server sh&utdown and/or restart 서버 일시종료 확인 및/또는 다시 시작(&U) S&ave JACK audio server configuration to: JACK 오디오 서버 구성 저장(&A): The server configuration local file name (auto-start) 서버 구성 로컬 파일 이름 (자동 시작) .jackdrc .jackdrc Whether to enable ALSA Sequencer (MIDI) support on startup 시작 시 ALSA 시퀀서(MIDI) 지원 활성화 여부 E&nable ALSA Sequencer support ALSA 시퀀서 지원 활성화(&N) Whether to enable D-Bus interface D-Bus 인터페이스 활성화 여부 &Enable D-Bus interface D-Bus 인터페이스 활성화(&E) Whether to stop JACK audio server on application exit 응용프로그램 종료 시 JACK 오디오 서버를 중지할지 여부 S&top JACK audio server on application exit 응용프로그램 종료 시 JACK 오디오 서버 중지(&S) Buttons 버튼 Whether to hide the left button group on the main window 기본 창에서 왼쪽 버튼 그룹을 숨길지 여부 Hide main window &Left buttons 기본 창 왼쪽 버튼 숨김(&L) Whether to hide the right button group on the main window 기본 창에서 오른쪽 버튼 그룹을 숨길지 여부 Hide main window &Right buttons 기본 창 오른쪽 버튼 숨김(&R) Whether to hide the transport button group on the main window 기본 창에서 트랜스포트 버튼 그룹을 숨길지 여부 Hide main window &Transport buttons 기본 창 트랜스포트 버튼 숨김(&T) Whether to hide the text labels on the main window buttons 기본 창 버튼의 텍스트 레이블을 숨길지 여부 Hide main window &button text labels 기본 창 버튼 텍스트 레이블 숨김(&B) Defaults 기본값 &Base font size: 기본 글꼴 크기(&B): Base application font size (pt.) 기본 응용 프로그램 글꼴 크기 (pt) 6 6 7 7 8 8 9 9 11 11 12 12 System 시스템 Cycle 사이클 HPET HPET Don't restrict self connect requests (default) 자체 연결 요청을 제한하지 않음 (기본값) Fail self connect requests to external ports only 외부 포트에만 자체 연결 요청 실패 Ignore self connect requests to external ports only 외부 포트에 대한 자체 연결 요청만 무시 Fail all self connect requests 모든 자체 연결 요청 실패 Ignore all self connect requests 모든 자체 연결 요청 무시 Warning 경고 Some settings have been changed: "%1" Do you want to save the changes? 일부 설정이 변경되었음: "%1" 변경 사항을 저장하시겠습니까? Delete preset: "%1" Are you sure? 사전설정 삭제: "%1" 확실하신가요? msec ms n/a 해당 없음 &Preset Name 사전설정 이름(&P) &Server Name 서버 이름(&S) &Server Path 서버 경로(&S) &Driver 드라이버(&D) &Interface 인터페이스(&I) Sample &Rate 샘플 레이트(&R) &Frames/Period 프레임/기간(&F) Periods/&Buffer 기간/버퍼(&B) Startup Script 스타트업 스크립트 Post-Startup Script 스타트업 후 스크립트 Shutdown Script 일시종료 스크립트 Post-Shutdown Script 일시종료 후 스크립트 Active Patchbay Definition 활성 패치베이 정의 Patchbay Definition files 패치베이 정의 파일 Messages Log 메시지 로그 Log files 로그 파일 Information 정보 Some settings may be only effective next time you start this application. 일부 설정은 다음에 이 응용프로그램을 시작할 때만 유효할 수 있습니다. Some settings have been changed. Do you want to apply the changes? 일부 설정이 변경되었습니다. 변경 사항을 적용하시겠습니까? qjackctlSocketForm Socket 소켓 &Socket 소켓(&S) &Name (alias): 이름 (별칭)(&N): Socket name (an alias for client name) 소켓 이름(클라이언트 이름의 별칭) Client name (regular expression) 클라이언트 이름 (정규식) Add plug to socket plug list 소켓 플러그 목록에 플러그 추가 Add P&lug 플러그 추가(&L) &Plug: 플러그(&P): Port name (regular expression) 포트 이름 (정규식) Socket plug list 소켓 플러그 목록 Socket Plugs / Ports 소켓 플러그 / 포트 Edit currently selected plug 현재 선택된 플러그 편집 &Edit 편집(&E) Remove currently selected plug from socket plug list 소켓 플러그 목록에서 현재 선택된 플러그 제거 &Remove 제거(&R) &Client: 클라이언트(&C): Move down currently selected plug in socket plug list 소켓 플러그 목록에서 현재 선택된 플러그 아래로 이동 &Down 아래로(&D) Move up current selected plug in socket plug list 소켓 플러그 목록에서 현재 선택된 플러그 위로 이동 &Up 위로(&U) Enforce only one exclusive cable connection 하나의 전용 케이블 연결만 적용 E&xclusive 독점적(&X) &Forward: Forward (clone) all connections from this socket 이 소켓의 모든 연결 전달하기 (복제) Type 유형 Audio socket type (JACK) 오디오 소켓 유형 (JACK) &Audio 오디오(&A) MIDI socket type (JACK) MIDI 소켓 유형 (JACK) &MIDI MIDI(&M) MIDI socket type (ALSA) MIDI 소켓 유형 (ALSA) AL&SA ALSA(&S) Plugs / Ports 플러그 / 포트 Error 오류 A socket named "%1" already exists. "%1" 이름을 가진 소켓이 이미 있습니다. Warning 경고 Some settings have been changed. Do you want to apply the changes? 일부 설정이 변경되었습니다. 변경 사항을 적용하시겠습니까? Add Plug 플러그 추가 Edit 편집 Remove 제거 Move Up 위로 이동 Move Down 아래로 이동 (None) (없음) qjackctlSocketList Output 출력 Input 입력 Socket 소켓 <New> - %1 <신규> - %1 Warning 경고 %1 about to be removed: "%2" Are you sure? %1 제거 예정: "%2" 확실하신가요? %1 <Copy> - %2 %1 <복사> - %2 qjackctlSocketListView Output Sockets / Plugs 출력 소켓 / 플러그 Input Sockets / Plugs 입력 소켓 / 플러그 qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_ru.ts0000644000000000000000000000013214771215054020556 xustar0030 mtime=1743067692.335636536 30 atime=1743067692.335636536 30 ctime=1743067692.335636536 qjackctl-1.0.4/src/translations/qjackctl_ru.ts0000644000175000001440000070020514771215054020552 0ustar00rncbcusers PortAudioProber Probing... Опрос… Please wait, PortAudio is probing audio hardware. Подождите немного, PortAudio опрашивает звуковой интерфейс. Warning Предупреждение Audio hardware probing timed out. Время опроса звукового интерфейса истекло. QObject Option -p requires an argument (preset). Ключ -p требует аргумента (профиль параметров). (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Usage: %1 [options] [command-and-args] Использование: %1 [ключи] [команды-и-аргументы] Options: Ключи: Start JACK audio server immediately. Запустить звуковой сервер JACK немедленно. Set default settings preset name. Указать имя профиля параметров по умолчанию. Set active patchbay definition file. Установить файл активного описания коммутатора. Set default JACK audio server name. Указать имя звукового сервера JACK по умолчанию. Show help about command line options. Показать справку о ключах командной строки. Show version information. Показать сведения о версии. Launch command with arguments. Запустить команду с аргументами. [command-and-args] [команда-и-аргументы] Option -a requires an argument (path). Ключу -a необходим аргумент (расположение). Option -n requires an argument (name). Ключу -n необходим аргумент (название). %1 (%2 frames) %1 (%2 выб.) Move Переместить Rename Переименовать qjackctlAboutForm About О программе About Qt О Qt &Close &Закрыть Version Версия Transport status control disabled. Управление состоянием передачи отключено. Realtime status disabled. Статус режима реального времени отключён. JACK Session support disabled. Поддержка JACK Session отключена. Using: Qt %1 Использует: Qt %1 JACK %1 JACK %1 Website Домашняя страница This program is free software; you can redistribute it and/or modify it Это программа является свободной; вы можете распространять и/или изменять её без ограничений under the terms of the GNU General Public License version 2 or later. на условиях лицензии GNU General Public License версии 2 или более новой. Debugging option enabled. Параметр отладки включён. System tray disabled. Область уведомления отключена. XRUN delay status disabled. Статус задержки XRUN отключён. Maximum delay status disabled. Статус максимальной задержки отключён. JACK MIDI support disabled. Поддержка JACK MIDI отключена. ALSA/MIDI sequencer support disabled. Поддержка секвенсера ALSA/MIDI отключена. JACK Port aliases support disabled. Поддержка алиасов портов JACK отключена. D-Bus interface support disabled. Поддержка интерфейса D-Bus отключена. qjackctlClientListView Readable Clients / Output Ports Порты выхода Writable Clients / Input Ports Порты входа &Connect &Соединить Alt+C Connect Alt+с &Disconnect &Отсоединить Alt+D Disconnect Alt+р Disconnect &All Отсоединить &все Alt+A Disconnect All Alt+в Re&name Пере&именовать Alt+N Rename Alt+и &Refresh &Обновить Alt+R Refresh Alt+о qjackctlConnect Warning Предупреждение This will suspend sound processing from all client applications. Are you sure? Обработка звука от клиентских приложений будет прекращена. Вы уверены? qjackctlConnectionsForm &Connect &Соединить Connect currently selected ports Соединить выбранные сейчас порты &Disconnect &Отсоединить Disconnect currently selected ports Отсоединить выбранные сейчас порты Disconnect &All Отсоединить &все Disconnect all currently connected ports Отсоединить все соединённые сейчас порты Connections Соединения Expand all client ports Раскрыть все порты клиентов E&xpand All &Раскрыть все &Refresh &Обновить Refresh current connections view Обновить отображение текущих соединений Audio Звук MIDI MIDI ALSA ALSA qjackctlConnectorView &Connect &Соединить Alt+C Connect Alt+с &Disconnect &Отсоединить Alt+D Disconnect Alt+р Disconnect &All Отсоединить &все Alt+A Disconnect All Alt+в &Refresh &Обновить Alt+R Refresh Alt+о qjackctlGraphCanvas Connect Соединить Disconnect Отсоединить qjackctlGraphForm Graph Граф &Graph &Граф &Edit &Правка &View &Вид &Zoom &Масштаб Co&lors &Цвета S&ort &Сортировка &Help &Справка &Connect &Соединить Connect Соединить Connect selected ports Соединить выбранные порты &Disconnect &Отсоединить Disconnect Отсоединить Disconnect selected ports Отсоединить выбранные порты Ctrl+C Ctrl+C T&humbview М&иниатюра Ctrl+D Ctrl+D Cl&ose &Закрыть Close Закрыть Close this application window Закрыть это окно приложения Select &All Выбрать &все Select All Выбрать все Ctrl+A Ctrl+A Select &None Снять в&ыделение Select None Снять выделение Ctrl+Shift+A Ctrl+Shift+A Select &Invert &Инвертировать выделение Select Invert Инвертировать выделение Ctrl+I Ctrl+I &Rename... Пере&именовать... Rename item Переименовать объект Rename Item Переименовать объект F2 F2 &Find... &Найти… Find Найти Find nodes Найти узлы Ctrl+F Ctrl+F &Menubar Панель &меню Menubar Панель меню Show/hide the main program window menubar Показать/скрыть панель меню программы Ctrl+M Ctrl+M &Toolbar Панель &инструментов Toolbar Панель инструментов Show/hide main program window file toolbar Показать/скрыть панель инструментов программы &Statusbar &Статусная строка Statusbar Статусная строка Show/hide the main program window statusbar Показать/скрыть статусную строку программы &Top Left &Вверху слева Top left Вверху слева Show the thumbnail overview on the top-left Показывать обзор миниатюр вверху слева Top &Right Вверху &справа Top right Вверху справа Show the thumbnail overview on the top-right Показывать обзор миниатюр вверху справа Bottom &Left &Внизу слева Bottom Left Внизу слева Bottom left Внизу слева Show the thumbnail overview on the bottom-left Показывать обзор миниатюр внизу слева &Bottom Right &Внизу справа Bottom right Внизу справа Show the thumbnail overview on the bottom-right Показывать обзор миниатюр внизу справа &None &Нет None Нет Hide thumbview Не показывать миниатюру Hide the thumbnail overview Не показывать обзор миниатюр Text Beside &Icons Текст &рядом со значками Text beside icons Текст рядом со значками Show/hide text beside icons Показывать или скрывать текст рядом со значками &Center &Центрировать Center Центрировать Center view Центрировать вид &Refresh О&бновить Refresh Обновить Refresh view Обновить вид F5 F5 Zoom &In &Приблизить Zoom In Приблизить Ctrl++ Ctrl++ Zoom &Out От&далить Zoom Out Отдалить Ctrl+- Ctrl+- Zoom &Fit Уместить вс&ё в окне Zoom Fit Уместить всё в окне Ctrl+0 Ctrl+0 Zoom &Reset Сбросить &масштаб Zoom Reset Сбросить масштаб Ctrl+1 Ctrl+1 &Zoom Range Приблизить в&ыделенное Zoom Range Приблизить выделенное JACK &Audio... JACK &Audio... JACK Audio color Цвет JACK Audio JACK &MIDI... JACK &MIDI... JACK MIDI JACK MIDI JACK MIDI color Цвет JACK MIDI ALSA M&IDI... ALSA M&IDI... ALSA MIDI ALSA MIDI ALSA MIDI color Цвет ALSA MIDI JACK &CV... JACK &CV... JACK CV color Цвет JACK CV JACK &OSC... JACK &OSC... JACK OSC JACK OSC JACK OSC color Цвет JACK OSC &Reset С&бросить Reset colors Сбросить цвета Port &Name По &названию порта Port name Название порта Sort by port name Сортировать по названию порта Port &Title По &заголовку порта Port title По заголовку порта Sort by port title Сортировать по заголовку порта Port &Index По &индексу порта Port index По индексу порта Sort by port index Сортировать по индексу порта &Ascending По &нарастанию Ascending По нарастанию Ascending sort order Порядок сортировки по нарастанию &Descending По &убыванию Descending По убыванию Descending sort order Порядок сортировки по убыванию Repel O&verlapping Nodes Отбросить п&ерекрывающиеся узлы Repel nodes Отбросить узлы Repel overlapping nodes Отбросить перекрывающиеся узлы Connect Thro&ugh Nodes Соединение чер&ез узлы Connect Through Nodes Соединение через узлы Connect through nodes Соединение через узлы Whether to draw connectors through or around nodes Определяет, проводить ли соединительные элементы через узлы или вокруг них &About... &О программе... About... О программе... About О программе Show information about this application program Показать информацию об этой программе About &Qt... О &Qt... About Qt... О Qt... About Qt О Qt Show information about the Qt toolkit Показать информацию о наборе инструментов Qt &Undo &Отмена &Redo &Возврат Undo last edit action Отменить последнее действие Redo last edit action Вернуть последнее действие Zoom Масштаб Ready Готово Colors - %1 Цвета — %1 qjackctlMainForm &Start &Запустить Start the JACK server Запустить сервер JACK S&top С&топ Stop the JACK server Остановить сервер JACK &Quit В&ыход Quit processing and exit Остановить сервер и выйти из программы JACK is starting... Выполняется запуск JACK... JACK is stopping... Выполняется остановка JACK... msec мс Error Ошибка JACK server state Состояние сервера JACK Sample rate Частота сэмплирования Time display Время Transport state Состояние передачи Transport BPM BPM передачи Transport time Время передачи &Play &Воспроизвести Start transport rolling Запустить прокрутку передачи Pa&use Пау&за Stop transport rolling Остановить прокрутку передачи St&atus С&татус Ab&out... О про&грамме... Show information about this application Показать информацию о приложении Show settings and options dialog Показать диалог настройки программы &Messages С&ообщения Patch&bay &Коммутатор Show/hide the patchbay editor window Показать/скрыть окно коммутатора &Connections Сое&динения successfully успешно Activating Активируется Starting Запуск The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. Программа продолжит работать в области уведомления. Для завершения выберите в контекстном меню области уведомления пункт «Выход». Startup script... Сценарий запуска... Startup script terminated Выполнение сценария запуска прекращено Started Запущен Stopping Остановка JACK was stopped Cервер JACK остановлен Shutdown script... Сценарий выключения... Shutdown script terminated Выполнение сценария выключения прекращено Inactive Не активен Active Активен Stopped Остановлен Could not load active patchbay definition. "%1" Disabled. Не удалось загрузить описание активного коммутатора. «%1» Отключено. Statistics reset. Перезапуск статистики Shutdown notification. Уведомление об остановке checked проверено connected соединено failed не удалось Client activated. Клиент активирован Post-startup script... Сценарий после запуска... Post-startup script terminated Выполнение сценария после запуска прекращено Client deactivated. Клиент деактивирован Transport start. Передача запущена Transport stop. Передача остановлена Yes Да No Нет Rolling Прокрутка Looping Цикл Transport time code Тайм-код передачи Elapsed time since last reset Времени с последней перезагрузки Elapsed time since last XRUN Времени с последнего XRUN disconnected отсоединено Command line argument... Аргумент командной строки... Command line argument started Аргумент командной строки запущен Information Информация Do you want to restart the JACK audio server? Перезапустить звуковой сервер JACK? Some settings will be only effective the next time you start this program. Некоторые изменения вступят в силу только при следующем запуске программы. JACK server mode Режим сервера JACK Server settings will be only effective after restarting the JACK audio server. Параметры работы сервера JACK вступят в силу только при следующем запуске сервера. RT RT &Hide С&крыть S&how &Показать &Stop &Стоп Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. Не удалось открыть секвенсер ALSA как клиентское приложение. Коммутатор ALSA MIDI будет недоступен. D-BUS: Service is available (%1 aka jackdbus). D-BUS: служба доступна (%1, известный как jackdbus). D-BUS: Service not available (%1 aka jackdbus). D-BUS: служба недоступна (%1, известный как jackdbus). Warning Предупреждение JACK is currently running. Do you want to terminate the JACK audio server? Сервер JACK работает. Вы хотите остановить его? Don't ask this again Больше не спрашивать with exit status=%1 со статусом выхода %1 Could not start JACK. Maybe JACK audio server is already started. Не удалось запустить JACK. Возможно, звуковой сервер уже запущен. Could not load preset "%1". Retrying with default. Не удалось загрузить профиль «%1». Попытка загрузить используемый по умолчанию профиль. Could not load default preset. Sorry. Не удалось запустить профиль по умолчанию. D-BUS: JACK server is starting... D-BUS: запускается сервер JACK... D-BUS: JACK server could not be started. Sorry D-BUS: не удалось запустить сервер JACK. Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Некоторые клиентские звуковые приложения всё ещё активны и подсоединены. Остановить звуковой сервер JACK? D-BUS: JACK server is stopping... D-BUS: сервер JACK останавливается... D-BUS: JACK server could not be stopped. Sorry D-BUS: не удалось остановить сервер JACK. Post-shutdown script... Выполняется сценарий после выключения… Post-shutdown script terminated Выполнение сценария после выключения прекращено JACK was started with PID=%1. JACK был запущен с PID=%1. Don't show this message again Больше не показывать это сообщение The preset aliases have been changed: "%1" Do you want to save the changes? Алиасы профилей изменились: «%1» Сохранить изменения? D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: сервер JACK был запущен (%1, известный как jackdbus). JACK is being forced... Принудительное выполнение JACK… D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: сервер JACK был остановлен (%1, известный как jackdbus). Transport BBT (bar.beat.ticks) BBT передачи (такт.доля.тики) Patchbay reset. Коммутатор сброшен. Patchbay activated. Коммутатор активирован. Patchbay deactivated. Коммутатор деактивирован. JACK connection graph change. Смена графа соединений JACK. XRUN callback (%1). Обратный вызов XRUN (%1). Buffer size change (%1). Смена размера буфера (%1). Freewheel started... Запущен свободный ход… Freewheel exited. Выход из режима свободного хода. Could not start JACK. Sorry. Не удалось запустить JACK. JACK has crashed. Произошёл сбой в работе JACK. JACK timed out. Превышено время ожидания запуска JACK. JACK write error. Ошибка записи JACK. JACK read error. Ошибка чтения JACK. Unknown JACK error (%d). Неизвестная ошибка JACK (%d). JACK property change. Изменение свойства JACK. ALSA connection graph change. Смена графа соединений ALSA. JACK active patchbay scan Сканирование активного коммутатора JACK. ALSA active patchbay scan Сканирование активного коммутатора ALSA. JACK connection change. Смена соединений JACK. ALSA connection change. Смена соединений ALSA. A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? В настоящее время активно определение коммутатора, что может привести к повторному соединению: %1 -> %2 Удалить соединение коммутатора? %1 (%2%, %3 xruns) %1 (%2%, %3 xrun) FW Свободный ход &Versioning &Версии Re&fresh О&бновить D-BUS: GetParameterConstraint('%1'): %2. (%3) D-BUS: GetParameterConstraint('%1'): %2. (%3) &Graph &Граф D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) Overall operation failed. Выполнение операции в целом неудачно. %1 is about to terminate. Are you sure? %1 сейчас прекратит работу. Вы уверены? Invalid or unsupported option. Некорректный или неподдерживаемый параметр Client name not unique. Имя клиента не уникально. Server is started. Сервер запущен. Unable to connect to server. Не удалось соединиться с сервером. Server communication error. Ошибка коммуникации с сервером. Client does not exist. Клиент не существует. Unable to load internal client. Не удалось загрузить внутренний клиент. Unable to initialize client. Не удалось инициализировать клиент. Unable to access shared memory. Не удалось получить доступ к разделяемой памяти. Client protocol version mismatch. Несовпадение версии клиентского протокола. Could not connect to JACK server as client. - %1 Please check the messages window for more info. Не удалось соединиться с сервером JACK. — %1 Просмотрите вывод в окне сообщений. Server configuration saved to "%1". Конфигурация сервера сохранена в «%1». Transport rewind. Перемотка к началу Transport backward. Перемотка назад Transport forward. Перемотка вперёд %1 (%2%) %1 (%2%) %1 % %1% %1 Hz %1Гц %1 frames %1 выб. %1 msec %1 мс XRUN callback (%1 skipped). Обратный вызов XRUN (%1 пропущен). Mi&nimize &Свернуть Rest&ore &Восстановить &Reset С&бросить &Presets &Профили S&ession С&еансы &Load... &Загрузить... &Save... &Сохранить… Save and &Quit... Сохранить и вы&йти… Save &Template... Сохранить &шаблон… &Transport &Передача &Rewind К &началу Set&up... &Параметры &Patchbay &Коммутатор &Connect &Соединения DSP Load Загрузка DSP XRUN Count (notifications) Число XRUN (уведомлений) Show/hide the session management window Показать/скрыть окно управления сеансами Show/hide the messages log/status window Показать скрыть окно журнала сообщений/состояния Show/hide the graph window Показать/скрыть окно графа Show/hide the connections window Показать/скрыть окно соединений Backward transport Перемотать назад &Backward Н&азад Forward transport Перемотать вперёд &Forward &Вперёд Rewind transport Перемотать к началу qjackctlMessagesStatusForm Messages / Status Сообщения/статус &Messages С&ообщения Messages log Журнал сообщений Messages output log Журнал выведенных сообщений &Status С&татус Status information Информация о статусе Statistics since last server startup Статистика с последнего запуска сервера Description Описание Value Значение Reset XRUN statistic values Обнулить статистику по рассинхронизации Re&set С&бросить Refresh XRUN statistic values Обновить статистику по рассинхронизации &Refresh &Обновить Server name Имя сервера Server state Статус сервера DSP Load Загрузка DSP Sample Rate Частота сэмплирования Buffer Size Размер буфера Realtime Mode Режим реального времени Transport state Состояние передачи Transport Timecode Тайм-код передачи Transport BBT BBT передачи Transport BPM BPM передачи XRUN count since last server startup Рассинхронизаций с последнего запуска сервера XRUN last time detected Последняя обнаруженная рассинхронизация XRUN last Последняя рассинхронизация XRUN maximum Максимальная рассинхронизация XRUN minimum Минимальная рассинхронизация XRUN average Средняя длительность рассинхронизаций XRUN total Всего рассинхронизаций Maximum scheduling delay Максимальная задержка расписания Time of last reset Время последнего сброса Logging stopped --- %1 --- Журналирование остановлено --- %1 --- Logging started --- %1 --- Журналирование запущено --- %1 --- qjackctlPaletteForm Color Themes Цветовые темы Name Название Current color palette name Название текущей цветовой палитры Save current color palette name Сохранить название текущей цветовой палитры Save Сохранить Delete current color palette name Удалить название текущей цветовой палитры Delete Удалить Palette Палитра Current color palette Текущая цветовая палитра Generate: Создать: Base color to generate palette Базовый цвет для генерирования палитры Reset all current palette colors Сбросить все используемые цвета Reset Сбросить Import a custom color theme (palette) from file Импорт пользовательской цветовой темы (палитры) из файла Import... Импорт... Export a custom color theme (palette) to file Экспорт пользовательской цветовой темы (палитры) из файла Export... Экспорт... Show Details Подробности Import File - %1 Импорт файла — %1 Palette files (*.%1) Файлы палитр (*.%1) Save Palette - %1 Сохранить палитру — %1 All files (*.*) Все файлы (*.*) Warning - %1 Предупреждение — %1 Could not import from file: %1 Sorry. Не удалось импортировать из файла: %1 Export File - %1 Экспорт файла — %1 Some settings have been changed. Do you want to discard the changes? Некоторые параметры изменились. Отменить изменения? Some settings have been changed: "%1". Do you want to save the changes? Некоторые параметры изменились: «%1» Сохранить изменения? qjackctlPaletteForm::PaletteModel Color Role Роль цвета Active Активен Inactive Не активен Disabled Выключен qjackctlPatchbay Warning Предупреждение This will disconnect all sockets. Are you sure? Все сокеты будут рассоединены. Продолжить? qjackctlPatchbayForm &New &Создать Create a new patchbay profile Создать новый профиль коммутатора &Load... &Загрузить... Load patchbay profile Загрузить профиль коммутатора &Save... &Сохранить... Save current patchbay profile Сохранить текущий профиль коммутатора Acti&vate &Активировать &Connect &Соединить Connect currently selected sockets Соединить выбранные сейчас сокеты &Disconnect &Рассоединить Disconnect currently selected sockets Рассоединить выбранные сейчас сокеты Disconnect &All Рассоединить &все Disconnect all currently connected sockets Рассоединить все соединённые сейчас сокеты &Refresh &Обновить Refresh current patchbay view Обновить текущий вид коммутатора Down Вниз Move currently selected output socket down one position Переместить выбранный сейчас сокет вниз на одну позицию Add... Добавить... Create a new output socket Создать новый сокет выхода Edit... Изменить... Edit currently selected input socket properties Изменить свойства выбранного сейчас сокета входа Up Вверх Move currently selected output socket up one position Переместить выбранный сейчас сокет вверх на одну позицию Remove Удалить Remove currently selected output socket Удалить выбранный сейчас сокет выхода Patchbay Коммутатор Remove currently selected input socket Удалить выбранный сейчас сокет входа Create a new input socket Создать новый сокет входа Edit currently selected output socket properties Изменить свойства выбранного сейчас сокета выхода Warning Предупреждение active активно New Patchbay definition Новое описание коммутатора Patchbay Definition files Файлы описания коммутатора Load Patchbay Definition Загрузить описание коммутатора Save Patchbay Definition Сохранить описание коммутатора The patchbay definition has been changed: "%1" Do you want to save the changes? Описание коммутатора изменилось: «%1» Сохранить изменения? %1 [modified] %1 [изменено] Untitled%1 Без имени %1 Error Ошибка Could not load patchbay definition file: "%1" Не удалось загрузить файл описания коммутатора: «%1» Could not save patchbay definition file: "%1" Не удалось сохранить файл описания коммутатора: «%1» Create patchbay definition as a snapshot of all actual client connections? Создать описание коммутатора как снимок активных соединений клиентов? Duplicate (copy) currently selected output socket Дублировать (копировать) выбранное в данный момент выходное гнездо Copy... Скопировать... Duplicate (copy) currently selected input socket Дублировать (копировать) выбранное в данный момент входное гнездо Expand all items Развернуть все элементы E&xpand All &Развернуть все Current (recent) patchbay profile(s) Текущий (недавний) профиль коммутатора Toggle activation of current patchbay profile Включить или отключить текущий профиль коммутатора qjackctlPatchbayView Add... Добавить... Edit... Изменить... Remove Удалить Move Up Выше Move Down Ниже &Connect &Соединить Alt+C Connect Alt+C &Disconnect &Отсоединить Alt+D Disconnect Alt+D Disconnect &All Отсоединить &все Alt+A Disconnect All Alt+A &Refresh &Обновить Alt+R Refresh Alt+R Exclusive Исключительный Copy... Скопировать... Forward Вперёд (None) (Нет) qjackctlSessionForm Session Сеанс Load session Загрузить сеанс &Load... &Загрузить… Recent session Недавние сеансы &Recent &Недавние Save session Сохранить сеанс &Versioning &Версии Re&fresh О&бновить Session clients / connections Клиенты и соединения сеанса Infra-clients / commands Инфра-клиенты и команды Infra-client Инфра-клиент Infra-command Инфра-команда Add infra-client Добавить инфра-клиент &Add &Добавить Edit infra-client Изменить инфра-клиент &Edit &Изменить Remove infra-client Удалить инфра-клиент Re&move &Удалить &Save... &Сохранить… Update session Обновить сеанс Client / Ports Клиенты/порты UUID UUID Command Команда &Save &Сохранить Load Session Загрузить сеанс Session directory Каталог сеансов Save Session Сохранить сеанс and Quit и выйти Template Шаблон &Clear О&чистить Warning Предупреждение A session could not be found in this folder: "%1" Не удалось найти сеанс в каталоге «%1» %1: loading session... %1: загружается сеанс... %1: load session %2. %1: загрузить сеанс %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? В этой папке уже есть сеанс: «%1» Вы уверены, что хотите перезаписать его? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Эта папка уже существует и не пуста: «%1» Вы уверены, что хотите перезаписать существующую папку? %1: saving session... %1: сохраняется сеанс... %1: save session %2. %1: сохранить сеанс %2. New Client Новый клиент Save and &Quit... Сохранить и вы&йти… Save &Template... Сохранить &шаблон… qjackctlSessionInfraClientItemEditor Infra-command Инфра-команда qjackctlSessionSaveForm Session Сеанс &Name: &Имя: Session name Имя сеанса &Directory: &Каталог: Session directory Каталог сеансов Browse for session directory Поиск каталога сеансов ... ... Save session versioning Сохранять версии сеансов &Versioning &Версии Warning Предупреждение Session directory does not exist: "%1" Do you want to create it? Каталог сеансов не существует: «%1» Создать его? Session Directory Каталог сеансов qjackctlSetupForm Settings Параметры jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters Параметры 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 Sample rate in frames per second Частота дискретизации выборок в секунду 6 6 7 7 8 8 9 9 10 10 Scheduler priority when running realtime Приоритет планировщика в режиме реального времени 21333 21333 16 16 32 32 Priorit&y: П&риоритет: &Wait (usec): О&жидание (мс): &Frames/Period: &Выборок в буфере: 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Frames per period between process() calls Выборок в период между вызовами process() Sample &Rate: &Частота дискр.: H/&W Meter Аппаратный &счётчик None Нет Rectangular Прямоугольное Shaped По очертаниям Triangular Треугольное Duplex Дуплекс Provide either audio capture, playback or both Разрешить захват звука, его воспроизведение или всё сразу hw:0 hw:0 &Timeout (msec): &Тайм-аут (мс): Dit&her: Подмешивание &шума: 200 200 500 500 1000 1000 2000 2000 5000 5000 Set client timeout limit in milliseconds Установить тайм-аут для клиента в миллисекундах &Interface: &Интерфейс: So&ft Mode &Программный режим &Monitor &Контроль Provide output monitor ports Задействовать порты контроля выхода &Realtime Режим &реал. времени Use realtime scheduling Использовать планирование в реал. времени (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Whether to give verbose output on messages Подробно ли выводить сообщения Latency: Задержка: Output latency in milliseconds, calculated based on the period, rate and buffer settings Задержка выхода в мс, расчитанных на основе настроек периода, частоты и буфера Options Параметры Scripting Сценарии Execute script on Start&up: Выполнять сценарий при &запуске: Whether to execute a custom shell script before starting up the JACK audio server. Выполнять ли собственный сценарий перед запуском сервера JACK. Execute script after &Startup: Выполнять сценарий после з&апуска: Whether to execute a custom shell script after starting up the JACK audio server. Выполнять ли собственный сценарий после запуска сервера JACK. Whether to execute a custom shell script after shuting down the JACK audio server. Выполнять ли собственный сценарий после остановки сервера JACK. Command line to be executed before starting up the JACK audio server Команда, выполняемая перед запуском сервера JACK ... ... Browse for script to be executed before starting up the JACK audio server Указать сценарий, выполняемый перед запуском сервера JACK Command line to be executed after starting up the JACK audio server Команда, выполняемая после запуска сервера JACK Browse for script to be executed after starting up the JACK audio server Указать сценарий, выполняемый после запуска сервера JACK Browse for script to be executed after shutting down the JACK audio server Указать сценарий, выполняемый после остановки сервера JACK Command line to be executed after shutting down the JACK audio server Команда, выполняемая после остановки сервера JACK Statistics Статистика &XRUN detection regex: &Регулярное выражение для определения XRUN: xrun of at least ([0-9|\.]+) msecs xrun не менее ([0-9|\.]+) мс Regular expression used to detect XRUNs on server output messages Регулярное выражение для определения рассинхронизаций среди сообщений от сервера Connections Соединения Patchbay definition file to be activated as connection persistence profile Файл описания коммутатора, активируемый как профиль постоянного соединения Browse for a patchbay definition file to be activated Указать активируемый файл описания коммутатора Activate &Patchbay persistence: Активировать &постоянный коммутатор: Whether to activate a patchbay definition for connection persistence profile. Активировать ли описание коммутатора для профиля постоянного соединения. Display Интерфейс Transport &BBT (bar:beat.ticks) &BBT передачи (такт:доля.тики) Elapsed time since last &Reset Время, прошедшее с последнего &сброса Elapsed time since last &XRUN Время, пошедшее с последней &рассинхронизации Messages Window Окно сообщений Sample messages text font display Каким будет шрифт для вывода сообщений сервера &Font... &Шрифт... Select font for the messages text display Выберите шрифт для отображения сообщений сервера msec мс n/a н/д Patchbay Definition files Файлы описания коммутатора Driv&er: &Драйвер: Preset &Name: Имя &профиля: Settings preset name Имя профиля параметров &Save &Сохранить Save settings as current preset name Сохранить параметры в текущий профиль &Delete &Удалить Delete current settings preset Удалить текущий профиль &Audio: &Звук: Force &16bit Принудительно &16 бит Force 16bit mode instead of failing over 32bit (default) Принудительно использовать 16-битный режим вместо 32-битного (по умолчанию) Periods/&Buffer: Периодов на &буфер: Time in seconds that client is delayed after server startup Сколько секунд клиент ждёт после запуска сервера > > Scripting argument meta-symbols Метасимволы аргументов в сценариях &Capture standard output &Захватывать стандартный вывод Whether to capture standard output (stdout/stderr) into messages window Захватывать ли стандартный вывод (stdout/stderr) Other Другое &Confirm application close За&прашивать подтверждение на выход Whether to ask for confirmation on application exit Спрашивать ли подтверждение на выход из программы &Preset Name Имя &профиля &Server Path За&пуск сервера &Driver &Драйвер &Interface &Интерфейс Sample &Rate &Частота дискр. &Frames/Period &Выборок/период Periods/&Buffer Периодов/&буфер Port Ma&ximum: &Макс. портов: Maximum number of ports the JACK server can manage Максимальное кол-во портов, обрабатываемых сервером JACK &Input Device: Устройство &входа: &Output Device: Устройство в&ыхода: /dev/dsp /dev/dsp No Memory Loc&k Б&ез блокировки памяти Do not attempt to lock memory, even if in realtime mode Не пытайтесь заблокировать память, даже в режиме реального времени &Ignore H/W &Игнорировать апп. буфер и период &Word Length: Ра&зрядность слова: Time Display Отображение времени Transport &Time Code &Тайм-код передачи Sample front panel normal display font Пример текста в малом счётчике Sample big time display font Пример текста в большом счётчике Normal display: Малый счётчик: Big Time display: Большой счётчик: &Messages limit: Предел кол-ва &сообщений: Whether to keep a maximum number of lines in the messages window Ограничивать ли количество строк в окне сообщений 100 100 250 250 2500 2500 The maximum number of message lines to keep in view Максимальное количество строк сообщений, доступное при просмотре &Start JACK audio server on application startup &Запускать звуковой сервер JACK при старте программы Whether to start JACK audio server immediately on application startup Запускать ли сервер JACK при старте QJackCtl &Keep child windows always on top О&кна программы всегда наверху Whether to keep all child windows on top of the main window Определяет, держать ли все дочерние окна поверх главного окна &Enable system tray icon &Включить область уведомления Whether to enable the system tray icon Включать ли область уведомления (системный лоток, system tray) S&ave JACK audio server configuration to: Со&хранять конфигурацию JACK в файл: Whether to save the JACK server command-line configuration into a local file (auto-start) Определяет, сохранять ли конфигурацию командной строки сервера JACK в локальный файл (автозапуск) .jackdrc .jackdrc The server configuration local file name (auto-start) Имя локального файла конфигурации сервера (автозапуск) System Система Cycle Цикл HPET HPET Don't restrict self connect requests (default) Не ограничивать запросы на самосоединение (по умолчанию) Fail self connect requests to external ports only Отклонять запросы на самосоединение только с внешними портами Ignore self connect requests to external ports only Игнорировать запросы на самосоединение только с внешними портами Fail all self connect requests Отклонять все запросы на самосоединение Ignore all self connect requests Игнорировать все запросы на самосоединение Warning Предупреждение Some settings have been changed: "%1" Do you want to save the changes? Некоторые параметры изменились: «%1» Сохранить изменения? Delete preset: "%1" Are you sure? Удалить профиль: «%1» Вы уверены? &Server Name &Имя сервера Startup Script Сценарий, выполняемый при запуске Post-Startup Script Сценарий, выполняемый после запуска Shutdown Script Сценарий, выполняемый при выключении Post-Shutdown Script Сценарий, выполняемый после выключения Active Patchbay Definition Активное описание коммутатора Messages Log Журнал сообщений Log files Файлы журналов Information Информация Some settings may be only effective next time you start this application. Некоторые параметры вступят в силу только при следующем запуске приложения. Some settings have been changed. Do you want to apply the changes? Некоторые параметры были изменены. Применить эти изменения? &Name: &Название: The JACK Audio Connection Kit sound server name Имя звукового сервера JACK The audio backend driver interface to use Используемый звуковой драйвер MIDI Driv&er: &Драйвер MIDI: The ALSA MIDI backend driver to use Используемый драйвер ALSA MIDI none нет raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Please do not touch these settings unless you know what you are doing. Меняйте эти параметры только если точно знаете, что делаете. Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) Разблокировать память основных библиотек интерфейсов (GTK+, QT, FLTK, Wine) &Unlock Memory &Разблокировать память Ignore xruns reported by the backend driver Игнорировать xrun, о которых сообщает драйвер Enable hardware metering on cards that support it Включить аппаратное измерение для поддерживающих эту функцию карт Ignore hardware period/buffer size Игнорировать аппаратный размер периода/буфера &Verbose messages &Подробный вывод Maximum input audio hardware channels to allocate Максимальное число резервируемых каналов входа External output latency (frames) Задержка внешнего выхода (в выборках) Capture Only Только захват Playback Only Только воспроизведение The PCM device name to use Имя используемого устройства PCM plughw:0 plughw:0 /dev/audio /dev/audio Alternate input device for capture Выберите устройство входа для захвата Maximum output audio hardware channels to allocate Максимальное резервируемое число звуковых каналов устройства Alternate output device for playback Альтернативное устройство воспроизведения External input latency (frames) Задержка внешнего входа (в выборках) Set dither mode Выберите способ подмешивания шума Server path (command line prefix) Путь к серверу (префикс командной строки) Number of periods in the hardware buffer Количество периодов в аппаратном буфере &Channels: &Каналов: 192000 192000 Word length Длина слова в байтах Maximum number of audio channels to allocate Максимальное число резервируемых звуковых каналов &Channels I/O: Ввод/вывод &каналов: &Latency I/O: &Задержка ввода/вывода: Server Suffi&x: Су&ффикс сервера: Whether to execute a custom shell script before shuting down the JACK audio server. Определяет, выполнять ли пользовательский сценарий оболочки перед выключением аудиосервера JACK Execute script on Shut&down: В&ыполнять сценарий при выходе: Browse for script to be executed before shutting down the JACK audio server Выбор сценария, который будет выполняться перед выключением аудиосервера JACK Command line to be executed before shutting down the JACK audio server Командная строка, которая будет выполняться перед выключением аудиосервера JACK Execute script after Shu&tdown: Выполнять сценарий после &выключения: Whether to reset all connections when a patchbay definition is activated. Определяет, сбрасывать ли все соединения при активации описания коммутатора &Reset all connections on patchbay activation С&брасывать все соединения при активации коммутатора Whether to issue a warning on active patchbay port disconnections. Определяет, показывать ли предупреждение о рассоединениии портов активного коммутатора &Warn on active patchbay disconnections Предупре&ждать о рассоединении в активном коммутаторе Logging Журналирование Messages log file Файл журнала сообщений Browse for the messages log file location Указать расположение файла журнала Whether to activate a messages logging to file. Определяет, сохранять ли протокол в файл журнала Setup Настройка Whether to use server synchronous mode Использовать ли синхронный режим сервера &Use server synchronous mode Использовать син&хронный режим сервера Advanced Дополнительные &Messages log file: Файл &журнала: Select font for front panel normal display Выбрать шрифт для малого счётчика Select font for big time display Выбрать шрифт для большого счётчика Whether to enable blinking (flashing) of the server mode (RT) indicator Определяет, включать ли мерцание (мигание) индикатора режима сервера (RT) Blin&k server mode indicator &Мерцать индикатором режима сервера Connections Window Окно соединений Sample connections view font Шрифт для диалога управления соединениями Select font for the connections view Выберите шрифт для просмотра соединений &Icon size: &Размер значков: The icon size for each item of the connections view Размер значка каждого элемента в окне соединений 16 x 16 16 × 16 32 x 32 32 × 32 64 x 64 64 × 64 Whether to enable in-place client/port name editing (rename) Определяет, разрешить ли редактирование (переименование) алиасов клиентов/портов Ena&ble client/port aliases editing (rename) Ра&зрешить редактирование (переименование) алиасов клиентов/портов Whether to enable client/port name aliases on the connections window Определяет, включать ли алиасы имён клиентов/портов в окне соединений E&nable client/port aliases &Разрешить алиасы клиентов/портов Server &Prefix: Пре&фикс сервера: Extra driver options (command line suffix) Дополнительные ключи драйвера (суффикс в командной строке) Start De&lay: Задер&жка запуска: secs с 0 msecs 0 мс Misc Разное Whether to stop JACK audio server on application exit Останавливать ли звуковой сервер JACK при выходе из приложения S&top JACK audio server on application exit Оста&навливать JACK при выходе из приложения Whether to start minimized to system tray Запускать ли приложение в области уведомления, скрывая основное окно Clear settings of current preset name Очистить параметры текущего профиля Clea&r О&чистить Cloc&k source: Источник данных часо&в: Clock source Источник данных часов S&elf connect mode: Режим &самосоединения: Whether to restrict client self-connections Определяет, ограничивать ли самосоединение клиентов Custom Пользовательские &Color palette theme: Тема &цветовой палитры: Custom color palette theme Пользовательская тема цветовой палитры Wonton Soup DO NOT TRANSLATE KXStudio DO NOT TRANSLATE Manage custom color palette themes Управлять пользовательскими темами цветовой палитры &Widget style theme: Тема стиля вид&жетов: Custom widget style theme Пользовательская тема стиля виджетов JACK client/port pretty-name (metadata) display mode Режим отображения читабельного имени (метаданных) клиента/порта JACK Enable JA&CK client/port pretty-names (metadata) Включить читабельные имена клиента/порта JA&CK (метаданные) Whether to ask for confirmation on JACK audio server shutdown and/or restart Определяет, нужно ли запрашивать подтверждение при выключении и/или перезапуске звукового сервера JACK Confirm server sh&utdown and/or restart Запрашивать по&дтверждение остановки и перезагрузки Whether to show system tray message on main window close Показывать ли сообщения программы в области уведомления, когда основное окно скрыто Sho&w system tray message on close Показывать сооб&щения в области уведомления Start minimi&zed to system tray Запускаться свёрнутым в системный &лоток Whether to enable ALSA Sequencer (MIDI) support on startup Включать ли при запуске поддержку MIDI-секвенсера ALSA E&nable ALSA Sequencer support &Включить поддержку секвенсера ALSA Whether to enable JACK D-Bus interface Включать ли интерфейс JACK по шине D-Bus &Enable JACK D-Bus interface Вкл&ючить интерфейс JACK к шине D-Bus Buttons Кнопки Whether to hide the left button group on the main window Скрывать ли группу кнопок в левой части основного окна Hide main window &Left buttons Скрывать &левые кнопки основного окна Whether to hide the right button group on the main window Скрывать ли группу кнопок в правой части основного окна Hide main window &Right buttons Скрывать прав&ые кнопки основного окна Whether to hide the transport button group on the main window Скрывать ли группу кнопок управления передачей в основном окне Hide main window &Transport buttons Скрывать кнопки &передачи Whether to hide the text labels on the main window buttons Скрывать ли надписи на кнопках в основном окне Hide main window &button text labels Скрывать по&дписи кнопок основного окна &JACK client/port aliases: &Алиасы клиентов/портов JACK: JACK client/port aliases display mode Режим отображения алиасов клиентов/портов JACK Default По умолчанию First Первый Second Второй Whether to replace Connections with Graph button on the main window Заменить ли кнопку «Соединения» на кнопку «Граф» в главном окне Replace Connections with &Graph button Заменить кнопку «Соединения» на кнопку «&Граф» Defaults Используемые по умолчанию параметры &Base font size: &Кегль шрифта в интерфейсе: Base application font size (pt.) Кегль шрифта приложения (пт.) 11 11 12 12 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to enable D-Bus interface Влючать ли интерфейс D-Bus &Enable D-Bus interface Вклю&чить интерфейс D-Bus Number of microseconds to wait between engine processes (dummy) Время ожидания в микросекундах между этапами обработки (фиктивное) netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to restrict to one single application instance (X11) Определяет, ограничивать ли до одной копии программы (X11) Single application &instance Зап&ускать только одну копию программы qjackctlSocketForm &Socket &Сокет &Client: &Клиент: Socket name (an alias for client name) Имя сокета (псевдоним имени клиента) &Name (alias): &Имя (псевдоним): Socket Plugs / Ports Сокетовые штепсели/порты Socket plug list Список штепселей сокета &Down В&низ &Up В&верх Add plug to socket plug list Добавить штепсель в список штепселей сокета Socket Сокет &Plug: &Штепсель: &Edit И&зменить &Remove &Удалить Remove currently selected plug from socket plug list Удалить выбранный штепсель из списка штепселей сокета Plugs / Ports Штепсели/порты Error Ошибка A socket named "%1" already exists. Сокет с именем «%1» уже существует. Add Plug Добавить штепсель Remove Удалить Edit Изменить Move Up Переместить выше Move Down Переместить ниже Client name (regular expression) Имя клиента (регулярное выражение) Add P&lug Добавить &штепсель Port name (regular expression) Имя порта (регулярное выражение) Type Тип &Audio &Звук Audio socket type (JACK) Тип звукового сокета (JACK) &MIDI &MIDI MIDI socket type (ALSA) Тип MIDI-сокета (ALSA) E&xclusive И&сключительный Enforce only one exclusive cable connection Принудительно только одно кабельное соединение Warning Предупреждение Some settings have been changed. Do you want to apply the changes? Некоторые параметры были изменены. Применить эти изменения? (None) (Нет) Edit currently selected plug Изменить выбранный штепсель Move down currently selected plug in socket plug list Переместить выбранный штепсель вниз в списке штепселей сокета Move up current selected plug in socket plug list Переместить выбранный штепсель вверх в списке штепселей сокета &Forward: &Передача: Forward (clone) all connections from this socket Передача (клонирование) всех соединения от этого сокета MIDI socket type (JACK) Тип MIDI-сокета (JACK) AL&SA AL&SA qjackctlSocketList Output Выход Input Вход Socket Сокет Warning Предупреждение <New> - %1 <Новый> — %1 %1 about to be removed: "%2" Are you sure? %1 будет удалён: «%2» Вы уверены? %1 <Copy> - %2 %1 <Копия> — %2 qjackctlSocketListView Output Sockets / Plugs Выходные сокеты/штепсели Input Sockets / Plugs Входные сокеты/штепсели qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_pt_BR.ts0000644000000000000000000000013214771215054021136 xustar0030 mtime=1743067692.335636536 30 atime=1743067692.334636541 30 ctime=1743067692.335636536 qjackctl-1.0.4/src/translations/qjackctl_pt_BR.ts0000644000175000001440000063770214771215054021145 0ustar00rncbcusers PortAudioProber Probing... Pesquisando... Please wait, PortAudio is probing audio hardware. Por favor espere, o PortAudio está testando o hardware de áudio. Warning Aviso Audio hardware probing timed out. O teste de hardware de áudio atingiu o tempo limite. QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Start JACK audio server immediately. Inicie o servidor de áudio JACK imediatamente Set default settings preset name. Defina o nome da predefinição das configurações padrão. Set active patchbay definition file. Definir arquivo de definição do patchbay ativo. Set default JACK audio server name. Defina o nome do servidor de áudio JACK padrão. Show help about command line options. Mostre ajuda sobre opções de linha de comando. Show version information. Mostrar informações da versão. Launch command with arguments. Execute o comando com argumentos. [command-and-args] [comando-e-args] Option -p requires an argument (preset). Opção -p requer um argumento (preset). Usage: %1 [options] [command-and-args] Uso: %1 [options] [command-and-args] Options: Opções: Option -a requires an argument (path). A opção -a requer um argumento (caminho). Option -n requires an argument (name). Opção -n requer um argumento (nome). %1 (%2 frames) %1 (%2 quadros) Move Mover Rename Renomear qjackctlAboutForm About Sobre About Qt Sobre QT &Close &Fechar Version Versão Debugging option enabled. Depuração habilitada. System tray disabled. Bandeja do sistema desativada. Transport status control disabled. Controle de status de transporte desativado. Realtime status disabled. Status de tempo real desativado. XRUN delay status disabled. Atraso de XRUN desativado. Maximum delay status disabled. Status de atraso máximo desativado. ALSA/MIDI sequencer support disabled. Suporte ao sequenciador ALSA/MIDI desativado. Using: Qt %1 Usando: Qt %1 JACK %1 JACK %1 Website Website This program is free software; you can redistribute it and/or modify it Este programa é software livre; você pode redistribuí-lo e / ou modificá-lo under the terms of the GNU General Public License version 2 or later. sob os termos da GNU General Public License versão 2 ou posterior. JACK MIDI support disabled. Suporte JACK MIDI desativado. JACK Port aliases support disabled. Suporte a aliases das portas JACK desativadao. D-Bus interface support disabled. Suporte à interface D-Bus desativado. JACK Session support disabled. Suporte para sessão JACK desativado. qjackctlClientListView &Connect &Conectar Alt+C Connect Alt+C &Disconnect &Desconectar Alt+D Disconnect Alt+D Disconnect &All Desconectar &Tudo Alt+A Disconnect All Alt+T Re&name Re&nomear Alt+N Rename Alt+N &Refresh &Atualizar Alt+R Refresh Alt+R Readable Clients / Output Ports Clientes legíveis / Portas de saída Writable Clients / Input Ports Clientes graváveis / Portas de entrada qjackctlConnect Warning Aviso This will suspend sound processing from all client applications. Are you sure? Isto suspenderá o processamento de som para todas as aplicações do cliente. Tem certeza? qjackctlConnectionsForm Audio Áudio &Connect &Conectar Connect currently selected ports Conectar portas selecionadas &Disconnect &Desconectar Disconnect currently selected ports Desconectar as portas selecionadas Disconnect &All Desconectar &Tudo Disconnect all currently connected ports Desconectar todas as portas selecionadas &Refresh &Atualizar Refresh current connections view Atualizar a visualização das conexões atuais Connections Conexões MIDI MIDI ALSA ALSA Expand all client ports Expandir todas as portas de clientes E&xpand All E&xpandir Tudo qjackctlConnectorView &Connect &Conectar Alt+C Connect Alt+C &Disconnect &Desconectar Alt+D Disconnect Alt+D Disconnect &All Desconectar &Tudo Alt+A Disconnect All Alt+T &Refresh &Atualizar Alt+R Refresh Alt+R qjackctlGraphCanvas Connect Conectar Disconnect Disconnectar qjackctlGraphForm Graph Gráfico &Graph &Gráfico &Edit &Editar &View &Visualizar &Zoom &Zoom Co&lors Co&res S&ort C&lassificar &Help &Ajuda &Connect &Conectar Connect Conectar Connect selected ports Conectar portas selecionadas &Disconnect &Desconectar Disconnect Desconectar Disconnect selected ports Desconectar portas selecionadas Ctrl+C Ctrl+C T&humbview M&iniatura Ctrl+D Ctrl+D Cl&ose Fe&char Close Fechar Close this application window Feche esta janela da aplicação Select &All Selecionar &Tudo Select All Selecionar Tudo Ctrl+A Ctrl+A Select &None Selecionar &Nenhum Select None Selecionar Nenhum Ctrl+Shift+A Ctrl+Shift+A Select &Invert Selecionar &Inverter Select Invert Selecionar Inverter Ctrl+I Ctrl+I &Rename... &Renomear... Rename item Renomear item Rename Item Renomear Item F2 F2 &Find... &Encontrar... Find Encontrar Find nodes Encontrar nós Ctrl+F Ctrl+F &Menubar &Barra de menu Menubar Barra de menu Show/hide the main program window menubar Mostrar/ocultar a barra de menus da janela principal do programa Ctrl+M Ctrl+M &Toolbar &Barra de ferramentas Toolbar Barra de ferramentas Show/hide main program window file toolbar Mostrar/ocultar a barra de ferramentas do arquivo da janela principal do programa &Statusbar &Barra de status Statusbar Barra de status Show/hide the main program window statusbar Mostrar/ocultar a barra de status da janela principal do programa &Top Left &Superior Esquerdo Top left Superior esquerdo Show the thumbnail overview on the top-left Mostrar a visão geral das miniaturas no canto superior esquerdo Top &Right Superior &Direito Top right Superior Direito Show the thumbnail overview on the top-right Mostrar a visão geral das miniaturas no canto superior direito Bottom &Left Inferior &Esquerdo Bottom Left Inferior Esquerdo Bottom left Inferior Esquedo Show the thumbnail overview on the bottom-left Mostrar a visão geral das miniaturas no canto inferior esquerdo &Bottom Right &Inferior Direito Bottom right Inferior Direito Show the thumbnail overview on the bottom-right Mostrar a visão geral das miniaturas no canto inferior direito &None &Nenhum None Nenhum Hide thumbview Esconder miniaturas Hide the thumbnail overview Ocultar a visão geral das miniaturas Text Beside &Icons Texto ao lado de &ícones Text beside icons Texto ao lado de ícones Show/hide text beside icons Mostrar/ocultar texto ao lado de ícones &Center &Centro Center Centro Center view Visão central &Refresh &Atualizar Refresh Atualizar Refresh view Atualizar visualização F5 F5 Zoom &In Ampli&ar Zoom In Ampliar Ctrl++ Ctrl++ Zoom &Out Diminu&ir Zoom Out Diminuir Ctrl+- Ctrl+- Zoom &Fit Ajuste de &Zoom Zoom Fit Ajuste de Zoom Ctrl+0 Ctrl+0 Zoom &Reset Redefinir &Zoom Zoom Reset Redefinir Zoom Ctrl+1 Ctrl+1 &Zoom Range &Alcance de Zoom Zoom Range Alcance de Zoom JACK &Audio... JACK &áudio... JACK Audio color Cor JACK Áudio JACK &MIDI... JACK &MIDI... JACK MIDI JACK MIDI JACK MIDI color Cor de JACK MIDI ALSA M&IDI... ALSA M&IDI... ALSA MIDI ALSA MIDI ALSA MIDI color Cor ALSA MIDI JACK &CV... JACK &CV... JACK CV color Cor JACK CV JACK &OSC... JACK &OSC... JACK OSC JACK OSC JACK OSC color Cor JACK OSC &Reset &Redefinir Reset colors Redefinir cores Port &Name &Nome da porta Port name Nome da porta Sort by port name Classificar por nome de porta Port &Title & Título da porta Port title Título da porta Sort by port title Classificar por título da porta Port &Index & Índice da porta Port index Índice da porta Sort by port index Classificar por índice da porta &Ascending &Ascendente Ascending Ascendente Ascending sort order Classificar por ordem ascendente &Descending &Descendente Descending Descendente Descending sort order Classificar por ordem descendente Repel O&verlapping Nodes Repelir Nós S&obrepostos Repel nodes Repelir nós Repel overlapping nodes Repelir nós sobrepostos Connect Thro&ugh Nodes Conecte-se A&través de nós Connect Through Nodes Conecte-se Através de Nós Connect through nodes Conecte-se através de nós Whether to draw connectors through or around nodes Desenhar conectores através ou ao redor dos nós &About... Sobre... About... Sobre... About Sobre... Show information about this application program Mostrar informações sobre este aplicativo About &Qt... Sobre &Qt... About Qt... Sobre Qt... About Qt Sobre Qt Show information about the Qt toolkit Mostrar informações sobre as ferramentas do Qt &Undo &Desfazer &Redo &Refazer Undo last edit action Desfazer última ação Redo last edit action Refazer última ação Zoom Zoom Ready Pronto Colors - %1 Cores - %1 qjackctlMainForm &Quit &Sair Quit processing and exit Terminar processamento e sair &Start &Iniciar Start the JACK server Iniciar servidor JACK S&top P&arar Stop the JACK server Parar servidor JACK St&atus E&stado Ab&out... So&bre... Show information about this application Mostrar informações sobre o aplicativo. Show settings and options dialog Mostrar opções e preferências &Messages &Mensagens Patch&bay Patch&bay Show/hide the patchbay editor window Mostrar/ocultar o editor de patchbay &Connect &Conexões JACK server state Estado do servidor JACK JACK server mode Modo do servidor JACK Sample rate Taxa de amostragem Time display Visor do tempo Transport state Estado do transporte Transport BPM BPM do transporte Transport time Tempo do transporte Show/hide the graph window Esconder/mostrar janela gráfica Show/hide the connections window Esconder/mostrar janela de conexões Backward transport Retroceder transporte Forward transport Avançar transporte (Alt+L) Rewind transport Rebobinar transporte Stop transport rolling Parar transporte Start transport rolling Iniciar transporte Warning Aviso successfully satisfatoriamente with exit status=%1 com saída estado %1 Could not load preset "%1". Retrying with default. Não foi possível carregar predefinição "%1". Tentando com a predefinição padrão. Could not load default preset. Sorry. Não foi possível carregar predefinição. Desculpe. Startup script... Script de inicialização... Startup script terminated O script de inicialização finalizou JACK is starting... JACK está iniciando... Could not start JACK. Sorry. Não foi possível iniciar o JACK. Desculpe. JACK is stopping... JACK está parando... The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. O programa seguirá rodando na bandeja do sistema. Para terminá-lo, por favor escolha "Sair" no menu contextual do ícone na bandeja de sistema. Shutdown script... Script de desligamento... Shutdown script terminated O script de desligamento finalizou JACK was stopped JACK foi parado Post-shutdown script... Script pós-desligamento... D-BUS: Service is available (%1 aka jackdbus). D-BUS: Disponível (%1 aka jackdbus). D-BUS: Service not available (%1 aka jackdbus). D-BUS: Indisponível (%1 aka jackdbus). Don't show this message again Não mostrar esta mensagem novamente Don't ask this again Não perguntar novamente D-BUS: JACK server is starting... D-BUS: Iniciando servidor JACK... D-BUS: JACK server could not be started. Sorry D-BUS: O servidor JACK não pode ser iniciado. Desculpe D-BUS: JACK server is stopping... D-BUS: Parando o servidor JACK... D-BUS: JACK server could not be stopped. Sorry D-BUS: O servidor JACK não pôde ser parado. Desculpe Post-shutdown script terminated O script pós-desligamento finalizou D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: O servidor JACK foi iniciado (%1 aka jackdbus). The preset aliases have been changed: "%1" Do you want to save the changes? Os aliases predefinidos foram alterados: "%1" Deseja salvar as alterações?? D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: O servidor JACK foi parado (%1 aka jackdbus). Error Erro Transport time code Código de tempo de transporte Elapsed time since last reset Tempo transcorrido desde o último reset Elapsed time since last XRUN Tempo transcorrido desde o último XRUN Patchbay activated. Patchbay ativado. Patchbay deactivated. Patchbay desativado. Statistics reset. Reiniciar estatísticas. msec mseg XRUN callback (%1). XRUN callback (%1). Buffer size change (%1). Mudança de tamanho de buffer (%1). Shutdown notification. Notificação de desligamento. Freewheel started... Modo roda-livre começou... Freewheel exited. Roda-livre saiu. JACK property change. Propriedades do JACK mudaram checked verificado connected conectado disconnected desconectado failed falhou Server configuration saved to "%1". Configuração do servidor salva em "%1". Client activated. Cliente ativado. Post-startup script... Script de pós-inicialização... Post-startup script terminated O script de pós-inicialização finalizou Command line argument... Argumento da linha de comando... Command line argument started Argumento da linha de comando iniciado Client deactivated. Cliente desativado. Transport rewind. Rebobinar transporte. Transport backward. Retroceder transporte. Starting Iniciando Transport start. Iniciar transporte. Stopping Parando Transport stop. Parar transporte. Transport forward. Avançar transporte. Stopped Parado Yes Sim No Não FW FW RT TR Rolling Rolando Looping Em loop XRUN callback (%1 skipped). XRUN callback (%1 omitidos). Started Iniciado Active Ativo Activating Ativando Inactive Inativo &Hide &Ocultar D-BUS: GetParameterConstraint('%1'): %2. (%3) D-BUS: GetParameterConstraint('%1'): %2. (%3) Mi&nimize Mi&nimizar S&how M&ostrar Rest&ore Rest&aurar &Stop &Parado &Reset &Reset &Connections &Conexões Server settings will be only effective after restarting the JACK audio server. As configurações do servidor só serão efetivadas após a reinicialização do servidor de áudio JACK. Do you want to restart the JACK audio server? Deseja reiniciar o servidor de audio do JACK? D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) Information Informação Some settings will be only effective the next time you start this program. Algumas configurações só serão efetivas na próxima vez que você iniciar este programa. Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. Não foi possível abrir o sequenciador do ALSA como um cliente. O patchbay MIDI do ALSA não estará disponivel. JACK is currently running. Do you want to terminate the JACK audio server? JACK se está sendo executado. Deseja finalziar o servidor de áudio JACK? Could not start JACK. Maybe JACK audio server is already started. Não foi possível incializar o JACK. Talves o JACK já tenha sido inicializado. Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Algumas aplicações de áudio estão ativas e conectadas. Deseja parar o servidor de áudio JACK? %1 is about to terminate. Are you sure? % 1 está prestes a terminar. Você tem certeza? JACK was started with PID=%1. JACK inicializou com PID=%1. JACK is being forced... JACK está sendo forçado... Patchbay reset. Patchbay redefinido JACK connection graph change. Alteração no gráfico de conexão JACK. JACK has crashed. JACK caiu. JACK timed out. Tempo de espera do JACK esgotado. JACK write error. Erro de gravação JACK. JACK read error. Error de leitura JACK. Unknown JACK error (%d). Erro JACK desconhecido (%d). ALSA connection graph change. Alteração no gráfico de conexão ALSA. JACK active patchbay scan Varredura ativa do patchbay do JACK ALSA active patchbay scan Varredura ativa do patchbay ALSA JACK connection change. Alteração de conexão JACK. ALSA connection change. Alteração de conexão ALSA. A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? Uma definição de patchbay está atualmente ativa, o que é provável para refazer esta conexão: %1 -> %2 Deseja remover a conexão? Overall operation failed. Operação global falhou. Invalid or unsupported option. Opcão inválida ou não soportada. Client name not unique. O nome do cliente não é único. Server is started. O servidor foi inicializado. Unable to connect to server. Não foi possível conectar-se ao servidor. Server communication error. Erro de comunicação com o servidor. Client does not exist. Cliente não existe. Unable to load internal client. Não é possível carregar o cliente interno. Unable to initialize client. Não é possível inicializar o cliente. Unable to access shared memory. Não é possível acessar a memória compartilhada. Client protocol version mismatch. Incompatibilidade de versão de protocolo do cliente. Could not connect to JACK server as client. - %1 Please check the messages window for more info. Não foi possível conectar-se ao servidor JACK como cliente. - %1 Por favor, verifique a janela de mensagens para mais informações. %1 (%2%) %1 (%2%) %1 % %1 % %1 Hz %1 Hz %1 frames %1 quadros %1 msec %1 mseg &Presets &Predefinições &Graph &Gráfico &Transport &Transporte &Rewind Re&bobinar &Play &Reproduzir Pa&use Pa&usa &Patchbay &Patchbay DSP Load Uso de CPU do DSP XRUN Count (notifications) Conta de XRUNs (notificações) &Backward &Retroceder &Forward &Avançar Set&up... Con&figurar... S&ession S&essão &Load... &Abrir... &Save... &Salvar... Save and &Quit... Salvar e &Sair... Save &Template... Salvar mo&delo... Show/hide the session management window Mostrar/ocultar a janela de gerenciamento de sessão Show/hide the messages log/status window Mostrar/ocultar a janela de log/status das mensagens Could not load active patchbay definition. "%1" Disabled. Não foi possível carregar a definição de patchbay ativa. "%1" Foi desabilitado. &Versioning &Versionamento Re&fresh At&ualizar %1 (%2%, %3 xruns) %1 (%2%, %3 xruns) Transport BBT (bar.beat.ticks) Transportar BBT (bar.beat.ticks) qjackctlMessagesStatusForm Messages / Status Mensagens / Status &Messages &Mensagens Messages log Registro de mensagens Messages output log Registro de mensagens &Status &Estado Status information Informação de estado Statistics since last server startup Estatísticas desde a última inicialização do servidor Description Descrição Value Valor Reset XRUN statistic values Reiniciar estatísticas de XRUN Re&set Re&iniciar Refresh XRUN statistic values Atualizar estatísticas de XRUN &Refresh &Atualizar Server name Nome do servidor Server state Estado do servidor DSP Load Uso de CPU do DSP Sample Rate Taxa de amostragem Buffer Size Tamanho do Buffer Realtime Mode Modo Realtime Transport state Estado do transporte Transport Timecode Código de tempo do transporte Transport BBT BBT do Transporte Transport BPM BPM do transporte XRUN count since last server startup XRUNs desde a última inicialização XRUN last time detected XRUN detectado última vez XRUN last Último XRUN XRUN maximum XRUN Máximo XRUN minimum XRUN Mínimo XRUN average Média de XRUNs XRUN total Total de XRUNs Maximum scheduling delay Atraso máximo de agendamento (scheduling) Time of last reset Hora da última reinicialização Logging stopped --- %1 --- Registro parado --- %1 --- Logging started --- %1 --- Registro iniciado --- %1 --- qjackctlPaletteForm Color Themes Temas de cores Name Nome Current color palette name Paleta de cor atual Save current color palette name Salvar paleta de cor atual Save Salvar Delete current color palette name Remover nome da paleta de cor atual Delete Remover Palette Paleta Current color palette Paleta de cor atual Generate: Gerar: Base color to generate palette Cor base para gerar paleta Reset all current palette colors Redefinir as paletas de cores atuais Reset Redefinir Import a custom color theme (palette) from file Importar paleta de cor personalizada de arquivo Import... Importar... Export a custom color theme (palette) to file Exportar paleta de cor personalizada para arquivo Export... Exportar... Show Details Mostrar detalhes Import File - %1 Importar arquivo - %1 Palette files (*.%1) Arquivos de paletas (*.%1) Save Palette - %1 Salvar Paleta - %1 All files (*.*) Todos os arquivos (*.*) Warning - %1 Aviso - %1 Could not import from file: %1 Sorry. Impossível importar de: %1 Desculpe. Export File - %1 Exportar para arquivo - %1 Some settings have been changed. Do you want to discard the changes? Algumas opções foram mudadas. Deseja descartar as mudanças? Some settings have been changed: "%1". Do you want to save the changes? Algumas opções foram mudadas: "%1". Deseja manter as mudanças? qjackctlPaletteForm::PaletteModel Color Role Papel da cor Active Ativo Inactive Inativo Disabled Desabilitado qjackctlPatchbay Warning Aviso This will disconnect all sockets. Are you sure? Isso desconectará todos os soquetes. Está certo disto? qjackctlPatchbayForm &New &Novo Create a new patchbay profile Crie um novo perfil de patchbay &Load... &Abrir... Load patchbay profile Carregar perfil de patchbay &Save... &Salvar... Save current patchbay profile Salvar o perfil atual do patchbay Acti&vate Ati&var Toggle activation of current patchbay profile Ativar/desativar perfil atual do patchbay &Connect &Conectar Connect currently selected sockets Conecte os soquetes atualmente selecionados &Disconnect &Desconectar Disconnect currently selected sockets Desconectar soquetes selecionados no momento Disconnect &All Desconectar &Tudo Disconnect all currently connected sockets Desconecte todos os soquetes conectados no momento &Refresh &Atualizar Refresh current patchbay view Atualizar a exibição atual do patchbay Down Baixar Move currently selected output socket down one position Mover o soquete de saída selecionado para uma posição abaixo Add... Adicionar... Create a new output socket Criar um novo soquete de saída Edit... Editar... Edit currently selected input socket properties Editar propriedades do soquete de entrada selecionadas Up Acima Move currently selected output socket up one position Mover o soquete de saída selecionado atualmente para cima uma posição Remove Remover Remove currently selected output socket Remover soquete de saída selecionado no momento Copy... Copiar... Duplicate (copy) currently selected output socket Duplicar (copiar) o soquete de saída selecionado Patchbay Patchbay Remove currently selected input socket Remover o soquete de entrada selecionado Duplicate (copy) currently selected input socket Duplicar (copiar) o soquete de entrada selecionado Create a new input socket Criar um novo soquete de entrada Edit currently selected output socket properties Editar as propriedades do soquete de saída selecionado Warning Aviso active Ativo New Patchbay definition Nova definição de patchbay Patchbay Definition files Arquivos de definições de patchbay Load Patchbay Definition Carregar definição de patchbay Save Patchbay Definition Salvar definição de patchbay The patchbay definition has been changed: "%1" Do you want to save the changes? A definição de patchbay foi alterada: "%1" Você quer salvar as alterações?? %1 [modified] %1 [modificado] Untitled%1 Sem Título%1 Error Erro Could not load patchbay definition file: "%1" Não foi possível carregar o arquivo de definição do patchbay: "%1" Could not save patchbay definition file: "%1" Não foi possível salvar o arquivo de definição do patchbay: "%1" Create patchbay definition as a snapshot of all actual client connections? Criar definição de patchbay como um snapshot de todas as conexões atuais do cliente?? Current (recent) patchbay profile(s) Perfil(is) atual(is) (recente(s)) do patchbay Expand all items Expandir todos os elementos E&xpand All E&xpandir Todos qjackctlPatchbayView Add... Adicionar... Edit... Editar... Copy... Copiar... Remove Remover Exclusive Exclusivo Move Up Subir Move Down Abaixar &Connect &Conectar Alt+C Connect Alt+C &Disconnect &Desconectar Alt+D Disconnect Alt+D Disconnect &All Desconectar &Tudo Alt+A Disconnect All Alt+T &Refresh &Atualizar Alt+R Refresh Alt+R Forward Avançar (None) (Nenhum) qjackctlSessionForm Load session Carregar sessão &Load... &Abrir... Recent session Sessão recente &Recent &Recente Save session Salvar sessão &Save... &Salvar... Client / Ports Cliente/Portas UUID UUID Command Comando Load Session Carregar Sessão Session directory Diretório da sessão Save Session Salvar Sessão and Quit e Sair Template Modelo &Clear &Limpar Warning Aviso A session could not be found in this folder: "%1" Não foi possível encontrar uma sessão nesta pasta: "%1" %1: loading session... %1: carregando sessão... %1: load session %2. %1: carregar sessão %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? Uma sessão já existe nesta pasta: "%1" Você tem certeza de sobrescrever a sessão existente? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Esta pasta já existe e não está vazia: "%1" Está certo de sobrescrever a pasta existente? %1: saving session... %1: salvando sessão... %1: save session %2. %: salvar sessão %2. Update session Atualizar sessão Save and &Quit... Salvar e &Sair... Save &Template... Salvar &Modelo... Session Sessão &Save &Salvar &Versioning &Versionamento Re&fresh At&ualizar Session clients / connections Conexões/clientes da sessão Infra-clients / commands Infra-clientes Infra-client Infra-cliente Infra-command Infra-comando Add infra-client Adicionar infra-cliente &Add &Adicionar Edit infra-client Editar infra-client &Edit &Editar Remove infra-client Remover infra-cliente Re&move Re&mover New Client Novo Cliente qjackctlSessionInfraClientItemEditor Infra-command Infra-comando qjackctlSessionSaveForm Session Sessão &Name: &Nome: Session name &Directory: Session directory Diretório da sessão Browse for session directory ... ... Save session versioning Salvar versionamento da sessão &Versioning &Versionamento Warning Aviso Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings Configurações Preset &Name: Nome da &Predefinição: (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Settings preset name Nome da predefinição de configurações &Save &Salvar Save settings as current preset name Salvar configurações como nome da predefinição atual &Delete &Deletar Delete current settings preset Excluir predefinição das configurações atuais jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE Driv&er: Dri&ver: dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters Parâmetros Number of periods in the hardware buffer Número de períodos no buffer de hardware Priorit&y: Prioridad&e: &Frames/Period: &Quadros/Período: 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Frames per period between process() calls Quadros por período entre as chamadas() de processo Port Ma&ximum: Portas Má&ximas: 21333 21333 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 Sample rate in frames per second Taxa de amostragem em quadros por segundo Scheduler priority when running realtime Prioridade do agendador ao executar em tempo real &Word Length: &Tamanho da palavra: Periods/&Buffer: Períodos/&Buffer: Word length Tamanho da palavra Maximum number of ports the JACK server can manage Número máximo de portas que o servidor JACK pode gerenciar &Wait (usec): &Espera (microseg): Sample &Rate: Taxa de &amostragem: &Timeout (msec): Limite de &Tempo (mseg): 200 200 500 500 1000 1000 2000 2000 5000 5000 Set client timeout limit in milliseconds Definir limite de tempo limite do cliente em milissegundos &Realtime &Tempo Real Use realtime scheduling Usar agendamento em tempo real No Memory Loc&k Sem b&loqueio de memória Do not attempt to lock memory, even if in realtime mode Não tente bloquear a memória, mesmo no modo de tempo real &Unlock Memory &Desbloquear Memória Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) Desbloquear memória de bibliotecas comuns do kit de ferramentas (GTK+, QT, FLTK, Wine) So&ft Mode Modo &Suave Ignore xruns reported by the backend driver Ignorar xruns informados pelo driver de back-end. O JACK terá menos tendência a desconectar as portas que não respondem. Útil quando não está sendo executado em tempo real. &Monitor &Monitor Provide output monitor ports Fornecer portas do monitor de saída Force &16bit Forçar &16bit Force 16bit mode instead of failing over 32bit (default) Forçar o modo de 16 bits em vez de falhar 32 bits (padrão) H/&W Meter Medidor de H/&W Enable hardware metering on cards that support it Ativar a medição de hardware em placas que a suportam &Ignore H/W &Ignorar H/W Ignore hardware period/buffer size Ignore o período do hardware/tamanho do buffer &Output Device: &Dispositivo de saída: &Interface: &Interface: Maximum input audio hardware channels to allocate Máximo de canais de hardware de áudio de entrada para alocar &Audio: &Áudio: Dit&her: Sua&vizado: External output latency (frames) Latência de saída externa (quadros) &Input Device: &Dispositivo de entrada: Duplex Duplex Capture Only Somente Captura Playback Only Somente Reprodução Provide either audio capture, playback or both Fornecer captura de áudio, reprodução ou ambos hw:0 hw:0 The PCM device name to use O nome do dispositivo PCM a ser usado > > /dev/dsp /dev/dsp Alternate input device for capture Dispositivo de entrada alternativo para captura Maximum output audio hardware channels to allocate Máximo de canais de hardware de áudio de saída para alocar Alternate output device for playback Dispositivo de saída alternativo para reprodução External input latency (frames) Latência de entrada externa (quadros) None Nenhum Rectangular Retangular Shaped Perfilado Triangular Triangular Set dither mode Definir modo de suavização Whether to give verbose output on messages Mostrar saída detalhada nas mensagens Time in seconds that client is delayed after server startup Tempo em segundos do atraso do cliente após a inicialização do servidor Latency: Latência: Output latency in milliseconds, calculated based on the period, rate and buffer settings Latência de saída em milissegundos, calculada com base nas configurações de período, taxa e buffer Options Opções Scripting Scripting Execute script on Start&up: Executar script na inicializa&ção: Whether to execute a custom shell script before starting up the JACK audio server. Executar um script personalizado antes de iniciar o servidor de áudio JACK. Execute script after &Startup: &Executar script após a inicialização: Whether to execute a custom shell script after starting up the JACK audio server. Executar um script de shell personalizado após iniciar o servidor de áudio JACK. Execute script on Shut&down: Executar script no desliga&mento: Whether to execute a custom shell script before shuting down the JACK audio server. Executar um script personalizado antes de desligar o servidor de áudio JACK. Command line to be executed before starting up the JACK audio server Linha de comando a ser executada antes de iniciar o servidor de áudio JACK Scripting argument meta-symbols Variáveis especiais de argumento do script ... ... Browse for script to be executed before starting up the JACK audio server Procure por script a ser executado antes de iniciar o servidor de áudio JACK Command line to be executed after starting up the JACK audio server Linha de comando a ser executada após o início do servidor de áudio JACK Browse for script to be executed after starting up the JACK audio server Procure pelo script a ser executado depois de iniciar o servidor de áudio JACK Browse for script to be executed before shutting down the JACK audio server Procure por script a ser executado antes de desligar o servidor de áudio JACK Command line to be executed before shutting down the JACK audio server Linha de comando a ser executada antes de desligar o servidor de áudio JACK Execute script after Shu&tdown: Execute o script após o desliga&mento: Whether to execute a custom shell script after shuting down the JACK audio server. Executar um script de shell personalizado após desligar o servidor de áudio JACK. Browse for script to be executed after shutting down the JACK audio server Procure pelo script a ser executado após desligar o servidor de áudio JACK Command line to be executed after shutting down the JACK audio server Linha de comando a ser executada após o desligamento do servidor de áudio JACK Statistics Estatísticas &Capture standard output &Capturar saída padrão Whether to capture standard output (stdout/stderr) into messages window Capturar saída padrão do JACK (stdout/stderr) na janela de mensagens &XRUN detection regex: &Expressão regular para detectar &XRUN: xrun of at least ([0-9|\.]+) msecs xrun de pelo menos ([0-9|\.]+) msegs Regular expression used to detect XRUNs on server output messages Expressão regular usada para detectar XRUNs em mensagens de saída do servidor Connections Conexões 10 10 Patchbay definition file to be activated as connection persistence profile Arquivo de definição de patchbay a ser ativado como perfil de persistência de conexão Browse for a patchbay definition file to be activated Procure um arquivo de definição de patchbay a ser ativado Activate &Patchbay persistence: Ativar a &persistência do Patchbay: Whether to activate a patchbay definition for connection persistence profile. Utilizar uma definição de patchbay para o perfil de persistência de conexão. Display Display Time Display Display de tempo Transport &Time Code Código de Tempo de &Transporte Transport &BBT (bar:beat.ticks) &BBT de Transporte (bar:beat:ticks) Elapsed time since last &Reset Tiempo transcorrido desde o último &Reset Elapsed time since last &XRUN Tempo transcorrido desde o último &XRUN Sample front panel normal display font Fonte de exibição normal do painel frontal da amostra Sample big time display font Exemplo de fonte de exibição de grande duração Big Time display: Display de tempo grande: &Font... Fon&te... Select font for front panel normal display Selecione a fonte para exibição normal do painel frontal Select font for big time display Selecione a fonte para exibição em grande escala Normal display: Display normal: Messages Window Janela de mensagens Sample messages text font display Exemplo de exibição de fonte de texto de mensagens Select font for the messages text display Selecione a fonte para a exibição do texto das mensagens &Messages limit: Limite de &Mensagens: Whether to keep a maximum number of lines in the messages window Manter um número máximo de linhas na janela de mensagens 100 100 250 250 2500 2500 The maximum number of message lines to keep in view Número máximo de linhas de mensagens para manter em vista Please do not touch these settings unless you know what you are doing. Por favor, não altere estas configurações, a menos que você saiba o que está fazendo. Connections Window Janela de conexões Sample connections view font Fonte de visualização de conexões de amostra Select font for the connections view Selecione a fonte para a visualização de conexões &Icon size: Tamanho de &Ícone: 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 The icon size for each item of the connections view O tamanho do ícone para cada item da visualização de conexões Ena&ble client/port aliases editing (rename) At&ivar edição de aliases de cliente/porta (renomear) Whether to enable in-place client/port name editing (rename) Ativar edição de nome de cliente/porta no local (renomear) E&nable client/port aliases Habilitar aliases para clientes/portas Whether to enable client/port name aliases on the connections window Ativar alias de nome de cliente/porta na janela de conexões Misc Misc Other Outro &Start JACK audio server on application startup Inicie o &servidor de áudio JACK na inicialização Whether to start JACK audio server immediately on application startup Iniciar o servidor de áudio JACK imediatamente na inicialização &Confirm application close Pedir &Confirmação ao sair Whether to ask for confirmation on application exit Perguntar antes de sair do qjackctl &Keep child windows always on top &Manter janelas filhas sempre no topo Whether to keep all child windows on top of the main window Manter todas as janelas filhas na parte superior da janela principal &Enable system tray icon Ativar ícone da ban&eja do sistema Whether to enable the system tray icon Ativar o ícone da bandeja do sistema S&ave JACK audio server configuration to: S&alvar a configuração del servidor JACK em: Whether to save the JACK server command-line configuration into a local file (auto-start) Salve a configuração da linha de comandos do servidor JACK em um arquivo local (início automático) .jackdrc .jackdrc The server configuration local file name (auto-start) O nome do arquivo local de configuração do servidor (início automático) Warning Aviso msec mseg n/a n/d &Preset Name Nome da &Predefinição &Server Path &Caminho do Servidor &Driver &Driver &Interface &Interface Sample &Rate &Taxa de Amostragem &Frames/Period &Quadros/Período Periods/&Buffer Períodos/&Buffer Patchbay Definition files Arquivos de definição do patchbay Some settings have been changed: "%1" Do you want to save the changes? Algumas configurações foram alteradas: "%1" Deseja salvá-las? System Sistema Cycle Ciclo HPET HPET Don't restrict self connect requests (default) Não restringir os pedidos de auto-conexão (padrão) Fail self connect requests to external ports only Falha nas solicitações de auto-conexão apenas para portas externas Ignore self connect requests to external ports only Ignorar solicitações de auto-conexão apenas para portas externas Fail all self connect requests Falha em todos os pedidos de auto-conexão Ignore all self connect requests Ignorar todos os pedidos de auto-conexão Delete preset: "%1" Are you sure? Deletar predefinição: "%1" Está certo disto? Startup Script Script de Inicialização Post-Startup Script Script de Post-Inicialização Shutdown Script Script de Desligamento Post-Shutdown Script Script de Pós-Desligamento Active Patchbay Definition Definição Ativa de Patchbay Messages Log Registro de Mensagens Log files Arquivos de registros Information Informação Some settings may be only effective next time you start this application. Algumas configurações podem ser eficazes apenas na próxima vez que você iniciar este aplicativo. Some settings have been changed. Do you want to apply the changes? Algumas configurações foram alteradas. Você quer aplicar as mudanças? The audio backend driver interface to use A interface do driver back-end de áudio a ser usada MIDI Driv&er: Driv&er MIDI: The ALSA MIDI backend driver to use O driver do ALSA MIDI para usar none nenhum raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 &Verbose messages &Mensagens detalhadas plughw:0 plughw:0 /dev/audio /dev/audio &Channels: &Canais: 192000 192000 Maximum number of audio channels to allocate Número máximo de canais de áudio a serem alocados Logging Registrando Messages log file Arquivo de registro de mensagns Browse for the messages log file location Procurar o local do arquivo de log de mensagens Whether to activate a messages logging to file. Ativar um log de mensagens para o arquivo. Advanced Avançado Whether to reset all connections when a patchbay definition is activated. Redefinir todas as conexões quando uma definição de patchbay for ativada. &Reset all connections on patchbay activation &Redefinir todas as conexões na ativação do patchbay Whether to issue a warning on active patchbay port disconnections. Emitir um aviso sobre desconexões de portas de patchbay ativas. &Warn on active patchbay disconnections &Avisar sobre desconexões de patchbay ativas &Messages log file: Registro de &mensagens: Whether to enable blinking (flashing) of the server mode (RT) indicator Ativar o piscar (intermitente) do indicador do modo do servidor (RT) Blin&k server mode indicator Pisc&ar o modo do servidor &JACK client/port aliases: Aliases de cliente/poprta para &JACK: JACK client/port aliases display mode Modo de exibição de aliases de cliente/porta JACK Default Padrão First Primeiro Second Segundo JACK client/port pretty-name (metadata) display mode Modo de exibição do nome customizado do client/porta JACK (metadata) Enable JA&CK client/port pretty-names (metadata) Ativar& nomes customizados (metadata) de clientes/portas JACK Whether to ask for confirmation on JACK audio server shutdown and/or restart Solicitar confirmação de desligamento e/ou reinicialização do servidor de áudio JACK Confirm server sh&utdown and/or restart &Confirme o desligamento e/ou reinício do servidor Whether to show system tray message on main window close Mostrar mensagem da bandeja do sistema na janela principal fechar Sho&w system tray message on close Mos&trar mensagem da bandeja do sistema ao fechar Whether to start minimized to system tray Iniciar minimizado na bandeja do sistema Start minimi&zed to system tray Iniciar minimi&zado na bandeja do sistema Setup Configuração Whether to restrict client self-connections Se deve restringir as auto-conexões do cliente Whether to use server synchronous mode Se deve usar o modo síncrono do servidor Clear settings of current preset name Limpar configurações do nome da predefinição atual Clea&r Limpa&r &Use server synchronous mode &Use o modo síncrono do servidor Cloc&k source: Cloc&k source: Clock source Fonte do Clock S&elf connect mode: M&odo de auto-conexão: Custom Personalizado &Color palette theme: &Tema de paleta de cor: Custom color palette theme Tema de paleta de cor personalizado Wonton Soup DO NOT TRANSLATE KXStudio DO NOT TRANSLATE Manage custom color palette themes Gerenciar temas de paleta de cor personalizada &Widget style theme: &Tema de estilo de widget: Custom widget style theme Tema customizado de estilo de widget: Whether to enable ALSA Sequencer (MIDI) support on startup Ativar o suporte ao seqüenciador de ALSA (MIDI) na inicialização E&nable ALSA Sequencer support Ativar Seque&nciador ALSA Whether to enable JACK D-Bus interface Ativar interface JACK D-Bus &Enable JACK D-Bus interface &Ativar interface JACK D-Bus Buttons Botões Whether to hide the left button group on the main window Ocultar o grupo de botões à esquerda na janela principal Hide main window &Left buttons Ocultar os &botões da esquerda da janela principal Whether to hide the right button group on the main window Ocultar o grupo de botões direito na janela principal Hide main window &Right buttons Ocultar os &botões da direita da janela principal Whether to hide the transport button group on the main window Ocultar o grupo de botões de transporte na janela principal Hide main window &Transport buttons Ocultar botões de &Transporte da janela principal Whether to hide the text labels on the main window buttons Ocultar os rótulos de texto nos botões da janela principal Hide main window &button text labels Ocultar rótulos de texto do &botão da janela principal Whether to replace Connections with Graph button on the main window Substituir Conexões pelo botão Gráfico na janela principal Replace Connections with &Graph button Substitua Conexões pelo botão &Gráfico Defaults Padrões &Base font size: Tamanho &básico de fonts: Base application font size (pt.) Tamanho básico de tipografias para a aplicação (pt.) 6 6 7 7 8 8 9 9 11 11 12 12 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to enable D-Bus interface Ativar interface D-Bus &Enable D-Bus interface &Ativar interface D-Bus Number of microseconds to wait between engine processes (dummy) Número de microssegundos a aguardar entre processos (dummy) netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to restrict to one single application instance (X11) Restringir a uma única instância do aplicativo (X11) Single application &instance Uma só &instância de aplicação &Name: &Nome: The JACK Audio Connection Kit sound server name O nome do servidor de áudio do JACK Audio Connection Kit &Server Name Nome do &Servidor Server path (command line prefix) Caminho do servidor (prefixo da linha de comando) &Channels I/O: &Canais de E/S: &Latency I/O: &Latência E/S: Start De&lay: Demora antes d&o início: secs segs 0 msecs 0 msegs Server Suffi&x: Sufixo do &Servidor: Server &Prefix: &Prefixo do servidor: Extra driver options (command line suffix) Opções extras para o driver (sufixo da linha de comando) Whether to stop JACK audio server on application exit Parar o servidor de áudio JACK na saída do aplicativo S&top JACK audio server on application exit Parar o servidor de áudio JACK na saída do aplicativo qjackctlSocketForm &Socket &Soquetes &Name (alias): &Nome (alias): Socket name (an alias for client name) Nome do soquete (um alias para o nome de cliente) Client name (regular expression) Nome do cliente (expressão regular) Add P&lug Adicionar P&lug Add plug to socket plug list Adicionar plugue à lista de plugues de soquetes &Plug: &Plugue: Port name (regular expression) Nome da porta (expressão regular) Socket Plugs / Ports Soquetes Plugues/Portas Socket plug list Lista de soquetes tipo plugue &Edit &Editar &Remove &Remover Remove currently selected plug from socket plug list Remover plug atualmente selecionado da lista de plugue de soquete Socket Soquete &Client: &Cliente: &Down &Baixar &Up &Subir E&xclusive E&xclusivo Enforce only one exclusive cable connection Aplicar apenas uma conexão a cabo exclusiva Type Tipo &Audio Á&udio Audio socket type (JACK) Soquete tipo áudio (JACK) &MIDI &MIDI MIDI socket type (ALSA) Soquete tipo MIDI (ALSA) Plugs / Ports Plugs/Portas Error Erro A socket named "%1" already exists. Um soquete chamado "%1" já existe. Add Plug Adicionar Plug Remove Remover Edit Editar Move Up Subir Move Down Abaixar Warning Aviso Some settings have been changed. Do you want to apply the changes? Algumas configurações foram alteradas. Você quer aplicar as mudanças? (None) (Nenhum) Edit currently selected plug Editar ficha atualmente selecionada Move down currently selected plug in socket plug list Mover para baixo o plug atualmente selecionado na lista de plugue de soquete Move up current selected plug in socket plug list Mover para cima a ficha selecionada atual na lista de plugues de soquete &Forward: &Avançar: Forward (clone) all connections from this socket Encaminhar (clonar) todas as conexões deste soquete MIDI socket type (JACK) Tipo de soquete MIDI (JACK) AL&SA AL&SA qjackctlSocketList Output Saída Input Entrada Socket Soquete Warning Aviso <New> - %1 <Novo> - %1 %1 about to be removed: "%2" Are you sure? A ponto de remover %1: "%2" Está certo disto? %1 <Copy> - %2 %1 <Copiar> - %2 qjackctlSocketListView Output Sockets / Plugs Soquetes de Saída/Plugues Input Sockets / Plugs Soquetes de Entrada/Plugues qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_es.ts0000644000000000000000000000013214771215054020537 xustar0030 mtime=1743067692.333636546 30 atime=1743067692.332636551 30 ctime=1743067692.333636546 qjackctl-1.0.4/src/translations/qjackctl_es.ts0000644000175000001440000063666714771215054020557 0ustar00rncbcusers PortAudioProber Probing... Detectando... Please wait, PortAudio is probing audio hardware. Por favor espere, PortAudio está detectando hardware de audio. Warning Advertencia Audio hardware probing timed out. La detección de hardware de audio ha expirado. QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Start JACK audio server immediately. Arrancar servidor de audio JACK inmediatamente. Set default settings preset name. Establecer nombre preset configuración predeterminada. Set active patchbay definition file. Establecer archivo definición patchbay activo. Set default JACK audio server name. Establecer nombre servidor de audio JACK predeterminado. Show help about command line options. Mostrar ayuda sobre opciones línea de comandos. Show version information. Mostrar información de versión. Launch command with arguments. Lanzar comando con argumentos. [command-and-args] [comando-y-args] Option -p requires an argument (preset). La opción -p nececita un argumento (nombre de un preset). Usage: %1 [options] [command-and-args] Uso: %1 [opciones] [comandos-y-argumentos] Options: Opciones: Option -a requires an argument (path). La opción -a requiere un argumento (ruta). Option -n requires an argument (name). La opción -n necesita un argumento (nombre). %1 (%2 frames) %1 (%2 cuadros) Move Mover Rename Renombrar qjackctlAboutForm About Acerca de About Qt Acerca de Qt &Close &Cerrar Version Versión Debugging option enabled. Depuración habilitada. System tray disabled. Bandeja del sistema deshabilitada. Transport status control disabled. Reporte del estado de transporte deshabilitado. Realtime status disabled. Estado de Realtime deshabilitado. XRUN delay status disabled. Reporte del retardo de XRUN deshabilitado. Maximum delay status disabled. Reporte del retardo máximo deshabilitado. ALSA/MIDI sequencer support disabled. Soporte para secuenciador ALSA/MIDI deshabilitado. Using: Qt %1 Usando: Qt %1 JACK %1 JACK %1 Website Website This program is free software; you can redistribute it and/or modify it Este programa es software libre; Usted puede redistribuirlo y/o modificarlo under the terms of the GNU General Public License version 2 or later. bajo los términos de la Licencia Pública General GNU versión 2 o posterior. JACK MIDI support disabled. Soporte MIDI en JACK deshabilitado. JACK Port aliases support disabled. Soporte para alias de los puertos de JACK deshabilitado. D-Bus interface support disabled. Soporte para la interfaz D-Bus deshabilitado. JACK Session support disabled. Soporte para sesiones de JACK deshabilitado. qjackctlClientListView &Connect &Conectar Alt+C Connect Alt+C &Disconnect &Desconectar Alt+D Disconnect Alt+D Disconnect &All Desconectar &Todo Alt+A Disconnect All Alt+T Re&name Cambiar &Nombre Alt+N Rename Alt+N &Refresh &Refrescar Alt+R Refresh Alt+R Readable Clients / Output Ports Puertos de Salida / Clientes Legibles Writable Clients / Input Ports Puertos de Entrada / Clientes Escribibles qjackctlConnect Warning Advertencia This will suspend sound processing from all client applications. Are you sure? Esto suspenderá el procesamiento de sonido de todas las aplicaciones. Está seguro? qjackctlConnectionsForm Audio Audio &Connect &Conectar Connect currently selected ports Conectar los puertos seleccionados &Disconnect &Desconectar Disconnect currently selected ports Desconectar los puertos seleccionados Disconnect &All Desconectar &Todo Disconnect all currently connected ports Desconectar todos los puertos seleccionados &Refresh &Refrescar Refresh current connections view Refrescar la vista actual de conexiones Connections Conexiones MIDI MIDI ALSA ALSA Expand all client ports Expandir todos los puertos de los clientes E&xpand All E&xpandir Todos qjackctlConnectorView &Connect &Conectar Alt+C Connect Alt+C &Disconnect &Desconectar Alt+D Disconnect Alt+D Disconnect &All Desconectar &Todo Alt+A Disconnect All Alt+T &Refresh &Refrescar Alt+R Refresh Alt+R qjackctlGraphCanvas Connect Conectar Disconnect Desconectar qjackctlGraphForm Graph Gráfico &Graph &Gráfico &Edit &Editar &View &Ver &Zoom &Zoom Co&lors Co&lores S&ort &Ordenar &Help A&yuda &Connect &Conectar Connect Conectar Connect selected ports Conectar puertos seleccionados &Disconnect &Desconectar Disconnect Desconectar Disconnect selected ports Desconectar puertos seleccionados Ctrl+C Ctrl+C T&humbview Vista pre&via Ctrl+D Ctrl+D Cl&ose C&errar Close Cerrar Close this application window Cerrar esta ventana de aplicación Select &All Seleccion&ar Todo Select All Seleccionar Todo Ctrl+A Ctrl+A Select &None No Seleccionar &Ninguno Select None No Seleccionar Ninguno Ctrl+Shift+A Ctrl+Shift+A Select &Invert Seleccionar &Invertir Select Invert Seleccionar Invertir Ctrl+I Ctrl+I &Rename... &Renombrar... Rename item Renombrar ítem Rename Item Renombrar ítem F2 F2 &Find... Find Find nodes Ctrl+F &Menubar Barra &Menú Menubar Barra Menú Show/hide the main program window menubar Muestra/oculta la barra de menú de la ventana principal Ctrl+M Ctrl+M &Toolbar Barra Herramien&tas Toolbar Barra herramientas Show/hide main program window file toolbar Muestra/oculta la barra de herramientas de la ventana principal &Statusbar Barra E&stado Statusbar Barra Estado Show/hide the main program window statusbar Muestra/oculta la barra de estado de la ventana principal &Top Left Par&te Superior Izquierda Top left Parte superior izquierda Show the thumbnail overview on the top-left Muestra la vista previa en la parte superior izquierda Top &Right Pa&rte Superior Derecha Top right Parte superior derecha Show the thumbnail overview on the top-right Muestra la vista previa en la parte superior derecha Bottom &Left Parte In&ferior Izquierda Bottom Left Parte Inferior Izquierda Bottom left Parte inferior izquierda Show the thumbnail overview on the bottom-left Muestra la vista previa en la parte inferior izquierda &Bottom Right Parte I&nferior Derecha Bottom right Parte inferior derecha Show the thumbnail overview on the bottom-right Muestra la vista previa en la parte inferior derecha &None &Ninguno None Ninguno Hide thumbview Oculta vista previa Hide the thumbnail overview Oculta la vista previa Text Beside &Icons Texto Junto a &Iconos Text beside icons Texto junto a iconos Show/hide text beside icons Muestra/oculta texto junto a iconos &Center &Centro Center Centro Center view Vista centro &Refresh &Refrescar Refresh Refrescar Refresh view Refrescar vista F5 F5 Zoom &In Zoom &In Zoom In Zoom In Ctrl++ Ctrl++ Zoom &Out Zoom &Out Zoom Out Zoom Out Ctrl+- Ctrl+- Zoom &Fit Zoom Enca&jar Zoom Fit Zoom Encajar Ctrl+0 Ctrl+0 Zoom &Reset Zoom &Resetear Zoom Reset Zoom Resetear Ctrl+1 Ctrl+1 &Zoom Range &Zoom Rango Zoom Range Zoom Rango JACK &Audio... JACK &Audio... JACK Audio color JACK Audio color JACK &MIDI... JACK &MIDI... JACK MIDI JACK MIDI JACK MIDI color JACK MIDI color ALSA M&IDI... ALSA M&IDI... ALSA MIDI ALSA MIDI ALSA MIDI color ALSA MIDI color JACK &CV... JACK &CV... JACK CV color JACK CV color JACK &OSC... JACK &OSC... JACK OSC JACK OSC JACK OSC color JACK OSC color &Reset &Resetear Reset colors Resetear colores Port &Name &Nombre Puerto Port name Nombre puerto Sort by port name Ordenar por nombre puerto Port &Title &Título Puerto Port title Título puerto Sort by port title Ordenar por título puerto Port &Index &Índice Puerto Port index Índice puerto Sort by port index Ordenar por índice puerto &Ascending &Ascendiente Ascending Ascendiente Ascending sort order Ordenar por orden ascendiente &Descending &Descendiente Descending Descendiente Descending sort order Ordenar por orden descendiente Repel O&verlapping Nodes Repeler Nodos S&uperpuestos Repel nodes Repeler nodos Repel overlapping nodes Repeler nodos superpuestos Connect Thro&ugh Nodes Conectar a Tra&vés de Nodos Connect Through Nodes Conectar a Través de Nodos Connect through nodes Conectar a través de nodos Whether to draw connectors through or around nodes Trazar conectores a través de o alrededor de nodos &About... &Acerca de... About... Acerca de... About Acerca de Show information about this application program Muestra información sobre esta aplicación About &Qt... Acerca de &Qt... About Qt... Acerca de Qt... About Qt Acerca de Qt Show information about the Qt toolkit Muestra información sobre las herramientas Qt &Undo Des&hacer &Redo &Rehacer Undo last edit action Deshacer última acción edición Redo last edit action Rehacer última acción edición Zoom Zoom Ready Preparado Colors - %1 Colores - %1 qjackctlMainForm &Quit &Salir Quit processing and exit Terminar procesamiento y salir &Start &Iniciar Start the JACK server Iniciar el servidor JACK S&top &Detener Stop the JACK server Detener el servidor JACK St&atus &Estado Ab&out... Ace&rca de... Show information about this application Mostrar información sobre esta aplicación Show settings and options dialog Mostrar el diálogo de opciones y preferencias &Messages &Mensajes Patch&bay Patch&bay Show/hide the patchbay editor window Mostrar / ocultar el editor de patchbay &Connect &Conectar JACK server state Estado del servidor JACK JACK server mode Modo del servidor JACK Sample rate Frecuencia de muestreo Time display Visor de tiempo Transport state Estado del transporte Transport BPM BPM del transporte Transport time Tiempo del transporte Show/hide the graph window Muestra/oculta la ventana del gráfico Show/hide the connections window Muestra/oculta la ventana de conexiones Backward transport Retroceder transporte Forward transport Avanzar transporte Rewind transport Rebobinar transporte (Alt+K) Stop transport rolling Detener el transporte (Shift+Espacio) Start transport rolling Iniciar el transporte (Espacio) Warning Advertencia successfully satisfactoriamente with exit status=%1 con estado %1 Could not load preset "%1". Retrying with default. No se pudo cargar el preset "%1". Probando con el predeterminado. Could not load default preset. Sorry. Lo siento. No se pudo cargar el preset predeterminado. Startup script... Script de inicio... Startup script terminated El script de inicio finalizó JACK is starting... JACK está iniciándose... Could not start JACK. Sorry. Lo siento. No se pudo iniciar JACK. JACK is stopping... JACK está deteniéndose... The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. El programa seguirá corriendo en la bandeja del sistema. Para terminarlo, por favor eljia "Salir" en el menú contextual del ícono en la bandeja del sistema. Shutdown script... Script de apagado... Shutdown script terminated El script de apagado finalizó JACK was stopped JACK ha sido detenido Post-shutdown script... Script de post - apagado... D-BUS: Service is available (%1 aka jackdbus). D-BUS: Disponible (%1 aka jackdbus). D-BUS: Service not available (%1 aka jackdbus). D-BUS: No disponible (%1 aka jackdbus). Don't show this message again No volver a mostrar este mensaje Don't ask this again No volver a preguntar esto D-BUS: JACK server is starting... D-BUS: Iniciando servidor JACK... D-BUS: JACK server could not be started. Sorry D-BUS: El servidor JACK no puede iniciarse. Disculpa D-BUS: JACK server is stopping... D-BUS: Deteniendo el servidor JACK... D-BUS: JACK server could not be stopped. Sorry D-BUS: El servidor JACK no puede detenerse. Disculpa Post-shutdown script terminated El script de post - apagado finalizó D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: El servidor JACK se ha iniciado (%1 aka jackdbus). The preset aliases have been changed: "%1" Do you want to save the changes? Los alias de presets han cambiado: "%1" Desea guardar los cambios? D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: El servidor JACK se ha detenido (%1 aka jackdbus). Error Error Transport time code Código de tiempo del transporte Elapsed time since last reset Tiempo transcurrido desde el último reset Elapsed time since last XRUN Tiempo transcurrido desde el último XRUN Patchbay activated. Patchbay activada. Patchbay deactivated. Patchbay desactivada. Statistics reset. Reiniciar estadísticas. msec mseg XRUN callback (%1). XRUN callback (%1). Buffer size change (%1). Cambio en el tamaño de buffer (%1). Shutdown notification. Notificación de apagado. Freewheel started... Freewheel iniciado... Freewheel exited. Freewheel parado. JACK property change. Cambio propiedad JACK. checked verificado connected conectado disconnected desconectado failed falló Server configuration saved to "%1". Configuración del servidor salvada en "%1". Client activated. Cliente activado. Post-startup script... Script de post - inicio... Post-startup script terminated El script de post - inicio finalizó Command line argument... Argumento de la línea de comando... Command line argument started Argumento de la línea de comando iniciado Client deactivated. Cliente desactivado. Transport rewind. Rebobinar transporte. Transport backward. Retroceder transporte. Starting Iniciando Transport start. Iniciar transporte. Stopping Deteniendo Transport stop. Detener transporte. Transport forward. Avanzar transporte. Stopped Detenido Yes Si No No FW FW RT RT Rolling Rolling Looping Looping XRUN callback (%1 skipped). XRUN callback (%1 omitidos). Started Iniciado Active Activo Activating Activando Inactive Inactivo &Hide &Ocultar D-BUS: GetParameterConstraint('%1'): %2. (%3) D-BUS: GetParameterConstraint('%1'): %2. (%3) Mi&nimize Mi&nimizar S&how &Mostrar Rest&ore &Restablecer &Stop &Detener &Reset &Reset &Connections &Conexiones Server settings will be only effective after restarting the JACK audio server. La configuración sólo se hará efectiva reiniciando el servidor JACK. Do you want to restart the JACK audio server? ¿Quieres reiniciar el servidor de audio JACK? D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) Information Información Some settings will be only effective the next time you start this program. Algunas configuraciones sólo se aplicarán la próxima vez que inicie este programa. Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. No se puede abrir el secuenciador ALSA como cliente El patchbay MIDI de ALSA no estará disponible. JACK is currently running. Do you want to terminate the JACK audio server? JACK se está ejecutando actualmente. ¿Desea detener el servidor de audio JACK? Could not start JACK. Maybe JACK audio server is already started. No puede iniciarse JACK. Quizás el servidor de audio JACK ya haya sido iniciado. Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Algunas aplicaciones de audio están activas y conectadas. Desea detener el servidor de audio JACK? %1 is about to terminate. Are you sure? %1 va a cerrarse. ¿Está seguro? JACK was started with PID=%1. JACK se inició con PID=%1. JACK is being forced... JACK está siendo forzado... Patchbay reset. Reseteo patchbay. JACK connection graph change. Cambio en gráfico de conexiones de JACK. JACK has crashed. JACK ha caído. JACK timed out. Tiempo de espera para JACK agotado. JACK write error. Error de escritura JACK. JACK read error. Error de lectura JACK. Unknown JACK error (%d). Error JACK desconocido (%d). ALSA connection graph change. Cambio en gráfico de conexiones ALSA. JACK active patchbay scan Escaneo del patchbay JACK activo ALSA active patchbay scan Escaneo del patchbay ALSA activo JACK connection change. Cambio en conexiones JACK. ALSA connection change. Cambio en conexiones de ALSA. A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? Una definición de patchbay está activa actualmente, y es probable que rehaga esta conexion: %1 -> %2 ¿Desea eliminar la conexion? Overall operation failed. La operación global falló. Invalid or unsupported option. Opción inválida o no soportada. Client name not unique. El nombre de cliente no es único. Server is started. El servidor está iniciado. Unable to connect to server. No puede conectarse al servidor. Server communication error. Error de comunicación con el servidor. Client does not exist. El cliente no existe. Unable to load internal client. No puede cargarse el cliente interno. Unable to initialize client. No puede inicializarse el cliente. Unable to access shared memory. No puede accederse a la memoria compartida. Client protocol version mismatch. La versión del protocolo cliente no concuerda. Could not connect to JACK server as client. - %1 Please check the messages window for more info. No puede conectarse al servidor JACK como cliente. - %1 Por favor revise la ventana de mensajes para mas información. %1 (%2%) %1 % %1 Hz %1 frames %1 cuadros %1 msec %1 mseg &Presets &Presets &Graph &Gráfico &Transport &Transporte &Rewind Re&bobinar &Play &Reproducir Pa&use Pa&usa &Patchbay &Patchbay DSP Load Uso de CPU del DSP XRUN Count (notifications) Cuenta de XRUN (notificaciones) &Backward &Retroceder &Forward &Avanzar Set&up... Set&up... S&ession S&esion &Load... &Abrir... &Save... &Guardar... Save and &Quit... Guardar y &Salir... Save &Template... Guardar Plan&tilla... Show/hide the session management window Mostrar/ocultar la ventana para administrar sesiones Show/hide the messages log/status window Mostrar/ocultar la ventana de estado/log Could not load active patchbay definition. "%1" Disabled. No se puede cargar el patchbay. "%1" Ha sido deshabilitado. &Versioning &Versiones Re&fresh Re&frescar %1 (%2%, %3 xruns) Transport BBT (bar.beat.ticks) BBT Transporte (compás.pulsación.fracciones) Transporte BBT (bar.beat.ticks) qjackctlMessagesStatusForm Messages / Status Mensajes / Estado &Messages &Mensajes Messages log Registro de mensajes Messages output log Registro de mensajes &Status &Estado Status information Información de estado Statistics since last server startup Estadísticas desde el último inicio de JACK Description Descripción Value Valor Reset XRUN statistic values Reiniciar estadísticas de XRUN Re&set Re&iniciar Refresh XRUN statistic values Refrescar estadísticas de XRUN &Refresh &Refrescar Server name Nombre del servidor Server state Estado del Servidor DSP Load Uso de CPU del DSP Sample Rate Frecuencia de muestreo Buffer Size Tamaño de Buffer Realtime Mode Modo Realtime Transport state Estado del transporte Transport Timecode Código de tiempo del transporte Transport BBT BBT del Transporte Transport BPM BPM del transporte XRUN count since last server startup XRUNs desde el último inicio XRUN last time detected Fecha de la última XRUN detectada XRUN last Última XRUN XRUN maximum Máximo de XRUN XRUN minimum Mínimo de XRUN XRUN average Promedio de XRUN XRUN total Total de XRUN Maximum scheduling delay Máximo retardo de programación (scheduling) Time of last reset Tiempo desde el último reset Logging stopped --- %1 --- Registro detenido --- %1 --- Logging started --- %1 --- Registro iniciado --- %1 --- qjackctlPaletteForm Color Themes Esquemas de Color Name Nombre Current color palette name Nombre actual paleta de colores Save current color palette name Guardar nombre actual paleta de colores Save Guardar Delete current color palette name Borrar nombre actual paleta de colores Delete Borrar Palette Paleta Current color palette Paleta de colores actual Generate: Generar: Base color to generate palette Color base para generar paleta Reset all current palette colors Resetear todos los colores de paleta Reset Resetear Import a custom color theme (palette) from file Importar un esquema de colores (paleta) personalizado de archivo Import... Importar... Export a custom color theme (palette) to file Exportar un esquema de colores (paleta) personalizado a archivo Export... Exportar... Show Details Mostrar Detalles Import File - %1 Importar Archivo - %1 Palette files (*.%1) Archivos de paleta (*.%1) Save Palette - %1 Guarda Paleta - %1 All files (*.*) Todos los archivos (*.*) Warning - %1 Advertencia - %1 Could not import from file: %1 Sorry. No se pudo importar desde archivo: %1 Disculpe. Export File - %1 Exportar archivo - %1 Some settings have been changed. Do you want to discard the changes? Algunos ajustes han sido modificados. ¿Desea descartar los cambios? Some settings have been changed: "%1". Do you want to save the changes? Algunos ajustes han sido modificados: "%1" Desea guardarlos? qjackctlPaletteForm::PaletteModel Color Role Rol Color Active Activo Inactive Inactivo Disabled Desactivado qjackctlPatchbay Warning Advertencia This will disconnect all sockets. Are you sure? Esto desconectará todos los sockets. ¿Está seguro? qjackctlPatchbayForm &New &Nueva Create a new patchbay profile Crear perfil nuevo de patchbay &Load... &Abrir... Load patchbay profile Cargar perfil de patchbay &Save... &Guardar... Save current patchbay profile Guardar el perfil actual del patchbay Acti&vate Acti&var Toggle activation of current patchbay profile Conmutar la activación del esquema actual &Connect &Conectar Connect currently selected sockets Conectar los puertos seleccionados &Disconnect &Desconectar Disconnect currently selected sockets Desconectar los puertos seleccionados Disconnect &All Desconectar &Todo Disconnect all currently connected sockets Desconectar todos los sockets actualmente conectados &Refresh &Refrescar Refresh current patchbay view Refrescar la vista actual Down Bajar Move currently selected output socket down one position Mover el socket de salida seleccionado una posición hacia abajo Add... Añadir... Create a new output socket Crear un nuevo socket de salida Edit... Editar... Edit currently selected input socket properties Editar las propiedades del socket de entrada seleccionado Up Subir Move currently selected output socket up one position Mover el socket de salida seleccionado una posición hacia arriba Remove Eliminar Remove currently selected output socket Eliminar el socket de salida seleccionado Copy... Copiar... Duplicate (copy) currently selected output socket Duplicar (copiar) el socket de salida seleccionado Patchbay Patchbay Remove currently selected input socket Eliminar el socket de entrada seleccionado Duplicate (copy) currently selected input socket Duplicar (copiar) el socket de entrada seleccionado Create a new input socket Crear un nuevo socket de entrada Edit currently selected output socket properties Editar las propiedades del socket de salida seleccionado Warning Advertencia active activa New Patchbay definition Nuevo esquema de patchbay Patchbay Definition files Archivos de esquemas de patchbay Load Patchbay Definition Cargar esquema de patchbay Save Patchbay Definition Guardar esquema de patchbay The patchbay definition has been changed: "%1" Do you want to save the changes? La definición del patchbay ha cambiado: "%1" ¿Desea guardar los cambios? %1 [modified] %1 [modificado] Untitled%1 SinNombre%1 Error Error Could not load patchbay definition file: "%1" No se puede cargar el archivo con el esquema del patchbay: "%1" Could not save patchbay definition file: "%1" No se puede guardar el archivo con el esquema del patchbay: "%1" Create patchbay definition as a snapshot of all actual client connections? ¿Crear un esquema del patchbay en base a una instantánea de las conexiones actuales? Current (recent) patchbay profile(s) Perfil actual (reciente) de patchbay Expand all items Expandir todos los elementos E&xpand All E&xpandir Todos qjackctlPatchbayView Add... Añadir... Edit... Editar... Copy... Copiar... Remove Eliminar Exclusive Exclusivo Move Up Subir Move Down Bajar &Connect &Conectar Alt+C Connect Alt+C &Disconnect &Desconectar Alt+D Disconnect Alt+D Disconnect &All Desconectar &Todo Alt+A Disconnect All Alt+T &Refresh &Refrescar Alt+R Refresh Alt+R Forward Avanzar (None) (Ninguno) qjackctlSessionForm Load session Cargar sesión &Load... &Abrir... Recent session Sesión reciente &Recent &Reciente Save session Guardar sesión &Save... &Guardar... Client / Ports Cliente / Puertos UUID UUID Command Comando Load Session Cargar Sesión Session directory Directorio de la sesión Save Session Guardar Sesión and Quit y Salir Template Plantilla &Clear &Limpiar Warning Advertencia A session could not be found in this folder: "%1" No se encontró una sesión en esta carpeta: "%1" %1: loading session... %1: cargando sesión... %1: load session %2. %1: cargar sesión %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? Una sesión ya existe en esta carpeta: "%1" ¿Está seguro de querer sobreescribirla? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Esta carpeta existe y no está vacía: "%1" ¿Está seguro de sobreescribir esta carpeta? %1: saving session... %1: guardando sesión... %1: save session %2. %1: guardar sesión %2. Update session Actualizar sesión Save and &Quit... Guardar y &Salir... Save &Template... Guardar Plan&tilla... Session Sesión &Save &Guardar &Versioning &Versiones Re&fresh Re&frescar Session clients / connections Clientes / conexiones de sesión Infra-clients / commands Infra-clientes / comandos Infra-client Infra-cliente Infra-command Infra-comando Add infra-client Añadir infra-cliente &Add &Añadir Edit infra-client Editar infra-cliente &Edit &Editar Remove infra-client Eliminar infra-cliente Re&move Eli&minar New Client Nuevo Cliente qjackctlSessionInfraClientItemEditor Infra-command Infra-comando qjackctlSessionSaveForm Session Sesión &Name: &Nombre: Session name &Directory: Session directory Directorio de la sesión Browse for session directory ... ... Save session versioning Guardar las versiones de la sesión &Versioning &Versiones Warning Advertencia Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings Configuraciones Preset &Name: &Nombre del Preset: (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Settings preset name Preset con las configuraciones &Save &Guardar Save settings as current preset name Guardar configuración en el preset actual &Delete &Eliminar Delete current settings preset Eliminar el preset con la configuración actual jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE Driv&er: Dri&ver: dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters Parámetros Number of periods in the hardware buffer Número de períodos en el buffer de hardware Priorit&y: &Prioridad: &Frames/Period: &Cuadros / Período: 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Frames per period between process() calls Cuadros por período entre llamadas a process() Port Ma&ximum: Má&ximos Puertos: 21333 21333 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 Sample rate in frames per second Frecuencia de muestreo en cuadros por segundo Scheduler priority when running realtime Prioridad del scheduler cuando se ejecuta en tiempo real &Word Length: &Largo de palabra: Periods/&Buffer: Períodos / &Buffer: Word length Tamaño de palabra Maximum number of ports the JACK server can manage Máximo número de puertos que podrá manejar el servidor JACK &Wait (usec): &Retardo (microseg): Sample &Rate: &Frecuencia de muestreo: &Timeout (msec): Límite de &Tiempo (mseg): 200 200 500 500 1000 1000 2000 2000 5000 5000 Set client timeout limit in milliseconds Establece el límite de tiempo de los clientes en milisegundos &Realtime Tiempo &Real Use realtime scheduling Usar prioridad(scheduling) de tiempo real No Memory Loc&k No b&loquear memoria Do not attempt to lock memory, even if in realtime mode No intentar bloquear memoria, incluso en modo de tiempo real &Unlock Memory &Desbloquear Memoria Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) No bloquear memoria de las librerías comunes (GTK+, QT, FLTK, Wine) So&ft Mode Modo &Tolerante Ignore xruns reported by the backend driver Ignorar las xruns reportadas por el driver de sonido. JACK tendrá menos tendencia a desconectar los puertos que no respondan. Útil cuando no se corre en tiempo real &Monitor &Monitorear Provide output monitor ports Proveer puertos para monitoreo de la salida Force &16bit Forzar &16bit Force 16bit mode instead of failing over 32bit (default) Forzar modo 16 bit en lugar de 32 bit (predeterminado) H/&W Meter Monitoreo por H/&W Enable hardware metering on cards that support it Habilitar monitoreo por hardware en las tarjetas que lo soporten &Ignore H/W &Ignorar H/W Ignore hardware period/buffer size Ignorar el tamaño de buffer / período del hardware &Output Device: Dispositiv&o de salida: &Interface: &Interfaz: Maximum input audio hardware channels to allocate Máximo número de canales de entrada por hardware a establecer &Audio: &Audio: Dit&her: &Suavizado: External output latency (frames) Latencia de la salida externa (cuadros) &Input Device: D&ispositivo de entrada: Duplex Duplex Capture Only Sólo Captura Playback Only Sólo Reproducción Provide either audio capture, playback or both Proveer de puertos de audio para captura, reproducción o ambos hw:0 The PCM device name to use Nombre del dispositivo PCM a usar > > /dev/dsp Alternate input device for capture Dispositivo de entrada alternativo para captura Maximum output audio hardware channels to allocate Máximo número de canales de salida por hardware a establecer Alternate output device for playback Dispositivo de salida alternativo para reproducción External input latency (frames) Latencia de la entrada externa (cuadros) None Ninguno Rectangular Rectangular Shaped Contorneado Triangular Triangular Set dither mode Establecer método de suavizado Whether to give verbose output on messages Mostrar información mas detallada en los mensajes Time in seconds that client is delayed after server startup Tiempo en segundos que el cliente es demorado luego de iniciar el servidor Latency: Latencia: Output latency in milliseconds, calculated based on the period, rate and buffer settings Latencia del sistema en milisegundos, calculada en base a la configuración de período, buffer y frecuencia de muestreo Options Opciones Scripting Scripting Execute script on Start&up: Script a ejecutar al iniciar el servi&dor: Whether to execute a custom shell script before starting up the JACK audio server. Ejecutar un script personalizado antes de iniciar el servidor JACK. Execute script after &Startup: &Script a ejecutar luego de iniciar: Whether to execute a custom shell script after starting up the JACK audio server. Ejecutar un script personalizado después de iniciar el servidor JACK. Execute script on Shut&down: Script a ejecutar antes de d&etener: Whether to execute a custom shell script before shuting down the JACK audio server. Ejecutar un script personalizado antes de detener el servidor JACK. Command line to be executed before starting up the JACK audio server Comando a ejecutar antes de iniciar el servidor JACK Scripting argument meta-symbols Variables especiales para pasar al script ... ... Browse for script to be executed before starting up the JACK audio server Buscar el script a ejecutar antes de iniciar el servidor de audio JACK Command line to be executed after starting up the JACK audio server Comando a ejecutar luego de iniciar el servidor JACK Browse for script to be executed after starting up the JACK audio server Buscar el script a ejecutar luego de iniciar el servidor de audio JACK Browse for script to be executed before shutting down the JACK audio server Buscar el script a ejecutar antes de terminar el servidor de audio JACK Command line to be executed before shutting down the JACK audio server Comando a ejecutar antes de detener el servidor JACK Execute script after Shu&tdown: Script a ejecutar luego de &Terminar: Whether to execute a custom shell script after shuting down the JACK audio server. Ejecutar un script personalizado después de terminar el servidor JACK. Browse for script to be executed after shutting down the JACK audio server Buscar el script a ejecutar luego de terminar el servidor de audio JACK Command line to be executed after shutting down the JACK audio server Comando a ejecutar luego de detener el servidor JACK Statistics Estadísticas &Capture standard output &Capturar salida estándar Whether to capture standard output (stdout/stderr) into messages window Capturar la salida estándar de JACK en la ventana de mensajes &XRUN detection regex: Expresión regular para detectar &XRUN: xrun of at least ([0-9|\.]+) msecs xrun de al menos ([0-9|\.]+) msegs Regular expression used to detect XRUNs on server output messages Expresión regular usada para detectar XRUNs en los mensajes del servidor Connections Conexiones 10 10 Patchbay definition file to be activated as connection persistence profile Esquemas de patchbay a activar como un perfil persistente de las conexiones Browse for a patchbay definition file to be activated Buscar el esquema de patchbay para activar Activate &Patchbay persistence: Activar &Persistencia del patchbay: Whether to activate a patchbay definition for connection persistence profile. Utilizar un perfil para conservar el esquema del patchbay entre sesiones. Display Display Time Display Display de tiempo Transport &Time Code Código de Tiempo del &Transporte Transport &BBT (bar:beat.ticks) &BBT del Transporte (compás:pulsación:frecuencia) Elapsed time since last &Reset Tiempo transcurrido desde el último &Reset Elapsed time since last &XRUN Tiempo transcurrido desde la última &XRUN Sample front panel normal display font Muestra de la fuente para el panel frontal Sample big time display font Muestra de la fuente para el display de tiempo grande Big Time display: Display de tiempo grande: &Font... Fuen&te... Select font for front panel normal display Seleccionar fuente para el panel normal Select font for big time display Seleccionar fuente para el display de tiempo grande Normal display: Display normal: Messages Window Ventana de Mensajes Sample messages text font display Muestra de la fuente para la ventana de mensajes Select font for the messages text display Seleccionar fuente para el display de mensajes &Messages limit: Límite de &Mensajes: Whether to keep a maximum number of lines in the messages window Almacenar un número limitado de líneas en la ventana de mensajes 100 100 250 250 2500 2500 The maximum number of message lines to keep in view Máximo número de líneas para mantener en la ventana de mensajes Please do not touch these settings unless you know what you are doing. Por favor no toques estos ajustes a menos que sepas lo que haces. Connections Window Ventana de Conexiones Sample connections view font Muestra de la fuente para la ventana de conexiones Select font for the connections view Seleccionar fuente para la ventana de conexiones &Icon size: Tamaño de &Icono: 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 The icon size for each item of the connections view Tamaño de ícono para cada ítem en la vista de conexiones Ena&ble client/port aliases editing (rename) Ha&bilitar la edición de alias para los puertos / clientes (renombrarlos) Whether to enable in-place client/port name editing (rename) Permitir la edición in-situ de los nobres asignados a puertos o clientes E&nable client/port aliases Habilitar alias para los nombres de &puertos / clientes Whether to enable client/port name aliases on the connections window Permitir alias para los puertos / clientes en la ventana de conexiones Misc Otras Other Otro &Start JACK audio server on application startup Iniciar el &servidor JACK al cargar qjackctl Whether to start JACK audio server immediately on application startup Iniciar JACK de forma automática cuando se lanza qjackctl &Confirm application close Pedir &confirmación al salir Whether to ask for confirmation on application exit Preguntar antes de salir de la aplicación &Keep child windows always on top &Las ventanas hijas siempre arriba Whether to keep all child windows on top of the main window Todas las ventanas creadas por qjackctl estarán sobre la ventana principal &Enable system tray icon Habilitar ícono en band&eja del sistema Whether to enable the system tray icon Permitir íconos en la bandeja del sistema S&ave JACK audio server configuration to: Gu&ardar la configuración del servidor JACK en: Whether to save the JACK server command-line configuration into a local file (auto-start) Guardar la línea de comando de JACK a un archivo (auto - inicio) .jackdrc .jackdrc The server configuration local file name (auto-start) El archivo con la configuración de JACK (auto-inicio) Warning Advertencia msec mseg n/a n/d &Preset Name Nombre del &Preset &Server Path Ruta hacia el &Servidor &Driver &Driver &Interface &Interfaz Sample &Rate &Frecuencia de muestreo &Frames/Period &Cuadros / Período Periods/&Buffer Períodos / &Buffer Patchbay Definition files Archivos de esquema de patchbay Some settings have been changed: "%1" Do you want to save the changes? Algunas configuraciones han cambiado: "%1" ¿Desea guardarlas? System Sistema Cycle Ciclo HPET HPET Don't restrict self connect requests (default) No restringir peticiones de auto-conexión (por defecto) Fail self connect requests to external ports only Solo suspender peticiones de auto-conexión a puertos externos Ignore self connect requests to external ports only Solo ignorar peticiones de auto-conexión a puertos externos Fail all self connect requests Suspender todas las peticiones de auto-conexión Ignore all self connect requests Ignorar todas las peticiones de auto-conexión Delete preset: "%1" Are you sure? Borrar preset: "%1" ¿Está seguro? Startup Script Script de Inicio Post-Startup Script Script de Post-Inicio Shutdown Script Script de Apagado Post-Shutdown Script Script de Post-Cierre Active Patchbay Definition Esquema Activo de Patchbay Messages Log Registro de Mensajes Log files Archivos de registros Information Información Some settings may be only effective next time you start this application. Algunos ajustes solo serán efectivos la próxima vez que arranques la aplicación. Some settings have been changed. Do you want to apply the changes? Algunas configuraciones han cambiado. ¿Desea aplicar los cambios? The audio backend driver interface to use El driver de audio a utilizar MIDI Driv&er: Driv&er MIDI: The ALSA MIDI backend driver to use El driver MIDI de ALSA a utilizar none ninguno raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 &Verbose messages Mensajes &Verbosos plughw:0 /dev/audio &Channels: &Canales: 192000 192000 Maximum number of audio channels to allocate El máximo número de canales de audio a utilizar Logging Registro Messages log file Archivo de registro de mensajes Browse for the messages log file location Ir hasta la ubicación del archivo con el registro de mensajes Whether to activate a messages logging to file. Guardar los mensajes a un archivo. Advanced Avanzado Whether to reset all connections when a patchbay definition is activated. Resetear todas las conexiones cuando se activa una definición de patchbay. &Reset all connections on patchbay activation &Resetear todas las conexiones con activación del patchbay Whether to issue a warning on active patchbay port disconnections. Avisar de desconexiones de puertos en patchbay activo. &Warn on active patchbay disconnections Ad&vertir cuando haya desconexiones en patchbay activo &Messages log file: Archivo con los &Mensajes: Whether to enable blinking (flashing) of the server mode (RT) indicator Hablilitar el parpadeo del indicador de modo del servidor (RT) Blin&k server mode indicator &Parpadeo del indicador de modo del servidor &JACK client/port aliases: Alias de cliente/puerto para &JACK: JACK client/port aliases display mode Modo de visualización de los alias cliente/puerto de JACK Default Predeterminado First Primero Second Segundo JACK client/port pretty-name (metadata) display mode Mostrar nombres personalizados (metadatos) de cliente/puerto JACK Enable JA&CK client/port pretty-names (metadata) Habilitar nombres personalizados (metadatos) de cliente/puerto JA&CK Whether to ask for confirmation on JACK audio server shutdown and/or restart Pedir confirmación al cerrar y/o reiniciar el servidor de audio JACK Confirm server sh&utdown and/or restart Confirmar cie&rre y/o reinicio del servidor Whether to show system tray message on main window close Mostrar mensaje en bandeja del sistema al cerrar ventana principal Sho&w system tray message on close M&ostrar mensaje en bandeja del sistema al cerrar Whether to start minimized to system tray Iniciar minimizado en la bandeja del sistema Start minimi&zed to system tray Iniciar minimi&zado en la bandeja del sistema Setup Configuración Whether to restrict client self-connections Restringir auto-conexiones de clientes Whether to use server synchronous mode Utilizar el modo síncrono del servidor Clear settings of current preset name Vaciar configuración preset actual Clea&r Vacia&r &Use server synchronous mode &Utilizar modo síncrono del servidor Cloc&k source: Fuente relo&j: Clock source Fuente reloj S&elf connect mode: Modo auto-con&exión: Custom Personalizado &Color palette theme: Esquema paleta &colores: Custom color palette theme Esquema paleta colores personalizado Wonton Soup DO NOT TRANSLATE KXStudio DO NOT TRANSLATE Manage custom color palette themes Gestionar esquema paleta colores personalizado &Widget style theme: Esquema estilo &widgets: Custom widget style theme Esquema estilo de widgets personalizado Whether to enable ALSA Sequencer (MIDI) support on startup Habilitar soporte para el Secuenciador ALSA (MIDI) al iniciar E&nable ALSA Sequencer support Habilitar Secue&nciador ALSA Whether to enable JACK D-Bus interface Activar el interfaz JACK D-Bus &Enable JACK D-Bus interface Activar int&erfaz JACK D-Bus Buttons Botones Whether to hide the left button group on the main window Ocultar el grupo de botones a la izquierda de la ventana principal Hide main window &Left buttons Ocultar botones de &la izquierda Whether to hide the right button group on the main window Ocultar el grupo de botones a la derecha de la ventana principal Hide main window &Right buttons Ocultar botones de la de&recha Whether to hide the transport button group on the main window Ocultar el grupo de botones del transporte en la ventana principal Hide main window &Transport buttons Ocultar los botones del &Transporte Whether to hide the text labels on the main window buttons Ocultar las etiquetas en los botones de la ventana principal Hide main window &button text labels Ocultar etiquetas de texto en los &botones Whether to replace Connections with Graph button on the main window Reemplazar Conexiones con botón de Gráfico en ventana principal Replace Connections with &Graph button Reemplazar Conexiones con botón de &Gráfico Defaults Predeterminados &Base font size: Tamaño &básico de tipografías: Base application font size (pt.) Tamaño básico de tipografías para la aplicación (pt.) 6 6 7 7 8 8 9 9 11 11 12 12 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to enable D-Bus interface Habilitar la interfaz por D-Bus &Enable D-Bus interface &Habilitar la interfaz via D-Bus Number of microseconds to wait between engine processes (dummy) Número de microsegundos a esperar entre procesamientos (dummy) netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to restrict to one single application instance (X11) Restringir una sola instancia de la aplicación (X11) Single application &instance Una sola &instancia &Name: &Nombre: The JACK Audio Connection Kit sound server name El nombre del servidor JACK Audio Connection Kit &Server Name Nombre del &Servidor Server path (command line prefix) Ruta del servidor (prefijo de la línea de comando) &Channels I/O: &Canales de E/S: &Latency I/O: &Latencia E/S: Start De&lay: Demora antes de&l inicio: secs segs 0 msecs 0 msegs Server Suffi&x: Sufijo del &Servidor: Server &Prefix: &Prefijo del servidor: Extra driver options (command line suffix) Opciones extra para el driver (sufijo de la línea de comandos) Whether to stop JACK audio server on application exit Detener el servidor JACK al salir de la aplicación S&top JACK audio server on application exit De&tener servidor JACK al salir de la aplicación qjackctlSocketForm &Socket &Socket &Name (alias): &Nombre (alias): Socket name (an alias for client name) Nombre del socket (un alias para el nombre de cliente) Client name (regular expression) Nombre del cliente (expresión regular) Add P&lug Añadir P&lug Add plug to socket plug list Añadir plug a la lista de sockets &Plug: &Plug: Port name (regular expression) Nombre del puerto (expresión regular) Socket Plugs / Ports Socket Plugs / Puertos Socket plug list Lista de socket tipo plug &Edit &Editar &Remove &Eliminar Remove currently selected plug from socket plug list Eliminar el plug seleccionado de la lista Socket Socket &Client: &Cliente: &Down &Bajar &Up &Subir E&xclusive E&xclusivo Enforce only one exclusive cable connection Permitir una conexión únicamente Type Tipo &Audio A&udio Audio socket type (JACK) Socket tipo audio (JACK) &MIDI &MIDI MIDI socket type (ALSA) Socket tipo MIDI (ALSA) Plugs / Ports Plugs / Puertos Error Error A socket named "%1" already exists. Un socket llamado "%1" ya existe. Add Plug Añadir Plug Remove Eliminar Edit Editar Move Up Subir Move Down Bajar Warning Advertencia Some settings have been changed. Do you want to apply the changes? Algunas configuraciones han cambiado. ¿Desea aplicar los cambios? (None) (Ninguno) Edit currently selected plug Editar el plug seleccionado Move down currently selected plug in socket plug list Mover hacia abajo en la lista el plug seleccionado Move up current selected plug in socket plug list Mover hacia arriba en la lista el plug seleccionado &Forward: &Avanzar: Forward (clone) all connections from this socket Reenviar (clonar) todas las conexiones desde este socket MIDI socket type (JACK) Tipo de socket MIDI (JACK) AL&SA AL&SA qjackctlSocketList Output Salida Input Entrada Socket Socket Warning Advertencia <New> - %1 <Nuevo> - %1 %1 about to be removed: "%2" Are you sure? A punto de ser eliminado %1: "%2" ¿Está seguro? %1 <Copy> - %2 %1 <Copia> - %2 qjackctlSocketListView Output Sockets / Plugs Sockets de Salida / Plugs Input Sockets / Plugs Sockets de Entrada / Plugs qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_sk.ts0000644000000000000000000000013214771215054020545 xustar0030 mtime=1743067692.335636536 30 atime=1743067692.335636536 30 ctime=1743067692.335636536 qjackctl-1.0.4/src/translations/qjackctl_sk.ts0000644000175000001440000064074114771215054020551 0ustar00rncbcusers PortAudioProber Probing... Zisťujem... Please wait, PortAudio is probing audio hardware. Počkajte, prosím, PortAudio zisťuje zvukový hardvér. Warning Upozornenie Audio hardware probing timed out. Vypršal časový limit počas zisťovania zvukového hardvéru. QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Usage: %1 [options] [command-and-args] Použitie: %1 [možnosti] [príkazy a argumenty] Options: Možnosti: Start JACK audio server immediately. Set default settings preset name. Set active patchbay definition file. Set default JACK audio server name. Show help about command line options. Show version information. Launch command with arguments. [command-and-args] Option -p requires an argument (preset). Možnosť -p vyžaduje argument (prednastavenie). Option -a requires an argument (path). Možnost -a vyžaduje argument (cesta). Option -n requires an argument (name). Možnosť -n vyžaduje argument (názov). %1 (%2 frames) %1 (%2 snímkov) Move Presunúť Rename Premenovať qjackctlAboutForm About O programe &Close &Zavrieť About Qt O Qt Version Verzia Debugging option enabled. Povolená voľba pre ladenie. System tray disabled. Zakázaná systémová oblasť. Transport status control disabled. Zakázané ovládanie stavu transportu. Realtime status disabled. Zakázaný stav spúšťania v reálnom čase. XRUN delay status disabled. Zákaz stav oneskorenia XRUN. Maximum delay status disabled. Zakázaný stav najväčšieho oneskorenia. JACK MIDI support disabled. JACK MIDI nie je podporovaný. JACK Session support disabled. Podpora pre sedenie JACK bola zakázaná. ALSA/MIDI sequencer support disabled. Podpora pre ALSA/MIDI radič (sequencer) bola vypnutá. Using: Qt %1 Používa: Qt %1 JACK %1 JACK %1 Website Webová stránka This program is free software; you can redistribute it and/or modify it Tento program je slobodným softvérom. Môžete ho šíriť a/alebo upravovať under the terms of the GNU General Public License version 2 or later. pri dodržaní podmienok licencie GNU General Public License verzie 2 alebo neskoršej. JACK Port aliases support disabled. Podpora pre prezývky prípojok JACK vypnutá. D-Bus interface support disabled. Podpora pre rozhranie D-Bus vypnutá. qjackctlClientListView Readable Clients / Output Ports Čitateľné prípojky pre klientov/výstupy Writable Clients / Input Ports Zapisovateľné prípojky pre klientov/výstupy &Connect &Spojiť Alt+C Connect Alt+C &Disconnect &Odpojiť Alt+D Disconnect Alt+D Disconnect &All O&dpojiť všetko Alt+A Disconnect All Alt+A Re&name &Premenovať Alt+N Rename Alt+N &Refresh &Obnoviť Alt+R Refresh Alt+R qjackctlConnect Warning Upozornenie This will suspend sound processing from all client applications. Are you sure? Týmto pozastavíte spracovanie zvuku pre všetky klientske aplikácie. Ste si istý? qjackctlConnectionsForm Connections Spojenia Audio Zvuk Connect currently selected ports Spojiť aktuálne vybraté prípojky &Connect &Spojiť Disconnect currently selected ports Odpojiť aktuálne vybraté prípojky &Disconnect O&dpojiť Disconnect all currently connected ports Odpojiť všetky aktuálne spojené prípojky Disconnect &All Odpojiť &všetko Expand all client ports Rozbaliť všetky klientske prípojky E&xpand All Ro&zbaliť všetko Refresh current connections view Obnoviť pohľad na aktuálne spojenia &Refresh &Obnoviť MIDI MIDI ALSA ALSA qjackctlConnectorView &Connect &Spojiť Alt+C Connect Alt+C &Disconnect &Odpojiť Alt+D Disconnect Alt+D Disconnect &All Odpojiť &všetko Alt+A Disconnect All Alt+A &Refresh &Obnoviť Alt+R Refresh Alt+R qjackctlGraphCanvas Connect Spojiť Disconnect Rozpojiť qjackctlGraphForm Graph Graf &Graph &Graf &Edit Úp&ravy &View &Pohľad &Zoom &Zväčšenie Co&lors &Farby S&ort &Triediť &Help Po&mocník &Connect &Spojenie Connect Spojiť Connect selected ports Spojiť vybraté prípojky &Disconnect &Odpojiť Disconnect Odpojiť Disconnect selected ports Odpojiť vybraté prípojky Ctrl+C T&humbview Ctrl+D Cl&ose &Zavrieť Close Zavrieť Close this application window Zavrieť okno tohto programu Select &All Vybrať &všetko Select All Vybrat všetko Ctrl+A Ctrl+A Select &None Nevybrať &nič Select None Nevybrať nič Ctrl+Shift+A Ctrl+Shift+A Select &Invert Otočiť &výber Select Invert Otočiť výber Ctrl+I Ctrl+I &Rename... &Premenovať... Rename item Premenovať položku Rename Item Premenovať položku F2 F2 &Find... Find Find nodes Ctrl+F &Menubar &Ponuková lišta Menubar Ponuková lišta Show/hide the main program window menubar Zobraziť/skryť hlavné okno programu s ponukovou lištou Ctrl+M Ctrl+M &Toolbar &Nástrojová lišta Toolbar Nástrojová lišta Show/hide main program window file toolbar Zobraziť/skryť hlavné okno programu s nástrojovou lištou &Statusbar &Stavový riadok Statusbar Stavový riadok Show/hide the main program window statusbar Zobraziť/skryť stavový riadok hlavného okna programu &Top Left Top left Show the thumbnail overview on the top-left Top &Right Top right Show the thumbnail overview on the top-right Bottom &Left Bottom Left Bottom left Show the thumbnail overview on the bottom-left &Bottom Right Bottom right Show the thumbnail overview on the bottom-right &None None Žiadny Hide thumbview Hide the thumbnail overview Text Beside &Icons Text &vedľa ikon Text beside icons Text vedľa ikon Show/hide text beside icons Zobraziť/skryť text vedľa ikon &Center &Centrovať Center Centrovať Center view Centrovať pohľad &Refresh &Obnoviť Refresh Obnoviť Refresh view Obnoviť pohľad F5 F5 Zoom &In &Priblížiť Zoom In Priblížiť Ctrl++ Ctrl++ Zoom &Out &Oddialiť Zoom Out Oddialiť Ctrl+- Ctrl+- Zoom &Fit &Prispôsobiť oknu Zoom Fit Prispôsobiť oknu Ctrl+0 Ctrl+0 Zoom &Reset Použiť &predvolené zväčšenie Zoom Reset Použiť predvolené zväčšenie Ctrl+1 Ctrl+1 &Zoom Range Rozsah &zväčšenia Zoom Range Rozsah zväčšenia JACK &Audio... JACK &Audio... JACK Audio color Farba JACK Audio JACK &MIDI... JACK &MIDI... JACK MIDI JACK MIDI JACK MIDI color Farba JACK MIDI ALSA M&IDI... ALSA MIDI ALSA MIDI ALSA MIDI color Farba ALSA MIDI JACK &CV... JACK &CV... JACK CV color Farba JACK CV JACK &OSC... JACK &OSC... JACK OSC JACK OSC JACK OSC color Farba JACK OSC &Reset &Obnoviť predvolené Reset colors Obnoviť predvolené farby Port &Name &Názov prípojky (port) Port name Názov prípojky (port) Sort by port name Triediť podľa názvu prípojky (port) Port &Title &Názov prípojky (port) Port title Názov prípojky (port) Sort by port title Triediť podľa názvu prípojky (port) Port &Index Čí&slo prípojky (port) Port index Číslo prípojky (port) Sort by port index Triediť podľa čísla prípojky (port) &Ascending &Vzostupne Ascending Vzostupne Ascending sort order Vzostupné poradie triedenia &Descending &Zostupne Descending Zostupne Descending sort order Zostupné poradie triedenia Repel O&verlapping Nodes Repel nodes Repel overlapping nodes Connect Thro&ugh Nodes Connect Through Nodes Connect through nodes Whether to draw connectors through or around nodes &About... &O programe... About... O programe... About O programe Show information about this application program Zobraziť informácie o tomto programe About &Qt... O &Qt... About Qt... O Qt... About Qt O Qt Show information about the Qt toolkit Zobraziť informácie o sade nástrojov prostredia Qt &Undo &Späť &Redo &Znova Undo last edit action Vrátiť poslednú úpravu späť Redo last edit action Vykonať poslednú upravu znova Zoom Zväčšenie Ready Pripravený Colors - %1 Farby - %1 qjackctlMainForm Quit processing and exit Zastaviť spracovanie a ukončiť program &Quit &Ukončiť Start the JACK server Spustiť server JACK &Start &Spustiť Stop the JACK server Zastaviť server JACK S&top &Zastaviť St&atus S&tav Show information about this application Zobraziť informácie o tomto programe Ab&out... &O programe... Set&up... &Nastavenia... Show settings and options dialog Zobraziť dialógové okno pre nastavenia a možnosti &Messages &Hlásenia Show/hide the patchbay editor window Zobraziť/skryť okno editoru so zapájacou doskou &Patchbay &Zapájacia doska &Connect S&pojiť JACK server state Stav serveru JACK JACK server mode Režim servera JACK DSP Load Zaťaženie DSP Sample rate Vzorkovacia frekvencia XRUN Count (notifications) Počet XRUN (oznámenia) Time display Údaj o čase Transport state Stav transportu Transport BPM Transport BPM Transport time Čas transportu Show/hide the session management window Zobraziť/skryť okno so správou sedenia Show/hide the messages log/status window Zobraziť/skryť okno so záznamami/stavom Show/hide the graph window Zobraziť/skryť okno s grafom Show/hide the connections window Zobraziť/skryť okno so spojeniami Backward transport Transport naspäť &Backward &Naspäť Forward transport Transport vpred &Forward &Vpred Rewind transport Pretočiť transport naspäť &Rewind &Pretočiť naspäť Stop transport rolling Zastaviť chod transportu Pa&use &Pozastaviť Start transport rolling Spustiť chod transportu &Play &Prehrať Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. Nepodarilo sa otvoriť radič (sekvencér) ALSA ako klienta. Zapájacia doska ALSA MIDI nebude dostupná. D-BUS: Service is available (%1 aka jackdbus). D-BUS: Služba je dostupná (%1 aka jackdbus). D-BUS: Service not available (%1 aka jackdbus). D-BUS: Služba nie je dostupná (%1 aka jackdbus). Information Informácie Warning Upozornenie JACK is currently running. Do you want to terminate the JACK audio server? Server JACK je aktuálne spustený. Chcete ukončiť zvukový server JACK? successfully úspešne with exit status=%1 s návratovou hodnotou = %1 Could not start JACK. Maybe JACK audio server is already started. Jack sa nepodarilo spustiť. Možno je už server JACK spustený. Could not load preset "%1". Retrying with default. Nepodarilo sa načítať nastavenie "%1". Skúšam to opäť s predvoleným nastavením. Could not load default preset. Sorry. Nepodarilo sa načítať predvolené nastavenie. Ľutujem. Startup script... Spúšťací skript... Startup script terminated Spúšťací skript bol ukončený D-BUS: JACK server is starting... D-BUS: Spúšťa sa server JACK... D-BUS: JACK server could not be started. Sorry D-BUS: Server JACK sa nepodarilo spustiť. Ľutujem JACK is starting... JACK sa spúšťa... Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Niektoré klientske zvukové aplikácie sú stále aktívne a pripojené. Chcete zastaviť zvukový server JACK? JACK is stopping... JACK sa zastavuje... Shutdown script... Vypínací skript... Don't ask this again Už sa nepýtať Shutdown script terminated Vypínací skript bol ukončený D-BUS: JACK server is stopping... D-BUS: Zastavuje sa server JACK... D-BUS: JACK server could not be stopped. Sorry D-BUS: Server JACK se nepodarilo zastaviť. Ľutujem Post-shutdown script... Skript po vypnutí... Post-shutdown script terminated Skript po vypnutí bol ukončený JACK was started with PID=%1. JACK bol spustený s PID = %1. %1 is about to terminate. Are you sure? D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: Server JACK bol spustený (%1 alebo tiež jackdbus). JACK is being forced... JACK je nútený... JACK was stopped JACK bol zastavený D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: Server JACK bol zastavený (%1 alebo tiež jackdbus). Error Chyba Transport time code Transport časového kódu Elapsed time since last reset Čas od posledného obnovenia továrenských nastavení Elapsed time since last XRUN Čas od posledného XRUN Patchbay activated. Zapájacia doska aktivovaná. Patchbay deactivated. Zapájacia doska deaktivovaná. Statistics reset. Štatistiky vynulované. msec ms JACK connection graph change. Graf spojení JACK zmenený. XRUN callback (%1). Spätné volanie (callback) XRUN (%1). Buffer size change (%1). Veľkosť vyrovnávacej pamäte zmenená (%1). Shutdown notification. Oznámenie o zastavení. Could not start JACK. Sorry. Nepodarilo sa spustiť JACK. Ľutujem. JACK has crashed. JACK spadol. JACK timed out. JACK - čas vypršal. JACK write error. Chyba pri zápise do JACKu. JACK read error. Chyba pri čítaní JACKu. Unknown JACK error (%d). Neznáma chyba JACKu (%d). ALSA connection graph change. Graf spojení ALSA zmenený. JACK active patchbay scan Skenovanie aktívnej zapájacej dosky JACK ALSA active patchbay scan Skenovanie aktívnej zapájacej dosky ALSA JACK connection change. Spojenie JACK zmenené. ALSA connection change. Spojenie ALSA zmenené. checked skontrolované connected spojené disconnected odpojené failed zlyhalo A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? Definícia zapájacej dosky je teraz aktívna, čo pravdepodobne znamená prerobenie tohto spojenia: %1 -> %2 Chcete odstrániť spojenie zapájacej dosky? The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. Program bude bežať ďalej v systémovej lište. Pre ukončenie programu vyberte, prosím, "Ukončiť" v kontextovej ponuke ikony na systémovej lište. Don't show this message again Toto hlásenie už viac nezobrazovať The preset aliases have been changed: "%1" Do you want to save the changes? Prezývky pre prednastavenia boli zmenené: "%1" Chcete uložiť zmeny? Transport BBT (bar.beat.ticks) Transport BBT (takt:doba.tiknutie - bar:beat.ticks) Patchbay reset. Uvedenie zapájacej dosky do predvolených nastavení. Could not load active patchbay definition. "%1" Disabled. Nepodarilo sa nahrať definíciu aktívnej zapájacej dosky. "%1" Zakázané. Freewheel started... Voľnobeh spustený... Freewheel exited. Voľnobeh ukončený. JACK property change. Vlastnosť JACK zmenená. Overall operation failed. Celková operácia sa nepodarila. Invalid or unsupported option. Neplatná alebo nepodporovaná voľba. Client name not unique. Názov klienta nie je jedinečný. Server is started. Server je spustený. Unable to connect to server. Nedá sa pripojiť k serveru. Server communication error. Chyba pri komunikácii so serverom. Client does not exist. Klient neexistuje. Unable to load internal client. Nepodarilo sa načítať interného klienta. Unable to initialize client. Nepodarilo sa inicializovať klienta. Unable to access shared memory. Nepodarilo sa pristúpiť ku zdieľanej pamäti. Client protocol version mismatch. Nesedí verzia protokolu klienta. Could not connect to JACK server as client. - %1 Please check the messages window for more info. Nepodarilo sa pripojiť k serveru JACK ako klient. - %1 Ďalšie informácie nájdete v okno s hláseniami. Server configuration saved to "%1". Nastavenie servera uložené do "%1". Client activated. Klient aktivovaný. Post-startup script... Skript po spustení... Post-startup script terminated Skript po spustení skončil Command line argument... Argument pre príkazový riadok... Command line argument started Argument pre príkazový riadok spustený Client deactivated. Klient deaktivovaný. Transport rewind. Pretočiť transport naspäť. Transport backward. Transport späť. Starting Spúšťa sa Transport start. Spustenie transportu. Stopping Zastavuje sa Transport stop. Transport zastavený. Transport forward. Transport vpred. Stopped Zastavené %1 (%2%) %1 (%2 %) %1 (%2%, %3 xruns) %1 (%2%, %3 xruns) %1 % %1 % %1 Hz %1 Hz %1 frames %1 snímkov Yes Áno No Nie FW FW RT RT Rolling Ide Looping Zapína sa do jednoduchého obvodu %1 msec %1 ms XRUN callback (%1 skipped). Spätné volanie (callback) XRUN (%1 preskočených). Started Spustené Active Aktívny Activating Aktivuje sa Inactive Neaktívny &Hide &Skryť D-BUS: GetParameterConstraint('%1'): %2. (%3) D-BUS: GetParameterConstraint('%1'): %2. (%3) Mi&nimize &Minimalizovať S&how &Zobraziť Rest&ore O&bnoviť &Stop &Zastaviť &Reset &Obnoviť predvolené &Presets &Prednastavenia &Versioning &Verzovanie Re&fresh &Aktualizovať S&ession Se&denie &Load... &Načítať... &Save... &Uložiť... Save and &Quit... Uložiť a &ukončiť... Save &Template... Uložiť ako ša&blónu... &Connections &Spojenia Patch&bay &Zapájacia doska &Graph &Graf &Transport &Transport Server settings will be only effective after restarting the JACK audio server. Nastavenia serveru sa prejavia až po opätovnom spustení serveru JACK. Do you want to restart the JACK audio server? Chcete zvukový server JACK spustiť znovu? D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: Nastaviť hodnotu parametra SetParameterValue('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: Vynulovať hodnotu parametra ResetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS: Získať hodnotu parametra GetParameterValue('%1'): %2. (%3) Some settings will be only effective the next time you start this program. Niektoré nastavenia sa prejavia až po ďalšom spustení tohto programu. qjackctlMessagesStatusForm Messages / Status Hlásenia/Stav &Messages &Správy Messages log Záznam správ Messages output log Výstup so záznamom správ &Status &Stav Status information Informácie o stave Statistics since last server startup Štatistiky od posledného spustenia servera Description Popis Value Hodnota Reset XRUN statistic values Vynulovať štatistiky hodnôt XRUN Re&set &Vynulovať Refresh XRUN statistic values Obnoviť údaje v štatistike XRUN &Refresh &Obnoviť Server name Názov servera Server state Stav servera DSP Load Zaťaženie DSP Sample Rate Vzorkovacia frekvencia Buffer Size Veľkosť vyrovnávacej pamäte Realtime Mode Režim skutočného času Transport state Stav transportu Transport Timecode Transport časového kódu Transport BBT Transport BBT Transport BPM Transport BPM XRUN count since last server startup Počet XRUN od posledného spustenia servera XRUN last time detected Čas poslednej detekcie XRUN XRUN last Posledné XRUN XRUN maximum Najväčšia hodnota XRUN XRUN minimum Najmenšia hodnota XRUN XRUN average Priemerná hodnota XRUN XRUN total Celkový počet XRUN Maximum scheduling delay Najväčšie oneskorenie času Time of last reset Čas od posledného vynulovania hodnôt Logging stopped --- %1 --- Záznam zastavený --- %1 --- Logging started --- %1 --- Záznam spustený --- %1 --- qjackctlPaletteForm Color Themes Farebné motívy Name Názov Current color palette name Názov aktuálnej farebnej palety Save current color palette name Uložiť názov aktuálnej farebnej palety Save Uložiť Delete current color palette name Odstrániť názov aktuálnej farebnej palety Delete Odstrániť Palette Paleta Current color palette Aktuálna farebná paleta Generate: Generovať: Base color to generate palette Základná farba pre vytvorenie palety Reset all current palette colors Vynulovať všetky farby palety Reset Vynulovať Import a custom color theme (palette) from file Importovať vlastný farebný motív (paletu) zo súboru Import... Importovať... Export a custom color theme (palette) to file Exportovať vlastný farebný motív (paletu) do súboru Export... Exportovať... Show Details Zobraziť podrobnosti Import File - %1 Importovať súbor - %1 Palette files (*.%1) Súbory s paletami (*.%1) Save Palette - %1 All files (*.*) Všetky súbory (*.*) Warning - %1 Upozornenie - %1 Could not import from file: %1 Sorry. Import zo súboru skončil s chybou. %1 Ľutujem. Export File - %1 Exportovať súbor - %1 Some settings have been changed. Do you want to discard the changes? Niektoré nastavenia boli zmenené. Chcete zahodiť zmeny? Some settings have been changed: "%1". Do you want to save the changes? Niektoré nastavenia boli zmenené: "%1" Chcete uložiť zmeny? qjackctlPaletteForm::PaletteModel Color Role Farebná rola Active Aktívna Inactive Neaktívna Disabled Vypnutá qjackctlPatchbay Warning Upozornenie This will disconnect all sockets. Are you sure? Toto odpojí všetky zásuvky. Ste si istý? qjackctlPatchbayForm Patchbay Zapájacia doska Move currently selected output socket down one position Posunúť aktuálne vybratú výstupnú zásuvku o jednu pozíciu nižšie Down Nižšie Create a new output socket Vytvoriť novú výstupnú zásuvku Add... Pridať... Edit currently selected input socket properties Upraviť vlastnosti aktuálne vybratej vstupnej zásuvky Edit... Upraviť... Move currently selected output socket up one position Posunúť aktuálne vybratú výstupnú zásuvku o jednu pozíciu vyššie Up Vyššie Remove currently selected output socket Odstrániť aktuálne vybratú výstupnú zásuvku Remove Odstrániť Duplicate (copy) currently selected output socket Duplikovať (kopírovať ) aktuálne vybratú výstupnú zásuvku Copy... Kopírovať... Remove currently selected input socket Odstrániť aktuálne vybratú vstupnú zásuvku Duplicate (copy) currently selected input socket Duplikovať (kopírovať ) aktuálne vybratú vstupnú zásuvku Create a new input socket Vytvoriť novú vstupnú zásuvku Edit currently selected output socket properties Upraviť vlastnosti aktuálne vybratej výstupnej zásuvky Connect currently selected sockets Spojiť aktuálne vybraté zásuvky &Connect S&pojiť Disconnect currently selected sockets Odpojiť aktuálne vybraté zásuvky &Disconnect &Odpojiť Disconnect all currently connected sockets Odpojiť všetky aktuálne vybraté zásuvky Disconnect &All &Odpojiť všetko Expand all items Rozbaliť všetky položky E&xpand All Rozbaliť &všetko Refresh current patchbay view Obnoviť pohľad na aktuálnu zapájaciu dosku &Refresh &Obnoviť Create a new patchbay profile Vytvoriť nový profil zapájacej dosky &New &Nový Load patchbay profile Načítať profil zapájacej dosky &Load... &Načítať... Save current patchbay profile Uložiť aktuálny profil zapájacej dosky &Save... &Uložiť... Current (recent) patchbay profile(s) Aktuálny (naposledy použitý) profil(y) zapájacej dosky Toggle activation of current patchbay profile Prepnúť aktivovanie aktuálneho profilu zapájacej dosky Acti&vate &Aktivovať Warning Upozornenie The patchbay definition has been changed: "%1" Do you want to save the changes? Definícia zapájacej dosky bola zmenená: "%1" Chcete uložiť zmeny? %1 [modified] %1 [zmenený] Untitled%1 Bez názvu%1 Error Chyba Could not load patchbay definition file: "%1" Nepodarilo sa nahrať súbor s definíciou zapájacej dosky: "%1" Could not save patchbay definition file: "%1" Nepodarilo sa uložiť súbor s definíciou zapájacej dosky: "%1" New Patchbay definition Nová definícia zapájacej dosky Create patchbay definition as a snapshot of all actual client connections? Vytvoriť definíciu zapájacej dosky ako snímok všetkých súčasných klientskych spojení? Load Patchbay Definition Načítať definíciu zapájacej dosky Patchbay Definition files Súbory s definíciami zapájacej dosky Save Patchbay Definition Uložiť definíciu zapájacej dosky active aktívne qjackctlPatchbayView Add... Pridať... Edit... Upraviť... Copy... Kopírovať... Remove Odstrániť Exclusive Výhradný Forward Dopredu (None) (Žiadny) Move Up Presunúť vyššie Move Down Presunúť nižšie &Connect &Spojiť Alt+C Connect Alt+C &Disconnect &Odpojiť Alt+D Disconnect Alt+D Disconnect &All &Odpojiť všetko Alt+A Disconnect All Alt+A &Refresh &Obnoviť Alt+R Refresh Alt+R qjackctlSessionForm Session Sedenie Load session Načítať sedenie &Load... &Načítať... Recent session Naposledy otvorené sedenie &Recent &Naposledy otvorené Save session Uložiť sedenie &Versioning &Verzovanie Re&fresh Ob&noviť Session clients / connections Klienti sedenia/spojenia Infra-clients / commands Infra-klienti/Príkazy Infra-client Infra-klient Infra-command Infra-príkaz Add infra-client Pridať infra-klienta &Add Prid&ať Edit infra-client Upraviť infra-klienta &Edit &Upraviť Remove infra-client Odstrániť infra-klienta Re&move &Odstrániť &Save... &Uložiť... Update session Obnoviť sedenie Client / Ports Klient/Prípojky UUID UUID Command Príkaz &Save &Uložiť Load Session Načítať sedenie Session directory Adresár so sedením Save Session Uložiť sedenie and Quit a ukončiť Template Šablóna &Clear &Vyčistiť Warning Upozornenie A session could not be found in this folder: "%1" Sedenie v tomto priečinku sa nepodarilo nájsť: "%1" %1: loading session... %1: načítava sa sedenie... %1: load session %2. %1: načítať sedenie %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? V tomto priečinku už existuje sedenie: "%1" Ste si istý, že chcete prepísať existujúce sedenie? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Tento priečinok už existuje a nie je prázdny: "%1" Ste si istý, že chcete prepísať existujúci priečinok? %1: saving session... %1: ukladá sa sedenie... %1: save session %2. %1: uložiť sedenie %2. New Client Nový klient Save and &Quit... Uložiť a &ukončiť... Save &Template... Uložiť ako š&ablónu... qjackctlSessionInfraClientItemEditor Infra-command Infra-príkaz qjackctlSessionSaveForm Session Sedenie &Name: &Názov: Session name &Directory: Session directory Adresár so sedením Browse for session directory ... ... Save session versioning Uložiť verzovanie sedenia &Versioning &Verzovanie Warning Upozornenie Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings Nastavenia Preset &Name: Názov prednastaveni&a: Settings preset name Názov prednastavenia (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Save settings as current preset name Uložiť nastavenia pod aktuálnym názvom prednastavenia &Save &Uložiť Delete current settings preset Odstrániť aktuálne prednastavenie &Delete &Odstrániť jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE Driv&er: &Ovládač: The audio backend driver interface to use Ovládač pre zvukové rozhranie, ktoré sa má použiť dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters Parametre MIDI Driv&er: Ovlá&dač MIDI: The ALSA MIDI backend driver to use Ovládač ALSA MIDI, ktorý sa bude používať none žiadny raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Time in seconds that client is delayed after server startup Čas v sekundách, o ktorý je klient oneskorený po spustení servera Latency: Oneskorenie (latencia): Output latency in milliseconds, calculated based on the period, rate and buffer settings Oneskorenie (latencia) výstupu v ms, ktorého výpočet je založený na nastavení periódy, frekvencie a vyrovnávacej pamäte Use realtime scheduling Použiť spracovanie v reálnom čase &Realtime &Reálny čas Do not attempt to lock memory, even if in realtime mode Nepokúšať sa uzamknúť pamäť, ani v režime reálneho času No Memory Loc&k &Nezamykať pamäť Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) Odomknúť pamäť bežných knižníc s nástrojmi (GTK+, QT, FLTK, Wine) &Unlock Memory &Odomknúť pamäť Ignore xruns reported by the backend driver Ignorovať xruny hlásené ovládačom So&ft Mode &Jednoduchý režim Provide output monitor ports Poskytnúť prípojky pre sledovanie výstupov (monitory) &Monitor &Sledovanie (monitor) Force 16bit mode instead of failing over 32bit (default) Vynútiť 16bitový režim miesto preklopenia do 32bitového (predvolený) Force &16bit Vynútiť &16bitový režim Enable hardware metering on cards that support it Povoliť prístrojové meranie pri kartách, ktoré to podporujú H/&W Meter H/&W meradlo Ignore hardware period/buffer size Ignorovať hardvérovú periódu/veľkosť vyrovnávacej pamäte &Ignore H/W &Ignorovať h/w Whether to give verbose output on messages Používať podrobný výstup v hláseniach &Verbose messages &Podrobné hlásenia &Output Device: &Výstupné zariadenie: &Interface: &Rozhranie: Maximum input audio hardware channels to allocate Maximálny počet prideliteľných vstupných zvukových kanálov hardvéru &Audio: &Zvuk: Dit&her: Vloženie šumu do signálu (dit&hering): External output latency (frames) Externé výstupné oneskorenie (latencia) v snímkoch &Input Device: Vstupné zar&iadenie: Provide either audio capture, playback or both Poskytnúť buď zaznamenávanie zvuku, prehrávanie alebo obe Duplex Obojsmerný (duplex) Capture Only Iba zaznamenávanie Playback Only Iba prehrávanie The PCM device name to use Názov zariadenia PCM, ktoré sa má použiť hw:0 hw:0 plughw:0 plughw:0 /dev/audio /dev/audio /dev/dsp /dev/dsp > > Alternate input device for capture Záložné vstupné zariadenie pre zaznamenávanie Maximum output audio hardware channels to allocate Maximálny počet prideliteľných výstupných zvukových kanálov hardvéru Alternate output device for playback Záložné výstupné zariadenie pre prehrávanie External input latency (frames) Externé vstupné oneskorenie (latencia) v snímkoch Set dither mode Nastaviť režim vloženia šumu do signálu (dithering) None Žiadny Rectangular Obdĺžnikový Shaped Obalová krivka Triangular Trojuholníkový Number of periods in the hardware buffer Počet periód vo vyrovnávacej pamäti hardvéru Priorit&y: &Priorita: &Frames/Period: &Snímky/Perióda: Frames per period between process() calls Snímkov za periódu medzi volaniami process() 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Port Ma&ximum: &Maximálny počet prípojok: &Channels: &Kanály: 21333 21333 Sample rate in frames per second Vzorkovacia frekvencia v snímkoch za sekundu 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 192000 192000 Scheduler priority when running realtime Priorita schedulera pri behu v reálnom čase &Word Length: &Dĺžka slova: Periods/&Buffer: &Periódy/Vyrovnávacia pamäť: Word length Dĺžka slova Maximum number of ports the JACK server can manage Najväčší počet prípojok, ktoré môže JACK spravovať &Wait (usec): &Čakať (µs): Sample &Rate: Frekvencia &vzorkovania: Maximum number of audio channels to allocate Maximálny počet prideliteľných zvukových kanálov &Timeout (msec): &Prekročenie času (ms): Set client timeout limit in milliseconds Nastaviť hranicu pre prekročenie času pre klienta v milisekundách 200 200 500 500 1000 1000 2000 2000 5000 5000 &Channels I/O: &Kanály vstup/výstup: &Latency I/O: &Oneskorenie vstup/výstup: Server Suffi&x: Príp&ona servera: Start De&lay: Oneskorenie sp&ustenia: secs s 0 msecs 0 ms Advanced Pokročilé Options Možnosti Scripting Skriptovanie Whether to execute a custom shell script before starting up the JACK audio server. Spustiť vlastný shellový skript pred spustením zvukového servera JACK. Execute script on Start&up: Vykonať skript pri &spustení: Whether to execute a custom shell script after starting up the JACK audio server. Spustiť vlastný shellový skript po spustení zvukového servera JACK. Execute script after &Startup: Vykonať skript &po spustení: Whether to execute a custom shell script before shuting down the JACK audio server. Spustiť vlastný shellový skript pred zastavením zvukového servera JACK. Execute script on Shut&down: Vykonať skript pri &zastavení: Command line to be executed before starting up the JACK audio server Príkazový riadok, ktorý bude spustený pred štartom zvukového servera JACK Scripting argument meta-symbols Metasymboly pre argumenty skriptovania Browse for script to be executed before starting up the JACK audio server Vybrať skript, ktorý bude spustený pred štartom zvukového servera JACK ... ... Command line to be executed after starting up the JACK audio server Príkazový riadok, ktorý bude spustený po štarte zvukového servera JACK Browse for script to be executed after starting up the JACK audio server Vybrať skript, ktorý bude spustený po štarte zvukového servera JACK Browse for script to be executed before shutting down the JACK audio server Vybrať skript, ktorý bude spustený pred vypnutím zvukového servera JACK Command line to be executed before shutting down the JACK audio server Príkazový riadok, ktorý bude spustený pred vypnutím zvukového servera JACK Whether to execute a custom shell script after shuting down the JACK audio server. Spustiť vlastný shellový skript po zastavení zvukového servera JACK. Execute script after Shu&tdown: Spustiť skript po &zastavení: Browse for script to be executed after shutting down the JACK audio server Vybrať skript, ktorý bude spustený po zastavení zvukového servera JACK Command line to be executed after shutting down the JACK audio server Príkazový riadok, ktorý bude spustený po zastavení zvukového servera JACK Statistics Štatistiky Whether to capture standard output (stdout/stderr) into messages window Posielať štandardný výstup (stdout/stderr) do okna s hláseniami &Capture standard output &Zachytávať štandardný výstup &XRUN detection regex: Regulárny výraz pre detekciu &XRUN: Regular expression used to detect XRUNs on server output messages Regulárny výraz použitý pre detekciu XRUNov v hláseniach posielaných serverom xrun of at least ([0-9|\.]+) msecs xrun aspoň ([0-9|\.]+) ms Connections Spojenia Whether to enable JACK D-Bus interface Či povoliť rozhranie JACK D-Bus &Enable JACK D-Bus interface &Povoliť rozhranie D-Bus JACK Whether to replace Connections with Graph button on the main window V hlavnom okne nahradiť tlačidlo Spojenia tlačidlom Graf Replace Connections with &Graph button Nahradiť tlačidlo Spojenia tlačidlom &Graf 10 10 Patchbay definition file to be activated as connection persistence profile Nastaviť súbor s definíciou zapájacej dosky ako stály profil spojenia Browse for a patchbay definition file to be activated Vybrať súbor s definíciou zapájacej dosky, ktorý sa má aktivovať Whether to activate a patchbay definition for connection persistence profile. Aktivovať definíciu zapájacej dosky pre stály profil spojenia. Activate &Patchbay persistence: Aktivovať &stály profil so zapájacou doskou: Logging Zaznamenávanie Messages log file Súbor so záznamom správ Browse for the messages log file location Vybrať umiestnenie súboru so záznamom správ Whether to activate a messages logging to file. Aktivovať zapisovanie správ do súboru. Setup Nastavenia Whether to restrict client self-connections Obmedziť vlastné klientske spojenia Whether to use server synchronous mode Použiť synchrónny režim servera Clear settings of current preset name Clea&r &Use server synchronous mode &Použiť synchrónny režim servera Please do not touch these settings unless you know what you are doing. Nemeňte, prosím, tieto nastavenia, ak neviete, čo znamenajú. Server &Prefix: P&redpona servera: Cloc&k source: Zdroj &hodín: Clock source Zdroj hodín S&elf connect mode: Režim &vlastného spojenia: Extra driver options (command line suffix) Ďalšie možnosti ovládača (prípona príkazového riadka) Whether to reset all connections when a patchbay definition is activated. Nastaviť všetky spojenia na predvolené pri aktivovaní definície zapájacej dosky. &Reset all connections on patchbay activation &Nastaviť všetky spojenia na predvolené hodnoty pri aktivovaní zapájacej dosky Whether to issue a warning on active patchbay port disconnections. Vypísať varovanie pri odpojení aktívnych prípojok zapájacej dosky. &Warn on active patchbay disconnections &Upozorňovať pri odpojení aktívnych prípojok zapájacej dosky &Messages log file: &Súbor so záznamom správ: Display Zobrazenie Time Display Údaj o čase Transport &Time Code Transport &časového kódu Transport &BBT (bar:beat.ticks) Transport &BBT (takt:doba.tiknutia) Elapsed time since last &Reset Č&as od posledného obnovenia továrenských nastavení Elapsed time since last &XRUN Čas od posledného &XRUN Sample front panel normal display font Ukážka zobrazenia bežného písma na prednom paneli Sample big time display font Ukážka písma veľkého zobrazenia údaju o čase Big Time display: Veľké zobrazenie údaju o čase: Select font for front panel normal display Vybrať písmo pre bežné zobrazenie na prednom paneli &Font... &Písmo... Select font for big time display Vybrať písmo pre veľké zobrazenie údaju o čase Normal display: Bežné zobrazenie: Whether to enable blinking (flashing) of the server mode (RT) indicator Povoliť blikanie indikátora režimu servera (RT) Blin&k server mode indicator P&ovoliť blikanie indikátora režimu servera (RT) Custom Vlastné &Color palette theme: &Motív farebnej palety: Custom color palette theme Vlastný motív farebnej palety Wonton Soup DO NOT TRANSLATE KXStudio DO NOT TRANSLATE Manage custom color palette themes Spravovať vlastné motívy farebnej palety &Widget style theme: Motív štýlu &prvkov: Custom widget style theme Vlastný motív štýlu prvkov Messages Window Okno so správami Sample messages text font display Ukážka zobrazenia písma textu správ Select font for the messages text display Vybrať písmo pre zobrazenie textu správ Whether to keep a maximum number of lines in the messages window Nastaviť maximálny počet riadkov zobrazených v okne so správami &Messages limit: &Limit správ: The maximum number of message lines to keep in view Maximálny počet riadkov, ktoré sa zobrazia v okne správ 100 100 250 250 2500 2500 Connections Window Prehľad spojení Sample connections view font Ukážka písma v prehľade spojení Select font for the connections view Vybrať písmo pre prehľad spojení &Icon size: &Veľkosť ikon: The icon size for each item of the connections view Veľkosť jednotlivých symbolov v prehľade spojení 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 Whether to enable in-place client/port name editing (rename) Povoliť editovanie mena klienta/prípojky na mieste (premenovanie) Ena&ble client/port aliases editing (rename) Po&voliť editovanie mena klienta/prípojky na mieste (premenovanie) Whether to enable client/port name aliases on the connections window Povoliť prezývky klienta/prípojky v okne s prehľadom spojení E&nable client/port aliases &Povoliť prezývky klienta/prípojky Server path (command line prefix) Cesta k serveru (predpona príkazového riadka) Misc Rôzne Other Ďalšie Whether to start JACK audio server immediately on application startup Spustiť zvukový server JACK ihneď po spustení aplikácie &Start JACK audio server on application startup &Spustiť zvukový server JACK ihneď po spustení aplikácie Whether to ask for confirmation on application exit Žiadať o potvrdenie pri ukončení aplikácie JACK client/port pretty-name (metadata) display mode Režim zobrazenia pekných názvov (metadát) klientov/prípojok JACK Enable JA&CK client/port pretty-names (metadata) Povoliť pekné názvy (metadáta) pre klientov/prípojky JA&CK &Confirm application close &Potvrdiť ukončenie aplikácie Whether to ask for confirmation on JACK audio server shutdown and/or restart Žiadať o potvrdenie pri vypínaní servera JACK a/alebo jeho reštarte Confirm server sh&utdown and/or restart Potvrdzovať &vypnutie servera a/alebo jeho reštartovanie Whether to keep all child windows on top of the main window Všetky ostatné okná zobrazovať nad hlavným oknom &Keep child windows always on top &Všetky ostatné okná zobrazovať vždy nad Whether to enable the system tray icon Zobrazovať ikonu v systémovej lište &Enable system tray icon Po&voliť ikonu v systémovej lište Whether to start minimized to system tray Spustiť program minimalizovaný do ikony na systémovej lište Start minimi&zed to system tray Spustiť program &minimalizovaný do ikony na systémovej lište Whether to save the JACK server command-line configuration into a local file (auto-start) Nastavenie príkazového riadka na spustenie servera JACK uložiť do lokálneho súboru (auto-start) S&ave JACK audio server configuration to: &Uložiť konfiguráciu zvukového servera JACK do: The server configuration local file name (auto-start) Názov lokálneho súboru s nastavením servera (auto-start) .jackdrc .jackdrc Whether to enable ALSA Sequencer (MIDI) support on startup Povoliť podporu (MIDI) pre radič (sekvencer) ALSA pri spustení E&nable ALSA Sequencer support P&ovoliť podporu (MIDI) pre radič (sekvencer) ALSA Buttons Tlačidlá Whether to hide the left button group on the main window Skryť skupinu s tlačidlami naľavo v hlavnom okne Hide main window &Left buttons Skryť ľ&avé tlačidlá v hlavnom okne Whether to hide the right button group on the main window Skyť skupinu s tlačidlami napravo v hlavnom okne Hide main window &Right buttons Skryť &pravé tlačidlá v hlavnom okne Whether to hide the transport button group on the main window Skryť skupinu s tlačidlami pre transport v hlavnom okne Hide main window &Transport buttons Skryť tlačidlá t&ransportu v hlavnom okne Whether to hide the text labels on the main window buttons Skryť textové popisy tlačidiel v hlavnom okne Hide main window &button text labels Skryť textové popisy &tlačidiel v hlavnom okne System Systém Cycle Cyklus HPET HPET Don't restrict self connect requests (default) Neobmedzovať požiadavky na vlastné spojenia (predvolené) Fail self connect requests to external ports only Prerušiť požiadavky na vlastné spojenia iba pre externé prípojky Ignore self connect requests to external ports only Ignorovať požiadavky na vlastné spojenia iba pre externé prípojky Fail all self connect requests Prerušiť všetky požiadavky na vlastné spojenia Ignore all self connect requests Ignorovať všetky požiadavky na vlastné spojenia Warning Upozornenie Some settings have been changed: "%1" Do you want to save the changes? Niektoré nastavenia boli zmenené: "%1" Chcete uložiť zmeny? Delete preset: "%1" Are you sure? Odstrániť prednastavenie: "%1" Ste si istý? msec ms n/a n/a &Preset Name Názov prednastaveni&a &Server Name &Názov servera &Server Path &Cesta k serveru &Driver &Ovládač &Interface &Rozhranie Sample &Rate Vzorkovacia &frekvencia &Frames/Period &Snímky/Perióda Periods/&Buffer Periódy/&Vyrovnávacia pamäť Startup Script Skript pre spustenie Post-Startup Script Skript po spustení Shutdown Script Skript pre vypnutie Post-Shutdown Script Skript po vypnutí Active Patchbay Definition Definícia aktívnej zapájacej dosky Patchbay Definition files Súbory s definíciou zapájacej dosky Messages Log Záznam správ Log files Súbory so zápismi Information Informácie Some settings may be only effective next time you start this application. Niektoré nastavenia sa prejavia až po ďalšom spustení tohto programu. Some settings have been changed. Do you want to apply the changes? Niektoré nastavenia boli zmenené. Chcete použiť zmeny? &JACK client/port aliases: &Prezývky pre klientov/prípojky JACK: JACK client/port aliases display mode Režim zobrazení prezývok klientov/prípojok JACK Default Predvolené First Prvý Second Druhý Whether to show system tray message on main window close Pri zatvorení hlavného okna zobraziť správu v systémovej lište Sho&w system tray message on close &Zobraziť správu v systémovej lište pri zatvorení Whether to stop JACK audio server on application exit Zastaviť zvukový server JACK pri ukončení aplikácie S&top JACK audio server on application exit &Zastaviť zvukový server JACK pri ukončení aplikácie Defaults Predvolené &Base font size: &Základná veľkosť písma: Base application font size (pt.) Základná veľkosť písma v aplikácii (pt.) 6 6 7 7 8 8 9 9 11 11 12 12 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 &Name: &Názov: The JACK Audio Connection Kit sound server name Názov zvukového servera JACK Audio Connection Kit netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Number of microseconds to wait between engine processes (dummy) Počet mikrosekúnd medzi procesmi ovládača (dummy) Whether to enable D-Bus interface Či povoliť rozhranie D-Bus &Enable D-Bus interface &Povoliť rozhranie D-Bus Whether to restrict to one single application instance (X11) Či obmedziť beh iba na jednu inštanciu programu (X11) Single application &instance &Iba jedna inštancia qjackctlSocketForm Socket Zásuvka &Socket &Zásuvka &Name (alias): &Názov (Prezývka): Socket name (an alias for client name) Názov zásuvky (prezývka pre názov klienta) Client name (regular expression) Názov pre klienta (regulárny výraz) Add plug to socket plug list Pridať zástrčku do zoznamu do zástrčkami do zásuvky Add P&lug &Pridať zástrčku &Plug: &Zástrčka: Port name (regular expression) Názov prípojky (regulárny výraz) Socket plug list Zoznam so zástrčkami do zásuvky Socket Plugs / Ports Zástrčky do zásuvky/Prípojky Edit currently selected plug Upraviť aktuálne zvolenú zástrčku &Edit &Upraviť Remove currently selected plug from socket plug list Odstrániť aktuálne zvolenú zástrčku zo zoznamu &Remove &Odstrániť &Client: &Klient: Move down currently selected plug in socket plug list Posunúť aktuálne zvolenú zástrčku v zozname nižšie &Down &Nižšie Move up current selected plug in socket plug list Posunúť aktuálne zvolenú zástrčku v zozname vyššie &Up &Vyššie Enforce only one exclusive cable connection Vynútiť jedno výlučné káblové spojenie E&xclusive Vý&lučné &Forward: &Klonovať: Forward (clone) all connections from this socket Klonovať všetky spojenia z tejto zásuvky Type Typ Audio socket type (JACK) Zvukový typ zásuvky JACK &Audio &Zvuk MIDI socket type (JACK) MIDI typ zásuvky (JACK) &MIDI &JACK-MIDI MIDI socket type (ALSA) MIDI typ zásuvky (ALSA) AL&SA AL&SA Plugs / Ports Zástrčky/Prípojky Error Chyba A socket named "%1" already exists. Zásuvka s názvom "%1" už existuje. Warning Upozornenie Some settings have been changed. Do you want to apply the changes? Niektoré nastavenia boli zmenené. Chcete použiť zmeny? Add Plug Pridať zástrčku Edit Upraviť Remove Odstrániť Move Up Presunúť vyššie Move Down Presunúť nižšie (None) (Žiadny) qjackctlSocketList Output Výstup Input Vstup Socket Zásuvka <New> - %1 <Nový> %1 Warning Upozornenie %1 about to be removed: "%2" Are you sure? %1 má byť odstránené: "%2" Ste si istý? %1 <Copy> - %2 %1 <Kópia> - %2 qjackctlSocketListView Output Sockets / Plugs Výstupné zásuvky/zástrčky Input Sockets / Plugs Vstupné zásuvky/zástrčky qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_it.ts0000644000000000000000000000013214771215054020544 xustar0030 mtime=1743067692.333636546 30 atime=1743067692.333636546 30 ctime=1743067692.333636546 qjackctl-1.0.4/src/translations/qjackctl_it.ts0000644000175000001440000063633614771215054020555 0ustar00rncbcusers PortAudioProber Probing... Rilevamento... Please wait, PortAudio is probing audio hardware. Aspetta per favore, PortAudio sta rilevando l'hardware audio. Warning Attenzione Audio hardware probing timed out. Rilevazione hardware audio fallita. QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Start JACK audio server immediately. Set default settings preset name. Set active patchbay definition file. Set default JACK audio server name. Show help about command line options. Show version information. Launch command with arguments. [command-and-args] Option -p requires an argument (preset). L'opzione -p richiede un argomento (preset). Usage: %1 [options] [command-and-args] Uso: %1 [opzioni] [comandi-e-argomenti] Options: Opzioni: Option -a requires an argument (path). L'opzione -a richiede un argomento (indirizzo). Option -n requires an argument (name). L'opzione -n richiede un argomento (nome). %1 (%2 frames) %1 (%2 fotogrammi) Move Rename qjackctlAboutForm About Info About Qt Info su QT &Close &Chiudi Version Versione Debugging option enabled. Opzione di debugging abilitata. System tray disabled. Area di notifica disabilitata. Transport status control disabled. Controllo dello stato del transport disabilitato. Realtime status disabled. Stato Realtime disabilitato. XRUN delay status disabled. Stato del ritardo degli XRUN disabilitato. Maximum delay status disabled. Stato del massimo ritardo disabilitato. ALSA/MIDI sequencer support disabled. Supporto del sequencer ALSA/MIDI disabilitato. Using: Qt %1 JACK %1 Website Sito Web This program is free software; you can redistribute it and/or modify it Questo programma è free software; è possibile ridistribuirlo e/o modificarlo under the terms of the GNU General Public License version 2 or later. nei termini della Licenza Pubblica Generale GNU versione 2 o superiore. JACK MIDI support disabled. Supporto del MIDI di Jack disabilitato. JACK Port aliases support disabled. Supporto per gli alias delle porte di Jack disabilitato. D-Bus interface support disabled. Supporto per l'interfaccia D-Bus disabilitato. JACK Session support disabled. supporto per le Sessioni di JACK disabilitato. qjackctlClientListView &Connect &Connetti &Disconnect &Disconnetti Disconnect &All Disconnetti &Tutto Re&name Ri&nomina &Refresh &Aggiorna Readable Clients / Output Ports Clients leggibili / Porte d'uscita Writable Clients / Input Ports Clients Scrivibili / Porte d'entrata Alt+C Connect Connetti Alt+C Alt+D Disconnect Disconnetti Alt+D Alt+A Disconnect All Disconnetti Tutto Alt+A Alt+N Rename Rinomina Alt+N Alt+R Refresh Aggiorna Alt+R qjackctlConnect Warning Attenzione This will suspend sound processing from all client applications. Are you sure? Quest'azione sospenderà l'elaborazione del suono da tutte le applicazioni clients. Sei sicuro? qjackctlConnectionsForm Audio Audio &Connect &Connetti Connect currently selected ports Connetti le porte selezionate &Disconnect &Disconnetti Disconnect currently selected ports Disconnetti le porte selezionate Disconnect &All Disconnetti &Tutto Disconnect all currently connected ports Disconnetti tutte le porte connesse &Refresh &Aggiorna Refresh current connections view Aggiorna la situazione delle connessioni Connections Connessioni MIDI MIDI ALSA ALSA Expand all client ports Espandi tutte le porte dei clients E&xpand All E&spandi tutto qjackctlConnectorView &Connect &Connetti Disconnect &All Disconnetti &Tutto &Refresh &Aggiorna Alt+C Connect Connetti Alt+C &Disconnect &Disconnetti Alt+D Disconnect Disconnetti Alt+D Alt+A Disconnect All Disconnetti Tutto Alt+A Alt+R Refresh Aggiorna Alt+R qjackctlGraphCanvas Connect Connetti Disconnect Disconnetti qjackctlGraphForm Graph &Graph Grafico &Edit &Modifica &View &Visualizza &Zoom &Zoom Co&lors S&ort &Help &Aiuto &Connect &Connetti Connect Connetti Connect selected ports Connetti le porte selezionate &Disconnect &Disconnetti Disconnect Disconnetti Disconnect selected ports Disconnetti le porte selezionate Ctrl+C T&humbview Ctrl+D Cl&ose Close Close this application window Select &All Seleziona &tutto Select All Seleziona tutto Ctrl+A Ctrl+A Select &None Non selezionare &nulla Select None Non selezionare nulla Ctrl+Shift+A Ctrl+Shift+A Select &Invert Selezione &inversa Select Invert Selezione inversa Ctrl+I Ctrl+I &Rename... Rename item Rename Item F2 F2 &Find... Find Find nodes Ctrl+F &Menubar Barra del &menu Menubar Barra del menu Show/hide the main program window menubar Mostra/nascondi la barra del menu della finestra principale del programma Ctrl+M Ctrl+M &Toolbar Barra degli s&trumenti Toolbar Barra degli strumenti Show/hide main program window file toolbar Mostra/nascondi la barra degli strumenti della finestra principale del programma &Statusbar Barra di &stato Statusbar Barra di stato Show/hide the main program window statusbar Mostra/nascondi la barra di stato della finestra principale del programma &Top Left Top left Show the thumbnail overview on the top-left Top &Right Top right Show the thumbnail overview on the top-right Bottom &Left Bottom Left Bottom left Show the thumbnail overview on the bottom-left &Bottom Right Bottom right Show the thumbnail overview on the bottom-right &None None Nessuno Hide thumbview Hide the thumbnail overview Text Beside &Icons Testo dietro le &icone Text beside icons Testo dietro le icone Show/hide text beside icons Mostra/nasconi testo dietro le icone &Center &Centro Center Centro Center view Visualizzazione centrata &Refresh &Aggiorna Refresh Aggiorna Refresh view Aggiorna la visualizzazione F5 F5 Zoom &In &Ingrandisci Zoom In Ingrandisci Ctrl++ Ctrl++ Zoom &Out Rim&picciolisci Zoom Out Rimpicciolisci Ctrl+- Ctrl+- Zoom &Fit &Adatta zoom Zoom Fit Adatta zoom Ctrl+0 Ctrl+0 Zoom &Reset &Ripristina zoom Zoom Reset Ripristina zoom Ctrl+1 Ctrl+1 &Zoom Range Zoom Range JACK &Audio... JACK Audio color JACK &MIDI... JACK MIDI JACK MIDI color ALSA M&IDI... ALSA MIDI ALSA MIDI color JACK &CV... JACK CV color JACK &OSC... JACK OSC JACK OSC color &Reset &Reset Reset colors Port &Name Port name Sort by port name Port &Title Port title Sort by port title Port &Index Port index Sort by port index &Ascending Ascending Ascending sort order &Descending Descending Descending sort order Repel O&verlapping Nodes Repel nodes Repel overlapping nodes Connect Thro&ugh Nodes Connect Through Nodes Connect through nodes Whether to draw connectors through or around nodes &About... &Info... About... Info... About Info Show information about this application program Mostra informazioni a proposito di questo programma applicativo About &Qt... Info su &Qt... About Qt... Info su Qt... About Qt Info su Qt Show information about the Qt toolkit Mostra informazioni a proposito del kit di strumenti Qt &Undo &Annulla &Redo &Ripeti Undo last edit action Redo last edit action Zoom Ready Pronto Colors - %1 qjackctlMainForm &Quit &Esci Quit processing and exit Termina il processo sonoro ed esci &Start &Avvia Start the JACK server Avvia il server JACK S&top &Ferma Stop the JACK server Ferma il server JACK St&atus &Stato Ab&out... Inf&o su... Show information about this application Mostra le info riguardo questo software Show settings and options dialog Mostra la finestra delle impostazioni/opzioni &Messages &Messaggi Patch&bay Patch&bay Show/hide the patchbay editor window Mostra/nascondi la finestra del patchbay &Connect &Connetti JACK server state Stato del server JACK JACK server mode Modalità del server JACK Sample rate Frequenza di Campionamento Time display Visuale del Tempo Transport state Stato del transport Transport BPM BPM del transport Transport time Tempo del transport Show/hide the graph window Show/hide the connections window Backward transport Retrocedi transport Forward transport Avanza transport Rewind transport Riavvolgi transport Stop transport rolling Ferma il transport Start transport rolling Fai partire il transport Warning Attenzione successfully con successo with exit status=%1 con stato di uscita %1 Could not load preset "%1". Retrying with default. Non sono riuscito a caricare il preset "%1". Provo con il predefinito. Could not load default preset. Sorry. Non riesco a caricare il preset predefinito. Mi dispiace. Startup script... Script di inizio... Startup script terminated Script di inizio terminato JACK is starting... JACK sta partendo... Could not start JACK. Sorry. Non riesco ad avviare JACK. Mi dispiace. JACK is stopping... JACK si sta arrestando... The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. Il programma continuerà a lavorare nel vassoio di sistema (system tray). Per terminarlo, clicca su "Esci" nel menù del tasto destro sull icona nel vassoio. Shutdown script... Script d'arresto... Shutdown script terminated Script d'arresto terminato JACK was stopped JACK è stato fermato Post-shutdown script... Script di post - arresto... D-BUS: Service is available (%1 aka jackdbus). D-BUS: Servizio disponibile (%1 aka jackdbus). D-BUS: Service not available (%1 aka jackdbus). D-BUS: Servizio non disponibile (%1 aka jackdbus). Don't show this message again Non mostrare più questo messaggio Don't ask this again Non chiederlo di nuovo D-BUS: JACK server is starting... D-BUS: JACK si sta avviando... D-BUS: JACK server could not be started. Sorry D-BUS: il server JACK non può essere avviato. Mi dispiace D-BUS: JACK server is stopping... D-BUS: JACK si sta arrestando... D-BUS: JACK server could not be stopped. Sorry D-BUS: il server JACK non può essere arrestato. Mi dispiace Post-shutdown script terminated Script di post - arresto terminato D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: JACK è stato avviato (%1 aka jackdbus). The preset aliases have been changed: "%1" Do you want to save the changes? Gli alias delle porte sono cambiati: "%1" Salvare i cambiamenti? D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: JACK è stato fermato (%1 aka jackdbus). Error Errore Transport time code Codice temporale del transport Elapsed time since last reset Tempo trascorso dall'ultimo reset Elapsed time since last XRUN Tempo trascorso dall'ultimo XRUN Patchbay activated. Patchbay attivato. Patchbay deactivated. Patchbay disattivato. Statistics reset. Resetta le statistiche. msec msec XRUN callback (%1). XRUN callback (%1). Buffer size change (%1). Cambio della dimensione del buffer (%1). Shutdown notification. Notifica dell'arresto. Freewheel started... Freewheel exited. JACK property change. Cambio di una proprietà di JACK. checked verificato connected connesso disconnected disconnesso failed fallito Server configuration saved to "%1". Configurazione del server salvata in "%1". Client activated. Client attivato. Post-startup script... Script post - avvio... Post-startup script terminated Script di post - avvio terminato Command line argument... Argomento della linea di comando... Command line argument started Argomento della linea di comando eseguita Client deactivated. Client disattivato. Transport rewind. Riavvorgere il transport. Transport backward. Retrocedere il transport. Starting Avvio Transport start. Transport partito. Stopping Arresto Transport stop. Transport arrestato. Transport forward. Avanzare il transport. Stopped Arrestato Yes Si No No FW RT RT Rolling Riproduzione Looping Looping XRUN callback (%1 skipped). XRUN callback (%1 omitidos). Started Avviato Active Attivo Activating Attivazione Inactive Inattivo &Hide &Nascondi D-BUS: GetParameterConstraint('%1'): %2. (%3) Mi&nimize Mi&nimizza S&how &Mostra Rest&ore &Ristabilisci &Stop &Ferma &Reset &Reset &Connections &Connessioni Server settings will be only effective after restarting the JACK audio server. I cambiamenti diventeranno effettivi solo al riavvio di JACK. Do you want to restart the JACK audio server? D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) Information Informazioni Some settings will be only effective the next time you start this program. Alcune modifiche saranno effettive solo al prossimo avvio dell'applicazione. Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. Non riesco ad aprire il sequencer ALSA come client. Il Patchbay MIDI non sarà disponibile. JACK is currently running. Do you want to terminate the JACK audio server? JACK è attualmente attivato. Vuoi arrestare il server JACK? Could not start JACK. Maybe JACK audio server is already started. Non riesco ad avviare JACK. Forse il server JACK è già avviato. Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Alcune applicazioni audio sono ancora attive e connesse. Vuoi arrestare il server JACK? %1 is about to terminate. Are you sure? JACK was started with PID=%1. JACK è stato avviato con PID=%1. JACK is being forced... JACK viene forzato... Patchbay reset. Ripristino della patchbay. JACK connection graph change. Grafico delle connessioni di JACK modificato. JACK has crashed. JACK ha crashato. JACK timed out. Tempo d'attesa per JACK terminato. JACK write error. Errore di scrittura di JACK. JACK read error. Errore di lettura di JACK. Unknown JACK error (%d). Errore di JACK sconosciuto (%d). ALSA connection graph change. Cambiamento nel grafico delle connessioni di ALSA. JACK active patchbay scan Scansione del patchbay per JACK activo ALSA active patchbay scan Scansione del patchbay per ALSA attivo JACK connection change. Connessioni di JACK cambiate. ALSA connection change. Connessioni di ALSA cambiate. A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? Una connessione è definita nel Patchbay, che probabilmente ripeterà la connessione: %1 -> %2 Vuoi rimuovere questa connessione dal Patchbay? Overall operation failed. Operazione fallita. Invalid or unsupported option. Opzione non valida o non supportata. Client name not unique. Il nome del client non è unico. Server is started. Il server JACK è stato avviato. Unable to connect to server. Impossibile connettersi al server JACK. Server communication error. Errore di comunicazione col server JACK. Client does not exist. Il client non esiste. Unable to load internal client. Impossibile caricare il client interno. Unable to initialize client. Impossibile inizializzare il client. Unable to access shared memory. Impossibile accedere alla memoria condivisa. Client protocol version mismatch. La versione del protocollo del client è incongruente. Could not connect to JACK server as client. - %1 Please check the messages window for more info. Non sono riuscito ad avviare JACK come client. - %1 Controlla la finestra dei messaggi per maggiori informazioni. %1 (%2%) %1 (%2%) %1 % %1 % %1 Hz %1 Hz %1 frames %1 fotogrammi %1 msec %1 msec &Presets &Presets &Graph &Grafico &Transport &Transport &Rewind &Riavvolgi &Play Ri&produci Pa&use Pa&usa &Patchbay &Patchbay DSP Load Carico DSP XRUN Count (notifications) Conteggio XRUN (notifiche) &Backward R&etrocedi &Forward &Avanza Set&up... Imp&ostazioni... S&ession S&essioni &Load... &Apri... &Save... &Salva... Save and &Quit... Salva ed E&sci... Save &Template... Salva &Modello... Show/hide the session management window Mostra/Nascondi la finestra di gestione delle sessioni Show/hide the messages log/status window Mostra/Nascondi la finestra di stato/log Could not load active patchbay definition. "%1" Disabled. Non riesco a caricare il file del patchbay attivo. "%1" Disabilitato. &Versioning &Versione Re&fresh Agg&iorna %1 (%2%, %3 xruns) %1 (%2%, %3 xruns) Transport BBT (bar.beat.ticks) BBT del Transport (battito:pulsazione:frazioni) qjackctlMessagesStatusForm Messages / Status &Messages &Messaggi Messages log Log dei messaggi Messages output log Log dei messaggi di output &Status &Stato Status information Informazioni sullo Stato Statistics since last server startup Statistiche dall'ultimo avvio del server Description Descrizione Value Valore Reset XRUN statistic values Reimposta le statistiche degli XRUN Re&set Reimpo&sta Refresh XRUN statistic values Aggiorna le statistiche degli XRUN &Refresh &Refresh Server name Nome del server Server state Stato del server DSP Load Carico DSP Sample Rate Frequenza di campionamento Buffer Size Dimensione del buffer Realtime Mode Modo Realtime Transport state Stato del transport Transport Timecode Codice temporale del transport Transport BBT BBT del transport Transport BPM BPM del transport XRUN count since last server startup Conteggio degli XRUN dall'ultimo avvio del server XRUN last time detected Momento dell'ultimo XRUN XRUN last Ultimo XRUN XRUN maximum XRUN massimi XRUN minimum XRUN minimi XRUN average XRUN medi XRUN total XRUN totali Maximum scheduling delay Massimo ritardo nello scheduling Time of last reset Tempo dell'ultimo reset Logging stopped --- %1 --- Logging fermato --- %1 --- Logging started --- %1 --- Logging avviato --- %1 --- qjackctlPaletteForm Color Themes Name Current color palette name Save current color palette name Save Delete current color palette name Delete Palette Current color palette Generate: Base color to generate palette Reset all current palette colors Reset Import a custom color theme (palette) from file Import... Export a custom color theme (palette) to file Export... Show Details Import File - %1 Palette files (*.%1) Save Palette - %1 All files (*.*) Warning - %1 Could not import from file: %1 Sorry. Export File - %1 Some settings have been changed. Do you want to discard the changes? Some settings have been changed: "%1". Do you want to save the changes? qjackctlPaletteForm::PaletteModel Color Role Active Attivo Inactive Inattivo Disabled qjackctlPatchbay Warning Attenzione This will disconnect all sockets. Are you sure? Questo disconnetterà tutte le porte. Sei sicuro? qjackctlPatchbayForm &New &Nuovo Create a new patchbay profile Crea un nuovo profilo Patchbay &Load... &Apri... Load patchbay profile Carica il profilo del Patchbay &Save... &Salva... Save current patchbay profile Salva il profilo corrente del Patchbay Acti&vate Atti&va Toggle activation of current patchbay profile Modifica lo stato di attivazione del Patchbay corrente &Connect &Connetti Connect currently selected sockets Connetti le porte selezionate &Disconnect &Disconnetti Disconnect currently selected sockets Disconnetti le porte selezionate Disconnect &All Disconnetti &Tutto Disconnect all currently connected sockets Disconnetti tutte le porte connesse &Refresh &Aggiorna Refresh current patchbay view Aggiorna la vista del Patchbay Down Giù Move currently selected output socket down one position Muovi la porta selezionata in basso Add... Aggiungi... Create a new output socket Crea una nuova porta d'uscita Edit... Modifica... Edit currently selected input socket properties Modifica la porta d'entrata selezionata Up Su Move currently selected output socket up one position Muovi la porta selezionata in alto Remove Rimuovi Remove currently selected output socket Rimuovi la porta d'uscita selezionata Copy... Copia... Duplicate (copy) currently selected output socket Duplica (copia) la porta d'uscita selezionata Patchbay Remove currently selected input socket Rimuovi la porta d'entrata selezionata Duplicate (copy) currently selected input socket Duplica (copia) la porta d'entrata selezionata Create a new input socket Crea una nuova porta d'entrata Edit currently selected output socket properties Modifica la porta d'uscita selezionata Warning Attenzione active attivo New Patchbay definition Nuova definizione del Patchbay Patchbay Definition files Files di definizione del Patchbay Load Patchbay Definition Carica definizione del Patchbay Save Patchbay Definition Salva definizione del Patchbay The patchbay definition has been changed: "%1" Do you want to save the changes? Le definizioni del Patchbay sono cambiate: "%1" Vuoi salvare le modifiche? %1 [modified] %1 [modificato] Untitled%1 Senza titolo%1 Error Errore Could not load patchbay definition file: "%1" Non riesco a caricare il file di definizioni del Patchbay: "%1" Could not save patchbay definition file: "%1" Non riesco a salvare il file di definizioni del Patchbay: "%1" Create patchbay definition as a snapshot of all actual client connections? Creo un Patchbay partendo dalle connessioni attuali? Current (recent) patchbay profile(s) Profilo (recente) del Patchbay Expand all items Espandi tutti gli elementi E&xpand All E&spandi tutto qjackctlPatchbayView Add... Aggiungi... Edit... Modifica... Copy... Copia... Remove Rimuovi Exclusive Esclusiva Move Up Porta su Move Down Porta giù &Connect &Connetti &Disconnect &Disconnetti Disconnect &All Desconnetti &Tutto &Refresh &Aggiorna Alt+R Refresh Alt+A Forward Avanza (None) (Nessuno) Alt+C Connect Connetti Alt+C Alt+D Disconnect Disconnetti Alt+D Alt+A Disconnect All Disconnetti Tutto Alt+A qjackctlSessionForm Load session Carica Sessione &Load... &Apri... Recent session Sessione recente &Recent &Recente Save session Salva sessione &Save... &Salva... Client / Ports Client / Porte UUID UUID Command Comando Load Session Carica Sessione Session directory Cartella della Sessione Save Session Salva Sessione and Quit ed Esci Template Modello &Clear Pulis&ci Warning Attenzione A session could not be found in this folder: "%1" non riesco a trovare una Sessione in questa cartella: "%1" %1: loading session... %1: carico la sessione... %1: load session %2. %1: carico la sessione %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? Una Sessione esiste già in questa cartella: "%1" Sovrascivo la Sessione? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Questa cartella esiste già e non è vuota: "%1" Sovrascrivo la cartella? %1: saving session... %1: salvo la sessione... %1: save session %2. %1: salvo la sessione %2. Update session Aggiorna sessione Save and &Quit... Salva ed Es&ci... Save &Template... Salva &Modello... Session &Save &Salva &Versioning &Versione Re&fresh Agg&iorna Session clients / connections Clients / connessioni della sessione Infra-clients / commands Comandi / infra-clients Infra-client Infra-client Infra-command Infra-comando Add infra-client Aggiungi un infra-client &Add &Aggiungi Edit infra-client Modifica un infra-client &Edit &Modifica Remove infra-client Rimuovi un infra-client Re&move &Rimuovi New Client Nuovo client qjackctlSessionInfraClientItemEditor Infra-command Infra-comando qjackctlSessionSaveForm Session &Name: &Nome: Session name &Directory: Session directory Cartella della Sessione Browse for session directory ... ... Save session versioning Salva la versione della sessione &Versioning &Versione Warning Attenzione Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings Impostazioni Preset &Name: &Nome del Preset: (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Settings preset name Nome del preset &Save &Salva Save settings as current preset name Salva le impostazioni sul preset corrente &Delete &Elimina Delete current settings preset Elimina il preset con le impostazioni correnti jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE Driv&er: Dri&ver: dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters Parametri Number of periods in the hardware buffer Numero di periodi nel buffer hardware Priorit&y: &Priorità: &Frames/Period: &Fotogrammi/Periodo: 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Frames per period between process() calls Fotogrammi per periodo tra chiamate a process() Port Ma&ximum: Numero mas&simo di porte: 21333 21333 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 Sample rate in frames per second Frequenza di campionamento in fotogrammi al secondo Scheduler priority when running realtime Priorità dello scheduler quando eseguito in realtime &Word Length: &Lunghezza delle parole: Periods/&Buffer: Periodi/&Buffer: Word length Lunghezza delle parole Maximum number of ports the JACK server can manage Numero massimo di porte che JACK può gestire &Wait (usec): &Attesa massima (microsec): Sample &Rate: &Campionamento: &Timeout (msec): &Attesa massima (msec): 200 200 500 500 1000 1000 2000 2000 5000 5000 Set client timeout limit in milliseconds Imposta il limite di tempo di attesa per il client, in msec &Realtime Tempo &Reale Use realtime scheduling Usa priorità dello scheduling in tempo reale No Memory Loc&k Non b&loccare memoria Do not attempt to lock memory, even if in realtime mode Non bloccare la memoria, anche in tempo reale &Unlock Memory &Sblocca Memoria Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) Sblocca la memoria per i toolkit classici (GTK+, QT, FLTK, Wine) So&ft Mode Modo So&ft Ignore xruns reported by the backend driver Ignora gli XRUN provenienti dal driver &Monitor &Monitor Provide output monitor ports Attiva porte d'uscita per il monitor Force &16bit Forza &16bit Force 16bit mode instead of failing over 32bit (default) Forza il modo 16bit invece del predefinito 32bit H/&W Meter Meter Hard&ware Enable hardware metering on cards that support it Abilita il metering per le schede che lo supportano &Ignore H/W &Ignora HardWare Ignore hardware period/buffer size Ignora la dimensione periodo/buffer dell'hardware &Output Device: Dispositiv&o d'uscita: &Interface: &Interfaccia: Maximum input audio hardware channels to allocate Numero massimo di canali hardware d'entrata &Audio: A&udio: Dit&her: Dit&her: External output latency (frames) Latenza esterna d'uscita (fotogrammi) &Input Device: D&ispositivo d'entrata: Duplex Duplex Capture Only Solo Cattura Playback Only Solo Riproduzione Provide either audio capture, playback or both Scegli se abilitare l'audio in cattura, in registrazione o entrambi hw:0 hw:0 The PCM device name to use Nome del dispositivo PCM da usare > > /dev/dsp Alternate input device for capture Seleziona il dispositivo alternativo d'entrata per la registrazione Maximum output audio hardware channels to allocate Numero massimo di canali hardware d'uscita Alternate output device for playback Seleziona il dispositivo alternativo d'uscita per la riproduzione External input latency (frames) Latenza esterna d'entrata (fotogrammi) None Nessuno Rectangular Rettangolare Shaped Modellato Triangular Triangolare Set dither mode Scegli il modo del dither Whether to give verbose output on messages Verbosità nei messaggi d'uscita Time in seconds that client is delayed after server startup Tempo di ritardo nell'avvio del server JACK (in secondi) Latency: Latenza: Output latency in milliseconds, calculated based on the period, rate and buffer settings Latenza d'uscita in millisecondi, calcolata in base al rapporto fra periodo, fotogrammi e buffer Options Opzioni Scripting Scripting Execute script on Start&up: Esegui script prima dell'Avvi&o: Whether to execute a custom shell script before starting up the JACK audio server. Eseguire uno script prima dell'avvio del server JACK. Execute script after &Startup: Esegui script dopo l'Avv&io: Whether to execute a custom shell script after starting up the JACK audio server. Eseguire uno script dopo l'avvio del server JACK. Execute script on Shut&down: Esegui script prima dell'Ar&resto: Whether to execute a custom shell script before shuting down the JACK audio server. Eseguire uno script prima dell'arresto del server JACK. Command line to be executed before starting up the JACK audio server Comando da eseguire prima dell'avvio di JACK Scripting argument meta-symbols Meta simboli utilizzabili negli script ... ... Browse for script to be executed before starting up the JACK audio server Cerca uno script da eseguire prima dell'avvio del server JACK Command line to be executed after starting up the JACK audio server Comando da eseguire dopo l'avvio di JACK Browse for script to be executed after starting up the JACK audio server Cerca uno script da eseguire dopo l'avvio del server JACK Browse for script to be executed before shutting down the JACK audio server Cerca uno script da eseguire prima dell'arresto del server JACK Command line to be executed before shutting down the JACK audio server Comando da eseguire prima dell'arresto di JACK Execute script after Shu&tdown: Esegui script dopo l'Ar&resto: Whether to execute a custom shell script after shuting down the JACK audio server. Eseguire uno script dopo l'arresto di JACK. Browse for script to be executed after shutting down the JACK audio server Cerca uno script da eseguire dopo l'arresto del server JACK Command line to be executed after shutting down the JACK audio server Comando da eseguire dopo l'arresto di JACK Statistics Statistiche &Capture standard output &Cattura l'output standard dei comandi Whether to capture standard output (stdout/stderr) into messages window Catturare l'output standard nella finestra dei messaggi &XRUN detection regex: Espressione regolare per individuare gli &XRUN: xrun of at least ([0-9|\.]+) msecs XRUN di ([0-9|\.]+) msecs al massimo Regular expression used to detect XRUNs on server output messages Espressione regolare usata per il riconoscimento degli XRUN Connections Connessioni 10 10 Patchbay definition file to be activated as connection persistence profile Attiva il Patchbay in maniera persistente Browse for a patchbay definition file to be activated Sfoglia i file per caricare un Patchbay salvato Activate &Patchbay persistence: Attiva un &Patchbay persistente: Whether to activate a patchbay definition for connection persistence profile. Attiva un Patchbay predefinito per effettuare connessioni persistenti. Display Display Time Display Display del tempo Transport &Time Code Codice temporale del &Transport Transport &BBT (bar:beat.ticks) &BBT del Transport (battuta:pulsazione:frazioni) Elapsed time since last &Reset Tempo trascorso dall'ultimo &Reset Elapsed time since last &XRUN Tempo trascorso dall'ultimo &XRUN Sample front panel normal display font Carattere normale da mostrare nel display frontale Sample big time display font Carattere grande da mostrare nel display frontale Big Time display: Display grande del tempo: &Font... Cara&ttere... Select font for front panel normal display Tipo di carattere normale da mostrare nel display frontale Select font for big time display Tipo di carattere grande da mostrare nel display frontale Normal display: Display normale: Messages Window Finestra dei messaggi Sample messages text font display Tipo di carattere per la finestra dei messaggi Select font for the messages text display Seleziona il tipo di carattere per la finestra dei messaggi &Messages limit: Limite dei &Messaggi: Whether to keep a maximum number of lines in the messages window Se limitare ad un numero massimo di righe nella finestra dei messaggi 100 100 250 250 2500 2500 The maximum number of message lines to keep in view Il numero massimo di messaggi da mostrare a vista Please do not touch these settings unless you know what you are doing. Si prega di non toccare queste impostazioni se non sai cosa stai facendo. Connections Window Finestra delle Connessioni Sample connections view font Tipo di carattere per la finestra delle connessioni Select font for the connections view Seleziona il tipo di carattere per la finestra delle connessioni &Icon size: Dimensione delle &Icone: 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 The icon size for each item of the connections view Dimensione delle icone per gli elementi nella finestra delle connessioni Ena&ble client/port aliases editing (rename) A&bilita la modifica degli alias di clients/porte (rinomina) Whether to enable in-place client/port name editing (rename) Permetti la modifica veloce dei nomi dei clients/porte E&nable client/port aliases Abilita gli alias per &porte/clients Whether to enable client/port name aliases on the connections window Permetti gli alias per i nomi dei clients/porte Misc Varie Other Altro &Start JACK audio server on application startup Avvia il &server JACK all'avvio dell'applicazione Whether to start JACK audio server immediately on application startup Avvia immediatamente il server JACK all'avvio dell'applicazione &Confirm application close &Chiedi conferma alla chiusura Whether to ask for confirmation on application exit Chiedi conferma prima di chiudere l'applicazione &Keep child windows always on top Mantieni le finestre fi&glie sempre sopra le altre Whether to keep all child windows on top of the main window Scegli se mantenere le finestre figlie sempre sopra le altre &Enable system tray icon Abilita l'icona nel vassoio di sist&ema Whether to enable the system tray icon Scegli se visualizzare un'icona sul vassoio di sistema (system tray) S&ave JACK audio server configuration to: S&alva la configurazione di JACK in: Whether to save the JACK server command-line configuration into a local file (auto-start) Scegli se salvare la configurazione del server JACK in un file locale (all'avvio) .jackdrc .jackdrc The server configuration local file name (auto-start) Configurazione locale del server (all'avvio) Warning Attenzione msec msec n/a n/d &Preset Name Nome del &Preset &Server Path Indirizzo del &Server &Driver &Driver &Interface &Interfaccia Sample &Rate &Frequenza di campionamento &Frames/Period &Fotogrammi/Periodo Periods/&Buffer Periodi/&Buffer Patchbay Definition files Files di definizione del Patchbay Some settings have been changed: "%1" Do you want to save the changes? Alcune impostazioni sono cambiate: "%1" Vuoi salvarle? System Cycle HPET Don't restrict self connect requests (default) Fail self connect requests to external ports only Ignore self connect requests to external ports only Fail all self connect requests Ignore all self connect requests Delete preset: "%1" Are you sure? Cancello Preset: "%1" Sei sicuro? Startup Script Script all'avvio Post-Startup Script Script dopo l'avvio Shutdown Script Script all'arresto Post-Shutdown Script Script dopo l'arresto Active Patchbay Definition Definizione attiva del Patchbay Messages Log Log dei messaggi Log files Files di log Information Informazioni Some settings may be only effective next time you start this application. Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono cambiate. Vuoi applicare i cambiamenti? The audio backend driver interface to use Driver dell'interfaccia audio da usare MIDI Driv&er: Driv&er MIDI: The ALSA MIDI backend driver to use Driver MIDI di ALSA da usare none nessuno raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 &Verbose messages &Verbosità nei messaggi plughw:0 plughw:0 /dev/audio /dev/audio &Channels: &Canali: 192000 192000 Maximum number of audio channels to allocate Massimo numero di canali audio allocabili Logging Logging Messages log file File di log dei messaggi Browse for the messages log file location Scegli il file in cui loggare i messaggi Whether to activate a messages logging to file. Scegli se attivare il logging dei messaggi su file. Advanced Avanzate Whether to reset all connections when a patchbay definition is activated. Ripristinare o no tutte le connessioni quando una definizione di patchbay è attivata. &Reset all connections on patchbay activation &Ripristina tutte le connessioni all'attivazione di una patchbay Whether to issue a warning on active patchbay port disconnections. Mostrare o no un avviso sulle disconnessioni di porte attive di una patchbay &Warn on active patchbay disconnections &Avvisa sulle disconnessioni di una patchbay attiva &Messages log file: File log dei &messaggi: Whether to enable blinking (flashing) of the server mode (RT) indicator Scegli se abilitare l'indicazione intermittente della modalità del server (RT) Blin&k server mode indicator Intermittenza nell'indicatore modo ser&ver &JACK client/port aliases: Alias clients/porte di &JACK: JACK client/port aliases display mode Modalità di visualizzazione degli alias di clients/porte Default Predefinito First Primo Second Secondo JACK client/port pretty-name (metadata) display mode Modo di visualizzazione « bel-nome » (metadati) di client/porta JACK Enable JA&CK client/port pretty-names (metadata) Attiva i «bei-nomi» (metadati) di client/porta JA&CK Whether to ask for confirmation on JACK audio server shutdown and/or restart Confirm server sh&utdown and/or restart Whether to show system tray message on main window close Mostrare o no il messaggio dell'area di notifica al momento della chiusura della finestra principale Sho&w system tray message on close &Mostrare il messaggio dell'area di notifica alla chiusura Whether to start minimized to system tray Avvia l'applicazione minimizzata come icona nel vassoio di sistema (system tray) Start minimi&zed to system tray Avvia minimi&zzato nel vassoio di sistema Setup Whether to restrict client self-connections Whether to use server synchronous mode Clear settings of current preset name Clea&r &Use server synchronous mode Cloc&k source: Clock source S&elf connect mode: Custom &Color palette theme: Custom color palette theme Wonton Soup DO NOT TRANSLATE KXStudio DO NOT TRANSLATE Manage custom color palette themes &Widget style theme: Custom widget style theme Whether to enable ALSA Sequencer (MIDI) support on startup Scegli se abilitare il sequencer ALSA (MIDI) all'avvio E&nable ALSA Sequencer support Abilita se&quencer ALSA Whether to enable JACK D-Bus interface Attivare o no l'interfaccia JACK D-Bus &Enable JACK D-Bus interface &Attiva l'interfaccia JACK D-Bus Buttons Pulsanti Whether to hide the left button group on the main window Scegli se nascondere i pulsanti a sinistra nella finestra principale Hide main window &Left buttons Nascondi i pu&lsanti di sinistra nella finestra principale Whether to hide the right button group on the main window Scegli se nascondere i pulsanti a destra nella finestra principale Hide main window &Right buttons Nascondi i pulsanti di dest&ra nella finestra principale Whether to hide the transport button group on the main window Scegli se nascondere i pulsanti del transport nella finestra principale Hide main window &Transport buttons Nascondi i pulsanti del &Transport nella finestra principale Whether to hide the text labels on the main window buttons Scegli se nascondere il testo dei pulsanti nella finestra principale Hide main window &button text labels Nascondi il testo dei p&ulsanti nella finestra principale Whether to replace Connections with Graph button on the main window Replace Connections with &Graph button Defaults Predefinite &Base font size: Dimensione &base dei caratteri: Base application font size (pt.) Dimesione predefinita dei caratteri nell'applicazione (pt.) 6 6 7 7 8 8 9 9 11 11 12 12 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to enable D-Bus interface Scegli se abilitare l'interfaccia D-Bus &Enable D-Bus interface &Abilita l'interfaccia D-Bus Number of microseconds to wait between engine processes (dummy) Microsecondi d'attesa fra i processi del motore (dummy) netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to restrict to one single application instance (X11) Scegli se registrare un'unica istanza dell'applicazione (X11) Single application &instance Permetti una sola &istanza &Name: &Nome: The JACK Audio Connection Kit sound server name Il nome del server audio Jack &Server Name Nome del &Server Server path (command line prefix) Indirizzo del server (prefisso nella riga di comando) &Channels I/O: &Canali I/O: &Latency I/O: &Latenza I/O: Start De&lay: Ritardo a&ll'avvio: secs secondi 0 msecs 0 millisecondi Server Suffi&x: Suffisso per il Ser&ver: Server &Prefix: Prefis&so per il Server: Extra driver options (command line suffix) Opzioni extra per il driver (suffisso nella riga di comando) Whether to stop JACK audio server on application exit Fermare o no il server audio JACK all'uscita dell'applicazione S&top JACK audio server on application exit &Fermare il server audio JACK alla chiusura dell'applicazione qjackctlSocketForm &Socket &Socket &Name (alias): &Nome (alias): Socket name (an alias for client name) Nome del socket (un alias per il nome del client) Client name (regular expression) Nome del client (espressione regolare) Add P&lug Aggiungi p&resa Add plug to socket plug list Aggiungi una presa alla lista delle prese &Plug: &Presa: Port name (regular expression) Nome della porta (espressione regolare) Socket Plugs / Ports Prese / Porte del Socket Socket plug list Lista dei socket tipo presa &Edit &Modifica &Remove &Rimuovi Remove currently selected plug from socket plug list Rimuovi la presa selezionata dalla lista del socket Socket Socket &Client: &Client: &Down &Giù &Up S&u E&xclusive Esclusi&vo Enforce only one exclusive cable connection Permetti una connessione da un solo cavo Type Tipo &Audio &Audio Audio socket type (JACK) Socket di tipo audio (JACK) &MIDI &MIDI MIDI socket type (ALSA) Socket di tipo MIDI (ALSA) Plugs / Ports Prese / Porte Error Errore A socket named "%1" already exists. Un socket chiamato "%1" esiste già. Add Plug Aggiungi presa Remove Rimuovi Edit Modifica Move Up Sposta Su Move Down Sposta Giù Warning Attenzione Some settings have been changed. Do you want to apply the changes? Alcune impostazioni sono state modificate. Applicare le modifiche ora? (None) (Nessuno) Edit currently selected plug Modifica la presa selezionata Move down currently selected plug in socket plug list Sposta giù la presa selezionata nella lista socket Move up current selected plug in socket plug list Sposta su la presa selezionata nella lista socket &Forward: C&lona: Forward (clone) all connections from this socket Clona tutte le connessioni di questo socket MIDI socket type (JACK) Tipo di socket MIDI (JACK) AL&SA AL&SA qjackctlSocketList Output Uscita Input Entrata Socket Socket Warning Attenzione <New> - %1 <Nuovo> - %1 %1 about to be removed: "%2" Are you sure? Sto per rimuovere %1: "%2" Sei sicuro? %1 <Copy> - %2 %1 <Copia> - %2 qjackctlSocketListView Output Sockets / Plugs Sockets / Prese d'uscita Input Sockets / Plugs Sockets / Prese d'entrata qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_ja.ts0000644000000000000000000000013214771215054020522 xustar0030 mtime=1743067692.334636541 30 atime=1743067692.333636546 30 ctime=1743067692.334636541 qjackctl-1.0.4/src/translations/qjackctl_ja.ts0000644000175000001440000065372414771215054020533 0ustar00rncbcusers PortAudioProber Probing... 検査中... Please wait, PortAudio is probing audio hardware. お待ちください。PortAudioがオーディオハードウェアを検査中です。 Warning 警告 Audio hardware probing timed out. オーディオハードウェア検査がタイムアウトしました。 QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Usage: %1 [options] [command-and-args] Options: Start JACK audio server immediately. Set default settings preset name. Set active patchbay definition file. Set default JACK audio server name. Show help about command line options. Show version information. Launch command with arguments. [command-and-args] Option -p requires an argument (preset). Option -a requires an argument (path). Option -n requires an argument (name). %1 (%2 frames) Move Rename qjackctlAboutForm About QjackCtlについて &Close 閉じる(&C) About Qt Qtについて Version バージョン Debugging option enabled. デバッグオプションは有効です。 System tray disabled. システムトレイは無効です。 Transport status control disabled. トランスポートステータスコントロールは無効です。 Realtime status disabled. リアルタイムステータスは無効です。 XRUN delay status disabled. XRUN遅延検出は無効です。 Maximum delay status disabled. 最大遅延ステータスは無効です。 JACK Port aliases support disabled. Jackポートエイリアスサポートは無効です。 JACK MIDI support disabled. JACK MIDIサポートは無効です。 JACK Session support disabled. JACKセッションサポートは無効です。 ALSA/MIDI sequencer support disabled. ALSA/MIDIシーケンサーサポートは無効です。 D-Bus interface support disabled. D-Busインターフェイスサポートは無効です。 Using: Qt %1 Qt %1 を使用 JACK %1 JACK %1 Website ウェブサイト This program is free software; you can redistribute it and/or modify it このプログラムはフリーソフトウェアです; GNU一般公衆ライセンスバージョン2以降の under the terms of the GNU General Public License version 2 or later. 条件の元で、あなたはこのプログラムを再配布かつ/あるいは変更できます。 qjackctlClientListView Readable Clients / Output Ports 出力可能クライアント/出力ポート Writable Clients / Input Ports 入力可能クライアント/入力ポート &Connect 接続(&C) Alt+C Connect &Disconnect 切断(&D) Alt+D Disconnect Disconnect &All すべて切断(&A) Alt+A Disconnect All Re&name リネーム(&N) Alt+N Rename &Refresh 更新(&R) Alt+R Refresh qjackctlConnect Warning 警告 This will suspend sound processing from all client applications. Are you sure? すべてのクライアントアプリケーションの サウンド処理をサスペンドします。 よろしいですか? qjackctlConnectionsForm Connections 接続 Audio オーディオ Connect currently selected ports 選択しているポートを接続します &Connect 接続(&C) Disconnect currently selected ports 選択しているポートを切断します &Disconnect 切断(&D) Disconnect all currently connected ports 接続しているすべてのポートを切断します Disconnect &All すべて切断(&A) Expand all client ports すべてのクライアントポートを展開します E&xpand All すべて展開(&X) Refresh current connections view 接続の表示を更新します &Refresh 更新(&R) MIDI ALSA qjackctlConnectorView &Connect 接続(&C) Alt+C Connect &Disconnect 切断(&D) Alt+D Disconnect Disconnect &All すべて切断(&A) Alt+A Disconnect All &Refresh 更新(&R) Alt+R Refresh qjackctlGraphCanvas Connect 接続 Disconnect 切断 qjackctlGraphForm Graph グラフ &Graph グラフ(&G) &Edit 編集(&E) &View 表示(&V) &Zoom 拡大/縮小(&Z) Co&lors 色(&L) S&ort 並べ替え(&O) &Help ヘルプ(&H) &Connect 接続(&C) Connect 接続 Connect selected ports 選択したポートを接続します &Disconnect 切断(&D) Disconnect 切断 Disconnect selected ports 選択したポートを切断します Ctrl+C T&humbview Ctrl+D Cl&ose 閉じる(&O) Close 閉じる Close this application window このウィンドウを終了します Select &All 全て選択(&A) Select All すべて選択します Ctrl+A Select &None 選択の解除(&N) Select None 選択を解除します Ctrl+Shift+A Select &Invert 選択の反転(&I) Select Invert 選択を反転します Ctrl+I &Rename... アイテム名の変更(&R)... Rename item アイテム名を変更します Rename Item アイテム名の変更 F2 &Find... Find Find nodes Ctrl+F &Menubar メニューバー(&M) Menubar メニューバー Show/hide the main program window menubar メインプログラムウィンドウのメニューバーの表示を切り替えます Ctrl+M &Toolbar ツールバー(&T) Toolbar ツールバー Show/hide main program window file toolbar メインプログラムウィンドウのツールバーの表示を切り替えます &Statusbar ステータスバー(&S) Statusbar ステータスバー Show/hide the main program window statusbar メインプログラムウィンドウのステータスバーを表示したり隠したりします &Top Left Top left Show the thumbnail overview on the top-left Top &Right Top right Show the thumbnail overview on the top-right Bottom &Left Bottom Left Bottom left Show the thumbnail overview on the bottom-left &Bottom Right Bottom right Show the thumbnail overview on the bottom-right &None None Hide thumbview Hide the thumbnail overview Text Beside &Icons アイコンテキストの表示(&I) Text beside icons アイコンテキストの表示 Show/hide text beside icons アイコンテキストを表示したり隠したりします &Center 中央寄せ(&C) Center 中央寄せ Center view 中央寄せします &Refresh 更新(&R) Refresh 更新 Refresh view ビューを更新します F5 Zoom &In 拡大(&I) Zoom In 拡大 Ctrl++ Zoom &Out 縮小(&O) Zoom Out 縮小 Ctrl+- Zoom &Fit ウィンドウに合わせる(&F) Zoom Fit ウィンドウに合わせる Ctrl+0 Zoom &Reset 表示のリセット(&R) Zoom Reset 表示リセット Ctrl+1 &Zoom Range 選択範囲の拡大(&Z) Zoom Range 選択範囲を拡大します JACK &Audio... JACK Audio (&A)... JACK Audio color JACK Audioの色 JACK &MIDI... JACK MIDI (&M)... JACK MIDI JACK MIDI JACK MIDI color JACK MIDIの色 ALSA M&IDI... ALSA MIDI ALSA MIDI ALSA MIDI color ALSA MIDIの色 JACK &CV... JACK CV (&C)... JACK CV color JACK CVの色 JACK &OSC... JACK OSC(&O)... JACK OSC JACK OSC JACK OSC color JACK OSCの色 &Reset リセット(&R) Reset colors 配色のリセット Port &Name ポート名(&N) Port name ポート名 Sort by port name ポート名で並べ替え Port &Title ポートタイトル(&T) Port title ポートタイトル Sort by port title ポートタイトルで並べ替え Port &Index ポートインデックス(&I) Port index ポートインデックス Sort by port index ポートインデックスで並べ替え &Ascending 昇順(&A) Ascending 昇順で並べ替え Ascending sort order 昇順で並べ替えます &Descending 降順(&D) Descending 降順で並べ替え Descending sort order 降順で並べ替えます Repel O&verlapping Nodes Repel nodes Repel overlapping nodes Connect Thro&ugh Nodes Connect Through Nodes Connect through nodes Whether to draw connectors through or around nodes &About... qjackctlについて(&A)... About... QjackCtlについて... About QjackCtlについて Show information about this application program このアプリケーションプログラムについての情報を表示します About &Qt... Qtについて(&Q)... About Qt... Qtについて... About Qt Qtについて Show information about the Qt toolkit Qtツールキットについての情報を表示します &Undo 元に戻す(&U) &Redo やり直す(&R) Undo last edit action 直前の作業を取り消します Redo last edit action 取り消した作業をやり直します Zoom 拡大率 Ready 準備できました Colors - %1 色 - %1 qjackctlMainForm Start the JACK server JACKサーバーを開始します &Start 開始(&S) Stop the JACK server JACKサーバを停止します S&top 停止(&T) JACK server state JACKサーバーの状態 JACK server mode JACKサーバーのモード DSP Load DSPの負荷 Sample rate サンプルレート XRUN Count (notifications) XRUNの回数(通知) Time display 時間の表示 Transport state トランスポートの状態 Transport BPM トランスポートのBPM Transport time トランスポートの時間 Quit processing and exit 処理を終わらせ終了します &Quit 終了(&Q) Show/hide the session management window セッション管理ウィンドウの表示を切り替えます S&ession セッション(&E) Show/hide the messages log/status window メッセージログ/状態ウィンドウを表示したり隠したりします &Messages メッセージ(&M) Show settings and options dialog 設定とオプションダイアログを表示 Set&up... 設定(&U)... Show/hide the graph window グラフウィンドウの表示を切り替えます Show/hide the connections window 接続ウィンドウの表示を切り替えます &Connect 接続(&C) Show/hide the patchbay editor window パッチベイ編集ウィンドウの表示を切り替えます &Patchbay パッチベイ(&P) Rewind transport トランスポートを先頭に戻します &Rewind 先頭に戻す(&R) Backward transport トランスポートを逆再生します &Backward 逆再生(&B) Start transport rolling トランスポートのローリングをスタートします &Play 再生(&P) Stop transport rolling トランスポートのローリングをストップします Pa&use 一時停止(&U) Forward transport トランスポートを早送りします &Forward 早送り(&F) Show information about this application このアプリケーションについての情報を表示します Ab&out... 情報(&O)... Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. クライアントとしてALSAシーケンサーを開くことができませんでした ALSA MIDIパッチベイは利用できません。 D-BUS: Service is available (%1 aka jackdbus). D-BUS: サービスを利用できます (%1 がjackdbusを意味します)。 D-BUS: Service not available (%1 aka jackdbus). D-BUS: サービスを利用できません (%1 がjackdbusを意味します)。 Information 情報 The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. このプログラムはシステムトレイに表示されます。 プログラムを終了する時は、システムトレイアイコンの コンテキストメニューで"Quit"を選択して下さい。 Don't show this message again このメッセージを再表示しません Warning 警告 JACK is currently running. Do you want to terminate the JACK audio server? JACKは動作中です。 JACKオーディオサーバーを終了しますか? %1 is about to terminate. Are you sure? %1を終了しようとしています: よろしいですか? successfully 成功 with exit status=%1 終了ステータス = %1 Could not start JACK. Maybe JACK audio server is already started. JACKを開始できませんでした。 おそらくJACKサウンドサーバーはもう開始しています。 Could not load preset "%1". Retrying with default. プリセット "%1" をロードできません。 デフォルトの設定でリトライします。 Could not load default preset. Sorry. デフォルトのプリセットをロードできません。 ごめんなさい。 Startup script... スタートアップスクリプト... Startup script terminated スタートアップスクリプトは終了しました D-BUS: JACK server is starting... D-BUS: JACKサーバーを開始しています... D-BUS: JACK server could not be started. Sorry D-BUS: JACKサーバーを開始できません。 ごめんなさい JACK is starting... JACKを開始しています... Some client audio applications are still active and connected. Do you want to stop the JACK audio server? アクティブな接続を持っているオーディオの クライアントがあります JACKオーディオサーバーを終了しますか? Shutdown script... シャットダウンスクリプト... Shutdown script terminated シャットダウンスクリプトは終了しました JACK is stopping... JACKを終了しています... D-BUS: JACK server is stopping... D-BUS: JACKサーバーを終了しています... D-BUS: JACK server could not be stopped. Sorry D-BUS: JACKサーバーを終了できませんでした。 ごめんなさい JACK was started with PID=%1. JACKはプロセスID=%1で開始しました。 D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: JACKサーバーはスタートしました (%1 がjackdbusを意味します)。 JACK is being forced... JACKを強制終了します... JACK was stopped JACKは終了しました D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: JACKサーバーは終了しました (%1 がjackdbusを意味します)。 Post-shutdown script... ポストシャットダウンスクリプト... Post-shutdown script terminated ポストシャットダウンスクリプトは終了しました Error エラー Don't ask this again この質問を繰り返さない The preset aliases have been changed: "%1" Do you want to save the changes? プリセットのエイリアス名が変更されています: "%1" 変更を保存しますか? Transport BBT (bar.beat.ticks) トランスポートのBBT(bar: beat, ticks) Transport time code トランスポートのタイムコード Elapsed time since last reset 最後のリセットからの経過時間 Elapsed time since last XRUN 最後のXRUNからの経過時間 Patchbay reset. パッチベイのリセット。 Could not load active patchbay definition. "%1" Disabled. アクティブなパッチベイ定義をロードできません。 "%1" 無効にしました。 Patchbay activated. パッチベイを有効にしました。 Patchbay deactivated. パッチベイを無効にしました。 Statistics reset. 統計のリセット。 msec ミリ秒 JACK connection graph change. JACK接続グラフを変更しました。 XRUN callback (%1). XRUNコールバック (%1)。 Buffer size change (%1). バッファサイズを変更しました (%1)。 Shutdown notification. シャットダウンの通知。 Freewheel started... Freewheelで開始しました... Freewheel exited. Freewheelで終了しました。 Could not start JACK. Sorry. JACKを開始できませんでした。 ごめんなさい。 JACK has crashed. JACKはクラッシュしました。 JACK timed out. JACKはタイムアウトしました。 JACK write error. JACK書き込みエラー。 JACK read error. JACK読み出しエラー。 Unknown JACK error (%d). 不明なJACKエラー (%d)。 JACK property change. JACKのプロパティーを変更しました。 ALSA connection graph change. ALSA接続グラフを変更しました。 JACK active patchbay scan JACKのアクティブなパッチベイのスキャン ALSA active patchbay scan ALSAのアクティブなパッチベイのスキャン JACK connection change. JACKの接続を変更しました。 ALSA connection change. ALSAのコネクションを変更しました。 checked 確認済み connected 接続中 disconnected 接続なし failed 失敗 A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? この接続を再度やり直すようなパッチベイ定義が 現在アクティブです: %1 -> %2 パッチベイ接続を削除しますか? Overall operation failed. 全操作が失敗しました。 Invalid or unsupported option. 不正なオプションか、サポートされていないオプションです。 Client name not unique. 重複したクライアント名です。 Server is started. サーバーを開始しました。 Unable to connect to server. サーバーに接続することができません。 Server communication error. サーバーとのコミュニケーションエラーです。 Client does not exist. クライアントが存在しません。 Unable to load internal client. 内部クライアントをロードできません。 Unable to initialize client. クライアントを初期化できません。 Unable to access shared memory. 共有メモリーへアクセスできません。 Client protocol version mismatch. クライアントのプロトコルバージョンが一致しません。 Could not connect to JACK server as client. - %1 Please check the messages window for more info. JACKサーバーとクライアントとして接続することができません。 - %1 メッセージウィンドウで詳細な情報を確認してください。 Server configuration saved to "%1". サーバー設定を "%1" に保存しました。 Client activated. クライアントは有効です。 Post-startup script... ポストスタートアップスクリプト... Post-startup script terminated ポストスタートアップスクリプトを終了しました Command line argument... コマンドライン引数... Command line argument started コマンドライン引数の開始 Client deactivated. クライアントは無効です。 Transport rewind. トランスポートを開始点まで戻します。 Transport backward. トランスポートを逆再生します。 Starting 開始 Transport start. トランスポートを開始しました。 Stopping 停止 Transport stop. トランスポートを停止しました。 Transport forward. トランスポートを早送りします。 Stopped 停止 %1 (%2%) %1 (%2%, %3 xruns) %1 % %1 Hz %1 frames %1 フレーム Yes はい No いいえ FW RT Rolling ローリング Looping ループ %1 msec %1ミリ秒 XRUN callback (%1 skipped). XRUNコールバック (%1 をスキップ)。 Started 開始 Active 有効 Activating 有効化 Inactive 無効 &Hide 隠す(&H) D-BUS: GetParameterConstraint('%1'): %2. (%3) Mi&nimize 最小化(&N) S&how 表示(&H) Rest&ore 元に戻す(&O) &Stop 停止(&S) &Reset リセット(&R) &Presets プリセット(&P) &Load... 読み出し(&L)... &Save... 保存(&S)... Save and &Quit... 保存して終了(&Q)... Save &Template... テンプレートを保存(&T)... &Versioning バージョン(&V) Re&fresh 更新(&F) St&atus 状態(&A) &Connections 接続(&C) Patch&bay パッチベイ(&B) &Graph グラフ(&G) &Transport トランスポート(&T) Server settings will be only effective after restarting the JACK audio server. サーバー設定はJACKオーディオサーバーを再起動後に 有効となります。 Do you want to restart the JACK audio server? JACKオーディオサーバーを再起動しますか? Some settings will be only effective the next time you start this program. いくつかの設定はこのプログラムを次回に起動した時に 有効となります。 D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) qjackctlMessagesStatusForm Messages / Status メッセージ/ステータス &Messages メッセージ(&M) Messages log メッセージのログ Messages output log メッセージ出力ログ &Status 状態(&S) Status information 状態の情報 Statistics since last server startup 最後にサーバーが開始してからの統計 Description 項目 Value Reset XRUN statistic values XRUN統計値をリセットします Re&set リセット(&S) Refresh XRUN statistic values XRUN統計値を更新します &Refresh 更新(&R) Server name サーバー名 Server state サーバーの状態 DSP Load DSP負荷 Sample Rate サンプルレート Buffer Size バッファサイズ Realtime Mode リアルタイムモード Transport state トランスポートの状態 Transport Timecode トランスポートのタイムコード Transport BBT トランスポートのBBT Transport BPM トランスポートのBPM XRUN count since last server startup 最後にサーバーが開始してからのXRUNの回数 XRUN last time detected XRUNが最後に検出された時間 XRUN last 最後のXRUN XRUN maximum XRUNの最大値 XRUN minimum XRUNの最小値 XRUN average XRUNの平均値 XRUN total XRUNの合計 Maximum scheduling delay スケジュール遅延の最大値 Time of last reset 最後のリセットの時間 Logging stopped --- %1 --- Logging started --- %1 --- qjackctlPaletteForm Color Themes 配色のテーマ Name 名前 Current color palette name 現在の色パレット名 Save current color palette name 現在の色パレット名を保存します Save 保存 Delete current color palette name 現在の色パレット名を削除します Delete 削除 Palette パレット Current color palette 現在の色パレット Generate: 作成: Base color to generate palette パレットを作成するベースとなる色 Reset all current palette colors 現在の色パレット名を全てリセットします Reset リセット Import a custom color theme (palette) from file ファイルからカスタム色テーマ(パレット)をインポートします Import... インポート... Export a custom color theme (palette) to file ファイルへカスタム色テーマ(パレット)をエクスポートします Export... エクスポート... Show Details 詳細表示 Import File - %1 ファイルのインポート - %1 Palette files (*.%1) パレットファイル (*.%1) Save Palette - %1 All files (*.*) 全ファイル (*.*) Warning - %1 警告 - %1 Could not import from file: %1 Sorry. ファイルからインポートできませんでした: %1 ごめんなさい。 Export File - %1 ファイルのエクスポート - %1 Some settings have been changed. Do you want to discard the changes? 設定が変更されています。 変更を破棄しますか? Some settings have been changed: "%1". Do you want to save the changes? 設定の一部が変更されています: "%1"。 変更を保存しますか? qjackctlPaletteForm::PaletteModel Color Role 色の役割 Active 有効 Inactive 無効 Disabled 使用不可 qjackctlPatchbay Warning 警告 This will disconnect all sockets. Are you sure? すべてのソケットを切断します よろしいですか? qjackctlPatchbayForm Patchbay パッチベイ Move currently selected output socket down one position 選択している出力ソケットを下へ移動します Down 下へ Create a new output socket 新しい出力ソケットを作成します Add... 追加... Edit currently selected input socket properties 選択している入力ソケットのプロパティを編集します Edit... 編集... Move currently selected output socket up one position 選択している出力ソケットを上に移動します Up 上へ Remove currently selected output socket 選択している出力ソケットを削除します Remove 削除 Duplicate (copy) currently selected output socket 選択している出力ソケットを複製(コピー)します Copy... コピー... Remove currently selected input socket 選択している入力ソケットを削除します Duplicate (copy) currently selected input socket 選択している入力ソケットを複製(コピー)します Create a new input socket 新しい入力ソケットを作成します Edit currently selected output socket properties 選択している出力ソケットのプロパティを編集します Connect currently selected sockets 選択しているソケットを接続します &Connect 接続(&C) Disconnect currently selected sockets 選択しているソケットを切断します &Disconnect 切断(&D) Disconnect all currently connected sockets 接続されているすべてのソケットを切断します Disconnect &All すべて切断(&A) Expand all items すべてのアイテムを展開します E&xpand All すべて展開(&X) Refresh current patchbay view パッチベイの表示を更新します &Refresh 更新(&R) Create a new patchbay profile 新しいパッチベイプロファイルを作成します &New 新規(&N) Load patchbay profile パッチベイプロファイルを読み出します &Load... 読み込み(&L)... Save current patchbay profile パッチベイプロファイルを保存します &Save... 保存(&S)... Current (recent) patchbay profile(s) 現在の(最近の)パッチベイプロファイル Toggle activation of current patchbay profile 現在のパッチベイプロファイルを有効にしたり無効にします Acti&vate 有効化(&V) Warning 警告 The patchbay definition has been changed: "%1" Do you want to save the changes? パッチベイの定義を変更しました: "%1" 変更を保存しますか? %1 [modified] %1 [変更] Untitled%1 無題%1 Error エラー Could not load patchbay definition file: "%1" パッチベイ定義ファイルを読み出せません: "%1" Could not save patchbay definition file: "%1" パッチベイ定義ファイルを保存できません: "%1" New Patchbay definition 新規パッチベイ定義 Create patchbay definition as a snapshot of all actual client connections? 現在有効な全クライアント接続をスナップショットとして パッチベイ定義を作成しますか? Load Patchbay Definition パッチベイの定義を読み出します Patchbay Definition files パッチベイ定義ファイル Save Patchbay Definition パッチベイの定義を保存します active アクティブ qjackctlPatchbayView Add... 追加... Edit... 編集... Copy... コピー... Remove 削除 Exclusive 排他的 Forward 早送り (None) (なし) Move Up 上へ移動 Move Down 下へ移動 &Connect 接続(&C) Alt+C Connect &Disconnect 切断(&D) Alt+D Disconnect Disconnect &All すべて切断(&A) Alt+A Disconnect All &Refresh 更新(&R) Alt+R Refresh qjackctlSessionForm Session セッション Load session セッションを読み出します &Load... 読み出し(&L)... Recent session 最近のセッション &Recent 最近のセッション(&R) Save session セッションを保存します &Save 保存(&S) &Versioning バージョン(&V) Update session セッションの更新 Re&fresh 更新(&F) Session clients / connections セッションのクライアント/接続 Client / Ports クライアント/ポート UUID Command コマンド Infra-clients / commands インフラクライアント/コマンド Infra-client インフラクライアント Infra-command インフラコマンド Add infra-client インフラクライアントを追加します &Add 追加(&A) Edit infra-client インフラクライアントを編集します &Edit 編集(&E) Remove infra-client インフラクライアントを削除します Re&move 削除(&M) &Save... 保存(&S)... Save and &Quit... 保存して終了(&Q)... Save &Template... テンプレートを保存(&T)... Load Session セッションを読み出し Session directory セッションのディレクトリ Save Session セッションの保存 and Quit と終了 Template テンプレート &Clear クリア(&C) Warning 警告 A session could not be found in this folder: "%1" このフォルダーにセッションはありません: "%1" %1: loading session... %1: セッションを読み出しています... %1: load session %2. %1: セッションの読み出し %2。 A session already exists in this folder: "%1" Are you sure to overwrite the existing session? セッションはすでにこのフォルダーにあります: "%1" 存在するセッションを上書きしますか? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? このフォルダーはすでに存在していて、空です: "%1" 存在するフォルダーを上書きしますか? %1: saving session... %1: セッションを保存しています... %1: save session %2. %1: セッションの保存 %2。 New Client 新規クライアント qjackctlSessionInfraClientItemEditor Infra-command インフラコマンド qjackctlSessionSaveForm Session セッション &Name: 名前(&N): Session name &Directory: Session directory セッションのディレクトリ Browse for session directory ... Save session versioning セッションのバージョンを保存します &Versioning バージョン(&V) Warning 警告 Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings 設定 Preset &Name: プリセット名(&N): Settings preset name プリセット設定名 (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Save settings as current preset name 設定を現在のプリセット名として保存 &Save 保存(&S) Delete current settings preset 現在のプリセットを削除します &Delete 削除(&D) jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE &Name: 名前(&N): The JACK Audio Connection Kit sound server name JACK Audio Connection Kitサウンドサーバー名 Driv&er: ドライバー(&E): The audio backend driver interface to use 使用するオーディオバックエンドドライバーインターフェイス dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters パラメーター MIDI Driv&er: MIDIドライバー(&E): The ALSA MIDI backend driver to use 使用するALSA MIDIバックエンドドライバー none raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Time in seconds that client is delayed after server startup サーバーを開始してからのクライアントが遅延する時間(秒) Latency: レイテンシー: Output latency in milliseconds, calculated based on the period, rate and buffer settings ピリオド、サンプルレートそしてバッファーサイズから計算した、出力のレイテンシ (ミリ秒) Use realtime scheduling リアルタイムスケジューリングを使用します &Realtime リアルタイム(&R) Do not attempt to lock memory, even if in realtime mode リアルタイムモードでなくても、メモリーをロックしないようにします No Memory Loc&k メモリーロックを無効(&K) Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) 一般的なツールキットライブラリーのメモリーをアンロックする (GTK+, QT, FLTK, Wine) &Unlock Memory メモリーのアンロック(&U) Ignore xruns reported by the backend driver バックエンドドライバーが報告するXRUNを無視します So&ft Mode ソフトモード(&F) Provide output monitor ports 出力モニター用にポートを提供します &Monitor モニター(&M) Force 16bit mode instead of failing over 32bit (default) 32ビットモード(デフォルト)で失敗する場合に16ビットモードを強制します Force &16bit 強制的に16bitを使用(&1) Enable hardware metering on cards that support it ハードウェアメーターをサポートしているカードではそれを有効にします H/&W Meter H/Wメーターを有効(&W) Ignore hardware period/buffer size ハードウェアのピリオド/バッファーサイズを無視します &Ignore H/W H/Wを無視(&I) Whether to give verbose output on messages メッセージに詳細な出力を行うかどうか &Verbose messages 詳細なメッセージ(&V) &Output Device: 出力デバイス(&O): &Interface: インターフェース(&I): Maximum input audio hardware channels to allocate 割り当てる入力オーディオハードウェアチャンネルの最大値 &Audio: オーディオ(&A): Dit&her: ディザリング(&H): External output latency (frames) 外部出力のレイテンシー(フレーム) &Input Device: 入力デバイス(&I): Provide either audio capture, playback or both 音声の入力か出力、あるいは入出力から選択します Duplex 入出力 Capture Only 入力のみ Playback Only 出力のみ The PCM device name to use 使用するPCMデバイス名 hw:0 plughw:0 /dev/audio /dev/dsp > Alternate input device for capture 録音のための入力デバイスを選択 Maximum output audio hardware channels to allocate 割り当てるオーディオ出力ハードウェアチャンネルの最大値 Alternate output device for playback 再生のための出力デバイス External input latency (frames) 外部入力のレイテンシー(フレーム) Set dither mode ディザリングモードを設定します None Rectangular Shaped Triangular Number of periods in the hardware buffer ハードウェアバッファーのピリオド数 Priorit&y: 優先度(&Y): &Frames/Period: フレーム/ピリオド(&F): Frames per period between process() calls process()呼び出し間のピリオド毎のフレーム数 16 32 64 128 256 512 1024 2048 4096 Port Ma&ximum: 最大ポート数(&X): &Channels: チャンネル数(&C): Number of microseconds to wait between engine processes (dummy) エンジンの処理間の待ち時間をマイクロ秒で指定します(dummy) 21333 Sample rate in frames per second サンプリングレートを1秒あたりのフレーム数で指定します 22050 32000 44100 48000 88200 96000 192000 Scheduler priority when running realtime リアルタイムモードで動作している場合のスケジューラーにおける優先度を設定します &Word Length: ワード長(&W): Periods/&Buffer: ピリオド/バッファー(&B): Word length ワード長 Maximum number of ports the JACK server can manage JACKサーバーが管理するポートの最大数 &Wait (usec): 待ち時間(マイクロ秒)(&W): Sample &Rate: サンプルレート(&R): Maximum number of audio channels to allocate 割り当てるオーディオチャンネルの最大値 &Timeout (msec): タイムアウト(ミリ秒)(&T): Set client timeout limit in milliseconds クライアントのタイムアウトの最大値をミリ秒で指定します Setup セットアップ Whether to restrict client self-connections クライアントのセルフ接続モードを制限するかどうか Whether to use server synchronous mode サーバーのsynchronousモードを使用するかどうか &Use server synchronous mode サーバーのsynchronousモードを使用する(&U) Please do not touch these settings unless you know what you are doing. 何をしようとしているか知っている場合に限りこれらの設定を変更してください。 200 500 1000 2000 5000 Cloc&k source: クロックソース(&K): Clock source クロックソース S&elf connect mode: セルフ接続モード(&E): Options オプション Scripting スクリプト Whether to execute a custom shell script before starting up the JACK audio server. JACKオーディオサーバーを開始する前に任意のシェルスクリプトを実行するかどうか。 Execute script on Start&up: スタートアップ時にスクリプトを実行(&U): Whether to execute a custom shell script after starting up the JACK audio server. JACKオーディオサーバーを開始した直後に任意のシェルスクリプトを実行するかどうか。 Execute script after &Startup: スタートアップ後にスクリプトを実行(&S): Whether to execute a custom shell script before shuting down the JACK audio server. JACKオーディオサーバーを終了する直前に任意のシェルスクリプトを実行するかどうか。 Execute script on Shut&down: シャットダウン時にスクリプトを実行(&D): Command line to be executed before starting up the JACK audio server JACKオーディオサーバーを開始する前に実行するコマンドライン Scripting argument meta-symbols メタシンボルとして使えるスクリプト引数 Browse for script to be executed before starting up the JACK audio server JACKオーディオサーバーを開始する前に実行するスクリプトを参照します ... Command line to be executed after starting up the JACK audio server JACKオーディオサーバーを開始した後に実行するコマンドライン Browse for script to be executed after starting up the JACK audio server JACKオーディオサーバーを開始した後に実行するスクリプトを参照します Browse for script to be executed before shutting down the JACK audio server JACKオーディオサーバーを終了する直前に実行するスクリプトを参照します Command line to be executed before shutting down the JACK audio server JACKオーディオサーバーを終了する直前に実行するコマンドライン Whether to execute a custom shell script after shuting down the JACK audio server. JACKオーディオサーバーを終了した直後に任意のシェルスクリプトを実行するかどうか。 Execute script after Shu&tdown: シャットダウン後にスクリプトを実行(&T): Browse for script to be executed after shutting down the JACK audio server JACKオーディオサーバーを終了した直後に実行するスクリプトを参照します Command line to be executed after shutting down the JACK audio server JACKオーディオサーバーを終了した直後に実行するコマンドライン Statistics 統計 Whether to capture standard output (stdout/stderr) into messages window メッセージウィンドウ中に標準出力(stdout/stderr)を記録するかどうか &Capture standard output 標準出力の記録(&C) &XRUN detection regex: XRUN検出の正規表現(&X): Regular expression used to detect XRUNs on server output messages サーバー出力メッセージ内においてXRUNを検出した際に使用される正規表現 xrun of at least ([0-9|\.]+) msecs Connections 接続 Whether to reset all connections when a patchbay definition is activated. パッチベイ定義を有効にした際に全接続をリセットするかどうか。 &Reset all connections on patchbay activation パッチベイ有効化に伴い全接続をリセットする(&R) Whether to issue a warning on active patchbay port disconnections. アクティブなパッチベイポート切断時に警告を表示するかどうか。 &Warn on active patchbay disconnections アクティブなパッチベイ切断時に警告(&W) Custom カスタム &Color palette theme: 色パレットテーマ(&C): Custom color palette theme カスタム色パレットテーマ Wonton Soup DO NOT TRANSLATE KXStudio DO NOT TRANSLATE Manage custom color palette themes カスタム色パレットテーマを管理します &Widget style theme: ウィジェットスタイルテーマ(&W): Custom widget style theme カスタムウィジェットスタイルテーマ Whether to enable JACK D-Bus interface JACK D-Busインターフェイスを有効にするかどうか &Enable JACK D-Bus interface JACK D-Busインターフェイスの有効化(&E) Whether to replace Connections with Graph button on the main window メインウィンドウの接続ボタンをグラフボタンと置き換えるかどうか Replace Connections with &Graph button 接続ボタンをグラフボタンと置き換える(&G) 10 Patchbay definition file to be activated as connection persistence profile 接続において持続して有効にするパッチベイ定義ファイルを指定します Browse for a patchbay definition file to be activated 有効にするパッチベイ定義の参照 Whether to activate a patchbay definition for connection persistence profile. 接続において持続して有効にするパッチベイ定義を有効にするかどうか。 Activate &Patchbay persistence: パッチベイの持続を有効化(&P): Logging ログの記録 Messages log file メッセージログファイル Browse for the messages log file location メッセージログファイルの場所を参照します Whether to activate a messages logging to file. メッセージログをファイルに記録するかどうか。 Server &Prefix: サーバー接頭辞(&P): Server path (command line prefix) サーバーパス(コマンドライン接頭辞) &Channels I/O: チャンネルI/O(&C): &Latency I/O: レイテンシーI/O(&L): Server Suffi&x: サーバー接尾辞(&X): Extra driver options (command line suffix) 任意のドライバーオプション(コマンドライン接尾辞) Start De&lay: 開始ディレイ(&L): secs 0 msecs 0ミリ秒 Clear settings of current preset name 現在のプリセット名の設定をクリアします Clea&r クリア(&R) &Messages log file: メッセージログファイル(&M): Display 表示 Time Display 時間表示 Transport &Time Code トランスポートのタイムコード(&T) Transport &BBT (bar:beat.ticks) トランスポートのBBT(bar: beat, ticks)(&B) Elapsed time since last &Reset 最後のリセットからの経過時間(&R) Elapsed time since last &XRUN 最後のXRUNからの経過時間(&X) Sample front panel normal display font フロントパネルの通常表示のサンプルフォント Sample big time display font ビッグタイム表示のフォントサンプル Big Time display: ビッグタイム表示: Select font for front panel normal display フロントパネルの通常表示に使用するフォントを選択します &Font... フォント(&F)... Select font for big time display ビッグタイム表示に使用するフォントを選択します Normal display: 通常表示: Whether to enable blinking (flashing) of the server mode (RT) indicator サーバーモード(RT)インジケーターを点滅するかどうか Blin&k server mode indicator サーバーモードインジケーターの点滅(&K) Messages Window メッセージウィンドウ Sample messages text font display メッセージテキスト表示に使用するフォントのサンプル Select font for the messages text display メッセージテキスト表示に使用するフォントを選択します Whether to keep a maximum number of lines in the messages window メッセージビューに1度に表示できる行数の最大値 &Messages limit: メッセージリミット(&M): The maximum number of message lines to keep in view メッセージビューに1度に表示できる行数の最大値 100 250 2500 Connections Window 接続ウィンドウ Sample connections view font 接続ビューに使用するフォントのサンプル Select font for the connections view 接続ビューに使用するフォントを選択します &Icon size: アイコンサイズ(&I): The icon size for each item of the connections view コネクションビューに表示されるアイコンのサイズ 16 x 16 32 x 32 64 x 64 Whether to enable client/port name aliases on the connections window 接続ウィンドウでクライアント/ポートのエイリアス名を有効とするかどうか E&nable client/port aliases クライアント/ポートのエイリアス名の有効化(&N) Whether to enable in-place client/port name editing (rename) クライアント/ポート名の編集(リネーム) Ena&ble client/port aliases editing (rename) クライアント/ポートのエイリアス名編集(リネーム)を有効化(&B) &JACK client/port aliases: JACKクライアント/ポート エイリアス(&J): Advanced 高度 JACK client/port aliases display mode JACKのクライアント/ポートエイリアス表示モード Default デフォルト First 1番目 Second 2番目 JACK client/port pretty-name (metadata) display mode JACKクライアント/ポートのわかりやすい名前(メタデータ)表示モード Enable JA&CK client/port pretty-names (metadata) JACKクライアント/ポートのわかりやすい名前(メタデータ)を有効にします(&C) Misc その他 Other その他 Whether to start JACK audio server immediately on application startup アプリケーション開始直後にJACKオーディオサーバーを開始するかどうか &Start JACK audio server on application startup JACKオーディオサーバーの自動起動(&S) Whether to ask for confirmation on application exit アプリケーションが終了する際に確認するかどうか &Confirm application close アプリケーションの終了の確認(&C) Whether to keep all child windows on top of the main window 子ウィンドウを常に前面に表示するかどうか &Keep child windows always on top 子ウィンドウを常に前面表示(&K) Whether to enable the system tray icon システムトレイアイコンを有効にするかどうか &Enable system tray icon システムトレイアイコンを有効(&E) Whether to show system tray message on main window close メインウィンドウを閉じる時システムトレイメッセージを表示するかどうか Sho&w system tray message on close 終了時にシステムトレイメッセージを表示する(&W) Whether to start minimized to system tray 開始時にシステムトレイアイコンのみ表示するかどうか Start minimi&zed to system tray 開始時にシステムトレイに最小化する(&Z) Whether to restrict to one single application instance (X11) アプリケーションのインスタンスをひとつに制限するかどうか(X11) Single application &instance シングルアプリケーションインスタンス(&I) Whether to save the JACK server command-line configuration into a local file (auto-start) JACKサーバーのコマンドライン設定をローカルファイルに保存するかどうか(自動で保存されます) Whether to ask for confirmation on JACK audio server shutdown and/or restart JACKオーディオサーバーのシャットダウンと再起動時に確認するかどうか Confirm server sh&utdown and/or restart サーバーのシャットダウンと再起動の確認(&U) S&ave JACK audio server configuration to: JACKオーディオサーバー設定の保存先(&A): The server configuration local file name (auto-start) サーバー設定ローカルファイル名(自動起動) .jackdrc Whether to enable ALSA Sequencer (MIDI) support on startup 開始時にALSAシーケンサー(MIDI)サポートを有効にするかどうか E&nable ALSA Sequencer support ALSAシーケンサーサポートを有効化(&N) Whether to enable D-Bus interface D-Busインターフェイスを有効にするかどうか &Enable D-Bus interface D-Busインターフェースの有効化(&E) Whether to stop JACK audio server on application exit アプリケーションが終了する時にJACKオーディオサーバーを停止するかどうか S&top JACK audio server on application exit JACKオーディオサーバーの自動終了(&S) Buttons ボタン Whether to hide the left button group on the main window メインウィンドウ上の左側ボタングループを隠すかどうか Hide main window &Left buttons メインウィンドウ左側のボタンを隠す(&L) Whether to hide the right button group on the main window メインウィンドウ上の右側ボタングループを隠すかどうか Hide main window &Right buttons メインウィンドウ右側のボタンを隠す(&R) Whether to hide the transport button group on the main window メインウィンドウのトランスポートボタングループを隠すかどうか Hide main window &Transport buttons メインウィンドウのトランスポートボタンを隠す(&T) Whether to hide the text labels on the main window buttons メインウィンドウボタン上のテキストラベルを隠すかどうか Hide main window &button text labels メインウィンドウボタンのテキストラベルを隠す(&B) Defaults デフォルト &Base font size: 基本フォントサイズ(&B): Base application font size (pt.) アプリケーションの基本フォントサイズ(pt) 6 7 8 9 11 12 System Cycle サイクル HPET Don't restrict self connect requests (default) セルフ接続の要求を制限しない(デフォルト) Fail self connect requests to external ports only 外部ポートに対してのみセルフ接続の要求を失敗させる Ignore self connect requests to external ports only 外部ポートに対するセルフ接続の要求を無視する Fail all self connect requests セルフ接続のすべての要求を失敗させます Ignore all self connect requests セルフ接続のすべての要求を無視します Warning 警告 Some settings have been changed: "%1" Do you want to save the changes? 設定の一部が変更されています: "%1" 変更を保存しますか? Delete preset: "%1" Are you sure? プリセットを削除します: "%1" よろしいですか? msec ミリ秒 n/a &Preset Name プリセット名(&P) &Server Name サーバー名(&S) &Server Path サーバーパス(&S) &Driver ドライバー(&D) &Interface インターフェース(&I) Sample &Rate サンプルレート(&R) &Frames/Period フレーム/ピリオド(&F) Periods/&Buffer ピリオド/バッファー(&B) Startup Script スタートアップスクリプト Post-Startup Script ポストスタートアップスクリプト Shutdown Script シャットダウンスクリプト Post-Shutdown Script ポストシャットダウンスクリプト Active Patchbay Definition 有効なパッチベイ定義 Patchbay Definition files パッチベイ定義ファイル Messages Log メッセージログ Log files ログファイル Information 情報 Some settings may be only effective next time you start this application. いくつかの設定はこのプログラムを 次回に起動した時に有効となります。 Some settings have been changed. Do you want to apply the changes? 設定が変更されました。 変更を適用しますか? qjackctlSocketForm Socket ソケット &Socket ソケット(&S) &Name (alias): 名前(エイリアス)(&N): Socket name (an alias for client name) ソケット名(クライアント名のエイリアス) Client name (regular expression) クライアント名 (正規表現) Add plug to socket plug list プラグをソケットプラグリストに追加します Add P&lug プラグ追加(&L) &Plug: プラグ(&P): Port name (regular expression) ポート名 (正規表現) Socket plug list ソケットプラグのリスト Socket Plugs / Ports ソケットプラグ/ポート Edit currently selected plug 選択しているプラグを編集します &Edit 編集(&E) Remove currently selected plug from socket plug list ソケットプラグリストから選択しているプラグを削除します &Remove 削除(&R) &Client: クライアント(&C): Move down currently selected plug in socket plug list ソケットプラグリストで選択しているプラグを下に移動します &Down 下へ(&D) Move up current selected plug in socket plug list ソケットプラグリストで選択しているプラグを上に移動します &Up 上へ(&U) Enforce only one exclusive cable connection 排他的なケーブル接続を強制します E&xclusive 排他的(&X) &Forward: 転送(&F): Forward (clone) all connections from this socket このソケットからすべての接続を転送(クローン)します Type タイプ Audio socket type (JACK) オーディオソケットタイプ(JACK) &Audio オーディオ(&A) MIDI socket type (JACK) MIDIソケットタイプ(JACK) &MIDI MIDI socket type (ALSA) MIDIソケットタイプ(ALSA) AL&SA ALSA(&S) Plugs / Ports プラグ/ポート Error エラー A socket named "%1" already exists. ソケット名 "%1" はすでに存在します。 Warning 警告 Some settings have been changed. Do you want to apply the changes? 設定が変更されました。 変更を適用しますか? Add Plug プラグの追加 Edit 編集 Remove 削除 Move Up 上へ移動 Move Down 下へ移動 (None) (なし) qjackctlSocketList Output 出力 Input 入力 Socket ソケット <New> - %1 <新規> - %1 Warning 警告 %1 about to be removed: "%2" Are you sure? %1を削除しようとしています: "%2" よろしいですか? %1 <Copy> - %2 %1 <コピー> - %2 qjackctlSocketListView Output Sockets / Plugs 出力ソケット / プラグ Input Sockets / Plugs 入力ソケット / プラグ qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_cs.ts0000644000000000000000000000013114771215054020534 xustar0030 mtime=1743067692.331636555 29 atime=1743067692.33063656 30 ctime=1743067692.331636555 qjackctl-1.0.4/src/translations/qjackctl_cs.ts0000644000175000001440000064240414771215054020537 0ustar00rncbcusers PortAudioProber Probing... Zjišťuje se... Please wait, PortAudio is probing audio hardware. Počkejte, prosím, PortAudio zjišťuje zvukový hardware. Warning Varování Audio hardware probing timed out. Došlo k překročení času při zjišťování zvukového hardware. QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Usage: %1 [options] [command-and-args] Použití: %1 [volby] [příkazy a argumenty] Options: Volby: Start JACK audio server immediately. Spustit zvukový server JACK okamžitě. Set default settings preset name. Nastavit název přednastavení výchozího nastavení. Set active patchbay definition file. Nastavit soubor s vymezením činné zapojovací desky. Set default JACK audio server name. Nastavit výchozí název zvukového serveru JACK. Show help about command line options. Ukázat nápovědu k volbám příkazového řádku. Show version information. Ukázat informace o verzi. Launch command with arguments. Spustit příkaz s argumenty. [command-and-args] [příkaz a argumenty] Option -p requires an argument (preset). Volba -p vyžaduje argument (preset, přednastavení). Option -a requires an argument (path). Volba -a vyžaduje argument (cesta). Option -n requires an argument (name). Volba -n vyžaduje argument (název). %1 (%2 frames) %1 (%2 snímků) Move Přesunout Rename Přejmenovat qjackctlAboutForm About O programu &Close &Zavřít About Qt O Qt Version Verze Debugging option enabled. Povolena volba pro ladění. System tray disabled. Zakázána oznamovací oblast. Transport status control disabled. Zakázáno ovládání stavu předání. Realtime status disabled. Zakázán stav provádění ve skutečném čase. XRUN delay status disabled. Zakázán stav zpoždění XRUN. Maximum delay status disabled. Zakázán stav největšího zpoždění. JACK MIDI support disabled. JACK MIDI není podporován. JACK Session support disabled. Podpora pro sezení JACK byla zakázána. ALSA/MIDI sequencer support disabled. ALSA/MIDI řadič (sequencer) není podporován. Using: Qt %1 Používající: Qt %1 JACK %1 JACK %1 Website Stránky This program is free software; you can redistribute it and/or modify it Tento program je svobodným programem. Můžete jej šířit a/nebo upravit under the terms of the GNU General Public License version 2 or later. za podmínek GNU General Public License ve verzi 2 nebo pozdější. JACK Port aliases support disabled. Podpora pro přezdívky přípojek JACK zakázána. D-Bus interface support disabled. Podpora pro rozhraní D-Bus zakázána. qjackctlClientListView Readable Clients / Output Ports Čitelné přípojky pro klienty/výstupy Writable Clients / Input Ports Zapisovatelné přípojky pro klienty/výstupy &Connect &Spojit Alt+C Connect Alt+C &Disconnect &Rozpojit Alt+D Disconnect Alt+D Disconnect &All &Rozpojit vše Alt+A Disconnect All Alt+A Re&name &Přejmenovat Alt+N Rename Alt+N &Refresh &Obnovit Alt+R Refresh Alt+R qjackctlConnect Warning Varování This will suspend sound processing from all client applications. Are you sure? Tímto se pozastaví zpracování zvuku u všech klientských aplikací. Jste si jistý? qjackctlConnectionsForm Connections Spojení Audio Zvuk Connect currently selected ports Spojit nyní vybrané přípojky &Connect &Spojit Disconnect currently selected ports Rozpojit nyní vybrané přípojky &Disconnect &Rozpojit Disconnect all currently connected ports Rozpojit všechny nyní spojené přípojky Disconnect &All &Rozpojit vše Expand all client ports Rozbalit všechny klientské přípojky E&xpand All Rozbalit &vše Refresh current connections view Obnovit pohled na nynější spojení &Refresh &Obnovit MIDI JACK-MIDI ALSA ALSA-MIDI qjackctlConnectorView &Connect &Spojit Alt+C Connect Alt+C &Disconnect &Rozpojit Alt+D Disconnect Alt+D Disconnect &All Rozpojit &vše Alt+A Disconnect All Alt+A &Refresh &Obnovit Alt+R Refresh Alt+R qjackctlGraphCanvas Connect Spojit Disconnect Rozpojit qjackctlGraphForm Graph Graf &Graph &Graf &Edit Úp&ravy &View &Pohled &Zoom &Zvětšení Co&lors &Barvy S&ort Ř&adit &Help &Nápověda &Connect &Spojení Connect Spojit Connect selected ports Spojit vybrané přípojky &Disconnect &Rozpojit Disconnect Rozpojit Disconnect selected ports Rozpojit vybrané přípojky Ctrl+C Ctrl+C T&humbview &Náhled Ctrl+D Ctrl+D Cl&ose &Zavřít Close Zavřít Close this application window Zavřít okno tohoto programu Select &All Vybrat &vše Select All Vybrat vše Ctrl+A Ctrl+A Select &None Nevybrat &nic Select None Nevybrat nic Ctrl+Shift+A Ctrl+Shift+A Select &Invert Obrátit &výběr Select Invert Obrátit výběr Ctrl+I Ctrl+I &Rename... &Přejmenovat... Rename item Přejmenovat položku Rename Item Přejmenovat položku F2 F2 &Find... Find Find nodes Ctrl+F &Menubar Pruh s &nabídkou Menubar Pruh s nabídkou Show/hide the main program window menubar Ukázat/Skrýt hlavní okno programu s nabídkovým pruhem Ctrl+M Ctrl+M &Toolbar Pruh s &nástroji Toolbar Pruh s nástroji Show/hide main program window file toolbar Ukázat/Skrýt hlavní okno programu s nástrojovým pruhem &Statusbar &Stavový řádek Statusbar Stavový řádek Show/hide the main program window statusbar Ukázat/Skrýt stavový řádek hlavního okna programu &Top Left &Nahoře vlevo Top left Nahoře vlevo Show the thumbnail overview on the top-left Zobrazit přehled náhledů v levém horním rohu Top &Right Nahoře v&pravo Top right Nahoře vpravo Show the thumbnail overview on the top-right Zobrazit přehled náhledů v pravém horním rohu Bottom &Left &Dole vlevo Bottom Left Dole vlevo Bottom left Dole vlevo Show the thumbnail overview on the bottom-left Zobrazit přehled náhledů v levém dolním rohu &Bottom Right &Dole vpravo Bottom right Dole vpravo Show the thumbnail overview on the bottom-right Zobrazit přehled náhledů v pravém dolním rohu &None Žá&dný None Žádný Hide thumbview Skrýt náhled Hide the thumbnail overview Skrýt přehled náhledů Text Beside &Icons Text &vedle ikon Text beside icons Text vedle ikon Show/hide text beside icons Ukázat/Skrýt text vedle ikon &Center &Vystředit Center Vystředit Center view Vystředit pohled &Refresh &Obnovit Refresh Obnovit Refresh view Obnovit pohled F5 F5 Zoom &In &Přiblížit Zoom In Přiblížit Ctrl++ Ctrl++ Zoom &Out &Oddálit Zoom Out Oddálit Ctrl+- Ctrl+- Zoom &Fit &Přizpůsobit zvětšení Zoom Fit Přizpůsobit zvětšení Ctrl+0 Ctrl+0 Zoom &Reset &Vrátit zvětšení na výchozí Zoom Reset Vrátit zvětšení na výchozí Ctrl+1 Ctrl+1 &Zoom Range Rozsah &zvětšení Zoom Range Rozsah zvětšení JACK &Audio... JACK &Audio... JACK Audio color Barva JACK Audio JACK &MIDI... JACK &MIDI... JACK MIDI JACK MIDI JACK MIDI color Barva JACK MIDI ALSA M&IDI... ALSA M&IDI... ALSA MIDI ALSA MIDI ALSA MIDI color Barva ALSA MIDI JACK &CV... JACK &CV... JACK CV color Barva JACK CV JACK &OSC... JACK &OSC... JACK OSC JACK OSC JACK OSC color Barva JACK OSC &Reset &Obnovit výchozí Reset colors Obnovit výchozí barvy Port &Name &Název přípojky (port) Port name Název přípojky (port) Sort by port name Řadit podle názvu přípojky (port) Port &Title &Titulek přípojky (port) Port title Titulek přípojky (port) Sort by port title Řadit podle titulku přípojky (port) Port &Index Čí&slo přípojky (port) Port index Číslo přípojky (port) Sort by port index Řadit podle čísla přípojky (port) &Ascending &Vzestupně Ascending Vzestupně Ascending sort order Vzestupné pořadí řazení &Descending &Sestupně Descending Sestupně Descending sort order Sestupné pořadí řazení Repel O&verlapping Nodes Zamítnout &překrývající se uzly Repel nodes Zamítnout uzly Repel overlapping nodes Zamítnout překrývající se uzly Connect Thro&ugh Nodes Připojit &přes uzly Connect Through Nodes Připojit přes uzly Connect through nodes Připojit přes uzly Whether to draw connectors through or around nodes Zda kreslit konektory skrz nebo kolem uzlů &About... &O programu... About... O programu... About O programu Show information about this application program Ukázat informace o tomto programu About &Qt... O &Qt... About Qt... O Qt... About Qt O Qt Show information about the Qt toolkit Ukázat informace o sadě nástrojů prostředí Qt &Undo &Zpět &Redo &Znovu Undo last edit action Vrátit poslední úpravu zpět Redo last edit action Provést poslední úpravu znovu Zoom Zvětšení Ready Připraven Colors - %1 Barvy - %1 qjackctlMainForm Quit processing and exit Ukončit zpracování signálu a ukončit program &Quit &Ukončit Start the JACK server Spustit server JACK &Start &Spustit Stop the JACK server Zastavit server JACK S&top &Zastavit St&atus &Stav Show information about this application Ukázat informace o této aplikaci Ab&out... &O... Set&up... &Nastavení... Show settings and options dialog Ukázat dialogové okno pro nastavení a volby &Messages &Hlášení Show/hide the patchbay editor window Ukázat/Skrýt okno editoru se zapojovací deskou &Patchbay &Zapojovací deska &Connect &Spojit JACK server state Stav serveru JACK JACK server mode Režim serveru JACK DSP Load Zatížení DSP Sample rate Vzorkovací kmitočet XRUN Count (notifications) Počet XRUN (oznámení) Time display Údaj o čase Transport state Stav předání Transport BPM Předání BPM Transport time Čas předání Show/hide the session management window Ukázat/Skrýt okno se správou sezení Show/hide the messages log/status window Ukázat/Skrýt okno se zápisy/stavem hlášení Show/hide the graph window Ukázat/Skrýt okno s grafem Show/hide the connections window Ukázat/Skrýt okno s obsahem Backward transport Předání zpět &Backward &Zpět Forward transport Předání dopředu &Forward &Dopředu Rewind transport Předání přetočit zpět &Rewind &Přetočit zpět Stop transport rolling Zastavit chod předání Pa&use &Pozastavit Start transport rolling Spustit chod předání &Play &Přehrát Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. Nepodařilo se otevřít řadič (sekvencer) ALSA jako klienta. Zapojovací deska ALSA MIDI nebude dostupná. D-BUS: Service is available (%1 aka jackdbus). D-BUS: Služba je dostupná (%1 aka jackdbus). D-BUS: Service not available (%1 aka jackdbus). D-BUS: Služba není dostupná (%1 aka jackdbus). Information Informace Warning Varování JACK is currently running. Do you want to terminate the JACK audio server? Server JACK nyní běží. Chcete ukončit zvukový server JACK? successfully úspěšně with exit status=%1 s vrácenou hodnotou = %1 Could not start JACK. Maybe JACK audio server is already started. JACK se nepodařilo spustit. Možná je server JACK už spuštěn. Could not load preset "%1". Retrying with default. Nastavení "%1" se nepodařilo nahrát. Zkouší se znovu s výchozím přednastavením. Could not load default preset. Sorry. Nepodařilo se nahrát výchozí přednastavení. Promiňte. Startup script... Skript pro spuštění... Startup script terminated Skript pro spuštění ukončen D-BUS: JACK server is starting... D-BUS: Spouští se server JACK... D-BUS: JACK server could not be started. Sorry D-BUS: Server JACK se nepodařilo spustit. Promiňte JACK is starting... JACK se spouští... Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Některé z klientských zvukových aplikací jsou stále činné a spojené. Chcete zastavit zvukový server JACK? JACK is stopping... JACK se zastavuje... Shutdown script... Skript pro zastavení chodu... Don't ask this again Neptat se znovu Shutdown script terminated Skript pro zastavení chodu ukončen D-BUS: JACK server is stopping... D-BUS: Zastavuje se server JACK... D-BUS: JACK server could not be stopped. Sorry D-BUS: Server JACK se nepodařilo zastavit. Promiňte Post-shutdown script... Skript pro po-zastavení chodu... Post-shutdown script terminated Skript pro po-zastavení chodu ukončen JACK was started with PID=%1. JACK byl puštěn s PID = %1. %1 is about to terminate. Are you sure? %1 má být skončen. Jste si jistý? D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: Server JACK byl spuštěn (%1 aka jackdbus). JACK is being forced... JACK je nucen... JACK was stopped JACK byl zastaven D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: Server JACK byl zastaven (%1 aka jackdbus). Error Chyba Transport time code Předání časového kódu Elapsed time since last reset Čas uplynulý od posledního obnovení výchozího nastavení Elapsed time since last XRUN Čas uplynulý od posledního XRUN Patchbay activated. Zapojovací deska uvedena do chodu. Patchbay deactivated. Zapojovací deska vyřazena z provozu. Statistics reset. Obnovení vychozího nastavení statistiky. msec ms JACK connection graph change. Nákres spojení JACK změněn. XRUN callback (%1). Zavolání nazpátek XRUN (%1). Buffer size change (%1). Velikost vyrovnávací paměti změněna (%1). Shutdown notification. Oznámení o zastavení. Could not start JACK. Sorry. Nepodařilo se spustit JACK. Promiňte. JACK has crashed. JACK spadl. JACK timed out. Překročení času u JACK. JACK write error. Chyba při psaní u JACK. JACK read error. Chyba při čtení u JACK. Unknown JACK error (%d). Neznámá chyba u JACK (%d). ALSA connection graph change. Nákres spojení ALSA změněn. JACK active patchbay scan Prohlédnutí činné zapojovací desky JACK ALSA active patchbay scan Prohlédnutí činné zapojovací desky ALSA JACK connection change. Spojení JACK změněno. ALSA connection change. Spojení ALSA změněno. checked přezkoušeno connected spojeno disconnected rozpojeno failed nepodařilo se A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? Vymezení zapojovací desky je nyní aktivní, což pravděpodobně znamená předělat toto spojení: %1 -> %2 Chcete odstranit spojení zapojovací desky? The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. Program poběží dále v oznamovací části panelu. Pro ukončení programu vyberte, prosím, "Ukončit" v související nabídce vyskakující z ikony v oznamovací části panelu. Don't show this message again Toto hlášení neukazovat znovu The preset aliases have been changed: "%1" Do you want to save the changes? Přezdívky pro přednastavení byly změněny: "%1" Chcete uložit změny? Transport BBT (bar.beat.ticks) Předání BBT (takt:doba.tiknutí - bar:beat.ticks) Patchbay reset. Uvedení zapojovací desky do výchozího stavu. Could not load active patchbay definition. "%1" Disabled. Nepodařilo se nahrát vymezení činné zapojovací desky. "%1" Zakázáno. Freewheel started... Volnoběh spuštěn... Freewheel exited. Volnoběh ukončen. JACK property change. Vlastnost JACK změněna. Overall operation failed. Celková operace se nezdařila. Invalid or unsupported option. Neplatná nebo nepodporovaná volba. Client name not unique. Název klienta není jedinečný. Server is started. Server je spuštěn. Unable to connect to server. Nelze se připojit k serveru. Server communication error. Chyba spojení se serverem. Client does not exist. Klient neexistuje. Unable to load internal client. Nepodařilo se nahrát vnitřního klienta. Unable to initialize client. Nepodařilo se inicializovat vnitřního klienta. Unable to access shared memory. Nepodařilo se přistoupit ke sdílené paměti. Client protocol version mismatch. Nevhodná verze klientského protokolu. Could not connect to JACK server as client. - %1 Please check the messages window for more info. Nepodařilo se připojit k serveru JACK jako klient. - %1 Další informace hledejte, prosím, v okně s hlášením. Server configuration saved to "%1". Nastavení serveru uloženo do "%1". Client activated. Klient uveden do chodu. Post-startup script... Skript pro po-spuštění... Post-startup script terminated Skript pro po-spuštění ukončen Command line argument... Argument pro příkazový řádek... Command line argument started Argument pro příkazový řádek spuštěn Client deactivated. Klient vyřazen z provozu. Transport rewind. Předání přetočit zpět. Transport backward. Předání zpět. Starting Spouští se Transport start. Spustit předání. Stopping Zastavuje se Transport stop. Zastavit předání. Transport forward. Předání dopředu. Stopped Zastaveno %1 (%2%) %1 (%2 %) %1 (%2%, %3 xruns) %1 (%2%, %3 xruns) %1 % %1 % %1 Hz %1 Hz %1 frames %1 snímků Yes Ano No Ne FW FW RT RT Rolling Jede Looping Zapíná se do jednoduchého obvodu %1 msec %1 ms XRUN callback (%1 skipped). Zavolání nazpátek XRUN (%1 přeskočeno). Started Běží Active Činný Activating Uvádí se do chodu Inactive Nečinný &Hide &Skrýt D-BUS: GetParameterConstraint('%1'): %2. (%3) D-BUS: Získat omezení parametru GetParameterConstraint('%1'): %2. (%3) Mi&nimize &Zmenšit S&how &Ukázat Rest&ore &Nahrát znovu &Stop &Zastavit &Reset &Obnovit výchozí &Presets &Přednastavení &Versioning &Verzování Re&fresh Ob&novit S&ession &Sezení &Load... &Nahrát... &Save... &Uložit... Save and &Quit... Uložit a &ukončit... Save &Template... Uložit jako &předlohu... &Connections &Spojení Patch&bay &Zapojovací deska &Graph &Graf &Transport &Předání Server settings will be only effective after restarting the JACK audio server. Nastavení serveru se projeví až po novém spuštění serveru JACK. Do you want to restart the JACK audio server? Chcete zvukový server JACK spustit znovu? D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: Nastavit hodnotu parametru SetParameterValue('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: Nastavit znovu hodnotu parametru ResetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS: Získat hodnotu parametru GetParameterValue('%1'): %2. (%3) Some settings will be only effective the next time you start this program. Některá nastavení se projeví až tehdy, když příště spustíte tento program. qjackctlMessagesStatusForm Messages / Status Hlášení/Stav &Messages &Hlášení Messages log Zápis hlášení Messages output log Zápis hlášení o výstupu &Status &Stav Status information Informace o stavu Statistics since last server startup Statistika od posledního spuštění serveru Description Popis Value Hodnota Reset XRUN statistic values Obnovit výchozí hodnoty údajů ve statistice XRUN Re&set &Obnovit výchozí Refresh XRUN statistic values Obnovit údaje ve statistice XRUN &Refresh &Obnovit Server name Název serveru Server state Stav serveru DSP Load Zatížení DSP Sample Rate Vzorkovací kmitočet Buffer Size Velikost vyrovnávací paměti Realtime Mode Režim skutečného času Transport state Stav předání Transport Timecode Předání časového kódu Transport BBT Předání BBT Transport BPM Předání BPM XRUN count since last server startup Počet XRUN od posledního spuštění serveru XRUN last time detected Čas posledního zjištění XRUN XRUN last Poslední XRUN XRUN maximum Největší počet XRUN XRUN minimum Nejmenší počet XRUN XRUN average Průměrný počet XRUN XRUN total Celkový počet XRUN Maximum scheduling delay Největší zpoždění času Time of last reset Čas od posledního obnovení výchozího nastavení Logging stopped --- %1 --- Zápis zastaven --- %1 --- Logging started --- %1 --- Zápis spuštěn --- %1 --- qjackctlPaletteForm Color Themes Barevné motivy Name Název Current color palette name Název nynější palety barev Save current color palette name Uložit název nynější palety barev Save Uložit Delete current color palette name Smazat název nynější palety barev Delete Smazat Palette Paleta Current color palette Nynější paleta barev Generate: Vytvořit: Base color to generate palette Základní barva pro vytvoření palety Reset all current palette colors Nastavit všechny barvy palety barev na výchozí Reset Obnovit výchozí Import a custom color theme (palette) from file Zavést vlastní barevný motiv (paleta) ze souboru Import... Zavést... Export a custom color theme (palette) to file Vyvést vlastní barevný motiv (paleta) do souboru Export... Vyvést... Show Details Ukázat podrobnosti Import File - %1 Zavést soubor - %1 Palette files (*.%1) Soubory s paletami (*.%1) Save Palette - %1 Uložit paletu - %1 All files (*.*) Všechny soubory (*.*) Warning - %1 Varování - %1 Could not import from file: %1 Sorry. Nepodařilo se zavést ze souboru. %1 Promiňte. Export File - %1 Vyvést soubor - %1 Some settings have been changed. Do you want to discard the changes? Některá nastavení byla změněna. Chcete zahodit změny? Some settings have been changed: "%1". Do you want to save the changes? Některá nastavení byla změněna: "%1" Chcete uložit změny? qjackctlPaletteForm::PaletteModel Color Role Barevná role Active Činné Inactive Nečinné Disabled Zakázáno qjackctlPatchbay Warning Varování This will disconnect all sockets. Are you sure? Tento krok odpojí všechny zásuvky. Jste si jistýr? qjackctlPatchbayForm Patchbay Zapojovací deska Move currently selected output socket down one position Posunout nyní vybrané výstupní zásuvky dolů o jedno místo Down Dolů Create a new output socket Vytvořit novou výstupní zásuvku Add... Přidat... Edit currently selected input socket properties Upravit vlastnosti nyní vybrané vstupní zásuvky Edit... Upravit... Move currently selected output socket up one position Posunout nyní vybrané výstupní zásuvky nahoru o jedno místo Up Nahoru Remove currently selected output socket Odstranit nyní vybranou výstupní zásuvku Remove Odstranit Duplicate (copy) currently selected output socket Zdvojit (kopírovat) nyní vybranou výstupní zásuvku Copy... Kopírovat... Remove currently selected input socket Odstranit nyní vybranou vstupní zásuvku Duplicate (copy) currently selected input socket Zdvojit (kopírovat) nyní vybranou vstupní zásuvku Create a new input socket Vytvořit novou vstupní zásuvku Edit currently selected output socket properties Upravit vlastnosti nyní vybrané výstupní zásuvky Connect currently selected sockets Spojit nyní vybrané zásuvky &Connect &Spojit Disconnect currently selected sockets Odpojit nyní vybrané zásuvky &Disconnect &Odpojit Disconnect all currently connected sockets Odpojit všechny nyní spojené zásuvky Disconnect &All &Odpojit vše Expand all items Rozbalit všechny položky E&xpand All Rozbalit &vše Refresh current patchbay view Obnovit nynější pohled na zapojovací desku &Refresh &Obnovit Create a new patchbay profile Vytvořit nový profil zapojovací desky &New &Nový Load patchbay profile Nahrát profil zapojovací desky &Load... &Nahrát... Save current patchbay profile Uložit nynější profil zapojovací desky &Save... &Uložit... Current (recent) patchbay profile(s) Nynější (naposledy použité) profil(y) zapojovací desky Toggle activation of current patchbay profile Přepnout spuštění nynějšího profilu zapojovací desky Acti&vate &Spustit Warning Varování The patchbay definition has been changed: "%1" Do you want to save the changes? Vymezení zapojovací desky bylo změněno: "%1" Chcete uložit změny? %1 [modified] %1 [změněn] Untitled%1 Bez názvu%1 Error Chyba Could not load patchbay definition file: "%1" Nepodařilo se nahrát soubor s vymezením zapojovací desky: "%1" Could not save patchbay definition file: "%1" Nepodařilo se uložit soubor s vymezením zapojovací desky: "%1" New Patchbay definition Nové vymezení zapojovací desky Create patchbay definition as a snapshot of all actual client connections? Vytvořit vymezení zapojovací desky jako snímek všech skutečných klientských spojení? Load Patchbay Definition Nahrát vymezení zapojovací desky Patchbay Definition files Soubory s vymezením zapojovací desky Save Patchbay Definition Uložit vymezení zapojovací desky active činný qjackctlPatchbayView Add... Přidat... Edit... Upravit... Copy... Kopírovat... Remove Odstranit Exclusive Výhradní Forward Dopředu (None) (Žádný) Move Up Přesunout nahoru Move Down Přesunout dolů &Connect &Spojit Alt+C Connect Alt+C &Disconnect &Rozpojit Alt+D Disconnect Alt+D Disconnect &All &Rozpojit vše Alt+A Disconnect All Alt+A &Refresh &Obnovit Alt+R Refresh Alt+R qjackctlSessionForm Session Sezení Load session Nahrát sezení &Load... &Nahrát... Recent session Naposledy otevřené sezení &Recent &Naposledy otevřené Save session Uložit sezení &Versioning &Verzování Re&fresh Ob&novit Session clients / connections Klienti sezení/spojení Infra-clients / commands Infra-klienti/Příkazy Infra-client Infra-klient Infra-command Infra-příkaz Add infra-client Přidat infra-klient &Add Přid&at Edit infra-client Upravit infra-klient &Edit &Upravit Remove infra-client Odstranit infra-klient Re&move &Odstranit &Save... &Uložit... Update session Obnovit sezení Client / Ports Klient/Přípojky UUID UUID Command Příkaz &Save &Uložit Load Session Nahrát sezení Session directory Adresář se sezením Save Session Uložit sezení and Quit a ukončit Template Předloha &Clear &Smazat Warning Varování A session could not be found in this folder: "%1" Sezení se v této složce nepodařilo nalézt: "%1" %1: loading session... %1: nahrává se sezení... %1: load session %2. %1: nahrát sezení %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? V této složce již existuje sezení: "%1" Jste si jistý, že chcete přepsat stávající sezení? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Tato složka již existuje a není prázdná: "%1" Jste si jistý, že chcete přepsat stávající složku? %1: saving session... %1: ukládá se sezení... %1: save session %2. %1: uložit sezení %2. New Client Nový klient Save and &Quit... Uložit a &ukončit... Save &Template... Uložit jako &předlohu... qjackctlSessionInfraClientItemEditor Infra-command Infra-příkaz qjackctlSessionSaveForm Session Sezení &Name: &Název: Session name &Directory: Session directory Adresář se sezením Browse for session directory ... ... Save session versioning Uložit verzování sezení &Versioning &Verzování Warning Varování Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings Nastavení Preset &Name: &Název přednastavení: Settings preset name Název pro přednastavení nastavení (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Save settings as current preset name Uložit nastavení s nynějším názvem přednastavení &Save &Uložit Delete current settings preset Smazat přednastavení nynějšího nastavení &Delete &Smazat jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE Driv&er: &Ovladač: The audio backend driver interface to use Rozhraní ovladače k zadní části zvuku, které se bude používat dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters Parametry MIDI Driv&er: Ovla&dač MIDI: The ALSA MIDI backend driver to use Ovladač k zadní části ALSA MIDI, který se bude používat none žádný raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Time in seconds that client is delayed after server startup Čas v sekundách, o který je klient opožděn po spuštění serveru Latency: Prodleva: Output latency in milliseconds, calculated based on the period, rate and buffer settings Výstupní prodleva v milisekundách, jejíž výpočet je založen na nastavení údobí (period), rychlosti (snímání) a vyrovnávací paměti Use realtime scheduling Použít zpracování ve skutečném čase &Realtime &Skutečný čas Do not attempt to lock memory, even if in realtime mode Nepokoušejte se uzamknout paměť, dokonce ani v režimu skutečného času No Memory Loc&k &Neuzamknout paměť Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) Odemknout paměť běžných knihoven s nástroji (GTK+, QT, FLTK, Wine) &Unlock Memory &Odemknout paměť Ignore xruns reported by the backend driver Přehlížet xruns hlášené ovladačem zadní části So&ft Mode &Snadný režim Provide output monitor ports Poskytnout přípojky pro sledování výstupu &Monitor &Sledování Force 16bit mode instead of failing over 32bit (default) Vynutit 16bitový režim namísto selhání ve 32bitovém (výchozí) Force &16bit Vynutit &16bitový režim Enable hardware metering on cards that support it Povolit přístrojové měření u karet, které to podporují H/&W Meter H/&W měřidlo Ignore hardware period/buffer size Přehlížet údobí (periodu)/velikost vyrovnávací paměti přístroje &Ignore H/W &Přehlížet H/W Whether to give verbose output on messages Dát hlášením podrobný výstup &Verbose messages &Podrobná hlášení &Output Device: &Výstupní zařízení: &Interface: &Rozhraní: Maximum input audio hardware channels to allocate Největší množství přidělitelných vstupních zvukových přístrojových kanálů &Audio: &Zvuk: Dit&her: &Vložení šumu do signálu (dithering): External output latency (frames) Vnější výstupní prodleva (snímky) &Input Device: Vstup&ní zařízení: Provide either audio capture, playback or both Poskytnout buď zachytávání zvuku, přehrávání nebo obojí Duplex Zdvojený Capture Only Pouze zachytávání Playback Only Pouze přehrávání The PCM device name to use Název používaného zařízení PCM hw:0 hw:0 plughw:0 plughw:0 /dev/audio /dev/audio /dev/dsp /dev/dsp > > Alternate input device for capture Střídat vstupní zařízení pro zachytávání Maximum output audio hardware channels to allocate Největší množství přidělitelných výstupních zvukových přístrojových kanálů Alternate output device for playback Střídat výstupní zařízení pro přehrávání External input latency (frames) Vnější vstupní prodleva (snímky) Set dither mode Nastavit režim vložení šumu do signálu (dithering) None Žádný Rectangular Obdélníkový Shaped Obalová křivka Triangular Trojúhelníkový Number of periods in the hardware buffer Počet údobí (period) ve vyrovnávací paměti přístroje Priorit&y: &Přednost: &Frames/Period: &Snímky/Údobí (perioda): Frames per period between process() calls Snímků za údobí (periodu) mezi voláním process() Aufrufen 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Port Ma&ximum: &Největší počet přípojek: &Channels: &Kanály: 21333 21333 Sample rate in frames per second Vzorkovací kmitočet (rychlost snímkování) ve snímcích za sekundu 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 192000 192000 Scheduler priority when running realtime Přednost rozvrhu při běhu ve skutečném čase &Word Length: &Délka slova: Periods/&Buffer: Ú&dobí/Vyrovnávací paměť: Word length Délka slova Maximum number of ports the JACK server can manage Největší počet přípojek, které server JACK může spravovat &Wait (usec): &Čekat (µs): Sample &Rate: Vzorkovací &kmitočet: Maximum number of audio channels to allocate Největší množství přidělitelných zvukových kanálů &Timeout (msec): &Překročení času (ms): Set client timeout limit in milliseconds Nastavit mez pro překročení času u klienta; údaj v milisekundách 200 200 500 500 1000 1000 2000 2000 5000 5000 &Channels I/O: &Kanály vstup/výstup: &Latency I/O: &Prodleva vstup/výstup: Server Suffi&x: Příp&ona serveru: Start De&lay: &Zpoždění spuštění: secs s 0 msecs 0 ms Advanced Pokročilé Options Volby Scripting Skriptování Whether to execute a custom shell script before starting up the JACK audio server. Provést vlastní shellový skript před spuštěním zvukového serveru JACK. Execute script on Start&up: Provést skript při &spuštění: Whether to execute a custom shell script after starting up the JACK audio server. Provést vlastní shellový skript po spuštění zvukového serveru JACK. Execute script after &Startup: Provést skript &po spuštění: Whether to execute a custom shell script before shuting down the JACK audio server. Provést vlastní shellový skript před zastavením zvukového serveru JACK. Execute script on Shut&down: Provést skript při zasta&vení: Command line to be executed before starting up the JACK audio server Příkazový řádek k provedení před spuštěním zvukového serveru JACK Scripting argument meta-symbols Meta symboly pro argument při skriptování Browse for script to be executed before starting up the JACK audio server Vybrat skript, který se provede před spuštěním zvukového serveru JACK ... ... Command line to be executed after starting up the JACK audio server Příkazový řádek k provedení po spuštění zvukového serveru JACK Browse for script to be executed after starting up the JACK audio server Vybrat skript, který se provede po spuštění zvukového serveru JACK Browse for script to be executed before shutting down the JACK audio server Vybrat skript, který se provede před zastavením zvukového serveru JACK Command line to be executed before shutting down the JACK audio server Příkazový řádek k provedení před zastavením zvukového serveru JACK Whether to execute a custom shell script after shuting down the JACK audio server. Provést vlastní shellový skript po zastavení zvukového serveru JACK. Execute script after Shu&tdown: Provést skript po zas&tavení: Browse for script to be executed after shutting down the JACK audio server Vybrat skript, který se provede po zastavení zvukového serveru JACK Command line to be executed after shutting down the JACK audio server Příkazový řádek k provedení po zastavení zvukového serveru JACK Statistics Statistika Whether to capture standard output (stdout/stderr) into messages window Vést obvyklý výstup (stdout/stderr) do okna s hlášeními &Capture standard output &Vést obvyklý výstup &XRUN detection regex: Pravidelný výraz pro zjištění &XRUN: Regular expression used to detect XRUNs on server output messages Pravidelný výraz užitý pro poznání XRUN v hlášeních posílaných serverem xrun of at least ([0-9|\.]+) msecs xrun alespoň ([0-9|\.]+) ms Connections Spojení Whether to enable JACK D-Bus interface Zda povolit rozhraní D-Bus JACJ &Enable JACK D-Bus interface &Povolit rozhraní D-Bus JACK Whether to replace Connections with Graph button on the main window Nahradit v hlavním okně Spojení tlačítkem pro graf Replace Connections with &Graph button Nahradit Spojení tlačítkem pro &graf 10 10 Patchbay definition file to be activated as connection persistence profile Spustit soubor s vymezením zapojovací desky jako stálý profil spojení Browse for a patchbay definition file to be activated Vybrat soubor s vymezením zapojovací desky pro spuštění Whether to activate a patchbay definition for connection persistence profile. Spustit stálý profil s vymezením zapojovací desky spojení. Activate &Patchbay persistence: Spustit stálý profil se &zapojovací deskou: Logging Provádění zápisu Messages log file Soubor se zápisem hlášení Browse for the messages log file location Vybrat místo pro umístění souboru se zápisem hlášení Whether to activate a messages logging to file. Zapnout provádění zápisu hlášení do souboru. Setup Nastavení Whether to restrict client self-connections Zda omezit vlastní spojení klienta Whether to use server synchronous mode Zda použít synchronizační režim serveru Clear settings of current preset name Vyprázdnit nastavení nynějšího názvu přednastavení Clea&r &Vymazat &Use server synchronous mode &Použít synchronizační režim serveru Please do not touch these settings unless you know what you are doing. Nedotýkejte se, prosím, těchto nastavení, pokud nevíte, co děláte. Server &Prefix: Pře&dpona serveru: Cloc&k source: Zdroj &hodin: Clock source Zdroj hodin S&elf connect mode: Režim &vlastního spojení: Extra driver options (command line suffix) Další volby pro ovladač (přípona příkazového řádku) Whether to reset all connections when a patchbay definition is activated. Nastavit všechna spojení na výchozí hodnoty, když je zapnuto vymezení zapojovací desky. &Reset all connections on patchbay activation &Nastavit všechna spojení při zapnutí zapojovací desky na výchozí hodnoty Whether to issue a warning on active patchbay port disconnections. Vydat varování při odpojení přípojek činné zapojovací desky. &Warn on active patchbay disconnections &Varovat při odpojení činné zapojovací desky &Messages log file: &Soubor se zápisem hlášení: Display Zobrazit Time Display Údaj o čase Transport &Time Code Předání &časového kódu Transport &BBT (bar:beat.ticks) Předání &BBT (takt:doba.tiknutí - bar:beat.ticks) Elapsed time since last &Reset Čas uplynulý od posledního &obnovení výchozího nastavení Elapsed time since last &XRUN Čas uplynulý od posledního &XRUN Sample front panel normal display font Předvést písmo pro obvyklé zobrazení na přední straně panelu Sample big time display font Předvést písmo pro velké zobrazení údaje o čase Big Time display: Velké zobrazení údaje o čase: Select font for front panel normal display Vybrat písmo pro zobrazení písma na přední straně panelu &Font... &Písmo... Select font for big time display Vybrat písmo pro velké zobrazení údaje o čase Normal display: Obvyklé zobrazení: Whether to enable blinking (flashing) of the server mode (RT) indicator Povolit mrkání indikátoru serverového režimu (realtime -RT) Blin&k server mode indicator Zobrazovat mr&kání indikátoru režimu serveru Custom Vlastní &Color palette theme: &Motiv palety barev: Custom color palette theme Vlastní motiv palety barev Wonton Soup DO NOT TRANSLATE KXStudio DO NOT TRANSLATE Manage custom color palette themes Spravovat vlastní motivy palety barev &Widget style theme: Motiv stylu &prvku: Custom widget style theme Vlastní motiv stylu prvku Messages Window Okno s hlášením Sample messages text font display Předvést zobrazení textu v okně s hlášením Select font for the messages text display Vybrat písmo pro zobrazení textu hlášení Whether to keep a maximum number of lines in the messages window Určit největší počet řádků zobrazovaných v okně s hlášením &Messages limit: &Největší počet hlášení: The maximum number of message lines to keep in view Největší počet řádků zobrazovaných v okně s hlášením 100 100 250 250 2500 2500 Connections Window Přehled spojení Sample connections view font Předvést zobrazení písma v přehledu spojení Select font for the connections view Vybrat písmo pro přehled spojení &Icon size: &Velikost ikon: The icon size for each item of the connections view Velikost jednotlivých symbolů v přehledu spojení 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 Whether to enable in-place client/port name editing (rename) Povolit úpravu vedlejšího názvu (přezdívka) klienta/přípojky (přejmenování) Ena&ble client/port aliases editing (rename) Po&volit úpravu vedlejšího názvu (přezdívka) klienta/přípojky (přejmenování) Whether to enable client/port name aliases on the connections window Povolit vedlejší názvy (přezdívky) klienta/přípojky v přehledu spojení E&nable client/port aliases &Povolit vedlejší názvy (přezdívky) klienta/přípojky Server path (command line prefix) Cesta k serveru (předpona příkazového řádku) Misc Různé Other Další Whether to start JACK audio server immediately on application startup Spustit zvukový server JACK okamžitě při spuštění aplikace &Start JACK audio server on application startup &Spustit zvukový server JACK okamžitě při spuštění aplikace Whether to ask for confirmation on application exit Žádat o potvrzení při ukončení aplikace JACK client/port pretty-name (metadata) display mode Režim zobrazení pěkných názvů (popisná data) pro klienty/přípojky JACK Enable JA&CK client/port pretty-names (metadata) Povolit pěkné názvy (popisná data) pro klienty/přípojky JA&CK &Confirm application close &Potvrdit ukončení aplikace Whether to ask for confirmation on JACK audio server shutdown and/or restart Zeptat se na potvrzení při vypnutí zvukového serveru JACK a/nebo jeho restartování Confirm server sh&utdown and/or restart Potvrdit &vypnutí serveru a/nebo jeho restartování Whether to keep all child windows on top of the main window Všechna další okna udržovat nad hlavním oknem &Keep child windows always on top &Všechna další okna udržovat vždy nahoře Whether to enable the system tray icon Ukázat ikonu v systémové části panelu &Enable system tray icon Po&volit ikonu v systémové části panelu Whether to start minimized to system tray Spustit program zmenšený do systémové části panelu Start minimi&zed to system tray Spustit program &zmenšený do systémové části panelu Whether to save the JACK server command-line configuration into a local file (auto-start) Nastavení příkazového řádku ke spuštění serveru JACK-uložit do místního souboru (auto-start) S&ave JACK audio server configuration to: Nastavení ke spuštění serveru JACK &uložit jako: The server configuration local file name (auto-start) Název místního souboru s nastavením serveru (auto-start) .jackdrc .jackdrc Whether to enable ALSA Sequencer (MIDI) support on startup Povolit podporu (MIDI) pro řadič (sekvencer) ALSA při spuštění E&nable ALSA Sequencer support P&ovolit podporu (MIDI) pro řadič (sekvencer) ALSA Buttons Tlačítka Whether to hide the left button group on the main window Skrýt skupinu s tlačítky nalevo v hlavním okně Hide main window &Left buttons Skrýt &levá tlačítka v hlavním okně Whether to hide the right button group on the main window Skrýt skupinu s tlačítky napravo v hlavním okně Hide main window &Right buttons Skrýt &pravá tlačítka v hlavním okně Whether to hide the transport button group on the main window Skrýt skupinu s tlačítky pro předání v hlavním okně Hide main window &Transport buttons Skrýt &předávací tlačítka v hlavním okně Whether to hide the text labels on the main window buttons Skrýt textové popisky tlačítek v hlavním okně Hide main window &button text labels Skrýt textové popisky &tlačítek v hlavním okně System Systém Cycle Kolo HPET HPET Don't restrict self connect requests (default) Neomezovat požadavky na vlastní spojení (výchozí) Fail self connect requests to external ports only Nesplnit požadavky na vlastní spojení jen pro vnější přípojky Ignore self connect requests to external ports only Přehlížet požadavky na vlastní spojení jen pro vnější přípojky Fail all self connect requests Nesplnit všechny požadavky na vlastní spojení Ignore all self connect requests Přehlížet všechny požadavky na vlastní spojení Warning Varování Some settings have been changed: "%1" Do you want to save the changes? Některá nastavení byla změněna: "%1" Chcete uložit změny? Delete preset: "%1" Are you sure? Smazat přednastavení "%1" Jste si jistý? msec ms n/a n/a &Preset Name &Název přednastavení &Server Name &Název serveru &Server Path &Cesta k serveru &Driver &Ovladač &Interface &Rozhraní Sample &Rate Vzorkovací &kmitočet &Frames/Period &Snímky/Údobí (perioda) Periods/&Buffer Ú&dobí/Vyrovnávací paměť Startup Script Skript pro spuštění Post-Startup Script Skript pro po-spuštění Shutdown Script Skript pro zastavení chodu Post-Shutdown Script Skript pro po-zastavení chodu Active Patchbay Definition Vymezení činné zapojovací desky Patchbay Definition files Soubory s vymezením zapojovací desky Messages Log Zápis s hlášením Log files Soubory se zápisy Information Informace Some settings may be only effective next time you start this application. Některá nastavení se projeví až tehdy, když příště spustíte tento program. Some settings have been changed. Do you want to apply the changes? Některá nastavení byla změněna. Chcete použít změny? &JACK client/port aliases: Vedlejší názvy (přezdívky) pro klienty/přípojky &JACK: JACK client/port aliases display mode Režim zobrazení vedlejších názvů (přezdívek) pro klienty/přípojky JACK Default Výchozí First První Second Druhý Whether to show system tray message on main window close Ukázat zprávu v oznamovací oblasti panelu při zavření hlavního okna Sho&w system tray message on close &Ukázat zprávu v oznamovací oblasti panelu při zavření Whether to stop JACK audio server on application exit Zastavit zvukový server JACK při ukončení aplikace S&top JACK audio server on application exit &Zastavit zvukový server JACK při ukončení aplikace Defaults Výchozí &Base font size: &Základní velikost písma: Base application font size (pt.) Základní velikost písma v aplikaci (pt.) 6 6 7 7 8 8 9 9 11 11 12 12 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 &Name: &Název: The JACK Audio Connection Kit sound server name Název zvukového serveru JACK Audio Connection Kit netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Number of microseconds to wait between engine processes (dummy) Počet mikrosekund, po které se čeká mezi strojovými procesy (dummy) Whether to enable D-Bus interface Zda povolit rozhraní D-Bus &Enable D-Bus interface &Povolit rozhraní D-Bus Whether to restrict to one single application instance (X11) Zda omezit na úroveň jednoho programu (X11) Single application &instance Ú&roveň jednoho programu qjackctlSocketForm Socket Zásuvka &Socket &Zásuvka &Name (alias): &Název (Přezdívka): Socket name (an alias for client name) Název zásuvky (přezdívka pro název klienta) Client name (regular expression) Název pro klienta (pravidelný výraz) Add plug to socket plug list Přidat zástrčku do seznamu se zástrčkami do zásuvky Add P&lug &Přidat zástrčku &Plug: &Zástrčka: Port name (regular expression) Název přípojky (pravidelný výraz) Socket plug list Seznam se zástrčkami do zásuvky Socket Plugs / Ports Zástrčky do zásuvky/Přípojky Edit currently selected plug Upravit nyní vybranou zástrčku &Edit &Upravit Remove currently selected plug from socket plug list Odstranit nyní vybranou zástrčku ze seznamu se zástrčkami do zásuvky &Remove &Odstranit &Client: &Klient: Move down currently selected plug in socket plug list Posunout nyní vybranou zástrčku v seznamu se zástrčkami do zásuvky dolů &Down &Dolů Move up current selected plug in socket plug list Posunout nyní vybranou zástrčku v seznamu se zástrčkami do zásuvky nahoru &Up &Nahoru Enforce only one exclusive cable connection Vynutit jedno výlučné kabelové spojení E&xclusive Vý&lučné &Forward: &Dopředu: Forward (clone) all connections from this socket Předat všechna spojení z této zásuvky (klonovat) Type Typ Audio socket type (JACK) Zvukový typ zásuvky (napojení) JACK &Audio &Zvuk MIDI socket type (JACK) MIDI typ zásuvky (napojení) (JACK) &MIDI &JACK-MIDI MIDI socket type (ALSA) MIDI typ zásuvky (napojení) (ALSA) AL&SA AL&SA-MIDI Plugs / Ports Zástrčky/Přípojky Error Chyba A socket named "%1" already exists. Zásuvka s názvem "%1" již existuje. Warning Varování Some settings have been changed. Do you want to apply the changes? Některá nastavení byla změněna. Chcete použít změny? Add Plug Přidat zástrčku Edit Upravit Remove Odstranit Move Up Přesunout nahoru Move Down Přesunout dolů (None) (Žádný) qjackctlSocketList Output Výstup Input Vstup Socket Zásuvka <New> - %1 <Nový> %1 Warning Varování %1 about to be removed: "%2" Are you sure? %1 má být odstraněno: "%2" Jste si jistý? %1 <Copy> - %2 %1 <Kopírovat> - %2 qjackctlSocketListView Output Sockets / Plugs Výstupní zásuvky/zástrčky Input Sockets / Plugs Vstupní zásuvky/zástrčky qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_tr.ts0000644000000000000000000000013214771215054020555 xustar0030 mtime=1743067692.335636536 30 atime=1743067692.335636536 30 ctime=1743067692.335636536 qjackctl-1.0.4/src/translations/qjackctl_tr.ts0000644000175000001440000064236614771215054020566 0ustar00rncbcusers PortAudioProber Probing... İnceleniyor... Please wait, PortAudio is probing audio hardware. Lütfen bekleyin, PortAudio ses donanımını araştırıyor. Warning Uyarı Audio hardware probing timed out. Ses donanımı incelemesi zaman aşımına uğradı. QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Usage: %1 [options] [command-and-args] Kullanımı: %1 [seçenekler] [komut ve bağımsız değişkenler] Options: Seçenekler: Start JACK audio server immediately. JACK ses sunucusunu hemen başlatın. Set default settings preset name. Varsayılan ayarların ön ayar adını ayarlayın. Set active patchbay definition file. Etkin bağlantı paneli tanım dosyasını ayarlayın. Set default JACK audio server name. Varsayılan JACK ses sunucusu adını ayarlayın. Show help about command line options. Komut satırı seçenekleriyle ilgili yardımı göster. Show version information. Sürüm bilgilerini göster. Launch command with arguments. Argümanlarla komutu başlatın. [command-and-args] [komut ve argümanlar] Option -p requires an argument (preset). Seçenek -p bir bağımsız değişken (ön ayar) gerektirir. Option -a requires an argument (path). Seçenek -a bir argüman (yol) gerektirir. Option -n requires an argument (name). Seçenek -n bir argüman (isim) gerektirir. %1 (%2 frames) %1 (%2 kare) Move Taşı Rename Yeniden adlandır qjackctlAboutForm About Hakkında &Close &Kapat About Qt Qt Hakkında Version Sürüm Debugging option enabled. Hata ayıklama seçeneği etkin. System tray disabled. Sistem tepsisi devre dışı. Transport status control disabled. Aktarım durumu kontrolü devre dışı. Realtime status disabled. Gerçek zamanlı durum devre dışı. XRUN delay status disabled. XRUN gecikme durumu devre dışı. Maximum delay status disabled. Maksimum gecikme durumu devre dışı. JACK MIDI support disabled. JACK MIDI desteği devre dışı bırakıldı. JACK Session support disabled. JACK Oturumu desteği devre dışı bırakıldı. ALSA/MIDI sequencer support disabled. ALSA/MIDI sıralayıcı desteği devre dışı. Using: Qt %1 Kullanılıyor: Qt %1 JACK %1 JACK %1 Website Web sitesi This program is free software; you can redistribute it and/or modify it Bu program özgür bir yazılımdır; yeniden dağıtabilir ve/veya değiştirebilirsiniz under the terms of the GNU General Public License version 2 or later. GNU Genel Kamu Lisansı sürüm 2 veya üzeri koşulları kapsamında. JACK Port aliases support disabled. JACK Bağlantı noktası takma ad desteği devre dışı. D-Bus interface support disabled. D-Bus arayüz desteği devre dışı. qjackctlClientListView Readable Clients / Output Ports Okunabilir İstemciler / Çıkış Bağlantı Noktaları Writable Clients / Input Ports Yazılabilir İstemciler / Giriş Bağlantı Noktaları &Connect &Bağlan Alt+C Connect Alt+C &Disconnect &Bağlantıyı Kes Alt+D Disconnect Alt+D Disconnect &All &Tüm Bağlantıları Kes Alt+A Disconnect All Alt+A Re&name &Yeniden adlandır Alt+N Rename Alt+N &Refresh &Yenile Alt+R Refresh Alt+R qjackctlConnect Warning Uyarı This will suspend sound processing from all client applications. Are you sure? Bu, tüm istemci uygulamalarında ses işlemeyi askıya alacaktır. Emin misin? qjackctlConnectionsForm Connections Bağlantılar Audio Ses Connect currently selected ports Seçili bağlantı noktalarını bağlayın &Connect &Bağlan Disconnect currently selected ports Seçili bağlantı noktalarının bağlantısını kes &Disconnect &Bağlantıyı kes Disconnect all currently connected ports Bağlı olan tüm bağlantı noktalarının bağlantısını kesin Disconnect &All &Tüm Bağlantıları Kes Expand all client ports Tüm istemci bağlantı noktalarını genişlet E&xpand All &Hepsini genişlet Refresh current connections view Mevcut bağlantılar görünümünü yenile &Refresh &Yenile MIDI MIDI ALSA ALSA qjackctlConnectorView &Connect &Bağlan Alt+C Connect Alt+C &Disconnect &Bağlantıyı Kes Alt+D Disconnect Alt+D Disconnect &All &Tüm Bağlantıları Kes Alt+A Disconnect All Alt+A &Refresh &Yenile Alt+R Refresh Alt+R qjackctlGraphCanvas Connect Bağlan Disconnect Bağlantıyı Kes qjackctlGraphForm Graph Grafik &Graph &Grafik &Edit &Düzenle &View &Görünüm &Zoom &Yakınlaştır Co&lors &Renkler S&ort &Sırala &Help Y&ardım &Connect &Bağlan Connect Bağlan Connect selected ports Seçilen bağlantı noktalarını bağlayın &Disconnect &Bağlantıyı Kes Disconnect Bağlantıyı Kes Disconnect selected ports Seçili bağlantı noktalarının bağlantısını kes Ctrl+C Ctrl+C T&humbview Ctrl+D Ctrl+D Cl&ose &Kapat Close Kapat Close this application window Bu uygulama penceresini kapat Select &All Hepsini &seç Select All Hepsini seç Ctrl+A Ctrl+A Select &None Hi&çbirini Seçme Select None Hiçbirini Seçme Ctrl+Shift+A Ctrl+Shift+A Select &Invert Seçimi &Çevir Select Invert Seçimi Çevir Ctrl+I Ctrl+I Ctrl+I &Rename... Y&eniden adladır... Rename item Öğeyi yeniden adlandır Rename Item Öğeyi yeniden adlandır F2 F2 &Find... Find Find nodes Ctrl+F &Menubar &Menü çubuğu Menubar Menü Çubuğu Show/hide the main program window menubar Ana program penceresi menü çubuğunu göster/gizle Ctrl+M Ctrl+M &Toolbar Araç &çubuğu Toolbar Araç çubuğu Show/hide main program window file toolbar Ana program penceresi araç çubuğunu göster/gizle &Statusbar &Durum çubuğu Statusbar Durum çubuğu Show/hide the main program window statusbar Ana program penceresi durum çubuğunu göster/gizle &Top Left Top left Show the thumbnail overview on the top-left Top &Right Top right Show the thumbnail overview on the top-right Bottom &Left Bottom Left Bottom left Show the thumbnail overview on the bottom-left &Bottom Right Bottom right Show the thumbnail overview on the bottom-right &None None Hiçbiri Hide thumbview Hide the thumbnail overview Text Beside &Icons &Simgeler Metnin Yanında Text beside icons Simgelerin metnin yanında Show/hide text beside icons Simgelerin yanındaki metni göster/gizle &Center &Ortala Center Ortala Center view Orta görünüm &Refresh &Yenile Refresh Yenile Refresh view Görünümü yenile F5 F5 Zoom &In &Yakınlaş Zoom In Yakınlaş Ctrl++ Ctrl++ Zoom &Out Uzak&klaş Zoom Out Uzaklaş Ctrl+- Ctrl+- Zoom &Fit Sığ&dır Zoom Fit Sığdır Ctrl+0 Ctrl+0 Zoom &Reset Yakınlaştırmayı sı&fırla Zoom Reset Yakınlaştırmayı Sıfırla Ctrl+1 Ctrl+1 &Zoom Range Seçili Alan&ı Yalınlaştır Zoom Range Yakınlaştırma Oranı JACK &Audio... JACK &Ses... JACK Audio color JACK Ses rengi JACK &MIDI... JACK &MIDI... JACK MIDI JACK MIDI JACK MIDI color JACK MIDI rengi ALSA M&IDI... ALSA M&IDI... ALSA MIDI ALSA MIDI ALSA MIDI color ALSA MIDI rengi JACK &CV... JACK &CV... JACK CV color JACK CV rengi JACK &OSC... JACK &OSC... JACK OSC JACK OSC JACK OSC color JACK OSC rengi &Reset &Sıfırla Reset colors Renkleri sıfırla Port &Name Bağlantı Noktası &Adı Port name Bağlantı Noktası Adı Sort by port name Bağlantı noktası adına göre sırala Port &Title Bağlantı Noktası &Başlığı Port title Bağlantı Noktası Başlığı Sort by port title Bağlantı Noktası Başığına Göre Sırala Port &Index Bağlantı Nokt&ası Dizini Port index Bağlantı Noktası Dizini Sort by port index Bağlantı noktası dizinine göre sırala &Ascending A&rtan Ascending Artan Ascending sort order Artan sıralama düzeni &Descending A&zalan Descending Azalan Descending sort order Azalan sıralama düzeni Repel O&verlapping Nodes Çakışan Düğ&ümleri Reddet Repel nodes Reddedilen düğümler Repel overlapping nodes Çakışan Düğümleri Reddet Connect Thro&ugh Nodes Düğümler Aracılığıyla Bağla&n Connect Through Nodes Düğümler Aracılığıyla Bağlan Connect through nodes Düğümler aracılığıyla bağlan Whether to draw connectors through or around nodes Bağlayıcıların düğümlerin içinden mi yoksa çevresinden mi çizileceği &About... &Hakkında... About... Hakkında... About HAkkında Show information about this application program Bu program hakkındaki bilgileri göster About &Qt... &QT Hakkında... About Qt... Qt Hakkında... About Qt Qt Hakkında Show information about the Qt toolkit Qt araç seti hakkındaki bilgileri göster &Undo &Geri Al &Redo &Yeniden Yap Undo last edit action Son düzenleme işlemini geri al Redo last edit action Son düzenleme eylemini yeniden yap Zoom Yakınlaştır Ready Hazır Colors - %1 Renkler - %1 qjackctlMainForm Quit processing and exit Çalışmayı bırak ve çık &Quit &Çıkış Start the JACK server JACK sunucusunu başlat &Start &Başlat Stop the JACK server JACK sunucusunu durdur S&top &Durdur St&atus D&urum Show information about this application Bu uygulama hakkındaki bilgileri göster Ab&out... &Hakkında... Set&up... &Ayarlar... Show settings and options dialog Ayarlar ve seçenekler iletişim kutusunu göster &Messages &Mesajlar Show/hide the patchbay editor window Bağlantı paneli düzenleyici penceresini göster/gizle &Patchbay Bağlantı &Paneli &Connect &Bağlan JACK server state JACK sunucu durumu JACK server mode JACK sunucu modu DSP Load DSP-Yükü Sample rate Örnekleme oranı XRUN Count (notifications) XRUN Sayısı (bildirimler) Time display Zaman göstergesi Transport state Transport durumu Transport BPM Transport BPM Transport time Transport zamanı Show/hide the session management window Oturum yönetimi penceresini göster/gizle Show/hide the messages log/status window Mesaj günlüğü/durum penceresini göster/gizle Show/hide the graph window Grafik penceresini göster/gizle Show/hide the connections window Bağlantı penceresini göster/gizle Backward transport Geriye &Backward &Geriye Forward transport İleriye &Forward &İlerle Rewind transport Geri sarma &Rewind G&eri sar Stop transport rolling Transport hareketini durdur Pa&use &Duraklat Start transport rolling Transport hareketini başlat &Play &Oynat Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. ALSA sıralayıcısı istemci olarak açılamadı. ALSA MIDI bağlantı paneli kullanılamayacak. D-BUS: Service is available (%1 aka jackdbus). D-BUS: Servis mevcut (%1 diğer adıyla jackdbus). D-BUS: Service not available (%1 aka jackdbus). D-BUS: Servisi mevcut değil (%1 diğer adıyla jackdbus). Information Bilgi Don't show this message again Bu mesajı bir daha gösterme Warning Uyarı JACK is currently running. Do you want to terminate the JACK audio server? JACK şu anda çalışıyor. JACK ses sunucusunu sonlandırmak istiyor musunuz? %1 is about to terminate. Are you sure? %1 sonlandırılmak üzere. Emin misin? successfully başarılı with exit status=%1 çıkış durumu=%1 ile Could not start JACK. Maybe JACK audio server is already started. JACK başlatılamadı. Belki JACK ses sunucusu zaten başlatılmıştır. Could not load preset "%1". Retrying with default. "%1" ön ayarı yüklenemedi. Varsayılan olarak yeniden deneniyor. Could not load default preset. Sorry. Varsayılan ön ayar yüklenemedi. Üzgünüm. Startup script... Başlangıç betiği... Startup script terminated Başlangıç betiği sonlandırıldı D-BUS: JACK server is starting... D-BUS: JACK sunucusu başlatılıyor... D-BUS: JACK server could not be started. Sorry D-BUS: JACK sunucusu başlatılamadı. Üzgünüm JACK is starting... JACK başlıyor... Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Bazı istemci ses uygulamaları hala aktif ve bağlılar. JACK ses sunucusunu durdurmak istiyor musunuz? JACK is stopping... JACK durduruluyor... Shutdown script... Kapatma betiği... The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. Program sistem tepsisinde çalışmaya devam edecektir. Programı sonlandırmak için lütfen sistem tepsisi/içerik menüsünden "Çık"ı seçin. Don't ask this again Bunu bir daha sorma Shutdown script terminated Kapatma betiği sonlandırıldı D-BUS: JACK server is stopping... D-BUS: JACK sunucusu durduruluyor... D-BUS: JACK server could not be stopped. Sorry D-BUS: JACK sunucusu durdurulamadı. Üzgünüm Post-shutdown script... Kapatma sonrası betiği... Post-shutdown script terminated Kapatma sonrası betiği sonlandırıldı JACK was started with PID=%1. JACK, PID=%1 ile başlatıldı. The preset aliases have been changed: "%1" Do you want to save the changes? Ön ayarlı takma adlar değiştirildi: "%1" Değişiklikleri kaydetmek istiyor musunuz? D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: JACK sunucusu başlatıldı (%1 diğer adıyla jackdbus). JACK is being forced... JACK zorlanıyor... JACK was stopped JACK durduruldu D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: JACK sunucusu durduruldu (%1 diğer adıyla jackdbus). Error Hata Transport BBT (bar.beat.ticks) Transport BBT (ölçü:vuruş.ticks) Transport time code Transport zaman Kodu Elapsed time since last reset Son sıfırlamadan bu yana geçen süre Elapsed time since last XRUN Son XRUN'dan bu yana geçen süre Patchbay reset. Bağlantı paneli sıfırlandı. Could not load active patchbay definition. "%1" Disabled. Etkin bağlantı paneli tanımı yüklenemedi. "%1" Engellendi. Patchbay activated. Bağlantı Paneli etkinleştirildi. Patchbay deactivated. Bağlantı paneli devre dışı bırakıldı. Statistics reset. İstatistikler sıfırlandı. msec msec JACK connection graph change. JACK bağlantı grafiği değişikliği. XRUN callback (%1). XRUN geri dönüşü (%1). Buffer size change (%1). Arabellek boyutu değişikliği (%1). Shutdown notification. Kapatma uyarıları. Freewheel started... BAşıboş hareket başlatıldı... Freewheel exited. Başıboş hareketten çıkeıldı. Could not start JACK. Sorry. JACK başlatılamadı. Üzgünüm. JACK has crashed. JACK çöktü. JACK timed out. JACK zaman aşımına uğradı. JACK write error. JACK yazma hatası. JACK read error. JACK okuma hatası. Unknown JACK error (%d). Bilinmeyen JACK hatası (%d). JACK property change. JACK özelliği değişikliği. ALSA connection graph change. ALSA bağlantı grafiği değişikliği. JACK active patchbay scan JACK aktif bağlantı paneli taraması ALSA active patchbay scan ALSA aktif bağlantı paneli taraması JACK connection change. JACK bağlantısı değişikliği. ALSA connection change. ALSA bağlantı değişikliği. checked kontrol connected bağlandı disconnected bağlantıyı kesildi failed başarısız A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? Şu anda bir bağlantı paneli tanımı etkin, bu bağlantıyı yeniden yapmak muhtemeldir: %1 -> %2 Patchbay bağlantısını kaldırmak istiyor musunuz? Overall operation failed. Genel işlem başarısız oldu. Invalid or unsupported option. Geçersiz veya desteklenmeyen seçenek. Client name not unique. İstemci adı benzersiz değil. Server is started. Sunucu başlatıldı. Unable to connect to server. Sunucuya bağlanılamıyor. Server communication error. Sunucu iletişim hatası. Client does not exist. İstemci mevcut değil. Unable to load internal client. Dahili istemci yüklenemiyor. Unable to initialize client. İstemci başlatılamıyor. Unable to access shared memory. Paylaşılan belleğe erişilemiyor. Client protocol version mismatch. İstemci protokolü sürüm uyuşmazlığı. Could not connect to JACK server as client. - %1 Please check the messages window for more info. İstemci olarak JACK sunucusuna bağlanılamadı. - %1 Daha fazla bilgi için lütfen mesaj penceresini kontrol edin. Server configuration saved to "%1". Sunucu yapılandırması "%1" dizinine kaydedildi. Client activated. İstemci etkinleştirildi. Post-startup script... Başlangıç sonrası betiği... Post-startup script terminated Başlangıç sonrası betiği sonlandırıldı Command line argument... Komut satırı argümanı... Command line argument started Komut satırı argümanı başlatıldı Client deactivated. İstemci devre dışı bırakıldı. Transport rewind. Geri sarma. Transport backward. Geriye. Starting Başlatılıyor Transport start. Oynat. Stopping Durduruluyor Transport stop. Durdur. Transport forward. İleriye. Stopped Durduruldu %1 (%2%) %1 (%2 %) %1 (%2%, %3 xruns) %1 (%2%, %3 xruns) %1 % %1 % %1 Hz %1 Hz %1 frames %1 Frames Yes Evet No Hayır FW FW RT GZ Rolling Hareket Ediyor Looping Döngü %1 msec %1 ms XRUN callback (%1 skipped). XRUN geri dönüşü (%1 atlananlar). Started Başlatıldı Active Aktif Activating Etkinleştiriliyor Inactive Etkin değil &Hide &Gizli D-BUS: GetParameterConstraint('%1'): %2. (%3) D-BUS: Parametre Kısıtlamasını Al('%1'): %2. (%3) Mi&nimize K&üçült S&how &Göster Rest&ore &Geri Yükle &Stop &Durdur &Reset &Sıfırla &Presets &Ön ayarlar &Versioning Sürüm &oluşturma Re&fresh &Yenile S&ession &Oturum &Load... &Yükle... &Save... &Kaydet... Save and &Quit... Kaydet ve &Cık... Save &Template... &Şablonu Kaydet... &Connections &Bağlantılar Patch&bay Bağlantı &Paneli &Graph &Grafik &Transport &Transport Server settings will be only effective after restarting the JACK audio server. Sunucu ayarları yalnızca JACK ses sunucusunun yeniden başlatılmasından sonra geçerli olacaktır. Do you want to restart the JACK audio server? JACK ses sunucusunu yeniden başlatmak istiyor musunuz? D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: Parametre Değerini Ayarlayın('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: Parametre Değerini Sıfırla('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS: Parametre Değerini Al('%1'): %2. (%3) Some settings will be only effective the next time you start this program. Bazı ayarlar programın bir sonraki başlangıcında etkili olacaktır. qjackctlMessagesStatusForm Messages / Status Mesajlar/Durum &Messages &Mesajlar Messages log Mesajlar günlüğü Messages output log Mesajlar çıkış günlüğü &Status &Durum Status information Durum bilgisi Statistics since last server startup Son sunucu başlangıcından bu yana istatistikler Description Tanım Value Değer Reset XRUN statistic values XRUN istatistik değerlerini sıfırla Re&set &Sıfırla Refresh XRUN statistic values XRUN istatistik değerlerini tazele &Refresh &Tazele Server name Sunucu adı Server state Sunucu durumu DSP Load DSP yükü Sample Rate Örnekleme oranı Buffer Size Arabellek Boyutu Realtime Mode Gerçek Zamanlı Modu Transport state Transport durumu Transport Timecode Transport Zaman Kodu Transport BBT Transport BBT Transport BPM Transport BPM XRUN count since last server startup Sunucunun son başlangıcından bu yana XRUN sayısı XRUN last time detected XRUN'ın en son algılandığı zaman XRUN last Son XRUN XRUN maximum En çok XRUN XRUN minimum En az XRUN XRUN average XRUN ortalaması XRUN total Toplam XRUN Maximum scheduling delay Maksimum planlama gecikmesi Time of last reset Son sıfırlama zamanı Logging stopped --- %1 --- Günlüğe kaydetme durduruldu --- %1 --- Logging started --- %1 --- Günlüğe kaydetme başlatıldı --- %1 --- qjackctlPaletteForm Color Themes Renk Temaları Name İsim Current color palette name Geçerli renk paleti adı Save current color palette name Geçerli renk paleti adını kaydet Save Kaydet Delete current color palette name Geçerli renk paleti adını sil Delete Sil Palette Palet Current color palette Geçerli renk paleti Generate: Oluştur: Base color to generate palette Palet oluşturmak için temel renk Reset all current palette colors Mevcut tüm palet renklerini sıfırla Reset Sıfırla Import a custom color theme (palette) from file Dosyadan özel bir renk temasını (palet) içe aktar Import... İçe aktar... Export a custom color theme (palette) to file Özel bir renk temasını (palet) dosyaya aktarma Export... Dışa Aktar... Show Details Detayları Göster Import File - %1 %1 dosyasını içe aktar Palette files (*.%1) Palet dosyaları (*.%1) Save Palette - %1 All files (*.*) Tüm dosyalar (*.*) Warning - %1 Uyarı - %1 Could not import from file: %1 Sorry. Dosyadan içe aktarılamadı: %1 Üzgünüm. Export File - %1 Dosyayı Dışa Aktar - %1 Some settings have been changed. Do you want to discard the changes? Bazı ayarlar değiştirildi. Değişiklikleri silmek istiyor musunuz? Some settings have been changed: "%1". Do you want to save the changes? Bazı ayarlar değiştirildi: "%1". Değişiklikleri kaydetmek istiyor musunuz? qjackctlPaletteForm::PaletteModel Color Role Renk Rolü Active Etkin Inactive Etkin değil Disabled Devredışı qjackctlPatchbay Warning Uyarı This will disconnect all sockets. Are you sure? Bu, tüm soketlerin bağlantısını kesecektir. Emin misin? qjackctlPatchbayForm Patchbay Bağlantı Paneli Move currently selected output socket down one position Seçili olan çıkış soketini bir konum aşağıya taşı Down Aşağı Create a new output socket Yeni bir çıkış soketi oluşturun Add... Ekle... Edit currently selected input socket properties Şu anda seçili olan giriş soketi özelliklerini düzenle Edit... Düzenle... Move currently selected output socket up one position Seçili olan çıkış soketini bir konum yukarı taşı Up Yukarı Remove currently selected output socket Şu anda seçili olan çıkış soketini kaldır Remove Kaldır Duplicate (copy) currently selected output socket Şu anda seçili olan çıkış soketini çoğalt (kopyala) Copy... Kopyala... Remove currently selected input socket Şu anda seçili olan giriş soketini kaldır Duplicate (copy) currently selected input socket Şu anda seçili olan giriş soketini çoğalt (kopyala) Create a new input socket Yeni bir giriş soketi oluşturun Edit currently selected output socket properties Şu anda seçili çıkış soketi özelliklerini düzenle Connect currently selected sockets Şu anda seçili olan soketleri bağlayın &Connect &Bağlan Disconnect currently selected sockets Şu anda seçili olan soketlerin bağlantısını kesin &Disconnect Ba&ğlantıyı Kes Disconnect all currently connected sockets Şu anda bağlı olan tüm soketlerin bağlantısını kesin Disconnect &All Bütün Bağ. &Kes Expand all items Tüm öğeleri genişlet E&xpand All Tümün&ü genişlet Refresh current patchbay view Mevcut bağlantı paneli görünümünü yenile &Refresh &Yenile Create a new patchbay profile Yeni bir bağlantı paneli profili oluşturun &New &Yeni Load patchbay profile Bağlantı paneli profilini yükle &Load... &Yükle... Save current patchbay profile Mevcut bağlantı paneli profilini kaydet &Save... &Kaydet... Current (recent) patchbay profile(s) Güncel (yeni) bağlantı paneli profil(ler)i Toggle activation of current patchbay profile Mevcut bağlantı paneli profilinin etkinleştirilmesini aç/kapat Acti&vate &Etkinleştir Warning Uyarı The patchbay definition has been changed: "%1" Do you want to save the changes? Bağlantı paneli tanımı değiştirildi: "%1" Değişiklikleri kaydetmek istiyor musunuz? %1 [modified] %1 [değiştirildi] Untitled%1 Başlıksız%1 Error Hata Could not load patchbay definition file: "%1" Bağlantı paneli tanım dosyası yüklenemedi: "%1" Could not save patchbay definition file: "%1" Bağlantı paneli tanım dosyası kaydedilemedi: "%1" New Patchbay definition Yeni bağlantı paneli tanımı Create patchbay definition as a snapshot of all actual client connections? Tüm istemci bağlantılarının anlık görüntü olarak bağlantı paneli tanımı oluşturulsun mu? Load Patchbay Definition Bağlantı Paneli Tanımını Yükle Patchbay Definition files Bağlantı Paneli Tanımını Kaydet Save Patchbay Definition Bağlantı Paneli Tanımını Kaydet active etkin qjackctlPatchbayView Add... Ekle... Edit... Düzenle... Copy... Kopyala... Remove Sil Exclusive Özel Forward İleri (None) (Hiçbiri) Move Up Yukarı taşı Move Down Aşağı Taşı &Connect &Bağlan Alt+C Connect Alt+C &Disconnect &Bağlantıyı Kes Alt+D Disconnect Alt+D Disconnect &All &Tüm Bağlantıları Kes Alt+A Disconnect All Alt+A &Refresh &Yenile Alt+R Refresh Alt+R qjackctlSessionForm Session Oturum Load session Oturum yükle &Load... &Yükle... Recent session Önceki Oturum &Recent &Önceki Save session Oturumu kaydet &Versioning Sürüm &oluştur Re&fresh &Yenile Infra-clients / commands Alt-istemciler / komutlar Infra-client Alt-istemci Infra-command Alt-komut Add infra-client Alt-istemci Ekle &Add &Ekle Edit infra-client Alt-istemciyi Düzenle &Edit &Düzenle Remove infra-client Alt-istemci Kaldır Re&move &Kaldır &Save... &Kaydet... Update session Oturumu Güncelle Session clients / connections Oturum istemcileri/bağlantıları Client / Ports İstemci / Bağlantı Noktaları UUID UUID Command Komut &Save &Kaydet Load Session Oturum Yükle Session directory Oturum dizini Save Session Oturumu Kaydet and Quit ve Çık Template Şablon &Clear &Temizle Warning Uyarı A session could not be found in this folder: "%1" Bu klasörde bir oturum bulunamadı: "%1" %1: loading session... %1: oturum yükleniyor... %1: load session %2. %1: oturum yükleniyor %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? Bu klasörde zaten bir oturum var: "%1" Mevcut oturumun üzerine yazacağınızdan emin misiniz? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Bu klasör zaten mevcut ve boş değil: "%1" Mevcut klasörün üzerine yazacağınızdan emin misiniz? %1: saving session... %1: oturum kaydediliyor... %1: save session %2. %1: oturum kaydediliyor %2. New Client Yeni İstemci Save and &Quit... Kaydet ve &Cık... Save &Template... &Şablonu Kaydet... qjackctlSessionInfraClientItemEditor Infra-command Alt-komut qjackctlSessionSaveForm Session Oturum &Name: &İsmi: Session name &Directory: Session directory Oturum dizini Browse for session directory ... ... Save session versioning Oturum sürümünü kaydet &Versioning Warning Uyarı Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings Ayarlar Preset &Name: &Önayar Adı: Settings preset name Ayarlar önayar adı (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Save settings as current preset name Ayarları mevcut ön ayar adı olarak kaydedin &Save &Kaydet Delete current settings preset Mevcut ön ayarları sil &Delete &Sil jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE Driv&er: Sü&rücü: The audio backend driver interface to use Kullanılacak ses arka uç sürücüsü arayüzü dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters Parametreler MIDI Driv&er: MIDI S&ürücüsü: The ALSA MIDI backend driver to use Kullanılacak ALSA MIDI arka uç sürücüsü none hiçbiri raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Time in seconds that client is delayed after server startup Sunucu başlatıldıktan sonra istemcinin geciktiği saniye cinsinden süre Latency: Gecikme: Output latency in milliseconds, calculated based on the period, rate and buffer settings Dönem, hız ve arabellek ayarlarına göre hesaplanan, milisaniye cinsinden çıkış gecikmesi Use realtime scheduling Gerçek zamanlı düzenlemeyi kullanın &Realtime &Gerçek Zamanlı Do not attempt to lock memory, even if in realtime mode Gerçek zamanlı modda olsa bile belleği kilitlemeye çalışmayın No Memory Loc&k Bellek Kilidi &Yok Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) Yaygın araç seti kitaplıkları (GTK+, QT, FLTK, Wine) belleğinin kilidini açın &Unlock Memory &Bellek Kilidini Aç Ignore xruns reported by the backend driver Arka uç sürücüsü tarafından bildirilen xrun'ları yoksay So&ft Mode &Yumuşak Mod Provide output monitor ports Çıkış monitör bağlantı noktalarını sağlayın &Monitor &Monitör Force 16bit mode instead of failing over 32bit (default) 32 bitin üzerine çıkmak yerine 16 bit modunu zorlayın (varsayılan) Force &16bit &16bit'i zorla Enable hardware metering on cards that support it Destekleyen kartlarda donanım ölçümünü etkinleştirin H/&W Meter H/&W Ölçer Ignore hardware period/buffer size Donanım periyodunu/arabellek boyutunu göz ardı et &Ignore H/W &H/W'yi Yoksay Whether to give verbose output on messages Mesajlara ayrıntılı çıktı verilip verilmeyeceği &Verbose messages &Ayrıntılı mesajlar &Output Device: &Çıkış aygıtı: &Interface: &Arayüz: Maximum input audio hardware channels to allocate Atanacak maksimum ses giriş donanımı &Audio: &Ses: Dit&her: Tit&reme: External output latency (frames) Harici çıkış gecikmesi (kareler) &Input Device: &Giriş Cihazı: Provide either audio capture, playback or both Ses yakalama, oynatma veya her ikisini de sağlayın Duplex Çift Yönlü Capture Only Yalnızca Yakala Playback Only Yalnızca Oynatma The PCM device name to use Kullanılacak PCM cihazı adı hw:0 hw:0 plughw:0 plughw:0 /dev/audio /dev/audio /dev/dsp /dev/dsp > > Alternate input device for capture Yakalama için alternatif giriş cihazı Maximum output audio hardware channels to allocate Atanacak maksimum ses çıkış donanımı Alternate output device for playback Oynatma için alternatif çıkış cihazı External input latency (frames) Harici giriş gecikmesi (kareler) Set dither mode Titreme modunu ayarla None Hiçbiri Rectangular Dikdörtgen Shaped Şekillendirilmiş Triangular Üçgensel Number of periods in the hardware buffer Donanım arabelleğindeki dönem sayısı Server &Prefix: Sunucu &Öneki: Server path (command line prefix) Sunucu yolu (komut satırı öneki) Priorit&y: &Öncelik: &Frames/Period: &Çerçeveler/Dönem: Frames per period between process() calls İşem() çağrıları arasındaki dönem başına kare sayısı 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Port Ma&ximum: Maksimum Bağlantı &Noktası : &Channels: &Kanallar: 21333 21333 Sample rate in frames per second Saniye başına kare cinsinden örnekleme hızı 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 192000 192000 Scheduler priority when running realtime Gerçek zamanlı çalıştırırken zamanlayıcı önceliği &Word Length: &Kelime uzunluğu: Periods/&Buffer: Dönemler/&Tampon: Word length Kelime uzunluğu Maximum number of ports the JACK server can manage JACK sunucusunun yönetebileceği maksimum bağlantı noktası sayısı &Wait (usec): &Bekle (usec): Sample &Rate: &Örnekleme Oranı: Maximum number of audio channels to allocate Atanacak maksimum ses kanalı sayısı &Timeout (msec): &Zaman Aşımı (msn): Set client timeout limit in milliseconds İstemci zaman aşımı sınırını milisaniye cinsinden ayarla 200 200 500 500 1000 1000 2000 2000 5000 5000 &Channels I/O: &Kanallar G/Ç: &Latency I/O: &Gecikme G/Ç: Server Suffi&x: Sunucu Ek&i: Start De&lay: Başlangıç &Gecikmesi: secs s 0 msecs 0 ms Whether to restrict client self-connections İstemcinin kendi kendine bağlantılarının kısıtlanıp kısıtlanmayacağı Advanced Gelişmiş Clear settings of current preset name Geçerli ön ayar adının ayarlarını temizle Clea&r &Temizle Cloc&k source: &Saat kaynağı: Clock source Saat kaynağı S&elf connect mode: K&endi kendine bağlantı modu: Options Seçenekler Scripting Betik Whether to execute a custom shell script before starting up the JACK audio server. JACK ses sunucusunu başlatmadan önce özel bir betik yürütülüp yürütülmeyeceği. Execute script on Start&up: Açılırken &betiği çalıştır: Whether to execute a custom shell script after starting up the JACK audio server. JACK ses sunucusunu başlattıktan sonra özel birbetiğin yürütülüp yürütülmeyeceği. Execute script after &Startup: Başlatmadan &sonra betiği çalıştır: Whether to execute a custom shell script before shuting down the JACK audio server. JACK ses sunucusunu kapatmadan önce özel bir betiğin yürütülüp yürütülmeyeceği. Execute script on Shut&down: Kapanırken be&tiği çalıştır: Command line to be executed before starting up the JACK audio server JACK ses sunucusunu başlatmadan önce yürütülecek betik Scripting argument meta-symbols Betik değişkeninin meta sembolleri Browse for script to be executed before starting up the JACK audio server JACK ses sunucusunu başlatmadan önce yürütülecek betiğe göz atın ... ... Command line to be executed after starting up the JACK audio server JACK ses sunucusunu başlattıktan sonra yürütülecek komut satırı Browse for script to be executed after starting up the JACK audio server JACK ses sunucusunu başlattıktan sonra yürütülecek komut dosyasına göz atın Browse for script to be executed before shutting down the JACK audio server JACK ses sunucusunu kapatmadan önce yürütülecek komut dosyasına göz atın Command line to be executed before shutting down the JACK audio server JACK ses sunucusunu kapatmadan önce yürütülecek komut satırı Whether to execute a custom shell script after shuting down the JACK audio server. JACK ses sunucusunu kapattıktan sonra özel bir kabuk komut dosyasının yürütülüp yürütülmeyeceği. Execute script after Shu&tdown: Kapatmadan sonra &betiği çalıştır: Browse for script to be executed after shutting down the JACK audio server JACK ses sunucusu kapatıldıktan sonra yürütülecek komut dosyasına göz atın Command line to be executed after shutting down the JACK audio server JACK ses sunucusu kapatıldıktan sonra yürütülecek komut satırı Statistics İstatistik Whether to capture standard output (stdout/stderr) into messages window Mesaj penceresine standart çıktının (stdout/stderr) yakalanıp yakalanmayacağı &Capture standard output &Standart çıktıyı yakala &XRUN detection regex: &XRUN algılama ifadesi: Regular expression used to detect XRUNs on server output messages Sunucu çıkış mesajlarındaki XRUN'ları tespit etmek için kullanılan normal ifade xrun of at least ([0-9|\.]+) msecs en az ([0-9|\.]+) msn xrun Connections Bağlantılar KXStudio KXStudio Whether to enable JACK D-Bus interface JACK D-Bus arayüzünün etkinleştirilip etkinleştirilmeyeceği &Enable JACK D-Bus interface &JACK D-Bus arayüzünü etkinleştir Whether to replace Connections with Graph button on the main window Bağlantıların ana penceredeki Grafik düğmesiyle değiştirilip değiştirilmeyeceği Replace Connections with &Graph button Bağlantıları &Grafik düğmesiyle değiştir 10 10 Patchbay definition file to be activated as connection persistence profile Bağlantı paneli tanım dosyası kalıcı bağlantı profili olarak etkinleştirilecek Browse for a patchbay definition file to be activated Etkinleştirilecek bir bağlantı paneli tanım dosyasına göz atın Whether to activate a patchbay definition for connection persistence profile. Kalıcı bağlantı profili için bir bağlantı paneli tanımının etkinleştirilip etkinleştirilmeyeceği. Activate &Patchbay persistence: &Bağlantı paneli kalıcılığını etkinleştirin: Logging Günlük Messages log file Mesajlar günlük dosyası Browse for the messages log file location Mesajlar günlük dosyası konumuna göz atın Whether to activate a messages logging to file. Günlüğe kaydedilen mesajların etkinleştirilip etkinleştirilmeyeceği. Setup Kurulum Whether to use server synchronous mode Sunucu senkronize modunun kullanılıp kullanılmayacağı &Use server synchronous mode &Sunucu eşzamanlı modunu kullan Please do not touch these settings unless you know what you are doing. Ne yaptığınızı bilmiyorsanız lütfen bu ayarlara dokunmayın. Extra driver options (command line suffix) Ekstra sürücü seçenekleri (komut satırı son eki) Whether to reset all connections when a patchbay definition is activated. Bir bağlantı paneli tanımı etkinleştirildiğinde tüm bağlantıların sıfırlanıp sıfırlanmayacağı. &Reset all connections on patchbay activation &Bağlantı paneli aktivasyonundaki tüm bağlantıları sıfırla Whether to issue a warning on active patchbay port disconnections. Etkin bağlantı panelinin bağlantı kesintilerinde uyarı verilip verilmeyeceği. &Warn on active patchbay disconnections &Etkin bağlantı paneli kesintilerinde uyar &Messages log file: &Mesajlar günlük dosyası: Display Görünüm Time Display Zaman Görünümü Transport &Time Code Transport &Zaman Kodu Transport &BBT (bar:beat.ticks) Transport &BBT (ölçü:vuruş.ticks) Elapsed time since last &Reset Son &Sıfırlamadan bu yana geçen süre Elapsed time since last &XRUN Son &XRUN'dan bu yana geçen süre Sample front panel normal display font Örnek ön panel normal ekran yazı tipi Sample big time display font Örnek büyük zamanlı ekran yazı tipi Big Time display: Büyük Zaman ekranı: Select font for front panel normal display Ön panel normal ekranı için yazı tipini seçin &Font... &Yazı tipi... Select font for big time display Büyük zamanlı gösterim için yazı tipini seçin Normal display: Normal ekran: Whether to enable blinking (flashing) of the server mode (RT) indicator Sunucu modu (RT) göstergesinin yanıp sönmesinin (yanıp sönmesinin) etkinleştirilip etkinleştirilmeyeceği Blin&k server mode indicator Yanıp sönen sunucu modu gösterges&i Custom Özel &Color palette theme: &Renk paleti teması: Custom color palette theme Özel renk paleti teması Wonton Soup DO NOT TRANSLATE DO NOT TRANSLATE Manage custom color palette themes Özel renk paleti temalarını yönetin &Widget style theme: &Widget stili teması: Custom widget style theme Özel widget stili teması Messages Window Mesajlar Penceresi Sample messages text font display Örnek mesaj metin yazı tipi ekranı Select font for the messages text display Mesaj metin ekranı için yazı tipini seçin Whether to keep a maximum number of lines in the messages window Mesaj penceresinde maksimum sayıda satır tutulup tutulmayacağı &Messages limit: &Mesaj sınırı: The maximum number of message lines to keep in view Görünümde tutulacak maksimum mesaj satırı sayısı 100 100 250 250 2500 2500 Connections Window Bağlantılar Penceresi Sample connections view font Örnek bağlantılar görünüm yazı tipi Select font for the connections view Bağlantılar görünümü için yazı tipini seçin &Icon size: &Simge boyutu: The icon size for each item of the connections view Bağlantılar görünümünün her bir öğesi için simge boyutu 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 Whether to enable in-place client/port name editing (rename) Yerinde istemci/bağlantı noktası adı düzenlemenin etkinleştirilip etkinleştirilmeyeceği (yeniden adlandırma) Ena&ble client/port aliases editing (rename) İstemci/&bağlantı noktası takma adlarını düzenlemeyi etkinleştir (yeniden adlandır) Whether to enable client/port name aliases on the connections window Bağlantılar penceresinde istemci/bağlantı noktası adı takma adlarının etkinleştirilip etkinleştirilmeyeceği E&nable client/port aliases İstemci/bağlantı noktası takma adlarını &etkinleştir Misc Çeşitli Other Whether to start JACK audio server immediately on application startup JACK ses sunucusunun uygulama başlangıcında hemen başlatılıp başlatılmayacağı &Start JACK audio server on application startup &Uygulama başlangıcında JACK ses sunucusunu başlat Whether to ask for confirmation on application exit Çıkışında onay sorulup sorulmayacağı JACK client/port pretty-name (metadata) display mode JACK istemcisi/bağlantı noktası güzel adı (meta veriler) görüntüleme modu Enable JA&CK client/port pretty-names (metadata) JA&CK istemci/bağlantı noktası güzel adlarını (meta veriler) etkinleştirin &Confirm application close &Uygulamayı kapatmayı onayla Whether to ask for confirmation on JACK audio server shutdown and/or restart JACK ses sunucusunun kapatılması ve/veya yeniden başlatılması konusunda onay istenip istenmeyeceği Confirm server sh&utdown and/or restart S&unucunun kapatılmasını ve/veya yeniden başlatılmasını onaylayın Whether to keep all child windows on top of the main window Tüm alt pencerelerin ana pencerenin üstünde tutulup tutulmayacağı &Keep child windows always on top &Alt pencereleri her zaman üstte tut Whether to enable the system tray icon Sistem tepsisi simgesinin etkinleştirilip etkinleştirilmeyeceği &Enable system tray icon &Sistem tepsisi simgesini etkinleştir Whether to start minimized to system tray Sistem tepsisine simge durumunda küçültülüp başlatılmayacağı Start minimi&zed to system tray Sistem tepsisinde k&üçültülmüş olarak başlat Whether to save the JACK server command-line configuration into a local file (auto-start) JACK sunucusu komut satırı yapılandırmasının yerel bir dosyaya kaydedilip kaydedilmeyeceği (otomatik başlatma) S&ave JACK audio server configuration to: &JACK ses sunucusu yapılandırmasını şu şekilde kaydedin: The server configuration local file name (auto-start) Sunucu yapılandırması yerel dosya adı (otomatik başlatma) .jackdrc .jackdrc Whether to enable ALSA Sequencer (MIDI) support on startup Başlangıçta ALSA Sıralayıcı (MIDI) desteğinin etkinleştirilip etkinleştirilmeyeceği E&nable ALSA Sequencer support &ALSA Sıralayıcı desteğini etkinleştirin Buttons Düğmeler Whether to hide the left button group on the main window Ana pencerede sol düğme grubunun gizlenip gizlenmeyeceği Hide main window &Left buttons Ana pencerede &Soldaki düğmeleri gizle Whether to hide the right button group on the main window Ana pencerede sağdaki düğme grubunun gizlenip gizlenmeyeceği Hide main window &Right buttons Ana pencerede &Sağdaki düğmeleri gizle Whether to hide the transport button group on the main window Ana pencerede transport düğmesi grubunun gizlenip gizlenmeyeceği Hide main window &Transport buttons Ana pencerede &Transport düğmelerini gizle Whether to hide the text labels on the main window buttons Ana pencere düğmelerindeki metin etiketlerinin gizlenip gizlenmeyeceği Hide main window &button text labels Ana pencerede &düğme metinlerini gizle System Sistem Cycle Döngü HPET HPET Don't restrict self connect requests (default) Kendi kendine bağlantı isteklerini kısıtlama (varsayılan) Fail self connect requests to external ports only Yalnızca harici bağlantı noktalarına yapılan kendi kendine bağlantı istekleri başarısız oldu Ignore self connect requests to external ports only Yalnızca harici bağlantı noktalarına yönelik kendi kendine bağlanma isteklerini yoksay Fail all self connect requests Tüm kendi kendine bağlantı isteklerinin başarısız Ignore all self connect requests Tüm kendi kendine bağlanma isteklerini yoksay Warning Uyarı Some settings have been changed: "%1" Do you want to save the changes? Bazı ayarlar değiştirildi: "%1" Değişiklikleri kaydetmek istiyor musunuz? Delete preset: "%1" Are you sure? Ön ayarı sil: "%1" Emin misin? msec ms n/a n/a &Preset Name &Ön Ayar Adı &Server Name &Sunucu adı &Server Path &Sunucu yolu &Driver &Sürücü &Interface &Arayüz Sample &Rate Örnekleme &Hızı &Frames/Period &Çerçeveler/Dönem Periods/&Buffer Dönemler/&Tampon Startup Script Başlangıç betiği Post-Startup Script Başlangıç Sonrası Betiği Shutdown Script Kapatma betiği Post-Shutdown Script Kapatma Sonrası Betiği Active Patchbay Definition Aktif Bağlantı Paneli Tanımı Patchbay Definition files Bağlantı Paneli Tanım dosyaları Messages Log Mesaj Günlüğü Log files Günlük dosyaları Information Bilgi Some settings may be only effective next time you start this application. Bazı ayarlar yalnızca bu uygulamayı bir sonraki başlatışınızda etkili olabilir. Some settings have been changed. Do you want to apply the changes? Bazı ayarlar değiştirildi. Değişiklikleri uygulamak istiyor musunuz? &JACK client/port aliases: &JACK istemci/bağlantı noktası takma adları: JACK client/port aliases display mode JACK istemcisi/bağlantı noktası takma adları görüntüleme modu Default Varsayılan First Birinci Second İkinci Whether to show system tray message on main window close Ana pencere kapatıldığında sistem tepsisi mesajının gösterilip gösterilmeyeceği Sho&w system tray message on close Kapatıldığın&da sistem tepsisi mesajını göster Whether to stop JACK audio server on application exit Uygulama çıkışında JACK ses sunucusunun durdurulup durdurulmayacağı S&top JACK audio server on application exit Uygulama çıkışında JACK ses sunucusunu &durdur Defaults Varsayılanlar &Base font size: &Temel yazı tipi boyutu: Base application font size (pt.) Temel uygulama yazı tipi boyutu (pt.) 6 6 7 7 8 8 9 9 11 11 12 12 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to enable D-Bus interface D-Bus arayüzünün etkinleştirilip etkinleştirilmeyeceği &Enable D-Bus interface &D-Bus arayüzünü etkinleştir Number of microseconds to wait between engine processes (dummy) Motor işlemleri arasında beklenecek mikrosaniye sayısı (dummy) &Name: &İsmi: The JACK Audio Connection Kit sound server name JACK Ses bağlantı araçları sunucusu adı netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to restrict to one single application instance (X11) Tek bir uygulama örneğiyle sınırlandırılıp kısıtlanmayacağı (X11) Single application &instance Tek uygulama &örneği qjackctlSocketForm Socket Bağlantı &Socket &Bağlantısı &Name (alias): &İsim (Takma ad): Socket name (an alias for client name) Bağlantı adı (istemci adı için bir takma ad) Client name (regular expression) İstemci adı (normal ifade) Add plug to socket plug list Soket fiş listesine bağlantı ekle Add P&lug Bağlantı &Ekle &Plug: Bağ&lantı Noktaları: Port name (regular expression) Bağlantı noktası adı (normal ifade) Socket plug list Bağlantı fişi listesi Socket Plugs / Ports Bağlantı Fişleri / Bağlantı Noktaları Edit currently selected plug Şu anda seçili olan fişi düzenle &Edit &Düzenle Remove currently selected plug from socket plug list Şu anda seçili olan fişi bağlantı fişi listesinden kaldır &Remove &Kaldır &Client: &İstemci: Move down currently selected plug in socket plug list &Down &Aşağı Move up current selected plug in socket plug list &Up &Yukarı Enforce only one exclusive cable connection Yalnızca tek bir özel kablo bağlantısına zorunlu kılın E&xclusive &Özel &Forward: &İleri: Forward (clone) all connections from this socket Type Tip Audio socket type (JACK) Ses soketi tipi (JACK) &Audio &Ses MIDI socket type (JACK) MIDI soket tipi (JACK) &MIDI &MIDI MIDI socket type (ALSA) MIDI soket tipi (ALSA) AL&SA &ALSA Plugs / Ports Fişler / Bağlantı Noktaları Error Hata A socket named "%1" already exists. "%1" adlı bir bağlantı zaten mevcut. Warning Uyarı Some settings have been changed. Do you want to apply the changes? Bazı ayarlar değiştirildi. Değişiklikleri uygulamak istiyor musunuz? Add Plug Bağlantı Ekle Edit Düzenle Remove Kaldır Move Up Yukarı Taşı Move Down Aşağı Taşı (None) (Hiçbiri) qjackctlSocketList Output Çıkış Input Giriş Socket Bağlantı <New> - %1 <Yeni> - %1 Warning Uyarı %1 about to be removed: "%2" Are you sure? %1 kaldırılmak üzere: "%2" Emin misin? %1 <Copy> - %2 %1 <Kopyala> - %2 qjackctlSocketListView Output Sockets / Plugs Çıkış Bağlantıları Input Sockets / Plugs Giriş Bağlantıları qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_de.ts0000644000000000000000000000013214771215054020520 xustar0030 mtime=1743067692.332636551 30 atime=1743067692.331636555 30 ctime=1743067692.332636551 qjackctl-1.0.4/src/translations/qjackctl_de.ts0000644000175000001440000063415214771215054020523 0ustar00rncbcusers PortAudioProber Probing... Please wait, PortAudio is probing audio hardware. Warning Warnung Audio hardware probing timed out. QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Usage: %1 [options] [command-and-args] Benutzung: %1 [Optionen] [Kommandos und Argumente] Options: Optionen: Start JACK audio server immediately. Set default settings preset name. Set active patchbay definition file. Set default JACK audio server name. Show help about command line options. Show version information. Launch command with arguments. [command-and-args] Option -p requires an argument (preset). Option -p benötigt ein Argument (Preset). Option -a requires an argument (path). Option -a benötigt ein Argument (Pfad). Option -n requires an argument (name). Option -n benötigt ein Argument (Name). %1 (%2 frames) Move Rename qjackctlAboutForm About &Close &Schließen About Qt Über Qt Version Version Debugging option enabled. Debugging-Option aktiviert. System tray disabled. Benachrichtigungsfeld deaktiviert. Transport status control disabled. Transportstatuskontrolle abgeschaltet. Realtime status disabled. Echtzeitstatus deaktiviert. XRUN delay status disabled. XRUN Verzögerungsstatus abgeschaltet. Maximum delay status disabled. Status für maximale Verzögerung abgeschaltet. JACK MIDI support disabled. JACK MIDI wird nicht unterstütz. JACK Session support disabled. JACK Session nicht unterstützt. ALSA/MIDI sequencer support disabled. ALSA/MIDI Sequencer wird nicht unterstützt. Using: Qt %1 JACK %1 Website Webseite This program is free software; you can redistribute it and/or modify it Dieses Programm ist freie Software; Sie können es gemäß der under the terms of the GNU General Public License version 2 or later. GNU General Public License weiterverteilen und/oder modifizieren. JACK Port aliases support disabled. Alternativnamen für JACK-Anschlüsse abgeschaltet. D-Bus interface support disabled. Unterstützung der D-Bus-Schnittstelle abgeschaltet. qjackctlClientListView Readable Clients / Output Ports Lesbare Clients/Ausgänge Writable Clients / Input Ports Beschreibbare Clients/Eingänge &Connect &Verbinden Alt+C Connect Alt+V &Disconnect &Trennen Alt+D Disconnect Alt+T Disconnect &All &Alle trennen Alt+A Disconnect All Alt+A Re&name &Umbenennen Alt+N Rename Alt+U &Refresh Au&ffrischen Alt+R Refresh Alt+F qjackctlConnect Warning Warnung This will suspend sound processing from all client applications. Are you sure? Hiermit wird die Klangverarbeitung aller Client-Anwendungen unterbrochen. Sind Sie sicher? qjackctlConnectionsForm Connections Verbindungen Audio Audio Connect currently selected ports Ausgewählte Anschlüsse verbinden &Connect &Verbinden Disconnect currently selected ports Ausgewählte Anschlüsse trennen &Disconnect &Trennen Disconnect all currently connected ports Alle verbundenen Anschlüsse trennen Disconnect &All &Alle trennen Expand all client ports Alle Client-Anschlüsse aufklappen E&xpand All Alle auf&klappen Refresh current connections view Ansicht der bestehenden Verbindungen erneuern &Refresh &Auffrischen MIDI JACK-MIDI ALSA ALSA-MIDI qjackctlConnectorView &Connect &Verbinden Alt+C Connect Alt+V &Disconnect &Trennen Alt+D Disconnect Trennen Disconnect &All &Alle trennen Alt+A Disconnect All Alt+A &Refresh Au&ffrischen Alt+R Refresh Alt+F qjackctlGraphCanvas Connect Disconnect qjackctlGraphForm Graph &Graph &Edit &Bearbeiten &View &Zoom Co&lors S&ort &Help &Connect Connect Connect selected ports &Disconnect &Trennen Disconnect Disconnect selected ports Ctrl+C T&humbview Ctrl+D Cl&ose Close Close this application window Select &All Select All Ctrl+A Select &None Select None Ctrl+Shift+A Select &Invert Select Invert Ctrl+I &Rename... Rename item Rename Item F2 &Find... Find Find nodes Ctrl+F &Menubar Menubar Show/hide the main program window menubar Ctrl+M &Toolbar Toolbar Show/hide main program window file toolbar &Statusbar Statusbar Show/hide the main program window statusbar &Top Left Top left Show the thumbnail overview on the top-left Top &Right Top right Show the thumbnail overview on the top-right Bottom &Left Bottom Left Bottom left Show the thumbnail overview on the bottom-left &Bottom Right Bottom right Show the thumbnail overview on the bottom-right &None None Keiner Hide thumbview Hide the thumbnail overview Text Beside &Icons Text beside icons Show/hide text beside icons &Center Center Center view &Refresh Refresh Refresh view F5 Zoom &In Zoom In Ctrl++ Zoom &Out Zoom Out Ctrl+- Zoom &Fit Zoom Fit Ctrl+0 Zoom &Reset Zoom Reset Ctrl+1 &Zoom Range Zoom Range JACK &Audio... JACK Audio color JACK &MIDI... JACK MIDI JACK MIDI color ALSA M&IDI... ALSA MIDI ALSA MIDI color JACK &CV... JACK CV color JACK &OSC... JACK OSC JACK OSC color &Reset &Zurücksetzen Reset colors Port &Name Port name Sort by port name Port &Title Port title Sort by port title Port &Index Port index Sort by port index &Ascending Ascending Ascending sort order &Descending Descending Descending sort order Repel O&verlapping Nodes Repel nodes Repel overlapping nodes Connect Thro&ugh Nodes Connect Through Nodes Connect through nodes Whether to draw connectors through or around nodes &About... About... About Show information about this application program About &Qt... About Qt... About Qt Über Qt Show information about the Qt toolkit &Undo &Redo Undo last edit action Redo last edit action Zoom Ready Colors - %1 qjackctlMainForm Quit processing and exit Signalverarbeitung und Programm beenden &Quit &Beenden Start the JACK server JACK-Server starten &Start &Start Stop the JACK server JACK-Server beenden S&top S&topp St&atus St&atus... Show information about this application Informationen über diese Anwendung anzeigen Ab&out... &Über... Set&up... &Einstellungen... Show settings and options dialog Dialogfenster für Einstellungen und Optionen anzeigen &Messages &Meldungen... Show/hide the patchbay editor window Steckfeldfenster anzeigen/verbergen &Patchbay Ste&ckfeld... &Connect &Verbinden... JACK server state Status des JACK-Servers JACK server mode Modus des JACK-Servers DSP Load DSP-Last Sample rate Abtastrate XRUN Count (notifications) XRUN Anzahl (Benachrichtigungen) Time display Zeitanzeige Transport state Transportstatus Transport BPM Transport BPM Transport time Transport Zeit Show/hide the session management window Fenster für Sitzungsmanagement anzeigen/verbergen Show/hide the messages log/status window Meldungsfenster anzeigen/verbergen Show/hide the graph window Show/hide the connections window Backward transport Transport rückwärts &Backward &Rückwärts Forward transport Transport vorwärts &Forward &Vorwärts Rewind transport Transport zurückspulen &Rewind &Zurückspulen Stop transport rolling Transportvorgang anhalten Pa&use Pa&usieren Start transport rolling Transportvorgang starten &Play Abs&pielen Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. ALSA Sequencer konnte nicht als Client geöffnet werden. Das ALSA-MIDI-Steckfeld wird nicht verfügbar sein. D-BUS: Service is available (%1 aka jackdbus). D-BUS: Dienst ist verfügbar (%1 aka jackdbus). D-BUS: Service not available (%1 aka jackdbus). D-Bus: Dienst ist nicht verfügbar (%1 aka jackdbus). Information Information Don't show this message again Diese Meldung nicht mehr anzeigen Warning Warnung JACK is currently running. Do you want to terminate the JACK audio server? Der JACK-Server läuft noch. Wollen Sie diesen beenden? %1 is about to terminate. Are you sure? successfully erfolgreich with exit status=%1 mit Rückgabewert = %1 Could not start JACK. Maybe JACK audio server is already started. Konnte JACK nicht starten. Möglicherweise läuft der JACK-Server schon. Could not load preset "%1". Retrying with default. Konnte Einstellung "%1" nicht laden. Versuche erneut mit Voreinstellung. Could not load default preset. Sorry. Konnte leider die Voreinstellung nicht laden. Startup script... Start-Skript... Startup script terminated Start-Skript beendet D-BUS: JACK server is starting... D-BUS: JACK-Server startet... D-BUS: JACK server could not be started. Sorry D-BUS: JACK-Server konnte nicht gestartet werden. Tut mir Leid JACK is starting... JACK startet... Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Einige Client-Audio-Anwendungen sind noch aktiv und verbunden. Wollen Sie den JACK-Server anhalten? JACK is stopping... JACK fährt herunter... Shutdown script... Herunterfahr-Skript... The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. Programm läuft weiter sichtbar als Symbol im Benachrichtigungsfeld. Zum Beenden des Programms, wählen Sie bitte "Beenden" im Kontextmenü des Benachrichtigungsfeldsymbols. Don't ask this again Nicht nochmal nachfragen Shutdown script terminated Herunterfahr-Skript beendet D-BUS: JACK server is stopping... D-BUS: JACK-Server fährt herunter... D-BUS: JACK server could not be stopped. Sorry D-BUS: JACK-Server konnte nicht angehalten werden. Tut mir Leid Post-shutdown script... Nach-Herunterfahr-Skript... Post-shutdown script terminated Nach-Herunterfahr-Skript beendet JACK was started with PID=%1. JACK wurde mit PID = %1 gestartet. The preset aliases have been changed: "%1" Do you want to save the changes? Die Alternativbezeichnungen für Voreinstellungen wurden verändert: "%1" Änderungen speichern? D-BUS: JACK server was started (%1 aka jackdbus). D-BUS: JACK-Server wurde gestartet (%1 aka jackdbus). JACK is being forced... JACK wird gezwungen... JACK was stopped JACK wurde angehalten D-BUS: JACK server was stopped (%1 aka jackdbus). D-BUS: JACK-Server wurde angehalten (%1 aka jackdbus). Error Fehler Transport BBT (bar.beat.ticks) Transport BBT (bar.beat.ticks) Transport time code Transport Timecode Elapsed time since last reset Seit dem letzten Zurücksetzen vergangene Zeit Elapsed time since last XRUN Seit dem letzten XRUN vergangene Zeit Patchbay reset. Steckfeld zurückgesetzt. Could not load active patchbay definition. "%1" Disabled. Konnte aktive Steckfelddefinition nicht laden. Patchbay activated. Steckfeld aktiviert. Patchbay deactivated. Steckfeld deaktiviert. Statistics reset. Statistik zurückgesetzt. msec ms JACK connection graph change. Schaubild der JACK-Verbindungen geändert. XRUN callback (%1). Buffer size change (%1). Puffergröße geändert (%1). Shutdown notification. Benachrichtigung zum Herunterfahren. Freewheel started... Freewheel exited. Could not start JACK. Sorry. Konnte JACK nicht starten. JACK has crashed. JACK ist abgestürzt. JACK timed out. JACK Zeitüberschreitung. JACK write error. JACK Schreibfehler. JACK read error. JACK Lesefehler. Unknown JACK error (%d). Unbekannter JACK-Fehler (%d). JACK property change. JACK-Eigenschaft geändert. ALSA connection graph change. Schaubild der ALSA-Verbindungen geändert. JACK active patchbay scan JACK aktive Steckfeldsuche ALSA active patchbay scan ALSA aktive Steckfeldsuche JACK connection change. JACK-Verbindung geändert. ALSA connection change. ALSA-Verbindung geändert. checked überprüft connected verbunden disconnected getrennt failed fehlgeschlagen A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? Zur Zeit ist eine Steckfeldkonfiguration aktiv, die wahrscheinlich diese Verbindung rückgängig macht: %1 -> %2 Wollen Sie diese Steckfeldverbindung entfernen? Overall operation failed. Gesamtbetrieb schlug fehl. Invalid or unsupported option. Ungültige oder nicht unterstützte Option. Client name not unique. Name des Clients nicht einzigartig. Server is started. Server ist gestartet. Unable to connect to server. Verbindungsaufnahme zum Server gescheitert. Server communication error. Server-Kommunikationsfehler. Client does not exist. Client existiert nicht. Unable to load internal client. Interner Client konnte nicht geladen werden. Unable to initialize client. Client konnte nicht initialisiert werden. Unable to access shared memory. Kein Zugriff auf Shared Memory möglich. Client protocol version mismatch. Unpassende Client-Protokollversion Could not connect to JACK server as client. - %1 Please check the messages window for more info. Keine Verbindungsaufnahme als Client zum JACK-Server möglich. - %1 Bitte sehen Sie im Meldungsfenster nach weiteren Informationen. Server configuration saved to "%1". Serverkonfiguration nach "%1" gespeichert. Client activated. Client aktiviert Post-startup script... Nach-Start-Skript... Post-startup script terminated Nach-Start-Skript beendet Command line argument... Kommandozeilenargument... Command line argument started Kommandozeilenargument gestartet Client deactivated. Client deaktiviert. Transport rewind. Transport zurückspulen. Transport backward. Transport zurück. Starting Startet Transport start. Transport starten. Stopping Stoppe Transport stop. Transport anhalten. Transport forward. Transport vorwärts. Stopped Steht %1 (%2%) %1 (%2 %) %1 (%2%, %3 xruns) %1 (%2%, %3 xruns) %1 % %1 % %1 Hz %1 Hz %1 frames %1 Frames Yes Ja No Nein FW RT RT Rolling Rollt Looping Schleifen ausführend %1 msec %1 ms XRUN callback (%1 skipped). XRUN callback (%1 übersprungen). Started Läuft Active Aktiv Activating Aktivierend Inactive Inaktiv &Hide &Verbergen D-BUS: GetParameterConstraint('%1'): %2. (%3) Mi&nimize Mi&nimieren S&how An&zeigen Rest&ore Neu&laden &Stop &Stopp &Reset &Zurücksetzen &Presets &Voreinstellungen &Versioning &Versionierung Re&fresh Au&ffrischen S&ession S&itzung... &Load... &Laden... &Save... &Speichern... Save and &Quit... Speichern und &beenden... Save &Template... &Vorlage speichern... &Connections &Verbindungen Patch&bay Steck&feld &Graph &Transport &Transport Server settings will be only effective after restarting the JACK audio server. Die Server-Einstellungen werden erst nach einem Neustart des JACK-Servers wirksam. Do you want to restart the JACK audio server? D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) Some settings will be only effective the next time you start this program. Einige Einstellungen werden erst nach einem Neustart des Programms wirksam. qjackctlMessagesStatusForm Messages / Status &Messages &Meldungen Messages log Meldungsprotokoll Messages output log Meldungsausgabeprotokoll &Status &Status Status information Statusinformationen Statistics since last server startup Statistik seit dem letzten Serverstart Description Beschreibung Value Wert Reset XRUN statistic values Daten der XRUN-Statistik zurücksetzen Re&set &Zurücksetzen Refresh XRUN statistic values Daten der XRUN-Statistik erneuern &Refresh &Auffrischen Server name Servername Server state Serverstatus DSP Load DSP-Last Sample Rate Abtastrate Buffer Size Puffergröße Realtime Mode Echtzeit-Modus Transport state Transportstatus Transport Timecode Transport Timecode Transport BBT Transport BBT Transport BPM Transport BPM XRUN count since last server startup Anzahl XRUNs seit dem letzten Serverstart XRUN last time detected Zeitpunkt der letzten XRUN-Beobachtung XRUN last Letzter XRUN XRUN maximum XRUN Maximum XRUN minimum XRUN Minimum XRUN average XRUN Durchschnitt XRUN total XRUN Summe Maximum scheduling delay Maximale Zeitverzögerung Time of last reset Zeitpunkt der letzten Zurücksetzung Logging stopped --- %1 --- Protokollierung angehalten --- %1 --- Logging started --- %1 --- Protokollierung gestartet --- %1 --- qjackctlPaletteForm Color Themes Name Current color palette name Save current color palette name Save Delete current color palette name Delete Palette Current color palette Generate: Base color to generate palette Reset all current palette colors Reset Import a custom color theme (palette) from file Import... Export a custom color theme (palette) to file Export... Show Details Import File - %1 Palette files (*.%1) Save Palette - %1 All files (*.*) Warning - %1 Could not import from file: %1 Sorry. Export File - %1 Some settings have been changed. Do you want to discard the changes? Some settings have been changed: "%1". Do you want to save the changes? qjackctlPaletteForm::PaletteModel Color Role Active Aktiv Inactive Inaktiv Disabled qjackctlPatchbay Warning Warnung This will disconnect all sockets. Are you sure? Diese Aktion wird alle Anschlüsse trennen. Sind Sie sicher? qjackctlPatchbayForm Patchbay Move currently selected output socket down one position Ausgewählten Ausgangsanschlus eine Position nach unten verschieben Down Ab Create a new output socket Einen neuen Ausgangsanschlus anlegen Add... Hinzufügen... Edit currently selected input socket properties Eigenschaften des gewählten Eingangsanschlusses bearbeiten Edit... Bearbeiten... Move currently selected output socket up one position Ausgewählten Ausgangsanschluss eine Position nach oben verschieben Up Auf Remove currently selected output socket Ausgewählten Ausgangsanschluss entfernen Remove Entfernen Duplicate (copy) currently selected output socket Dupliziere den gewählten Ausgangsanschluss Copy... Kopieren... Remove currently selected input socket Ausgewählten Eingangsanschluss entfernen Duplicate (copy) currently selected input socket Dupliziere den gewählten Eingangsanschluss Create a new input socket Einen neuen Eingangsanschluss anlegen Edit currently selected output socket properties Eigenschaften des gewählten Ausgangsanschlusses bearbeiten Connect currently selected sockets Gewählte Anschlüsse miteinander verbinden &Connect &Verbinden Disconnect currently selected sockets Verbindung zwischen den gewählten Anschlüssen trennen &Disconnect &Trennen Disconnect all currently connected sockets Alle verbundenen Anschlüsse trennen Disconnect &All &Alle trennen Expand all items Alle Einträge aufklappen E&xpand All Alle auf&klappen Refresh current patchbay view Steckfeldansicht auffrischen &Refresh Auf&frischen Create a new patchbay profile Neues Steckfeldprofil anlegen &New &Neu Load patchbay profile Steckfeldprofil laden &Load... &Laden... Save current patchbay profile Aktuelles Steckfeldprofil speichern &Save... &Speichern... Current (recent) patchbay profile(s) Aktuelle (zuletzt verwendete) Steckfeldprofile Toggle activation of current patchbay profile Aktivierung des aktuellen Steckfeldprofils umschalten Acti&vate A&ktivieren Warning Warnung The patchbay definition has been changed: "%1" Do you want to save the changes? Die Steckfelddefinition wurde verändert: "%1" Wollen Sie die Änderungen speichern? %1 [modified] %1 [verändert] Untitled%1 Unbenannt%1 Error Fehler Could not load patchbay definition file: "%1" Konnte Steckfelddefinitionsdatei nicht laden: "%1" Could not save patchbay definition file: "%1" Konnte Steckfelddefinitionsdatei nicht speichern: "%1" New Patchbay definition Neue Steckfelddefinition Create patchbay definition as a snapshot of all actual client connections? Steckfelddefinitionsdatei als Schnappschuss der aktuell vorhandenen Verbindungen erstellen? Load Patchbay Definition Steckfelddefinition laden Patchbay Definition files Steckfelddefinitionsdateien Save Patchbay Definition Speichere Steckfelddefinition active aktiv qjackctlPatchbayView Add... Hinzufügen... Edit... Bearbeiten... Copy... Kopieren... Remove Entfernen Exclusive Exklusiv Forward Weiterleiten (None) (Keine) Move Up Nach oben Move Down Nach unten &Connect &Verbinden Alt+C Connect Alt+V &Disconnect &Trennen Alt+D Disconnect Alt+T Disconnect &All &Alle trennen Alt+A Disconnect All Alt+A &Refresh Auf&frischen Alt+R Refresh Alt+F qjackctlSessionForm Session Load session Sitzung laden &Load... &Laden... Recent session Letzte Sitzung &Recent &Zuletzt Save session Sitzung speichern &Versioning &Versionierung Re&fresh Au&ffrischen Infra-clients / commands Infra-client Infra-command Add infra-client &Add &Hinzufügen Edit infra-client &Edit &Bearbeiten Remove infra-client Re&move En&tfernen &Save... &Speichern... Update session Sitzung aktualisieren Session clients / connections Client / Ports Client/Eingänge UUID UUID Command Kommando &Save &Speichern Load Session Sitzung laden Session directory Sitzungsverzeichnis Save Session Sitzung speichern and Quit und beenden Template Vorlage &Clear &Löschen Warning Warnung A session could not be found in this folder: "%1" Eine Sitzung konnte in diesem Verzeichnis nicht gefunden werden: "%1" %1: loading session... %1: lade Sitzung... %1: load session %2. %1: lade Sitzung %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? Es existiert bereits eine Sitzung in diesem Verzeichnis: "%1" Soll diese Sitzung überschrieben werden? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Dieses Verzeichnis existiert bereits und ist nicht leer: "%1" Soll das existierende Verzeichnis überschrieben werden? %1: saving session... %1: speichere Sitzung... %1: save session %2. %1: speichere Sitzung %2. New Client Neuer Client Save and &Quit... Speichern und &beenden... Save &Template... &Vorlage speichern... qjackctlSessionInfraClientItemEditor Infra-command qjackctlSessionSaveForm Session &Name: &Name: Session name &Directory: Session directory Sitzungsverzeichnis Browse for session directory ... ... Save session versioning Sitzungsversionierung speichern &Versioning &Versionierung Warning Warnung Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings Einstellungen Preset &Name: &Benennung: Settings preset name Benennung der Einstellung (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Save settings as current preset name Einstellungen mit aktueller Benennung speichern &Save &Speichern Delete current settings preset Aktuelle Einstellung löschen &Delete &Löschen jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE Driv&er: Trei&ber: The audio backend driver interface to use Zu nutzender Audio-Schnittstellentreiber dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters Parameter MIDI Driv&er: MIDI-&Treiber: The ALSA MIDI backend driver to use Zu nutzender ALSA-MIDI-Treiber none keiner raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Time in seconds that client is delayed after server startup Zeitverzögerung für den Client nach Start des Servers Latency: Latenz: Output latency in milliseconds, calculated based on the period, rate and buffer settings Ausgangslatenz in Millisekunden. Berechnung basiert auf Perioden-, Abtastraten- und Puffereinstellungen Use realtime scheduling Echtzeitverarbeitung nutzen &Realtime Echt&zeit Do not attempt to lock memory, even if in realtime mode Keinen Arbeitsspeicher sperren, auch nicht im Echtzeitmodus No Memory Loc&k Spei&cher nicht sperren Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) Arbeitsspeicher von gängigen Bibliotheken (GTK+, Qt, FLTK, Wine) entsperren &Unlock Memory S&peicher entsperren Ignore xruns reported by the backend driver Xruns des Schnittstellentreibers ignorieren So&ft Mode So&ft-Modus Provide output monitor ports Anschlüsse zur Ausgangsüberwachung anbieten &Monitor &Überwachung Force 16bit mode instead of failing over 32bit (default) 16-Bit-Modus erzwingen statt versuchsweiser Aktivierung des 32-Bit-Modus (voreingestellt) Force &16bit &16 Bit erzwingen Enable hardware metering on cards that support it Hardware-Messung bei Karten aktivieren, die diese unterstützen H/&W Meter H/W &Messung Ignore hardware period/buffer size Ignoriere Periode/Puffergröße der Hardware &Ignore H/W &Ignoriere H/W Whether to give verbose output on messages Ausführliche Meldungen anzeigen &Verbose messages Aus&führliche Meldungen &Output Device: A&usgabegerät: &Interface: S&chnittstelle: Maximum input audio hardware channels to allocate Maximum belegbarer Audio-Hardware-Eingänge &Audio: &Audio: Dit&her: External output latency (frames) Externe Ausgangslatenz (Frames) &Input Device: Eingangsger&ät: Provide either audio capture, playback or both Entweder Audio-Aufnahme, -Wiedergabe oder beides anbieten Duplex Duplex Capture Only Nur Aufnahme Playback Only Nur Wiedergabe The PCM device name to use Name des genutzten PCM-Gerätes hw:0 hw:0 plughw:0 plughw:0 /dev/audio /dev/audio /dev/dsp /dev/dsp > > Alternate input device for capture Alternativer Geräteeingang für Aufnahme Maximum output audio hardware channels to allocate Maximum der belegbaren Audio-Hardware-Ausgänge Alternate output device for playback Alternatives Ausgabegerät für Wiedergabe External input latency (frames) Externe Eingangslatenz (Frames) Set dither mode Dither-Modus festlegen None Keiner Rectangular Rechteck Shaped Hüllkurve Triangular Dreieck Number of periods in the hardware buffer Anzahl der Perioden im Hardware-Puffer Server &Prefix: Server &Präfix: Server path (command line prefix) Serverpfad (Kommandozeilen Präfix) Priorit&y: Priorit&ät: &Frames/Period: &Frames/Periode: Frames per period between process() calls Frames pro Periode zwischen process() Aufrufen 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Port Ma&ximum: Ma&ximaler Port: &Channels: &Kanäle: 21333 21333 Sample rate in frames per second Abtastrate in Frames pro Sekunde 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 192000 192000 Scheduler priority when running realtime Priorität für die Echtzeitsteuerung &Word Length: Wortl&änge: Periods/&Buffer: Per&ioden/Puffer: Word length Wortlänge Maximum number of ports the JACK server can manage Maximum an Anschlüssen, die der JACK-Server verarbeiten kann &Wait (usec): &Warten (µs) Sample &Rate: Abtast&rate: Maximum number of audio channels to allocate Maximale Anzahl der belegbaren Audiokanäle festlegen &Timeout (msec): &Timeout (ms): Set client timeout limit in milliseconds Timeout-Limitierung für Clients festlegen; Angabe in Millisekunden 200 200 500 500 1000 1000 2000 2000 5000 5000 &Channels I/O: &Kanäle I/O: &Latency I/O: &Latenz I/O: Server Suffi&x: Server Suffi&x: Start De&lay: Startver&zögerung: secs s 0 msecs 0 ms Whether to restrict client self-connections Advanced Clear settings of current preset name Clea&r Cloc&k source: Clock source S&elf connect mode: Options Optionen Scripting Skript-Steuerung Whether to execute a custom shell script before starting up the JACK audio server. Festlegen, ob ein angepasstes Shell-Skript vor dem Start des JACK-Servers ausgeführt werden soll Execute script on Start&up: Skript &beim Start ausführen: Whether to execute a custom shell script after starting up the JACK audio server. Festlegen, ob ein angepasstes Shell-Skript nach dem Start des JACK-Servers ausgeführt werden soll. Execute script after &Startup: Skript &nach Start ausführen: Whether to execute a custom shell script before shuting down the JACK audio server. Festlegen, ob ein angepasstes Shell-Skript vor dem Herunterfahren des JACK-Servers ausgeführt werden soll Execute script on Shut&down: Skript beim &Herunterfahren ausführen: Command line to be executed before starting up the JACK audio server Vor dem Starten des JACK-Servers ausgeführte Kommandozeile Scripting argument meta-symbols Meta-Symbole der Skriptargumente Browse for script to be executed before starting up the JACK audio server Skript auswählen, das vor dem Starten des JACK-Servers ausgeführt wird ... ... Command line to be executed after starting up the JACK audio server Nach dem Starten des JACK-Servers ausgeführte Kommandozeile Browse for script to be executed after starting up the JACK audio server Skript auswählen, das nach dem Starten des JACK-Servers ausgeführt wird Browse for script to be executed before shutting down the JACK audio server Skript auswählen, das vor dem Herunterfahren des JACK-Servers ausgeführt wird Command line to be executed before shutting down the JACK audio server Vor dem Herunterfahren des JACK-Servers ausgeführte Kommandozeile Whether to execute a custom shell script after shuting down the JACK audio server. Festlegen, ob ein angepasstes Shell-Skript nach dem Herunterfahren des JACK-Servers ausgeführt werden soll. Execute script after Shu&tdown: Skript nach dem Herunter&fahren ausführen: Browse for script to be executed after shutting down the JACK audio server Skript auswählen, das nach dem Herunterfahren des JACK-Servers ausgeführt wird Command line to be executed after shutting down the JACK audio server Nach dem Herunterfahren des JACK-Servers ausgeführte Kommandozeile Statistics Statistik Whether to capture standard output (stdout/stderr) into messages window Standardausgabe (stdout/stderr) in Meldungsfenster umleiten &Capture standard output Standardausgabe &umleiten &XRUN detection regex: Regular expression used to detect XRUNs on server output messages Regulärer Ausdruck zur Erkennung von XRUNs in vom Server gesendeten Meldungen xrun of at least ([0-9|\.]+) msecs xrun mit mindestens ([0-9|\.]+) ms Connections Verbindungen KXStudio Whether to enable JACK D-Bus interface &Enable JACK D-Bus interface Whether to replace Connections with Graph button on the main window Replace Connections with &Graph button 10 10 Patchbay definition file to be activated as connection persistence profile Steckfelddefinitionsdatei als beständiges Verbindungsprofil aktivieren Browse for a patchbay definition file to be activated Eine Steckfelddefinitionsdatei zum aktivieren wählen Whether to activate a patchbay definition for connection persistence profile. Ein beständiges Verbindungsprofil für das Steckfeld aktivieren. Activate &Patchbay persistence: Steck&feldkonfiguration hat Bestand: Logging Protokollierung Messages log file Protokolldatei für Meldungen Browse for the messages log file location Speicherort für Protokolldatei wählen Whether to activate a messages logging to file. Protokollierung der Meldungen in eine Datei festlegen. Setup Whether to use server synchronous mode &Use server synchronous mode Please do not touch these settings unless you know what you are doing. Extra driver options (command line suffix) Sonderoptionen für Treiber (Kommandozeilen Präfix) Whether to reset all connections when a patchbay definition is activated. Alle Verbindungen zurücksetzen, wenn eine Steckfeldkonfiguration aktiviert wird &Reset all connections on patchbay activation Alle &Verbindungen bei Steckfaktivierung zurücksetzen Whether to issue a warning on active patchbay port disconnections. Warnung anzeigen, wenn eine aktive Verbindung getrennt wird &Warn on active patchbay disconnections Beim &Trennen aktiver Verbindungen warnen &Messages log file: &Protokolldatei: Display Anzeige Time Display Zeitanzeige Transport &Time Code Transport &BBT (bar:beat.ticks) Elapsed time since last &Reset Seit dem letzten &Zurücksetzen verstrichene Zeit Elapsed time since last &XRUN Seit dem letzten &XRUN verstrichene Zeit Sample front panel normal display font Beispielhafte Darstellung der normalen Anzeige Sample big time display font Beispielhafte Darstellung der großen Anzeige Big Time display: Große Zeitanzeige: Select font for front panel normal display Schriftart für normale Anzeige wählen &Font... &Schriftart... Select font for big time display Schriftart für große Zeitanzeige wählen Normal display: Normale Anzeige: Whether to enable blinking (flashing) of the server mode (RT) indicator Realtime-Indikator (RT) für Servermodus blinkend darstellen Blin&k server mode indicator Ser&vermodus blinkend darstellen Custom &Color palette theme: Custom color palette theme Wonton Soup DO NOT TRANSLATE DO NOT TRANSLATE Manage custom color palette themes &Widget style theme: Custom widget style theme Messages Window Meldungsfenster Sample messages text font display Beispielhafte Darstellung des Textes im Meldungsfenster Select font for the messages text display Schriftart für Text im Meldungsfenster wählen Whether to keep a maximum number of lines in the messages window Maximale Anzahl der im Meldungsfenster angezeigten Zeilen festlegen &Messages limit: &Meldungsmaximum: The maximum number of message lines to keep in view Maximale Anzahl der Nachrichten im Meldungsfenster 100 100 250 250 2500 2500 Connections Window Verbindungsübersicht Sample connections view font Beispielhafte Darstellung der Schrift in der Verbindungsübersicht Select font for the connections view Schriftart für Verbindungsübersicht wählen &Icon size: &Symbolgröße: The icon size for each item of the connections view Größe der einzelnen Symbole in der Verbindungsübersicht 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 Whether to enable in-place client/port name editing (rename) Direktes Bearbeiten der Client/Anschluss-Alternativbezeichnung (Alias) erlauben Ena&ble client/port aliases editing (rename) Bearbeiten von &Deckbezeichnungen für Client/Anschlüsse Whether to enable client/port name aliases on the connections window Verwendung von Deckbezeichnungen (Alias) für Anschlüsse in der Verbindungsübersicht erlauben E&nable client/port aliases Dec&kbezeichnungen (Alias) für Client/Anschlüsse Misc Verschiedenes Other Weiteres Whether to start JACK audio server immediately on application startup JACK-Server unmittelbar bei Anwendungsstart starten &Start JACK audio server on application startup JACK-&Server bei Anwendungsstart starten Whether to ask for confirmation on application exit Vor dem Beenden des JACK-Servers nachfragen JACK client/port pretty-name (metadata) display mode Enable JA&CK client/port pretty-names (metadata) &Confirm application close Beenden der An&wendung bestätigen Whether to ask for confirmation on JACK audio server shutdown and/or restart Confirm server sh&utdown and/or restart Whether to keep all child windows on top of the main window Alle Kindfenster oberhalb des Hauptfensters halten &Keep child windows always on top &Kindfenster immer oben belassen Whether to enable the system tray icon Anwendungssymbol im Benachrichtigungsfeld anzeigen &Enable system tray icon S&ymbol im Benachrichtigungsfeld anzeigen Whether to start minimized to system tray Anwendung minimiert als Symbol im Benachrichtigungsfeld starten Start minimi&zed to system tray Minimiert im &Benachrichtigungsfeld starten Whether to save the JACK server command-line configuration into a local file (auto-start) Kommandozeilenkonfiguration zum Starten des JACK-Servers in einer lokalen Datei speichern (auto-start) S&ave JACK audio server configuration to: Konfi&guration für JACK-Server speichern unter: The server configuration local file name (auto-start) Name der lokal gespeicherten Serverkonfigurationsdatei (auto-start) .jackdrc .jackdrc Whether to enable ALSA Sequencer (MIDI) support on startup Unterstützung für den ALSA Sequencer (MIDI) beim Programmstart aktivieren E&nable ALSA Sequencer support Unterstützung für ALSA-Se&quencer bereitstellen Buttons Schaltflächen Whether to hide the left button group on the main window Linke Schaltflächengruppe im Hauptfenster verbergen Hide main window &Left buttons &Linke Schaltflächen des Hauptfensters verbergen Whether to hide the right button group on the main window Rechte Schaltflächengruppe im Hauptfenster verbergen Hide main window &Right buttons &Rechte Schaltflächen des Hauptfensters verbergen Whether to hide the transport button group on the main window Schaltflächen der Transportsteuerung im Hauptfenster verbergen Hide main window &Transport buttons Schaltflächen für &Transportsteuerung verbergen Whether to hide the text labels on the main window buttons Beschriftung der Schaltflächen im Hauptfenster verbergen Hide main window &button text labels Besch&riftung der Schaltflächen verbergen System Cycle HPET Don't restrict self connect requests (default) Fail self connect requests to external ports only Ignore self connect requests to external ports only Fail all self connect requests Ignore all self connect requests Warning Warnung Some settings have been changed: "%1" Do you want to save the changes? Einige Einstellungen wurden verändert: "%1" Wollen Sie diese speichern? Delete preset: "%1" Are you sure? Voreinstellung löschen: "%1" Sind Sie sicher? msec ms n/a n/a &Preset Name Benennung der &Voreinstellung &Server Name &Servername &Server Path &Serverpfad &Driver Trei&ber &Interface Sc&hnittstelle Sample &Rate Abtast&rate &Frames/Period &Frames/Periode Periods/&Buffer Perioden/&Puffer Startup Script Start-Skript Post-Startup Script Nach-Start-Skript Shutdown Script Herunterfahr-Skript Post-Shutdown Script Nach-Herunterfahr-Skript Active Patchbay Definition Aktive Steckfelddefinition Patchbay Definition files Steckfelddefinitionsdateien Messages Log Meldungsprotokoll Log files Protokolldateien Information Information Some settings may be only effective next time you start this application. Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? &JACK client/port aliases: Deckbezeichnungen bei &JACK-Anschlüssen: JACK client/port aliases display mode Anzeigemodus für die JACK-Client/Anschlussbenennung Default Voreinstellung First Erster Second Zweiter Whether to show system tray message on main window close Nachrichten des Benachrichtigungsfelds beim Schließen des Hauptfensters anzeigen Sho&w system tray message on close &Nachrichten des Benachrichtigungsfelds beim Beenden anzeigen Whether to stop JACK audio server on application exit JACK Audio-Server bei Programmbeendung anhalten S&top JACK audio server on application exit JACK Audio-&Server bei Programmbeendung anhalten Defaults Voreinstellungen &Base font size: &Basisschriftgröße: Base application font size (pt.) Generelle Schriftgröße (pt.) für die Anwendung festlegen 6 6 7 7 8 8 9 9 11 11 12 12 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to enable D-Bus interface D-Bus-Schnittstelle aktivieren &Enable D-Bus interface D-Bus-S&chnittstelle aktivieren Number of microseconds to wait between engine processes (dummy) Wartezeit in Mikrosekunden zwischen Verarbeitungsprozessen (dummy) &Name: &Name: The JACK Audio Connection Kit sound server name Name des JACK Audio Connection Kit Soundservers netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to restrict to one single application instance (X11) Festlegen, ob nur eine Anwendungsinstanz (X11) gestartet werden darf Single application &instance Nur eine Anwendungsinstan&z zulassen qjackctlSocketForm Socket Anbindung &Socket &Anschluss &Name (alias): &Name (Alias): Socket name (an alias for client name) Anschlussbenennung (Alias für Name des Clients) Client name (regular expression) Name des Clients (Regulärer Ausdruck) Add plug to socket plug list Füge Anschluss zur Liste hinzu Add P&lug &Anschluss hinzufügen &Plug: A&nschluss: Port name (regular expression) Anschlussbezeichnung (Regulärer Ausdruck) Socket plug list Anschlussliste Socket Plugs / Ports Socket-Anschlüsse Edit currently selected plug Ausgewählten Anschluss bearbeiten &Edit &Bearbeiten Remove currently selected plug from socket plug list Ausgewählten Anschluss von der Liste entfernen &Remove En&tfernen &Client: &Client: Move down currently selected plug in socket plug list Ausgewählten Anschluss in Liste nach unten schieben &Down A&b Move up current selected plug in socket plug list Ausgewählten Anschluss in Liste nach oben schieben &Up Au&f Enforce only one exclusive cable connection Erzwinge eine singuläre Kabelverbindung E&xclusive E&xklusiv &Forward: &Weiterleiten: Forward (clone) all connections from this socket Alle Verbindungen dieses Anschlusses weiterleiten (klonen) Type Typ Audio socket type (JACK) JACK-Audio-Anbindung &Audio JACK-&Audio MIDI socket type (JACK) JACK-MIDI-Anbindung &MIDI JACK-&MIDI MIDI socket type (ALSA) ALSA-MIDI-Anbindung AL&SA AL&SA-MIDI Plugs / Ports Anschlüsse Error Fehler A socket named "%1" already exists. Socket mit dem Namen "%1" existiert bereits. Warning Warnung Some settings have been changed. Do you want to apply the changes? Einige Einstellungen wurden verändert. Wollen Sie diese übernehmen? Add Plug Anschluss hinzufügen Edit Bearbeiten Remove Entfernen Move Up Auf Move Down Ab (None) (Keiner) qjackctlSocketList Output Ausgang Input Eingang Socket Anbindung <New> - %1 <Neu> - %1 Warning Warnung %1 about to be removed: "%2" Are you sure? %1 soll entfernt werden: "%2" Sind Sie sicher? %1 <Copy> - %2 %1 <Kopieren> - %2 qjackctlSocketListView Output Sockets / Plugs Ausgangsanschlüsse Input Sockets / Plugs Eingangsanschlüsse qjackctl-1.0.4/src/translations/PaxHeaders/qjackctl_nl.ts0000644000000000000000000000013214771215054020541 xustar0030 mtime=1743067692.334636541 30 atime=1743067692.334636541 30 ctime=1743067692.334636541 qjackctl-1.0.4/src/translations/qjackctl_nl.ts0000644000175000001440000063267414771215054020553 0ustar00rncbcusers PortAudioProber Probing... Please wait, PortAudio is probing audio hardware. Warning Opgelet Audio hardware probing timed out. QObject (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Option -p requires an argument (preset). Optie -p vereist een argument (preset). Usage: %1 [options] [command-and-args] Gebruik: %1 [opties] [commandos-en-args] Options: Opties: Start JACK audio server immediately. Set default settings preset name. Set active patchbay definition file. Set default JACK audio server name. Show help about command line options. Show version information. Launch command with arguments. [command-and-args] Option -a requires an argument (path). Optie -a vereist een argument (pad). Option -n requires an argument (name). Optie -n vereist een argument (naam). %1 (%2 frames) Move Rename qjackctlAboutForm About About Qt Over Qt &Close &Sluiten Version Versie Debugging option enabled. Debug optie geactiveerd. System tray disabled. Systeem pictogram uitgeschakeld. Transport status control disabled. Transport status controle uitgeschakeld. Realtime status disabled. Realtime status uitgeschakeld. XRUN delay status disabled. XRUN delay status uitgeschakeld. Maximum delay status disabled. Maximum delay status uitgeschakeld. JACK Session support disabled. Jack Sessie ondersteuning uitgeschakeld. ALSA/MIDI sequencer support disabled. ALSA/MIDI sequencer ondersteuning uitgeschakeld. Using: Qt %1 JACK %1 Website Webstek This program is free software; you can redistribute it and/or modify it Dit programma is vrije software; je mag het doorgeven en/of aanpassen under the terms of the GNU General Public License version 2 or later. volgens de bepalingen in de GNU-General Public Licentie versie 2 of later. JACK MIDI support disabled. JACK MIDI ondersteuning uitgeschakeld. JACK Port aliases support disabled. JACK Poort alias ondersteuning uitgeschakeld. D-Bus interface support disabled. D-Bus interface ondersteuning uitgeschakeld. qjackctlClientListView &Connect &Verbinden Alt+C Connect Koppelen Alt+K &Disconnect Af&Koppelen Alt+D Disconnect Afkoppelen Alt+K Disconnect &All &Alles afkoppelen Alt+A Disconnect All Alles afkoppelen Alt+A Re&name Her&noemen Alt+N Rename Hernoemen Alt+N &Refresh Ve&rversen Alt+R Refresh Verversen Alt+R Readable Clients / Output Ports Leesbare clients / Uitgangspoorten Writable Clients / Input Ports Beschrijfbare clients / ingangspoorten qjackctlConnect Warning Opgelet This will suspend sound processing from all client applications. Are you sure? Dit zal het verwerken van geluid onderbreken voor alle client toepassingen. Bent u zeker? qjackctlConnectionsForm Audio Audio &Connect &Verbinden Connect currently selected ports Verbind geselecteerde poorten &Disconnect Af&Koppelen Disconnect currently selected ports Geselecteerde poorten loskoppelen Disconnect &All &Alles afkoppelen Disconnect all currently connected ports Alle verbonden poorten afkoppelen Connections Verbindingen Expand all client ports Toon alle client poorten E&xpand All &Toon alles &Refresh Ve&rversen Refresh current connections view Ververs huidig verbindingen venster MIDI MIDI ALSA ALSA qjackctlConnectorView &Connect &Verbinden Alt+C Connect Verbinden Alt+V &Disconnect Af&Koppelen Alt+D Disconnect Afkoppelen - Knippen Alt+K Disconnect &All &Alles afkoppelen Alt+A Disconnect All Alles afkoppelen Alt+A &Refresh &Verversen Alt+R Refresh Verversen Alt+V qjackctlGraphCanvas Connect Disconnect qjackctlGraphForm Graph &Graph &Edit B&ewerken &View &Zoom Co&lors S&ort &Help &Connect Connect Connect selected ports &Disconnect Disconnect Disconnect selected ports Ctrl+C T&humbview Ctrl+D Cl&ose Close Close this application window Select &All Select All Ctrl+A Select &None Select None Ctrl+Shift+A Select &Invert Select Invert Ctrl+I &Rename... Rename item Rename Item F2 &Find... Find Find nodes Ctrl+F &Menubar Menubar Show/hide the main program window menubar Ctrl+M &Toolbar Toolbar Show/hide main program window file toolbar &Statusbar Statusbar Show/hide the main program window statusbar &Top Left Top left Show the thumbnail overview on the top-left Top &Right Top right Show the thumbnail overview on the top-right Bottom &Left Bottom Left Bottom left Show the thumbnail overview on the bottom-left &Bottom Right Bottom right Show the thumbnail overview on the bottom-right &None None Geen Hide thumbview Hide the thumbnail overview Text Beside &Icons Text beside icons Show/hide text beside icons &Center Center Center view &Refresh Refresh Refresh view F5 Zoom &In Zoom In Ctrl++ Zoom &Out Zoom Out Ctrl+- Zoom &Fit Zoom Fit Ctrl+0 Zoom &Reset Zoom Reset Ctrl+1 &Zoom Range Zoom Range JACK &Audio... JACK Audio color JACK &MIDI... JACK MIDI JACK MIDI color ALSA M&IDI... ALSA MIDI ALSA MIDI color JACK &CV... JACK CV color JACK &OSC... JACK OSC JACK OSC color &Reset &Herstel Reset colors Port &Name Port name Sort by port name Port &Title Port title Sort by port title Port &Index Port index Sort by port index &Ascending Ascending Ascending sort order &Descending Descending Descending sort order Repel O&verlapping Nodes Repel nodes Repel overlapping nodes Connect Thro&ugh Nodes Connect Through Nodes Connect through nodes Whether to draw connectors through or around nodes &About... About... About Show information about this application program About &Qt... About Qt... About Qt Over Qt Show information about the Qt toolkit &Undo &Redo Undo last edit action Redo last edit action Zoom Ready Colors - %1 qjackctlMainForm &Quit &Sluiten Quit processing and exit Stop proces en sluit af &Start Sta&rt Start the JACK server Start de JACK server S&top S&top Stop the JACK server Stop de JACK server St&atus St&atus Ab&out... &over… Show information about this application Toon informatie over deze toepassing Show settings and options dialog Toon instellingen en opties venster &Messages &Berichten &Patchbay I don't know a translation to dutch for the word patchbay &Patchbay Show/hide the patchbay editor window Toon/verberg de patchbay editor &Connect &Verbindingen Set&up... &Instellingen… JACK server state JACK server status JACK server mode JACK server mode Sample rate No translation known to Dutch Sample rate Time display Tijd weergave Transport state Transport status Transport BPM Transport BPM Transport time Transport tijd Show/hide the session management window Toon/verberg het sessie management venster Show/hide the messages log/status window Toon/verberg het berichten log/status venster Show/hide the graph window Show/hide the connections window &Backward &Terug Backward transport Terugwaarts afspelen &Forward &Voorwaarts Forward transport Voorwaarts afspelen &Rewind Te&rugspoelen Rewind transport Terugspoelen Pa&use Pa&use Stop transport rolling Stop het afspelen &Play &Spelen Start transport rolling Start het afspelen Warning Opgelet successfully met succes with exit status=%1 met exit status=%1 Could not load preset "%1". Retrying with default. Kon de preset « %1 » niet laden. Opnieuw aan het proberen met standaard. Could not load default preset. Sorry. Kon de standaard preset niet inladen. Sorry. Startup script... Opstart script... Startup script terminated Opstart script beëindigd JACK is starting... JACK start op... Could not start JACK. Sorry. JACK kon niet opstarten. Sorry. JACK is stopping... JACK stopt... Shutdown script... Afsluit script... Don't ask this again Shutdown script terminated Afsluit script beëindigd Post-shutdown script... Na-afsluit script... Post-shutdown script terminated Na-afsluit script beëindigd JACK was stopped JACK is gestopt The preset aliases have been changed: "%1" Do you want to save the changes? De preset aliases zijn aangepast: « %1 » Wil u deze aanpassingen opslaan? Error Fout Transport time code Transport tijdscode Elapsed time since last reset Verlopen tijd sinds laatste reset Elapsed time since last XRUN Verlopen tijd sinds laatste XRUN Patchbay activated. Patchbay ingeschakeld. Patchbay deactivated. Patchbay uitgeschakeld. Statistics reset. Initialisatie van statistieken. msec ms XRUN callback (%1). Buffer size change (%1). Buffergrootte aanpassing (%1). Shutdown notification. Afluit melding. Freewheel started... Freewheel exited. checked this is correct if checked means "controlled to see if everything is OK", but if it means checked like in a check box, then the translation should be: "aangevinkt" nagekeken connected verbonden disconnected afgesloten failed mislukt Server configuration saved to "%1". Server configuratie opgeslagen in « %1 ». Client activated. Client geactiveerd. Post-startup script... Na-startup script... Post-startup script terminated Na-startup script beëindigd Command line argument... Command line argument started Client deactivated. Client gedeactiveerd. Transport rewind. Transport terugspoelen. Transport backward. Transport achterwaarts. Starting Startend Transport start. Stopping Stoppend Transport stop. Transport forward. Transport voorwaarts. Stopped Gestopt Yes Ja No Nee FW RT RT Rolling Looping XRUN callback (%1 skipped). XRUN callback (%1 overgeslagen). Started Gestart Active Actief Activating Activering Inactive Inactief &Hide Ver&hullen D-BUS: GetParameterConstraint('%1'): %2. (%3) Mi&nimize Verklei&nen S&how &Tonen Rest&ore &Herstellen &Stop &Stop &Reset &Herstel &Presets &Presets &Versioning Re&fresh &Connections &Verbindingen Patch&bay &Graph &Transport Server settings will be only effective after restarting the JACK audio server. Server instellingen worden toegepast na het herstarten van de JACK audio server. Information Informatie Some settings will be only effective the next time you start this program. Sommige instellingen worden pas toegepast nadat u dit programma opnieuw opstart. DSP Load DSP-Verbruik XRUN Count (notifications) XRUN Telling (meldingen) JACK connection graph change. JACK verbindingen tekening aangepast. ALSA connection graph change. ALSA verbindingen aangepast. JACK connection change. JACK verbindingen aangepast. ALSA connection change. ALSA verbindingen aangepast. JACK is currently running. Do you want to terminate the JACK audio server? JACK wordt momenteel gebruikt. Wil u de JACK audio server stoppen? D-BUS: Service is available (%1 aka jackdbus). DBUS : Service is beschikbaar (%1 ook gekend als jackdbus). D-BUS: Service not available (%1 aka jackdbus). DBUS : Service is niet beschikbaar (%1 ook gekend als jackdbus). The program will keep running in the system tray. To terminate the program, please choose "Quit" in the context menu of the system tray icon. Het programma zal in de systeem balk blijven lopen. Om het programma te stoppen, gelieve « Sluiten » te kiezen in het menu van het systeem balk icoon. Don't show this message again Could not start JACK. Maybe JACK audio server is already started. Kon JACK niet starten. Misschien is de JACK audio server al gestart. D-BUS: JACK server is starting... D-BUS : JACK server start op… D-BUS: JACK server could not be started. Sorry DBUS : JACK server kon niet worden gestart. Sorry Some client audio applications are still active and connected. Do you want to stop the JACK audio server? Sommige client audio toepassingen zijn nog steeds actief en verbonden. Wil u de JACK audio server stoppen? %1 is about to terminate. Are you sure? D-BUS: JACK server is stopping... DBUS : JACK server is stoppende… D-BUS: JACK server could not be stopped. Sorry D-BUS : JACK server kon niet worden gestopt. Sorry JACK was started with PID=%1. JACK is gestart met PID=%1. D-BUS: JACK server was started (%1 aka jackdbus). DBUS : JACK server is gestart (%1 ook gekend als jackdbus). JACK is being forced... JACK wordt geforceerd… D-BUS: JACK server was stopped (%1 aka jackdbus). DBUS : JACK server werd gestopt (%1 soit jackdbus). Transport BBT (bar.beat.ticks) Patchbay reset. Could not load active patchbay definition. "%1" Disabled. JACK has crashed. JACK is ingestort. JACK timed out. JACK was te laat. JACK write error. JACK schrijffout. JACK read error. JACK leesfout. Unknown JACK error (%d). Onbekende JACK fout (%d). JACK property change. Overall operation failed. Gehele toepassing gefaald. Invalid or unsupported option. Ongeldige of niet-ondersteunde optie. Client name not unique. Client naam niet uniek. Server is started. Server is gestart. Unable to connect to server. Kan niet met de server verbinden. Server communication error. Server communicatie fout. Client does not exist. Client bestaat niet. Unable to load internal client. Kan interne client niet laden. Unable to initialize client. Kan client niet initializeren. Unable to access shared memory. Geen toegang tot gedeeld geheugen. Client protocol version mismatch. Client protocol versie ongeldig. Could not connect to JACK server as client. - %1 Please check the messages window for more info. Kon niet verbinden als client met de JACK server. - %1 Gelieve het berichten venster te lezen voor meer info. %1 (%2%) %1 (%2%) %1 (%2%, %3 xruns) %1 % %1 % %1 Hz %1 Hz %1 frames %1 frames %1 msec %1 ms S&ession S&essie &Load... &Laden... &Save... &Bewaren… Save and &Quit... Bewaren en af&sluiten… Save &Template... &Template bewaren… Do you want to restart the JACK audio server? D-BUS: SetParameterValue('%1', '%2'): %3. (%4) D-BUS : SetParameterValue('%1', '%2') : %3. (%4) D-BUS: ResetParameterValue('%1'): %2. (%3) D-BUS : ResetParameterValue('%1') : %2. (%3) D-BUS: GetParameterValue('%1'): %2. (%3) D-BUS : GetParameterValue('%1') : %2. (%3) Could not open ALSA sequencer as a client. ALSA MIDI patchbay will be not available. Kon de ALSA sequencer niet als client openen. De ALSA MIDI patchbay zal niet beschikbaar zijn. JACK active patchbay scan JACK actieve patchbay scan ALSA active patchbay scan ALSA actieve patchbay scan A patchbay definition is currently active, which is probable to redo this connection: %1 -> %2 Do you want to remove the patchbay connection? Er is een patchbay definitie actief, die deze verbinding waarschijnlijk zal herstellen: %1 -> %2 Wil u de patchbay verbinding verwijderen? qjackctlMessagesStatusForm Messages / Status &Messages &Meldingen Messages log Meldingen logboek Messages output log Meldingen uitgang logboek &Status &Status Status information Status informatie Statistics since last server startup Statistiek sinds laatste server opstart Description Beschrijving Value Waarde Reset XRUN statistic values Initialiseer XRUN statistiek waarden Re&set Refresh XRUN statistic values Ververs XRUN statistiek waarden &Refresh &Ververs Server name Server naam Server state Server status DSP Load DSP lading Sample Rate Buffer Size Buffergrootte Realtime Mode Realtime Modus Transport state Transport status Transport Timecode Transport Tijdscode Transport BBT Transport BPM XRUN count since last server startup Aantal XRUNS sinds laatste server opstart XRUN last time detected Laatst opgemerkte XRUN XRUN last Laatste XRUN XRUN maximum XRUN minimum XRUN average XRUN gemiddelde XRUN total XRUN totaal Maximum scheduling delay Time of last reset Tijd sinds laatste reset Logging stopped --- %1 --- Loggen gestopt --- %1 --- Logging started --- %1 --- Loggen gestart --- %1 --- qjackctlPaletteForm Color Themes Name Current color palette name Save current color palette name Save Delete current color palette name Delete Palette Current color palette Generate: Base color to generate palette Reset all current palette colors Reset Import a custom color theme (palette) from file Import... Export a custom color theme (palette) to file Export... Show Details Import File - %1 Palette files (*.%1) Save Palette - %1 All files (*.*) Warning - %1 Could not import from file: %1 Sorry. Export File - %1 Some settings have been changed. Do you want to discard the changes? Some settings have been changed: "%1". Do you want to save the changes? qjackctlPaletteForm::PaletteModel Color Role Active Actief Inactive Inactief Disabled qjackctlPatchbay Warning Opgelet This will disconnect all sockets. Are you sure? Dit zal alle sockets ontkoppelen. Bent u zeker? qjackctlPatchbayForm &New &Nieuw Create a new patchbay profile Creëer een nieuw patchbay profiel &Load... &Laden… Load patchbay profile Laad patchbay profiel &Save... &Bewaren... Save current patchbay profile Bewaar huidig patchbay profiel Patchbay Expand all items Toon alle items E&xpand All &Toon alle Current (recent) patchbay profile(s) Huidig (recent) patchbay profiel(en) Acti&vate Acti&veer Toggle activation of current patchbay profile Schakel activatie van huidig patchbay profiel in/uit &Connect &Verbind Connect currently selected sockets Verbind huidige geselecteerde sockets &Disconnect &Ontkoppel Disconnect currently selected sockets Ontkoppel huidig geselecteerde sockets Disconnect &All Ontkoppel &alle Disconnect all currently connected sockets Ontkoppel alle huidige verbonden sockets &Refresh Ve&rvers Refresh current patchbay view Ververs huidig patchbay venster Down Omlaag Move currently selected output socket down one position Verplaats de geselecteerde uitgang socket één positie omlaag Add... Voeg toe… Create a new output socket Creëer een nieuwe uitgang socket Edit... Bewerk... Edit currently selected input socket properties Bewerk eigenschappen van geselecteerde ingang socket Up Omhoog Move currently selected output socket up one position Verplaats de geselecteerde uitgang socket één positie omhoog Remove Verwijder Remove currently selected output socket Verwijder de geselecteerde uitgang socket Copy... Kopieer… Duplicate (copy) currently selected output socket Dupliceer de geselecteerde uitgang socket Remove currently selected input socket Verwijder de geselecteerde uitgang socket Duplicate (copy) currently selected input socket Dupliceer de geselecteerde ingang socket Create a new input socket Creëer een nieuwe ingang socket Edit currently selected output socket properties Bewerk eigenschappen van geselecteerde uitgang socket Warning Opgelet Error Fout New Patchbay definition Nieuwe patchbay definitie Patchbay Definition files Patchbay definitie bestanden Load Patchbay Definition Laad Patchbay Definitie Save Patchbay Definition Bewaar Patchbay Definitie active actief The patchbay definition has been changed: "%1" Do you want to save the changes? De patchbay definitie is aangepast : « %1 » Wil u de veranderingen bewaren? %1 [modified] %1 [aangepast] Untitled%1 Ongetieteld%1 Could not load patchbay definition file: "%1" Kon patchbay definite bestand niet laden : « %1 » Could not save patchbay definition file: "%1" Kon patchbay definitie bestand niet bewaren : « %1 » Create patchbay definition as a snapshot of all actual client connections? Creëer patchbay definitie als een momentopname van alle huidige client verbindingen? qjackctlPatchbayView Add... Voeg toe… Edit... Bewerk… Copy... Kopieer… Remove Verwijder Exclusive Exclusief (None) (Geen) Forward Vooruit Move Up Omhoog Move Down Omlaag &Connect &Verbind Alt+C Connect Verbind Alt+V &Disconnect &Loskoppelen Alt+D Disconnect Loskoppelen Alt+L Disconnect &All &Alle loskoppelen Alt+A Disconnect All Alle loskoppelen Alt+A &Refresh Ve&rvers Alt+R Refresh Ververs Alt+R qjackctlSessionForm Session Load session Laad sessie &Load... &Laden… Recent session Vorige sessie &Recent Vo&rige Save session Bewaar sessie &Versioning Re&fresh Session clients / connections Infra-clients / commands Infra-client Infra-command Add infra-client &Add Edit infra-client &Edit B&ewerken Remove infra-client Re&move &Save... &Bewaar… Update session Sessie updaten Client / Ports Client / Poorten UUID UUID Command Opdracht &Save &Bewaren Load Session Laad sessie Session directory Sessie map Save Session Bewaar Sessie and Quit en Sluit Template Sjabloon &Clear &Wissen Warning Opgelet A session could not be found in this folder: "%1" Een sessie werd niet gevonden in deze map: « %1 » %1: loading session... %1 : sessie laden… %1: load session %2. %1: sessie laden %2. A session already exists in this folder: "%1" Are you sure to overwrite the existing session? Een sessie bestaat al in deze map: « %1 » Bent u zeker dat u deze bestaande sessie wil overschrijven ? This folder already exists and is not empty: "%1" Are you sure to overwrite the existing folder? Deze map bestaat al en is niet leeg : « %1 » Bent u zeker dat u de bestaande map wil vervangen ? %1: saving session... %1 : sessie wordt bewaard… %1: save session %2. %1 : sessie wordt bewaard %2. New Client Save and &Quit... &Bewaren en afsluiten… Save &Template... Bewaar S&jabloon… qjackctlSessionInfraClientItemEditor Infra-command qjackctlSessionSaveForm Session &Name: &Naam: Session name &Directory: Session directory Sessie map Browse for session directory ... Save session versioning &Versioning Warning Opgelet Session directory does not exist: "%1" Do you want to create it? Session Directory qjackctlSetupForm Settings Instellingen Preset &Name: Preset &Naam: (default) DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/38 Settings preset name Naam instellingen preset &Save &Bewaren Save settings as current preset name Bewaar instellingen als huidige preset naam &Delete &Wissen Delete current settings preset Huidige instellingen preset wissen jackd DO NOT TRANSLATE jackdmp DO NOT TRANSLATE jackstart DO NOT TRANSLATE Driv&er: Driv&er: dummy DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 sun DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 oss DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 alsa DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 portaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 coreaudio DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 firewire DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Parameters Parameters Number of periods in the hardware buffer Aantal periodes in hardware buffer Priorit&y: Pri&oriteit : &Frames/Period: &Frames/Periode: 16 16 32 32 64 64 128 128 256 256 512 512 1024 1024 2048 2048 4096 4096 Frames per period between process() calls Frames per periode tussen process() calls Port Ma&ximum: Poorten ma&ximum : 21333 21333 22050 22050 32000 32000 44100 44100 48000 48000 88200 88200 96000 96000 192000 192000 Sample rate in frames per second Sample rate in frames per seconde Scheduler priority when running realtime Scheduler prioriteit wanneer in realtime modus &Word Length: &Resolutie (bit) : Periods/&Buffer: Periodes/&Buffer : Word length Resolutie Maximum number of ports the JACK server can manage Maximum aantal poorten dat de JACK server aankan &Wait (usec): &Wacht (µsec): Sample &Rate: Sample &Rate (Hz): &Timeout (msec): &Timeout (in ms) : 200 200 500 500 1000 1000 2000 2000 5000 5000 Set client timeout limit in milliseconds Zet client timeout limiet in milisecondes &Realtime &Realtime Use realtime scheduling Gebruik realtime scheduling No Memory Loc&k Geen Memory Loc&k Do not attempt to lock memory, even if in realtime mode Probeer niet om geheugen te "locken", zelfs niet in realtime modus &Unlock Memory &Unlock Memory Unlock memory of common toolkit libraries (GTK+, QT, FLTK, Wine) Deblokkeer geheugen van gemeenschappelijke toolkit libraries (GTK+, QT, FLTK, Wine) So&ft Mode So&ft Mode Ignore xruns reported by the backend driver Negeer xruns meldingen van de backend driver &Monitor &Monitor Provide output monitor ports Voorzie monitor uitgang poorten Force &16bit Forceer &16bit Force 16bit mode instead of failing over 32bit (default) Forceer 16bit in plaats van te falen bij 32bit (standaard) H/&W Meter H/&W Meter Enable hardware metering on cards that support it Schakel hardware meten in op kaarten die het ondersteunen &Ignore H/W &Negeer H/W Ignore hardware period/buffer size Negeer hardware period/buffer grootte &Output Device: &Output Apparaat: &Interface: &Interface : Maximum input audio hardware channels to allocate Maximum bruikbare input audio hardware kanalen &Audio: &Audio: Dit&her: Dit&her: External output latency (frames) Externe output vertraging (in frames) &Input Device: &Input Apparaat : Duplex Duplex Capture Only Enkel opnemen Playback Only Enkel afspelen Provide either audio capture, playback or both Voorzie audio opname, afspelen of beide hw:0 hw:0 The PCM device name to use De PCM apparaats naam te gebruiken > > &Name: &Naam: The JACK Audio Connection Kit sound server name De JACK Audio Connectie Kit geluid server naam /dev/dsp /dev/dsp Alternate input device for capture Alternatief input apparaat voor opname Maximum output audio hardware channels to allocate Maximum bruikbare output audio hardware kanalen Alternate output device for playback Alternatief output apparaat voor afspelen External input latency (frames) Externe input vertraging (in frames) None Geen Rectangular Blok Shaped Sinus Triangular Driehoek Set dither mode Kies dither modus Whether to give verbose output on messages Geef veel info bij berichten Time in seconds that client is delayed after server startup Tijd in secondes waarmee de client wordt vertraagd na opstarten van de server Latency: Vertraging: Output latency in milliseconds, calculated based on the period, rate and buffer settings Output vertraging in milliseconden, berekend vanuit periodes, rate en buffer instellingen Options Opties Scripting Scripts Execute script on Start&up: Script &uitvoeren voor opstarten: Whether to execute a custom shell script before starting up the JACK audio server. Custom shell script uitvoeren vóór het opstarten van de JACK audio server. Execute script after &Startup: &Script uitvoeren na opstarten: Whether to execute a custom shell script after starting up the JACK audio server. Custom shell script uitvoeren na het opstarten van de JACK audio server. Execute script on Shut&down: Script uitvoeren &bij afsluiten: Whether to execute a custom shell script before shuting down the JACK audio server. Custom shell script uitvoeren vóór het afsluiten van de JACK audio server. Command line to be executed before starting up the JACK audio server Commando om uit te voeren vóór het opstarten van de JACK audio server Scripting argument meta-symbols Script argument meta symbolen ... Browse for script to be executed before starting up the JACK audio server Bladeren naar een script om uit te voeren vóór het starten van de JACK audio server Command line to be executed after starting up the JACK audio server Commando om uit te voeren na het opstarten van de JACK audio server Browse for script to be executed after starting up the JACK audio server Bladeren naar een script om uit te voeren na het starten van de JACK audio server Browse for script to be executed before shutting down the JACK audio server Bladeren naar een script om uit te voeren vóór het stoppen van de JACK audio server Command line to be executed before shutting down the JACK audio server Commando om uit te voeren vóór het stoppen van de JACK audio server Execute script after Shu&tdown: Script uitvoeren &na afsluiten: Whether to execute a custom shell script after shuting down the JACK audio server. Custom shell script uitvoeren na het afsluiten van de JACK audio server. Browse for script to be executed after shutting down the JACK audio server Bladeren naar een script om uit te voeren na het stoppen van de JACK audio server Command line to be executed after shutting down the JACK audio server Commando om uit te voeren na het stoppen van de JACK audio server Statistics Statistieken &Capture standard output Standaard &output weergeven Whether to capture standard output (stdout/stderr) into messages window Standaard output (stdout/stderr) weergeven in berichten venster &XRUN detection regex: regex voor &XRUN detectie: xrun of at least ([0-9|\.]+) msecs xrun van ten minste ([0-9|\.]+) ms Regular expression used to detect XRUNs on server output messages Expression régulière utilisée pour détecter les désynchronisations (XRUN) dans les messages de sortie du serveur Connections Verbindingen 10 10 Patchbay definition file to be activated as connection persistence profile Patchbay definitie bestand om verbindingen profiel te bewaren Browse for a patchbay definition file to be activated Bladeren naar een patchbay definitie bestand om te activeren Activate &Patchbay persistence: Activeer &Patchbay bewaring: Whether to activate a patchbay definition for connection persistence profile. Patchbay definitie bestand activeren om verbindingen profiel te bewaren. Display Weergave Time Display Tijdsweergave Server Suffi&x: Transport &Time Code Transport &Time Code Transport &BBT (bar:beat.ticks) Transport &BBT (bar:beat.ticks) Elapsed time since last &Reset Verlopen tijd sinds laatste &Reset Elapsed time since last &XRUN Verlopen tijd sinds laatste &XRUN Sample front panel normal display font Voorbeeld hoofdvenster normale weergave lettertype Sample big time display font Voorbeeld grote klok weergave lettertype Big Time display: Grote klok weergave: &Font... &Lettertype… Select font for front panel normal display Kies lettertype voor hoofdvenster normale weergave Select font for big time display Kies lettertype voor grote klok weergave Normal display: Normale weergave: Messages Window Berichten venster Sample messages text font display Voorbeeld lettertype voor berichten Select font for the messages text display Kies lettertype voor tekst in berichtenvenster &Messages limit: &Berichten limiet: Whether to keep a maximum number of lines in the messages window Een maximum aantal lijnen behouden in het berichten venster 100 100 250 250 2500 2500 The maximum number of message lines to keep in view Het maximum aantal berichten om in beeld te houden Connections Window Verbindingen venster Sample connections view font Voorbeeld lettertype verbindingen venster Select font for the connections view Kies lettertype voor het verbindingen venster &Icon size: &Icoon grootte: 16 x 16 16 x 16 32 x 32 32 x 32 64 x 64 64 x 64 The icon size for each item of the connections view De grootte van het icoon voor elk element uit het verbindingen venster Ena&ble client/port aliases editing (rename) Client/poort &hernoemen mogelijk maken (aliases) Whether to enable in-place client/port name editing (rename) Bewerken van de naam van een client/poort toestaan E&nable client/port aliases Activeer client/p&ort aliasen Whether to enable client/port name aliases on the connections window Alternatieve naam (alias) van client/poort tonen in verbindingen venster Misc Meer Other Andere &Start JACK audio server on application startup &Start JACK audio server bij opstarten van QjackCtl Whether to start JACK audio server immediately on application startup JACK audio server onmiddelijk starten bij opstarten van de toepassing &Confirm application close &Bevestig sluiten van QjackCtl Whether to ask for confirmation on application exit Vragen om bevestiging wanneer de toepassing wordt beëindigd &Keep child windows always on top &Kind vensters steeds bovenaan houden Whether to keep all child windows on top of the main window Kind vensters al dan niet over het hoofdvenster laten verschijnen &Enable system tray icon Activ&eer systeem balk icoon Whether to enable the system tray icon Minimaliseren naar systeem balk icoon of niet S&ave JACK audio server configuration to: Bew&aar JACK audio server configuratie als: Whether to save the JACK server command-line configuration into a local file (auto-start) De JACK server commando configuratie in een lokaal bestand opslaan (auto start) .jackdrc .jackdrc The server configuration local file name (auto-start) Naam van het lokale server configuratie bestand (auto start) Buttons Knoppen Hide main window &Left buttons Verberg knoppen aan &linkerkant van hoofdvenster Whether to hide the left button group on the main window De knoppen groep aan de linkerkant van het hoofdvenster verbergen Hide main window &Right buttons Verberg knoppen aan &rechterkant van hoofdvenster Whether to hide the right button group on the main window De knoppen groep aan de rechterkant van het hoofdvenster verbergen Hide main window &Transport buttons Verberg hoofdvenster &Transport knoppen Whether to hide the transport button group on the main window De transport knoppengroep in het hoofdvenster al dan niet verbergen Hide main window &button text labels Verberg tekst bij &knoppen in hoofdvenster Whether to hide the text labels on the main window buttons Verberg de tekst labels onder knoppen in het hoofdvenster Warning Opgelet msec ms n/a n/a &Preset Name &Preset Naam &Server Name &Server Naam &Server Path &Server Pad &Driver &Driver &Interface &Interface Sample &Rate Sample &Rate &Frames/Period &Frames/Periode Periods/&Buffer Periodes/&Buffer Startup Script Opstart Script Post-Startup Script Na-opstart Script Shutdown Script Afsluit Script Post-Shutdown Script Na-afsluit Script Patchbay Definition files Patchbay Definitie bestanden Active Patchbay Definition Actieve Patchbay Definitie The audio backend driver interface to use De te gebruiken audio backend driver interface &Verbose messages Uit&voerige berichten MIDI Driv&er: MIDI Driv&er: none geen raw DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 seq DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 The ALSA MIDI backend driver to use De te gebruiken ALSA MIDI backend driver plughw:0 plughw:0 Some settings have been changed: "%1" Do you want to save the changes? Sommige instellingen zijn veranderd: « %1 » Wil u deze aanpassingen opslaan? Delete preset: "%1" Are you sure? Verwijder preset : « %1 » Bent u zeker? Information Informatie Some settings may be only effective next time you start this application. Some settings have been changed. Do you want to apply the changes? Sommige instellingen zijn veranderd. Wil u de veranderingen toepassen? Messages Log Berichten Log System Cycle HPET Don't restrict self connect requests (default) Fail self connect requests to external ports only Ignore self connect requests to external ports only Fail all self connect requests Ignore all self connect requests Log files Log bestanden netone DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 /dev/audio /dev/audio &Channels: &Sporen: Server path (command line prefix) Maximum number of audio channels to allocate Maximum aantal te gebruiken audio sporen &Channels I/O: &Latency I/O: Logging Loggen Messages log file Berichten log bestand Browse for the messages log file location Blader naar de berichten log bestand locatie Whether to activate a messages logging to file. Berichten opslaan in een bestand activeren. Server &Prefix: Extra driver options (command line suffix) Start De&lay: secs 0 msecs Please do not touch these settings unless you know what you are doing. &Messages log file: &Berichten log bestand: Whether to enable blinking (flashing) of the server mode (RT) indicator Activeer het knipperen van de server modus (RT) indicator Blin&k server mode indicator &Knipperende server modus indicator &JACK client/port aliases: &JACK client/poort aliassen: JACK client/port aliases display mode JACK client/poort aliassen weergave modus Default Standaard First Eerste Second Tweede Whether to start minimized to system tray Start met geminimaliseerd systeem balk icoon JACK client/port pretty-name (metadata) display mode Advanced Whether to reset all connections when a patchbay definition is activated. &Reset all connections on patchbay activation Whether to issue a warning on active patchbay port disconnections. &Warn on active patchbay disconnections Enable JA&CK client/port pretty-names (metadata) Whether to ask for confirmation on JACK audio server shutdown and/or restart Confirm server sh&utdown and/or restart Whether to show system tray message on main window close Sho&w system tray message on close Start minimi&zed to system tray Whether to restrict to one single application instance (X11) Beperken tot één enkele toepassings instantie (X11) Single application &instance Slechts één QjackCtl laten draa&ien Whether to enable ALSA Sequencer (MIDI) support on startup Activeer ALSA Sequencer (MIDI) ondersteuning bij opstarten Setup Whether to restrict client self-connections Whether to use server synchronous mode Clear settings of current preset name Clea&r &Use server synchronous mode Cloc&k source: Clock source S&elf connect mode: Custom &Color palette theme: Custom color palette theme Wonton Soup DO NOT TRANSLATE KXStudio DO NOT TRANSLATE Manage custom color palette themes &Widget style theme: Custom widget style theme E&nable ALSA Sequencer support Activeer &ALSA Sequencer ondersteuning Whether to enable JACK D-Bus interface &Enable JACK D-Bus interface Whether to stop JACK audio server on application exit S&top JACK audio server on application exit Whether to replace Connections with Graph button on the main window Replace Connections with &Graph button Defaults Standaard &Base font size: &Basis lettertype grootte: Base application font size (pt.) Basis lettertype grootte voor toepassing (pt.) 6 6 7 7 8 8 9 9 11 11 12 12 net DO NOT TRANSLATE - https://github.com/rncbc/qjackctl/issues/54 Whether to enable D-Bus interface D-Bus activeren &Enable D-Bus interface &D-Bus interface activeren Number of microseconds to wait between engine processes (dummy) Aantal microseconden wachten tussen engine processen (dummie) qjackctlSocketForm &Socket &Socket &Name (alias): &Naam (alias): Socket name (an alias for client name) Socket naam (een alias voor client naam) Client name (regular expression) Client naam (reguliere expressie) Add P&lug Plug &toevoegen Add plug to socket plug list Plug toevoegen aan socket plug lijst &Plug: &Plug: Port name (regular expression) Poort naam (reguliere expressie) Socket Plugs / Ports Socket Plugs / Poorten Socket plug list Socket plug lijst &Edit B&ewerken &Remove &Verwijderen Remove currently selected plug from socket plug list Verwijder geselecteerde plug uit socket plug lijst Socket Socket &Client: &Client: &Down Om&laag &Up Om&hoog E&xclusive E&xclusief Enforce only one exclusive cable connection Sta slechts één enkele aansluiting toe &Forward: &Stuur door: Forward (clone) all connections from this socket Stuur alle verbindingen van deze socket door (clonen) Type Type &Audio &Audio Audio socket type (JACK) Audio socket type (JACK) &MIDI &MIDI MIDI socket type (ALSA) MIDI socket type (ALSA) Plugs / Ports Plugs / Poorten Add Plug Plug toevoegen Remove Verwijder Edit Bewerken Error Fout A socket named "%1" already exists. Een socket genaamd « %1 » bestaat al. Move Up Omhoog Move Down Omlaag (None) (Geen) Edit currently selected plug Bewerk de geselecteerde plug Move down currently selected plug in socket plug list Verplaats geselecteerde plug omlaag in socket plug lijst Move up current selected plug in socket plug list Verplaats geselecteerde plug omhoog in socket plug lijst Warning Opgelet Some settings have been changed. Do you want to apply the changes? Sommige instellingen zijn veranderd. Wil u de veranderingen toepassen? MIDI socket type (JACK) MIDI socket type (JACK) AL&SA AL&SA qjackctlSocketList Output Uitgang Input Ingang Socket Socket Warning Opgelet <New> - %1 <Nieuw> - %1 %1 about to be removed: "%2" Are you sure? %1 zal verwijderd worden: « %2 » Bent u zeker? %1 <Copy> - %2 %1 <Kopiëer> - %2 qjackctlSocketListView Output Sockets / Plugs Uitgang Sockets / Plugs Input Sockets / Plugs Ingang Sockets / Plugs qjackctl-1.0.4/src/PaxHeaders/qjackctlPatchbayFile.txt0000644000000000000000000000012714771215054020000 xustar0029 mtime=1743067692.32863657 29 atime=1743067692.32863657 29 ctime=1743067692.32863657 qjackctl-1.0.4/src/qjackctlPatchbayFile.txt0000644000175000001440000000263414771215054017771 0ustar00rncbcusersqjackctlPatchbayFile format specification ----------------------------------------- plug-name . . . . . . plug-name . . . . . . # # # . # . # . # . . . patchbay-name := string-literal patchbay-version := string-literal socket-name := string-literal socket-type := "audio" | "midi" | "jack-audio" | "jack-midi" | "alsa-midi" # slot-name := string-literal # slot-mode := "open" | "half" | "full" client-name := string-regexp (JACK/ALSA client name) plug-name := string-regexp (JACK/ALSA port name) exclusive-flag := "on" | "off" | "yes" | "no" | "1" | "0" qjackctl-1.0.4/src/PaxHeaders/qjackctlMainForm.ui0000644000000000000000000000013214771215054016747 xustar0030 mtime=1743067692.326636579 30 atime=1743067692.326636579 30 ctime=1743067692.326636579 qjackctl-1.0.4/src/qjackctlMainForm.ui0000644000175000001440000005673214771215054016754 0ustar00rncbcusers rncbc aka Rui Nuno Capela JACK Audio Connection Kit - Qt GUI Interface. Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. qjackctlMainForm 0 0 300 100 :/images/qjackctl.svg 4 4 0 0 28 28 Qt::TabFocus Start the JACK server &Start :/images/start1.png false Qt::ToolButtonTextBesideIcon 0 0 28 28 Qt::TabFocus Stop the JACK server S&top :/images/stop1.png Qt::ToolButtonTextBesideIcon 0 0 true QFrame::Panel QFrame::Sunken 2 0 50 0 8 JACK server state Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter false 2 20 0 8 JACK server mode Qt::AlignCenter false 40 0 8 DSP Load Qt::AlignCenter false 50 0 8 Sample rate Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 30 0 8 XRUN Count (notifications) Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter false 2 130 0 14 75 true Time display Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 50 0 8 Transport state Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter false 2 30 0 8 Transport BPM Qt::AlignCenter false 80 0 8 75 true Transport time Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 0 0 28 28 Qt::TabFocus Quit processing and exit &Quit :/images/quit1.png Qt::ToolButtonTextBesideIcon 0 0 28 28 Qt::TabFocus Show/hide the session management window S&ession :/images/session1.png true Qt::ToolButtonTextBesideIcon 0 0 28 28 Qt::TabFocus Show/hide the messages log/status window &Messages :/images/messagesstatus1.png true Qt::ToolButtonTextBesideIcon 0 0 28 28 Qt::TabFocus Show settings and options dialog Set&up... :/images/setup1.png true Qt::ToolButtonTextBesideIcon 0 0 28 28 Qt::TabFocus Show/hide the graph window &Graph :/images/graph1.png true Qt::ToolButtonTextBesideIcon 0 0 28 28 Qt::TabFocus Show/hide the connections window &Connect :/images/connections1.png true Qt::ToolButtonTextBesideIcon 0 0 28 28 Qt::TabFocus Show/hide the patchbay editor window &Patchbay :/images/patchbay1.png true Qt::ToolButtonTextBesideIcon 0 0 28 28 Qt::TabFocus Rewind transport &Rewind :/images/rewind1.png 0 0 28 28 Qt::TabFocus Backward transport &Backward :/images/backward1.png true 0 0 28 28 Qt::TabFocus Start transport rolling &Play :/images/play1.png true 0 0 28 28 Qt::TabFocus Stop transport rolling Pa&use :/images/pause1.png 0 0 28 28 Qt::TabFocus Forward transport &Forward :/images/forward1.png true 0 0 28 28 Qt::TabFocus Show information about this application Ab&out... :/images/about1.png Qt::ToolButtonTextBesideIcon StartToolButton StopToolButton QuitToolButton MessagesStatusToolButton SessionToolButton SetupToolButton GraphToolButton ConnectionsToolButton PatchbayToolButton RewindToolButton BackwardToolButton PlayToolButton PauseToolButton ForwardToolButton AboutToolButton qjackctl-1.0.4/src/PaxHeaders/qjackctlSetup.cpp0000644000000000000000000000013214771215054016504 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSetup.cpp0000644000175000001440000010342214771215054016476 0ustar00rncbcusers// qjackctlSetup.cpp // /**************************************************************************** Copyright (C) 2003-2025, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlSetup.h" #include #include #include #include #include #include #include #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) #include #include #if defined(Q_OS_WINDOWS) #include #endif #endif #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #include #endif #ifdef CONFIG_JACK_VERSION #include #endif // Default (translated) preset name. QString qjackctlSetup::g_sDefName; // Default (translated) preset name. (static) const QString& qjackctlSetup::defName (void) { if (g_sDefName.isEmpty()) g_sDefName = QObject::tr("(default)"); return g_sDefName; } // Constructor. qjackctlSetup::qjackctlSetup (void) : m_settings(QJACKCTL_DOMAIN, QJACKCTL_TITLE) { bStartJackCmd = false; loadSetup(); } // Destructor; qjackctlSetup::~qjackctlSetup (void) { // saveSetup(); } // Settings accessor. QSettings& qjackctlSetup::settings (void) { return m_settings; } // Explicit load method. void qjackctlSetup::loadSetup (void) { m_settings.beginGroup("/Presets"); sDefPreset = m_settings.value("/DefPreset", defName()).toString(); sOldPreset = m_settings.value("/OldPreset").toString(); QString sPrefix = "/Preset%1"; int i = 0; for (;;) { QString sItem = m_settings.value(sPrefix.arg(++i)).toString(); if (sItem.isEmpty()) break; presets.append(sItem); } m_settings.endGroup(); #ifdef __APPLE__ // alternative custom defaults, as the mac theme does not look good with our custom widgets sCustomColorTheme = "KXStudio"; sCustomStyleTheme = "Fusion"; #endif m_settings.beginGroup("/Options"); bSingleton = m_settings.value("/Singleton", true).toBool(); // sServerName = m_settings.value("/ServerName").toString(); bStartJack = m_settings.value("/StartJack", false).toBool(); // bStartJackCmd = m_settings.value("/StartJackCmd", false).toBool(); bStopJack = m_settings.value("/StopJack", true).toBool(); bStartupScript = m_settings.value("/StartupScript", false).toBool(); sStartupScriptShell = m_settings.value("/StartupScriptShell").toString(); bPostStartupScript = m_settings.value("/PostStartupScript", false).toBool(); sPostStartupScriptShell = m_settings.value("/PostStartupScriptShell").toString(); bShutdownScript = m_settings.value("/ShutdownScript", false).toBool(); sShutdownScriptShell = m_settings.value("/ShutdownScriptShell").toString(); bPostShutdownScript = m_settings.value("/PostShutdownScript", false).toBool(); sPostShutdownScriptShell = m_settings.value("/PostShutdownScriptShell").toString(); bStdoutCapture = m_settings.value("/StdoutCapture", true).toBool(); sXrunRegex = m_settings.value("/XrunRegex", "xrun of at least ([0-9|\\.]+) msecs").toString(); bActivePatchbay = m_settings.value("/ActivePatchbay", false).toBool(); sActivePatchbayPath = m_settings.value("/ActivePatchbayPath").toString(); bActivePatchbayReset = m_settings.value("/ActivePatchbayReset", false).toBool(); bQueryDisconnect = m_settings.value("/QueryDisconnect", true).toBool(); bMessagesLog = m_settings.value("/MessagesLog", false).toBool(); sMessagesLogPath = m_settings.value("/MessagesLogPath", "qjackctl.log").toString(); iTimeDisplay = m_settings.value("/TimeDisplay", 0).toInt(); sMessagesFont = m_settings.value("/MessagesFont").toString(); bMessagesLimit = m_settings.value("/MessagesLimit", true).toBool(); iMessagesLimitLines = m_settings.value("/MessagesLimitLines", 1000).toInt(); sDisplayFont1 = m_settings.value("/DisplayFont1").toString(); sDisplayFont2 = m_settings.value("/DisplayFont2").toString(); bDisplayEffect = m_settings.value("/DisplayEffect", true).toBool(); bDisplayBlink = m_settings.value("/DisplayBlink", true).toBool(); sCustomColorTheme = m_settings.value("/CustomColorTheme", sCustomColorTheme).toString(); sCustomStyleTheme = m_settings.value("/CustomStyleTheme", sCustomStyleTheme).toString(); iJackClientPortAlias = m_settings.value("/JackClientPortAlias", 0).toInt(); bJackClientPortMetadata = m_settings.value("/JackClientPortMetadata", false).toBool(); iConnectionsIconSize = m_settings.value("/ConnectionsIconSize", QJACKCTL_ICON_16X16).toInt(); sConnectionsFont = m_settings.value("/ConnectionsFont").toString(); bQueryClose = m_settings.value("/QueryClose", true).toBool(); bQueryShutdown = m_settings.value("/QueryShutdown", true).toBool(); bQueryRestart = m_settings.value("/QueryRestart", false).toBool(); bKeepOnTop = m_settings.value("/KeepOnTop", false).toBool(); bSystemTray = m_settings.value("/SystemTray", false).toBool(); bSystemTrayQueryClose = m_settings.value("/SystemTrayQueryClose", true).toBool(); bStartMinimized = m_settings.value("/StartMinimized", false).toBool(); bServerConfig = m_settings.value("/ServerConfig", true).toBool(); sServerConfigName = m_settings.value("/ServerConfigName", ".jackdrc").toString(); bAlsaSeqEnabled = m_settings.value("/AlsaSeqEnabled", true).toBool(); bDBusEnabled = m_settings.value("/DBusEnabled", false).toBool(); bJackDBusEnabled = m_settings.value("/JackDBusEnabled", false).toBool(); bAliasesEnabled = m_settings.value("/AliasesEnabled", false).toBool(); bAliasesEditing = m_settings.value("/AliasesEditing", false).toBool(); bLeftButtons = m_settings.value("/LeftButtons", true).toBool(); bRightButtons = m_settings.value("/RightButtons", true).toBool(); bTransportButtons = m_settings.value("/TransportButtons", true).toBool(); bTextLabels = m_settings.value("/TextLabels", true).toBool(); bGraphButton = m_settings.value("/GraphButton", true).toBool(); iBaseFontSize = m_settings.value("/BaseFontSize", 0).toInt(); m_settings.endGroup(); m_settings.beginGroup("/Defaults"); sPatchbayPath = m_settings.value("/PatchbayPath").toString(); iMessagesStatusTabPage = m_settings.value("/MessagesStatusTabPage", 0).toInt(); iConnectionsTabPage = m_settings.value("/ConnectionsTabPage", 0).toInt(); bSessionSaveVersion = m_settings.value("/SessionSaveVersion", true).toBool(); m_settings.endGroup(); // Load recent patchbay list... m_settings.beginGroup("/Patchbays"); sPrefix = "/Patchbay%1"; i = 0; for (;;) { QString sItem = m_settings.value(sPrefix.arg(++i)).toString(); if (sItem.isEmpty()) break; if (QFileInfo(sItem).exists()) patchbays.append(sItem); } m_settings.endGroup(); // Load recent session directory list... m_settings.beginGroup("/SessionDirs"); sPrefix = "/SessionDir%1"; i = 0; for (;;) { QString sItem = m_settings.value(sPrefix.arg(++i)).toString(); if (sItem.isEmpty()) break; if (QFileInfo(sItem).isDir()) sessionDirs.append(sItem); } m_settings.endGroup(); } // Explicit save method. void qjackctlSetup::saveSetup (void) { // Save all settings and options... m_settings.beginGroup("/Program"); m_settings.setValue("/Version", PROJECT_VERSION); m_settings.endGroup(); m_settings.beginGroup("/Presets"); m_settings.setValue("/DefPreset", sDefPreset); m_settings.setValue("/OldPreset", sOldPreset); // Save last preset list. QString sPrefix = "/Preset%1"; int i = 0; QStringListIterator iter(presets); while (iter.hasNext()) m_settings.setValue(sPrefix.arg(++i), iter.next()); // Cleanup old entries, if any... while (!m_settings.value(sPrefix.arg(++i)).toString().isEmpty()) m_settings.remove(sPrefix.arg(i)); m_settings.endGroup(); m_settings.beginGroup("/Options"); m_settings.setValue("/Singleton", bSingleton); // m_settings.setValue("/ServerName", sServerName); m_settings.setValue("/StartJack", bStartJack); // m_settings.setValue("/StartJackCmd", bStartJackCmd); m_settings.setValue("/StopJack", bStopJack); m_settings.setValue("/StartupScript", bStartupScript); m_settings.setValue("/StartupScriptShell", sStartupScriptShell); m_settings.setValue("/PostStartupScript", bPostStartupScript); m_settings.setValue("/PostStartupScriptShell", sPostStartupScriptShell); m_settings.setValue("/ShutdownScript", bShutdownScript); m_settings.setValue("/ShutdownScriptShell", sShutdownScriptShell); m_settings.setValue("/PostShutdownScript", bPostShutdownScript); m_settings.setValue("/PostShutdownScriptShell", sPostShutdownScriptShell); m_settings.setValue("/StdoutCapture", bStdoutCapture); m_settings.setValue("/XrunRegex", sXrunRegex); m_settings.setValue("/ActivePatchbay", bActivePatchbay); m_settings.setValue("/ActivePatchbayPath", sActivePatchbayPath); m_settings.setValue("/ActivePatchbayReset", bActivePatchbayReset); m_settings.setValue("/QueryDisconnect", bQueryDisconnect); m_settings.setValue("/MessagesLog", bMessagesLog); m_settings.setValue("/MessagesLogPath", sMessagesLogPath); m_settings.setValue("/TimeDisplay", iTimeDisplay); m_settings.setValue("/MessagesFont", sMessagesFont); m_settings.setValue("/MessagesLimit", bMessagesLimit); m_settings.setValue("/MessagesLimitLines", iMessagesLimitLines); m_settings.setValue("/DisplayFont1", sDisplayFont1); m_settings.setValue("/DisplayFont2", sDisplayFont2); m_settings.setValue("/DisplayEffect", bDisplayEffect); m_settings.setValue("/DisplayBlink", bDisplayBlink); m_settings.setValue("/CustomColorTheme", sCustomColorTheme); m_settings.setValue("/CustomStyleTheme", sCustomStyleTheme); m_settings.setValue("/JackClientPortAlias", iJackClientPortAlias); m_settings.setValue("/JackClientPortMetadata", bJackClientPortMetadata); m_settings.setValue("/ConnectionsIconSize", iConnectionsIconSize); m_settings.setValue("/ConnectionsFont", sConnectionsFont); m_settings.setValue("/QueryClose", bQueryClose); m_settings.setValue("/QueryShutdown", bQueryShutdown); m_settings.setValue("/QueryRestart", bQueryRestart); m_settings.setValue("/KeepOnTop", bKeepOnTop); m_settings.setValue("/SystemTray", bSystemTray); m_settings.setValue("/SystemTrayQueryClose", bSystemTrayQueryClose); m_settings.setValue("/StartMinimized", bStartMinimized); m_settings.setValue("/ServerConfig", bServerConfig); m_settings.setValue("/ServerConfigName", sServerConfigName); m_settings.setValue("/AlsaSeqEnabled", bAlsaSeqEnabled); m_settings.setValue("/DBusEnabled", bDBusEnabled); m_settings.setValue("/JackDBusEnabled", bJackDBusEnabled); m_settings.setValue("/AliasesEnabled", bAliasesEnabled); m_settings.setValue("/AliasesEditing", bAliasesEditing); m_settings.setValue("/LeftButtons", bLeftButtons); m_settings.setValue("/RightButtons", bRightButtons); m_settings.setValue("/TransportButtons", bTransportButtons); m_settings.setValue("/TextLabels", bTextLabels); m_settings.setValue("/GraphButton", bGraphButton); m_settings.setValue("/BaseFontSize", iBaseFontSize); m_settings.endGroup(); m_settings.beginGroup("/Defaults"); m_settings.setValue("/PatchbayPath", sPatchbayPath); m_settings.setValue("/MessagesStatusTabPage", iMessagesStatusTabPage); m_settings.setValue("/ConnectionsTabPage", iConnectionsTabPage); m_settings.setValue("/SessionSaveVersion", bSessionSaveVersion); m_settings.endGroup(); // Save patchbay list... m_settings.beginGroup("/Patchbays"); sPrefix = "/Patchbay%1"; i = 0; QStringListIterator iter2(patchbays); while (iter2.hasNext()) m_settings.setValue(sPrefix.arg(++i), iter2.next()); // Cleanup old entries, if any... while (!m_settings.value(sPrefix.arg(++i)).toString().isEmpty()) m_settings.remove(sPrefix.arg(i)); m_settings.endGroup(); // Save session directory list... m_settings.beginGroup("/SessionDirs"); sPrefix = "/SessionDir%1"; i = 0; QStringListIterator iter3(sessionDirs); while (iter3.hasNext()) m_settings.setValue(sPrefix.arg(++i), iter3.next()); // Cleanup old entries, if any... while (!m_settings.value(sPrefix.arg(++i)).toString().isEmpty()) m_settings.remove(sPrefix.arg(i)); m_settings.endGroup(); // Commit all changes to disk. m_settings.sync(); } //--------------------------------------------------------------------------- // Aliases preset management methods. bool qjackctlSetup::loadAliases (void) { QString sPreset = sDefPreset; QString sSuffix; if (sPreset != defName() && !sPreset.isEmpty()) { sSuffix = '/' + sPreset; // Check if on list. if (!presets.contains(sPreset)) return false; } // Load preset aliases... const QString sAliasesKey = "/Aliases" + sSuffix; m_settings.beginGroup(sAliasesKey); m_settings.beginGroup("/Jack"); // FIXME: Audio aliases.audioOutputs.loadSettings(m_settings, "/Outputs"); aliases.audioInputs.loadSettings(m_settings, "/Inputs"); m_settings.endGroup(); m_settings.beginGroup("/Midi"); aliases.midiOutputs.loadSettings(m_settings, "/Outputs"); aliases.midiInputs.loadSettings(m_settings, "/Inputs"); m_settings.endGroup(); m_settings.beginGroup("/Alsa"); aliases.alsaOutputs.loadSettings(m_settings, "/Outputs"); aliases.alsaInputs.loadSettings(m_settings, "/Inputs"); m_settings.endGroup(); m_settings.endGroup(); aliases.dirty = false; aliases.key = sPreset; return true; } bool qjackctlSetup::saveAliases (void) { const QString& sPreset = aliases.key; QString sSuffix; if (sPreset != defName() && !sPreset.isEmpty()) { sSuffix = "/" + sPreset; // Append to list if not already. if (!presets.contains(sPreset)) presets.prepend(sPreset); } // Save preset aliases... const QString sAliasesKey = "/Aliases" + sSuffix; // m_settings.remove(sAliasesKey); m_settings.beginGroup(sAliasesKey); m_settings.beginGroup("/Jack"); // FIXME: Audio aliases.audioOutputs.saveSettings(m_settings, "/Outputs"); aliases.audioInputs.saveSettings(m_settings, "/Inputs"); m_settings.endGroup(); m_settings.beginGroup("/Midi"); aliases.midiOutputs.saveSettings(m_settings, "/Outputs"); aliases.midiInputs.saveSettings(m_settings, "/Inputs"); m_settings.endGroup(); m_settings.beginGroup("/Alsa"); aliases.alsaOutputs.saveSettings(m_settings, "/Outputs"); aliases.alsaInputs.saveSettings(m_settings, "/Inputs"); m_settings.endGroup(); m_settings.endGroup(); aliases.dirty = false; return true; } //--------------------------------------------------------------------------- // Preset struct methods. void qjackctlPreset::clear (void) { sServerPrefix.clear(); sServerName .clear(); bRealtime = true; bSoftMode = false; bMonitor = false; bShorts = false; bNoMemLock = false; bUnlockMem = false; bHWMeter = false; bIgnoreHW = false; iPriority = 0; iFrames = 0; iSampleRate = 0; iPeriods = 0; iWordLength = 0; iWait = 0; iChan = 0; sDriver .clear(); sInterface .clear(); iAudio = 0; iDither = 0; iTimeout = 0; sInDevice .clear(); sOutDevice .clear(); iInChannels = 0; iOutChannels = 0; iInLatency = 0; iOutLatency = 0; iStartDelay = 2; bSync = false; bVerbose = false; iPortMax = 0; sMidiDriver .clear(); sServerSuffix.clear(); ucClockSource = 0; ucSelfConnectMode = 0; fixup(); } void qjackctlPreset::load ( QSettings& settings, const QString& sSuffix ) { settings.beginGroup("/Settings" + sSuffix); sServerPrefix = settings.value("/Server", sServerPrefix).toString(); sServerName = settings.value("/ServerName", sServerName).toString(); bRealtime = settings.value("/Realtime", bRealtime).toBool(); bSoftMode = settings.value("/SoftMode", bSoftMode).toBool(); bMonitor = settings.value("/Monitor", bMonitor).toBool(); bShorts = settings.value("/Shorts", bShorts).toBool(); bNoMemLock = settings.value("/NoMemLock", bNoMemLock).toBool(); bUnlockMem = settings.value("/UnlockMem", bUnlockMem).toBool(); bHWMeter = settings.value("/HWMeter", bHWMeter).toBool(); bIgnoreHW = settings.value("/IgnoreHW", bIgnoreHW).toBool(); iPriority = settings.value("/Priority", iPriority).toInt(); iFrames = settings.value("/Frames", iFrames).toInt(); iSampleRate = settings.value("/SampleRate", iSampleRate).toInt(); iPeriods = settings.value("/Periods", iPeriods).toInt(); iWordLength = settings.value("/WordLength", iWordLength).toInt(); iWait = settings.value("/Wait", iWait).toInt(); iChan = settings.value("/Chan", iChan).toInt(); sDriver = settings.value("/Driver", sDriver).toString(); sInterface = settings.value("/Interface", sInterface).toString(); iAudio = settings.value("/Audio", iAudio).toInt(); iDither = settings.value("/Dither", iDither).toInt(); iTimeout = settings.value("/Timeout", iTimeout).toInt(); sInDevice = settings.value("/InDevice", sInDevice).toString(); sOutDevice = settings.value("/OutDevice", sOutDevice).toString(); iInChannels = settings.value("/InChannels", iInChannels).toInt(); iOutChannels = settings.value("/OutChannels", iOutChannels).toInt(); iInLatency = settings.value("/InLatency", iInLatency).toInt(); iOutLatency = settings.value("/OutLatency", iOutLatency).toInt(); iStartDelay = settings.value("/StartDelay", iStartDelay).toInt(); bSync = settings.value("/Sync", bSync).toBool(); bVerbose = settings.value("/Verbose", bVerbose).toBool(); iPortMax = settings.value("/PortMax", iPortMax).toInt(); sMidiDriver = settings.value("/MidiDriver", sMidiDriver).toString(); sServerSuffix = settings.value("/ServerSuffix", sServerSuffix).toString(); ucClockSource = settings.value("/ClockSource", ucClockSource).value(); ucSelfConnectMode = settings.value("/SelfConnectMode", ucSelfConnectMode).value(); settings.endGroup(); fixup(); } void qjackctlPreset::save ( QSettings& settings, const QString& sSuffix ) { settings.beginGroup("/Settings" + sSuffix); settings.setValue("/Server", sServerPrefix); settings.setValue("/ServerName", sServerName); settings.setValue("/Realtime", bRealtime); settings.setValue("/SoftMode", bSoftMode); settings.setValue("/Monitor", bMonitor); settings.setValue("/Shorts", bShorts); settings.setValue("/NoMemLock", bNoMemLock); settings.setValue("/UnlockMem", bUnlockMem); settings.setValue("/HWMeter", bHWMeter); settings.setValue("/IgnoreHW", bIgnoreHW); settings.setValue("/Priority", iPriority); settings.setValue("/Frames", iFrames); settings.setValue("/SampleRate", iSampleRate); settings.setValue("/Periods", iPeriods); settings.setValue("/WordLength", iWordLength); settings.setValue("/Wait", iWait); settings.setValue("/Chan", iChan); settings.setValue("/Driver", sDriver); settings.setValue("/Interface", sInterface); settings.setValue("/Audio", iAudio); settings.setValue("/Dither", iDither); settings.setValue("/Timeout", iTimeout); settings.setValue("/InDevice", sInDevice); settings.setValue("/OutDevice", sOutDevice); settings.setValue("/InChannels", iInChannels); settings.setValue("/OutChannels", iOutChannels); settings.setValue("/InLatency", iInLatency); settings.setValue("/OutLatency", iOutLatency); settings.setValue("/StartDelay", iStartDelay); settings.setValue("/Sync", bSync); settings.setValue("/Verbose", bVerbose); settings.setValue("/PortMax", iPortMax); settings.setValue("/MidiDriver", sMidiDriver); settings.setValue("/ServerSuffix", sServerSuffix); settings.setValue("/ClockSource", ucClockSource); settings.setValue("/SelfConnectMode", ucSelfConnectMode); settings.endGroup(); } void qjackctlPreset::fixup (void) { if (sServerPrefix.isEmpty()) { sServerPrefix = "jackd"; #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) sServerPrefix += " -S -X winmme"; #endif } if (sDriver.isEmpty()) { #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) sDriver = "portaudio"; #elif defined(__APPLE__) sDriver = "coreaudio"; #elif defined(__FreeBSD__) sDriver = "oss"; #else sDriver = "alsa"; #endif } #ifdef CONFIG_JACK_MIDI if (!sMidiDriver.isEmpty() && sMidiDriver != "raw" && sMidiDriver != "seq") sMidiDriver.clear(); #endif } //--------------------------------------------------------------------------- // Preset management methods. bool qjackctlSetup::loadPreset ( qjackctlPreset& preset, const QString& sPreset ) { QString sSuffix; if (sPreset != defName() && !sPreset.isEmpty()) { sSuffix = '/' + sPreset; // Check if on list. if (!presets.contains(sPreset)) return false; } preset.load(m_settings, sSuffix); return true; } bool qjackctlSetup::savePreset ( qjackctlPreset& preset, const QString& sPreset ) { QString sSuffix; if (sPreset != defName() && !sPreset.isEmpty()) { sSuffix = '/' + sPreset; // Append to list if not already. if (!presets.contains(sPreset)) presets.prepend(sPreset); } preset.save(m_settings, sSuffix); return true; } bool qjackctlSetup::deletePreset ( const QString& sPreset ) { QString sSuffix; if (sPreset != defName() && !sPreset.isEmpty()) { sSuffix = '/' + sPreset; const int iPreset = presets.indexOf(sPreset); if (iPreset < 0) return false; presets.removeAt(iPreset); m_settings.remove("/Settings" + sSuffix); m_settings.remove("/Aliases" + sSuffix); } return true; } //------------------------------------------------------------------------- // Command-line argument stuff. // #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) void qjackctlSetup::show_error( const QString& msg ) { #if defined(Q_OS_WINDOWS) QMessageBox::information(nullptr, QApplication::applicationName(), msg); #else const QByteArray tmp = msg.toUtf8() + '\n'; ::fputs(tmp.constData(), stderr); #endif } #else // Help about command line options. void qjackctlSetup::print_usage ( const QString& arg0 ) { QTextStream out(stderr); const QString sEot = "\n\t"; const QString sEol = "\n\n"; out << QObject::tr("Usage: %1" " [options] [command-and-args]").arg(arg0) + sEol; out << QJACKCTL_TITLE " - " + QObject::tr(QJACKCTL_SUBTITLE) + sEol; out << QObject::tr("Options:") + sEol; out << " -s, --start" + sEot + QObject::tr("Start JACK audio server immediately.") + sEol; out << " -p, --preset=[label]" + sEot + QObject::tr("Set default settings preset name.") + sEol; out << " -a, --active-patchbay=[path]" + sEot + QObject::tr("Set active patchbay definition file.") + sEol; out << " -n, --server-name=[label]" + sEot + QObject::tr("Set default JACK audio server name.") + sEol; out << " -h, --help" + sEot + QObject::tr("Show help about command line options.") + sEol; out << " -v, --version" + sEot + QObject::tr("Show version information.") + sEol; } #endif // Parse command line arguments into m_settings. bool qjackctlSetup::parse_args ( const QStringList& args ) { int iCmdArgs = 0; #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) QCommandLineParser parser; parser.setApplicationDescription( QJACKCTL_TITLE " - " + QObject::tr(QJACKCTL_SUBTITLE)); parser.addOption({{"s", "start"}, QObject::tr("Start JACK audio server immediately.")}); parser.addOption({{"p", "preset"}, QObject::tr("Set default settings preset name."), "label"}); parser.addOption({{"a", "active-patchbay"}, QObject::tr("Set active patchbay definition file."), "path"}); parser.addOption({{"n", "server-name"}, QObject::tr("Set default JACK audio server name."), "name"}); const QCommandLineOption& helpOption = parser.addHelpOption(); const QCommandLineOption& versionOption = parser.addVersionOption(); parser.addPositionalArgument("command-and-args", QObject::tr("Launch command with arguments."), QObject::tr("[command-and-args]")); if (!parser.parse(args)) { show_error(parser.errorText()); return false; } if (parser.isSet(helpOption)) { show_error(parser.helpText()); return false; } if (parser.isSet(versionOption)) { QString sVersion = QString("%1 %2\n") .arg(QJACKCTL_TITLE) .arg(QCoreApplication::applicationVersion()); sVersion += QString("Qt: %1").arg(qVersion()); #if defined(QT_STATIC) sVersion += "-static"; #endif sVersion += '\n'; #ifdef CONFIG_JACK_VERSION sVersion += QString("JACK: %1\n").arg(jack_get_version_string()); #endif show_error(sVersion); return false; } if (parser.isSet("start")) { bStartJackCmd = true; } if (parser.isSet("preset")) { const QString& sVal = parser.value("preset"); if (sVal.isEmpty()) { show_error(QObject::tr("Option -p requires an argument (preset).")); return false; } sDefPreset = sVal; } if (parser.isSet("active-patchbay")) { const QString& sVal = parser.value("active-patchbay"); if (sVal.isEmpty()) { show_error(QObject::tr("Option -a requires an argument (path).")); return false; } bActivePatchbay = true; sActivePatchbayPath = sVal; } if (parser.isSet("server-name")) { const QString& sVal = parser.value("server-name"); if (sVal.isEmpty()) { show_error(QObject::tr("Option -n requires an argument (name).")); return false; } sServerName = sVal; } foreach (const QString& sArg, parser.positionalArguments()) { if (sArg != "-T" && sArg != "-ndefault") { cmdLine.append(sArg); ++iCmdArgs; } } #else QTextStream out(stderr); const QString sEol = "\n\n"; const int argc = args.count(); for (int i = 1; i < argc; ++i) { QString sArg = args.at(i); if (iCmdArgs > 0) { sCmdArgs.append(sArg); ++iCmdArgs; continue; } QString sVal; const int iEqual = sArg.indexOf('='); if (iEqual >= 0) { sVal = sArg.right(sArg.length() - iEqual - 1); sArg = sArg.left(iEqual); } else if (i < argc - 1) sVal = args.at(i + 1); if (sArg == "-s" || sArg == "--start") { bStartJackCmd = true; } else if (sArg == "-p" || sArg == "--preset") { if (sVal.isNull()) { out << QObject::tr("Option -p requires an argument (preset).") + sEol; return false; } sDefPreset = sVal; if (iEqual < 0) ++i; } else if (sArg == "-a" || sArg == "--active-patchbay") { if (sVal.isNull()) { out << QObject::tr("Option -a requires an argument (path).") + sEol; return false; } bActivePatchbay = true; sActivePatchbayPath = sVal; if (iEqual < 0) ++i; } else if (sArg == "-n" || sArg == "--server-name") { if (sVal.isNull()) { out << QObject::tr("Option -n requires an argument (name).") + sEol; return false; } sServerName = sVal; if (iEqual < 0) ++i; } else if (sArg == "-h" || sArg == "--help") { print_usage(args.at(0)); return false; } else if (sArg == "-v" || sArg == "--version") { out << QString("Qt: %1").arg(qVersion()); #if defined(QT_STATIC) out << "-static"; #endif out << '\n'; #ifdef CONFIG_JACK_VERSION out << QString("JACK: %1\n") .arg(jack_get_version_string()); #endif out << QString("%1: %2\n") .arg(QJACKCTL_TITLE) .arg(PROJECT_VERSION); return false; } // FIXME: Avoid auto-start jackd stuffed args! else if (sArg != "-T" && sArg != "-ndefault") { // Here starts the optional command line... cmdLine.append(sArg); ++iCmdArgs; } } #endif // HACK: If there's a command line, it must be spawned on background... if (iCmdArgs > 0) cmdLine.append("&"); // Alright with argument parsing. return true; } //--------------------------------------------------------------------------- // Combo box history persistence helper implementation. void qjackctlSetup::loadComboBoxHistory ( QComboBox *pComboBox, int iLimit ) { const bool bBlockSignals = pComboBox->blockSignals(true); // Load combobox list from configuration settings file... m_settings.beginGroup("/History/" + pComboBox->objectName()); if (m_settings.childKeys().count() > 0) { pComboBox->setUpdatesEnabled(false); pComboBox->setDuplicatesEnabled(false); pComboBox->clear(); for (int i = 0; i < iLimit; ++i) { const QString& sText = m_settings.value( "/Item" + QString::number(i + 1)).toString(); if (sText.isEmpty()) break; pComboBox->addItem(sText); } pComboBox->setUpdatesEnabled(true); } m_settings.endGroup(); pComboBox->blockSignals(bBlockSignals); } void qjackctlSetup::saveComboBoxHistory ( QComboBox *pComboBox, int iLimit ) { const bool bBlockSignals = pComboBox->blockSignals(true); int iCount = pComboBox->count(); // Add current text as latest item (if not blank)... const QString& sCurrentText = pComboBox->currentText(); if (!sCurrentText.isEmpty()) { for (int i = 0; i < iCount; ++i) { const QString& sText = pComboBox->itemText(i); if (sText == sCurrentText) { pComboBox->removeItem(i); --iCount; break; } } pComboBox->insertItem(0, sCurrentText); pComboBox->setCurrentIndex(0); ++iCount; } while (iCount >= iLimit) pComboBox->removeItem(--iCount); // Save combobox list to configuration settings file... m_settings.beginGroup("/History/" + pComboBox->objectName()); for (int i = 0; i < iCount; ++i) { const QString& sText = pComboBox->itemText(i); if (sText.isEmpty()) break; m_settings.setValue("/Item" + QString::number(i + 1), sText); } m_settings.endGroup(); pComboBox->blockSignals(bBlockSignals); } //--------------------------------------------------------------------------- // Splitter widget sizes persistence helper methods. void qjackctlSetup::loadSplitterSizes ( QSplitter *pSplitter, QList& sizes ) { // Try to restore old splitter sizes... if (pSplitter) { m_settings.beginGroup("/Splitter/" + pSplitter->objectName()); QStringList list = m_settings.value("/sizes").toStringList(); if (!list.isEmpty()) { sizes.clear(); QStringListIterator iter(list); while (iter.hasNext()) sizes.append(iter.next().toInt()); } pSplitter->setSizes(sizes); m_settings.endGroup(); } } void qjackctlSetup::saveSplitterSizes ( QSplitter *pSplitter ) { // Try to save current splitter sizes... if (pSplitter) { m_settings.beginGroup("/Splitter/" + pSplitter->objectName()); QStringList list; QList sizes = pSplitter->sizes(); QListIterator iter(sizes); while (iter.hasNext()) list.append(QString::number(iter.next())); if (!list.isEmpty()) m_settings.setValue("/sizes", list); m_settings.endGroup(); } } //--------------------------------------------------------------------------- // Widget geometry persistence helper methods. void qjackctlSetup::loadWidgetGeometry ( QWidget *pWidget, bool bVisible ) { // Try to restore old form window positioning. if (pWidget) { // if (bVisible) pWidget->show(); -- force initial exposure? m_settings.beginGroup("/Geometry/" + pWidget->objectName()); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) const QByteArray& geometry = m_settings.value("/geometry").toByteArray(); if (geometry.isEmpty()) { QWidget *pParent = pWidget->parentWidget(); if (pParent) pParent = pParent->window(); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) if (pParent == nullptr) pParent = QApplication::desktop(); #endif if (pParent) { QRect wrect(pWidget->geometry()); wrect.moveCenter(pParent->geometry().center()); pWidget->move(wrect.topLeft()); } } else { pWidget->restoreGeometry(geometry); } #else//--LOAD_OLD_GEOMETRY QPoint wpos; QSize wsize; wpos.setX(m_settings.value("/x", -1).toInt()); wpos.setY(m_settings.value("/y", -1).toInt()); wsize.setWidth(m_settings.value("/width", -1).toInt()); wsize.setHeight(m_settings.value("/height", -1).toInt()); if (wpos.x() > 0 && wpos.y() > 0) pWidget->move(wpos); if (wsize.width() > 0 && wsize.height() > 0) pWidget->resize(wsize); #endif // else // pWidget->adjustSize(); if (!bVisible) bVisible = m_settings.value("/visible", false).toBool(); if (bVisible && !bStartMinimized) pWidget->show(); else pWidget->hide(); m_settings.endGroup(); } } void qjackctlSetup::saveWidgetGeometry ( QWidget *pWidget, bool bVisible ) { // Try to save form window position... // (due to X11 window managers ideossincrasies, we better // only save the form geometry while its up and visible) if (pWidget) { m_settings.beginGroup("/Geometry/" + pWidget->objectName()); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) m_settings.setValue("/geometry", pWidget->saveGeometry()); #else//--SAVE_OLD_GEOMETRY const QPoint& wpos = pWidget->pos(); const QSize& wsize = pWidget->size(); m_settings.setValue("/x", wpos.x()); m_settings.setValue("/y", wpos.y()); m_settings.setValue("/width", wsize.width()); m_settings.setValue("/height", wsize.height()); #endif if (!bVisible) bVisible = pWidget->isVisible(); m_settings.setValue("/visible", bVisible && !bStartMinimized); m_settings.endGroup(); } } // end of qjackctlSetup.cpp qjackctl-1.0.4/src/PaxHeaders/config.h.cmake0000644000000000000000000000013214771215054015660 xustar0030 mtime=1743067692.318540145 30 atime=1743067692.318540145 30 ctime=1743067692.318540145 qjackctl-1.0.4/src/config.h.cmake0000644000175000001440000000676514771215054015666 0ustar00rncbcusers#ifndef CONFIG_H #define CONFIG_H /* Define to the title of this package. */ #cmakedefine PROJECT_TITLE "@PROJECT_TITLE@" /* Define to the name of this package. */ #cmakedefine PROJECT_NAME "@PROJECT_NAME@" /* Define to the version of this package. */ #cmakedefine PROJECT_VERSION "@PROJECT_VERSION@" /* Define to the description of this package. */ #cmakedefine PROJECT_DESCRIPTION "@PROJECT_DESCRIPTION@" /* Define to the homepage of this package. */ #cmakedefine PROJECT_HOMEPAGE_URL "@PROJECT_HOMEPAGE_URL@" /* Define to the copyright of this package. */ #cmakedefine PROJECT_COPYRIGHT "@PROJECT_COPYRIGHT@" /* Define to the domain of this package. */ #cmakedefine PROJECT_DOMAIN "@PROJECT_DOMAIN@" /* Default installation prefix. */ #cmakedefine CONFIG_PREFIX "@CONFIG_PREFIX@" /* Define to target installation dirs. */ #cmakedefine CONFIG_BINDIR "@CONFIG_BINDIR@" #cmakedefine CONFIG_LIBDIR "@CONFIG_LIBDIR@" #cmakedefine CONFIG_DATADIR "@CONFIG_DATADIR@" #cmakedefine CONFIG_MANDIR "@CONFIG_MANDIR@" /* Define if debugging is enabled. */ #cmakedefine CONFIG_DEBUG @CONFIG_DEBUG@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SIGNAL_H @HAVE_SIGNAL_H@ /* Define if JACK library is available. */ #cmakedefine CONFIG_JACK @CONFIG_JACK@ /* Define if ALSA library is available. */ #cmakedefine CONFIG_ALSA_SEQ @CONFIG_ALSA_SEQ@ /* Define if PORTAUDIO library is available. */ #cmakedefine CONFIG_PORTAUDIO @CONFIG_PORTAUDIO@ /* Define if jack/statistics.h is available. */ #cmakedefine CONFIG_JACK_STATISTICS @CONFIG_JACK_STATISTICS@ /* Define if CoreAudio/CoreAudio.h is available (Mac OS X). */ #cmakedefine CONFIG_COREAUDIO @CONFIG_COREAUDIO@ /* Define if JACK session support is available. */ #cmakedefine CONFIG_JACK_SESSION @CONFIG_JACK_SESSION@ /* Define if JACK metadata support is available. */ #cmakedefine CONFIG_JACK_METADATA @CONFIG_JACK_METADATA@ /* Define if JACK MIDI support is available. */ #cmakedefine CONFIG_JACK_MIDI @CONFIG_JACK_MIDI@ /* Define if JACK CV support is available. */ #cmakedefine CONFIG_JACK_CV @CONFIG_JACK_CV@ /* Define if JACK OSC support is available. */ #cmakedefine CONFIG_JACK_OSC @CONFIG_JACK_OSC@ /* Define if D-Bus interface is enabled. */ #cmakedefine CONFIG_DBUS @CONFIG_DBUS@ /* Define if unique/single instance is enabled. */ #cmakedefine CONFIG_XUNIQUE @CONFIG_XUNIQUE@ /* Define if debugger stack-trace is enabled. */ #cmakedefine CONFIG_STACKTRACE @CONFIG_STACKTRACE@ /* Define if system tray is enabled. */ #cmakedefine CONFIG_SYSTEM_TRAY @CONFIG_SYSTEM_TRAY@ /* Define if jack_tranport_query is available. */ #cmakedefine CONFIG_JACK_TRANSPORT @CONFIG_JACK_TRANSPORT@ /* Define if jack_is_realtime is available. */ #cmakedefine CONFIG_JACK_REALTIME @CONFIG_JACK_REALTIME@ /* Define if jack_get_xrun_delayed_usecs is available. */ #cmakedefine CONFIG_JACK_XRUN_DELAY @CONFIG_JACK_XRUN_DELAY@ /* Define if jack_get_max_delayed_usecs is available. */ #cmakedefine CONFIG_JACK_MAX_DELAY @CONFIG_JACK_MAX_DELAY@ /* Define if jack_set_port_rename_callback is available. */ #cmakedefine CONFIG_JACK_PORT_RENAME @CONFIG_JACK_PORT_RENAME@ /* Define if jack_port_get_aliases is available. */ #cmakedefine CONFIG_JACK_PORT_ALIASES @CONFIG_JACK_PORT_ALIASES@ /* Define if jack_get_version_string is available. */ #cmakedefine CONFIG_JACK_VERSION @CONFIG_JACK_VERSION@ /* Define if jack_free is available. */ #cmakedefine CONFIG_JACK_FREE @CONFIG_JACK_FREE@ /* Define if Wayland is supported */ #cmakedefine CONFIG_WAYLAND @CONFIG_WAYLAND@ #endif /* CONFIG_H */ qjackctl-1.0.4/src/PaxHeaders/qjackctlGraph.h0000644000000000000000000000013214771215054016112 xustar0030 mtime=1743067692.324636588 30 atime=1743067692.324636588 30 ctime=1743067692.324636588 qjackctl-1.0.4/src/qjackctlGraph.h0000644000175000001440000004527114771215054016113 0ustar00rncbcusers// qjackctlGraph.h // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlGraph_h #define __qjackctlGraph_h #include #include #include #include #include #include #include class QGestureEvent; class QPinchGesture; // Forward decls. class qjackctlGraphCanvas; class qjackctlGraphNode; class qjackctlGraphPort; class qjackctlGraphConnect; class qjackctlGraphCommand; class qjackctlGraphMoveCommand; class qjackctlAliases; class qjackctlAliasList; class QStyleOptionGraphicsItem; class QRubberBand; class QUndoCommand; class QUndoStack; class QSettings; class QGraphicsProxyWidget; class QLineEdit; class QMouseEvent; class QWheelEvent; class QKeyEvent; //---------------------------------------------------------------------------- // qjackctlGraphItem -- Base graphics item. class qjackctlGraphItem : public QGraphicsPathItem { public: // Constructor. qjackctlGraphItem(QGraphicsItem *parent = nullptr); // Basic color accessors. void setForeground(const QColor& color); const QColor& foreground() const; void setBackground(const QColor& color); const QColor& background() const; // Marking methods. void setMarked(bool marked); bool isMarked() const; // Highlighting methods. void setHighlight(bool hilite); bool isHighlight() const; // Raise item z-value (dynamic always-on-top). void raise(); // Item modes. enum Mode { None = 0, Input = 1, Output = 2, Duplex = Input | Output }; // Item hash/map key. class ItemKey { public: // Constructors. ItemKey (const QString& name, Mode mode, uint type = 0) : m_name(name), m_mode(mode), m_type(type) {} ItemKey (const ItemKey& key) : m_name(key.name()), m_mode(key.mode()), m_type(key.type()) {} // Key accessors. const QString& name() const { return m_name; } Mode mode() const { return m_mode; } uint type() const { return m_type; } // Hash/map key comparators. bool operator== (const ItemKey& key) const { return ItemKey::type() == key.type() && ItemKey::mode() == key.mode() && ItemKey::name() == key.name(); } private: // Key fields. QString m_name; Mode m_mode; uint m_type; }; typedef QHash ItemKeys; // Item-type hash (static) static uint itemType(const QByteArray& type_name); // Rectangular editor extents. virtual QRectF editorRect() const; // Path and bounding rectangle override. void setPath(const QPainterPath& path); // Bounding rectangle accessor. const QRectF& itemRect() const; private: // Instance variables. QColor m_foreground; QColor m_background; bool m_marked; bool m_hilite; QRectF m_rect; }; // Item hash function. inline uint qHash ( const qjackctlGraphItem::ItemKey& key ) { return qHash(key.name()) ^ qHash(uint(key.mode())) ^ qHash(key.type()); } //---------------------------------------------------------------------------- // qjackctlGraphPort -- Port graphics item. class qjackctlGraphPort : public qjackctlGraphItem { public: // Constructor. qjackctlGraphPort(qjackctlGraphNode *node, const QString& name, Mode mode, uint type = 0); // Destructor. ~qjackctlGraphPort(); // Graphics item type. enum { Type = QGraphicsItem::UserType + 2 }; int type() const { return Type; } // Accessors. qjackctlGraphNode *portNode() const; void setPortName(const QString& name); const QString& portName() const; void setPortMode(Mode mode); Mode portMode() const; bool isInput() const; bool isOutput() const; void setPortType(uint type); uint portType() const; void setPortTitle(const QString& title); const QString& portTitle() const; void setPortIndex(int index); int portIndex() const; QPointF portPos() const; // Connection-list methods. void appendConnect(qjackctlGraphConnect *connect); void removeConnect(qjackctlGraphConnect *connect); void removeConnects(); qjackctlGraphConnect *findConnect(qjackctlGraphPort *port) const; // Connect-list accessor. const QList& connects() const; // Selection propagation method... void setSelectedEx(bool is_selected); // Highlighting propagation method... void setHighlightEx(bool is_highlight); // Special port-type color business. void updatePortTypeColors(qjackctlGraphCanvas *canvas); // Port hash/map key. class PortKey : public ItemKey { public: // Constructors. PortKey(qjackctlGraphPort *port) : ItemKey(port->portName(), port->portMode(), port->portType()) {} }; // Port sorting type. enum SortType { PortName = 0, PortTitle, PortIndex }; static void setSortType(SortType sort_type); static SortType sortType(); // Port sorting order. enum SortOrder { Ascending = 0, Descending }; static void setSortOrder(SortOrder sort_order); static SortOrder sortOrder(); // Port sorting comparators. struct Compare { bool operator()(qjackctlGraphPort *port1, qjackctlGraphPort *port2) const { return qjackctlGraphPort::lessThan(port1, port2); } }; struct ComparePos { bool operator()(qjackctlGraphPort *port1, qjackctlGraphPort *port2) const { return (port1->scenePos().y() < port2->scenePos().y()); } }; // Rectangular editor extents. QRectF editorRect() const; // Connector curve draw style (through vs. around nodes) static void setConnectThroughNodes(bool on); static bool isConnectThroughNodes(); protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QVariant itemChange(GraphicsItemChange change, const QVariant& value); // Natural decimal sorting comparators. static bool lessThan(qjackctlGraphPort *port1, qjackctlGraphPort *port2); static bool lessThan(const QString& s1, const QString& s2); private: // instance variables. qjackctlGraphNode *m_node; QString m_name; Mode m_mode; uint m_type; QString m_title; int m_index; QGraphicsTextItem *m_text; QList m_connects; int m_selectx; int m_hilitex; static SortType g_sort_type; static SortOrder g_sort_order; }; //---------------------------------------------------------------------------- // qjackctlGraphNode -- Node graphics item. class qjackctlGraphNode : public qjackctlGraphItem { public: // Constructor. qjackctlGraphNode(const QString& name, Mode mode, uint type = 0); // Destructor.. ~qjackctlGraphNode(); // Graphics item type. enum { Type = QGraphicsItem::UserType + 1 }; int type() const { return Type; } // Accessors. void setNodeName(const QString& name); const QString& nodeName() const; void setNodeMode(Mode mode); Mode nodeMode() const; void setNodeType(uint type); uint nodeType() const; void setNodeIcon(const QIcon& icon); const QIcon& nodeIcon() const; void setNodeTitle(const QString& title); QString nodeTitle() const; // Port-list methods. qjackctlGraphPort *addPort(const QString& name, Mode mode, int type = 0); qjackctlGraphPort *addInputPort(const QString& name, int type = 0); qjackctlGraphPort *addOutputPort(const QString& name, int type = 0); void removePort(qjackctlGraphPort *port); void removePorts(); // Port finder (by name, mode and type) qjackctlGraphPort *findPort(const QString& name, Mode mode, uint type = 0); // Port-list accessor. const QList& ports() const; // Reset port markings, destroy if unmarked. void resetMarkedPorts(); // Path/shape updater. void updatePath(); // Node hash key. class NodeKey : public ItemKey { public: // Constructors. NodeKey(qjackctlGraphNode *node) : ItemKey(node->nodeName(), node->nodeMode(), node->nodeType()) {} }; // Rectangular editor extents. QRectF editorRect() const; protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QVariant itemChange(GraphicsItemChange change, const QVariant& value); private: // Instance variables. QString m_name; Mode m_mode; uint m_type; QIcon m_icon; QString m_title; QGraphicsPixmapItem *m_pixmap; QGraphicsTextItem *m_text; qjackctlGraphPort::ItemKeys m_portkeys; QList m_ports; }; //---------------------------------------------------------------------------- // qjackctlGraphConnect -- Connection-line graphics item. class qjackctlGraphConnect : public qjackctlGraphItem { public: // Constructor. qjackctlGraphConnect(); // Destructor.. ~qjackctlGraphConnect(); // Graphics item type. enum { Type = QGraphicsItem::UserType + 3 }; int type() const { return Type; } // Accessors. void setPort1(qjackctlGraphPort *port); qjackctlGraphPort *port1() const; void setPort2(qjackctlGraphPort *port); qjackctlGraphPort *port2() const; // Active disconnection. void disconnect(); // Path/shaper updaters. void updatePathTo(const QPointF& pos); void updatePath(); // Selection propagation method... void setSelectedEx(qjackctlGraphPort *port, bool is_selected); // Highlighting propagation method... void setHighlightEx(qjackctlGraphPort *port, bool is_highlight); // Special port-type color business. void updatePortTypeColors(); // Connector curve draw style (through vs. around nodes) static void setConnectThroughNodes(bool on); static bool isConnectThroughNodes(); protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QVariant itemChange(GraphicsItemChange change, const QVariant& value); QPainterPath shape() const; private: // Instance variables. qjackctlGraphPort *m_port1; qjackctlGraphPort *m_port2; // Connector curve draw style (through vs. around nodes) static bool g_connect_through_nodes; }; //---------------------------------------------------------------------------- // qjackctlGraphCanvas -- Canvas graphics scene/view. class qjackctlGraphCanvas : public QGraphicsView { Q_OBJECT public: // Constructor. qjackctlGraphCanvas(QWidget *parent = nullptr); // Destructor. ~qjackctlGraphCanvas(); // Accessors. QGraphicsScene *scene() const; QUndoStack *commands() const; void setSettings(QSettings *settings); QSettings *settings() const; // Canvas methods. void addItem(qjackctlGraphItem *item); void removeItem(qjackctlGraphItem *item); // Current item accessor. qjackctlGraphItem *currentItem() const; // Connection predicates. bool canConnect() const; bool canDisconnect() const; // Edit predicates. bool canRenameItem() const; bool canSearchItem() const; // Zooming methods. void setZoom(qreal zoom); qreal zoom() const; void setZoomRange(bool zoomrange); bool isZoomRange() const; // Clean-up all un-marked nodes... void resetNodes(uint node_type); void clearNodes(uint node_type); // Special node finder. qjackctlGraphNode *findNode( const QString& name, qjackctlGraphItem::Mode mode, uint type = 0) const; // Whether it's in the middle of something... bool isBusy() const; // Port (dis)connections notifiers. void emitConnected(qjackctlGraphPort *port1, qjackctlGraphPort *port2); void emitDisconnected(qjackctlGraphPort *port1, qjackctlGraphPort *port2); // Rename notifier. void emitRenamed(qjackctlGraphItem *item, const QString& name); // Other generic notifier. void emitChanged(); // Graph canvas state methods. bool restoreState(); bool saveState() const; // Repel overlapping nodes... void setRepelOverlappingNodes(bool on); bool isRepelOverlappingNodes() const; void repelOverlappingNodes(qjackctlGraphNode *node, qjackctlGraphMoveCommand *move_command = nullptr, const QPointF& delta = QPointF()); void repelOverlappingNodesAll( qjackctlGraphMoveCommand *move_command = nullptr); // Graph colors management. void setPortTypeColor(uint port_type, const QColor& color); const QColor& portTypeColor(uint port_type); void updatePortTypeColors(uint port_type = 0); void clearPortTypeColors(); // Clear all selection. void clearSelection(); // Clear all state. void clear(); // Client/port aliases accessors. void setAliases(qjackctlAliases *aliases); qjackctlAliases *aliases() const; // Snap into position helper. QPointF snapPos(const QPointF& pos) const; // Search placeholder text accessors. void setSearchPlaceholderText(const QString& text); QString searchPlaceholderText() const; // Update the canvas palette. void updatePalette(); signals: // Node factory notifications. void added(qjackctlGraphNode *node); void updated(qjackctlGraphNode *node); void removed(qjackctlGraphNode *node); // Port (dis)connection notifications. void connected(qjackctlGraphPort *port1, qjackctlGraphPort *port2); void disconnected(qjackctlGraphPort *port1, qjackctlGraphPort *port2); void connected(qjackctlGraphConnect *connect); // Generic change notification. void changed(); // Rename notification. void renamed(qjackctlGraphItem *item, const QString& name); public slots: // Dis/connect selected items. void connectItems(); void disconnectItems(); // Select actions. void selectAll(); void selectNone(); void selectInvert(); // Edit actions. void renameItem(); void searchItem(); // Discrete zooming actions. void zoomIn(); void zoomOut(); void zoomFit(); void zoomReset(); // Update all nodes. void updateNodes(); // Update all connectors. void updateConnects(); protected slots: // Rename item slots. void renameTextChanged(const QString&); void renameEditingFinished(); // Search item slots. void searchTextChanged(const QString&); void searchEditingFinished(); protected: // Item finder (internal). qjackctlGraphItem *itemAt(const QPointF& pos) const; // Port (dis)connection commands. void connectPorts( qjackctlGraphPort *port1, qjackctlGraphPort *port2, bool is_connect); // Mouse event handlers. void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event); // Keyboard event handler. void keyPressEvent(QKeyEvent *event); // Gesture event handlers. bool event(QEvent *event); bool gestureEvent(QGestureEvent *event); void pinchGesture(QPinchGesture *pinch); // Graph node key helper. QString nodeKey(qjackctlGraphNode *node) const; // Zoom in rectangle range. void zoomFitRange(const QRectF& range_rect); // Graph node position state methods. bool restoreNode(qjackctlGraphNode *node); bool saveNode(qjackctlGraphNode *node) const; // Update editors position and size. void updateRenameEditor(); void updateSearchEditor(); // Bounding margins/limits... const QRectF& boundingRect(bool reset = false); void boundingPos(QPointF& pos); // Start search editor... void startSearchEditor(const QString& text = QString()); void resizeEvent(QResizeEvent *event) override; private: // Mouse pointer dragging states. enum DragState { DragNone = 0, DragStart, DragMove, DragScroll }; // Instance variables. QGraphicsScene *m_scene; DragState m_state; QPointF m_pos; qjackctlGraphItem *m_item; qjackctlGraphConnect *m_connect; QRubberBand *m_rubberband; qreal m_zoom; bool m_zoomrange; bool m_gesture; qjackctlGraphNode::ItemKeys m_nodekeys; QList m_nodes; QUndoStack *m_commands; QSettings *m_settings; QList m_selected; int m_selected_nodes; bool m_repel_overlapping_nodes; // Graph port colors. QHash m_port_colors; // Item renaming stuff. qjackctlGraphItem *m_rename_item; QLineEdit *m_rename_editor; int m_renamed; // Original node position (for move command). QPointF m_pos1; // Allowed auto-scroll margins/limits (for move command). QRectF m_rect1; // Item search stuff. QLineEdit *m_search_editor; // Client/port aliases database. qjackctlAliases *m_aliases; }; //---------------------------------------------------------------------------- // qjackctlGraphSect -- Generic graph driver class qjackctlGraphSect { public: // Constructor. qjackctlGraphSect(qjackctlGraphCanvas *canvas); // Destructor (virtual) virtual ~qjackctlGraphSect() {} // Accessors. qjackctlGraphCanvas *canvas() const; // Generic sect/graph methods. void addItem(qjackctlGraphItem *item, bool is_new = true); void removeItem(qjackctlGraphItem *item); // Clean-up all un-marked items... void resetItems(uint node_type); void clearItems(uint node_type); // Special node finder. qjackctlGraphNode *findNode( const QString& name, qjackctlGraphItem::Mode mode, int type = 0) const; // Client/port renaming method. virtual void renameItem(qjackctlGraphItem *item, const QString& name); protected: // Client/port item aliases accessor. virtual QList item_aliases( qjackctlGraphItem *item) const = 0; private: // Instance variables. qjackctlGraphCanvas *m_canvas; QList m_connects; }; //---------------------------------------------------------------------------- // qjackctlGraphThumb -- Thumb graphics scene/view. class qjackctlGraphThumb : public QFrame { Q_OBJECT public: // Corner position. enum Position { None = 0, TopLeft, TopRight, BottomLeft, BottomRight }; // Constructor. qjackctlGraphThumb(qjackctlGraphCanvas *canvas, Position position = BottomLeft); // Destructor. ~qjackctlGraphThumb(); // Accessors. qjackctlGraphCanvas *canvas() const; void setPosition(Position position); Position position() const; // Emit context-menu request. void requestContextMenu(const QPoint& pos); // Request re-positioning. void requestPosition(Position position); // Update the thumb-view palette. void updatePalette(); signals: // Context-menu request. void contextMenuRequested(const QPoint& pos); // Re-positioning request. void positionRequested(int position); public slots: // Update view slot. void updateView(); protected: // Update position. void updatePosition(); // Forward decl. class View; private: // Inatance members. qjackctlGraphCanvas *m_canvas; Position m_position; View *m_view; }; #endif // __qjackctlGraph_h // end of qjackctlGraph.h qjackctl-1.0.4/src/PaxHeaders/qjackctlJackConnect.h0000644000000000000000000000013214771215054017233 xustar0030 mtime=1743067692.325636584 30 atime=1743067692.325636584 30 ctime=1743067692.325636584 qjackctl-1.0.4/src/qjackctlJackConnect.h0000644000175000001440000001151014771215054017221 0ustar00rncbcusers// qjackctlJackConnect.h // /**************************************************************************** Copyright (C) 2003-2023, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #ifndef __qjackctlJackConnect_h #define __qjackctlJackConnect_h #include "qjackctlAbout.h" #include "qjackctlConnect.h" #include // Forward declarations. class qjackctlJackPort; class qjackctlJackClient; class qjackctlJackClientList; class qjackctlJackConnect; // Connection port type. #define QJACKCTL_JACK_AUDIO 0 #define QJACKCTL_JACK_MIDI 1 // Pixmap-set array indexes/types. #define QJACKCTL_JACK_CLIENTI 0 // Input client item pixmap. #define QJACKCTL_JACK_CLIENTO 1 // Output client item pixmap. #define QJACKCTL_JACK_PORTPTI 2 // Physcal Terminal Input port pixmap. #define QJACKCTL_JACK_PORTPTO 3 // Physical Terminal Output port pixmap. #define QJACKCTL_JACK_PORTPNI 4 // Physical Non-terminal Input port pixmap. #define QJACKCTL_JACK_PORTPNO 5 // Physical Non-terminal Output port pixmap. #define QJACKCTL_JACK_PORTLTI 6 // Logical Terminal Input port pixmap. #define QJACKCTL_JACK_PORTLTO 7 // Logical Terminal Output port pixmap. #define QJACKCTL_JACK_PORTLNI 8 // Logical Non-terminal Input port pixmap. #define QJACKCTL_JACK_PORTLNO 9 // Logical Non-terminal Output port pixmap. #define QJACKCTL_JACK_PIXMAPS 10 // Number of pixmaps in array. // Jack port list item. class qjackctlJackPort : public qjackctlPortItem { public: // Constructor. qjackctlJackPort(qjackctlJackClient *pClient, unsigned long ulPortFlags); // Default destructor. ~qjackctlJackPort(); // Pretty/display name method (virtual override). void updatePortName(bool bRename = false); // Tooltip text builder (virtual override). QString tooltip() const; }; // Jack client list item. class qjackctlJackClient : public qjackctlClientItem { public: // Constructor. qjackctlJackClient(qjackctlJackClientList *pClientList); // Default destructor. ~qjackctlJackClient(); // Jack port lookup. qjackctlJackPort *findJackPort(const QString& sPortName); // Pretty/display name method (virtual override). void updateClientName(bool bRename = false); }; // Jack client list. class qjackctlJackClientList : public qjackctlClientList { public: // Constructor. qjackctlJackClientList(qjackctlClientListView *pListView, bool bReadable); // Default destructor. ~qjackctlJackClientList(); // Jack port lookup. qjackctlJackPort *findJackClientPort(const QString& sClientPort); // Client:port refreshner (return newest item count). int updateClientPorts(); // Jack client port aliases mode. static void setJackClientPortAlias(int iJackClientPortAlias); static int jackClientPortAlias(); // Jack client port pretty-name (metadata) mode. static void setJackClientPortMetadata(bool bJackClientPortMetadata); static bool isJackClientPortMetadata(); private: // Jack client port aliases mode. static int g_iJackClientPortAlias; // Jack client port pretty-name (metadata) mode. static bool g_bJackClientPortMetadata; }; //---------------------------------------------------------------------------- // qjackctlJackConnect -- Connections model integrated object. class qjackctlJackConnect : public qjackctlConnect { public: // Constructor. qjackctlJackConnect(qjackctlConnectView *pConnectView, int iJackType); // Default destructor. ~qjackctlJackConnect(); // Connection type accessors. int jackType() const; // Common pixmap accessor. const QPixmap& pixmap (int iPixmap) const; protected: // Virtual Connect/Disconnection primitives. bool connectPorts (qjackctlPortItem *pOPort, qjackctlPortItem *pIPort); bool disconnectPorts (qjackctlPortItem *pOPort, qjackctlPortItem *pIPort); // Update port connection references. void updateConnections(); // Update icon size implementation. void updateIconPixmaps(); private: // Local pixmap-set janitor methods. void createIconPixmaps(); void deleteIconPixmaps(); // Local variables. int m_iJackType; // Local pixmap-set array. QPixmap *m_apPixmaps[QJACKCTL_JACK_PIXMAPS]; }; #endif // __qjackctlJackConnect_h // end of qjackctlJackConnect.h qjackctl-1.0.4/src/PaxHeaders/qjackctlPaletteForm.cpp0000644000000000000000000000013214771215054017626 xustar0030 mtime=1743067692.326636579 30 atime=1743067692.326636579 30 ctime=1743067692.326636579 qjackctl-1.0.4/src/qjackctlPaletteForm.cpp0000644000175000001440000010105514771215054017620 0ustar00rncbcusers// qjackctlPaletteForm.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlAbout.h" #include "qjackctlPaletteForm.h" #include "ui_qjackctlPaletteForm.h" #include #include #include #include #include #include #include #include #include #include #include // Local static consts. static const char *ColorThemesGroup = "/ColorThemes/"; static const char *PaletteEditorGroup = "/PaletteEditor/"; static const char *DefaultDirKey = "DefaultDir"; static const char *ShowDetailsKey = "ShowDetails"; static const char *DefaultSuffix = "conf"; static struct { const char *key; QPalette::ColorRole value; } g_colorRoles[] = { { "Window", QPalette::Window }, { "WindowText", QPalette::WindowText }, { "Button", QPalette::Button }, { "ButtonText", QPalette::ButtonText }, { "Light", QPalette::Light }, { "Midlight", QPalette::Midlight }, { "Dark", QPalette::Dark }, { "Mid", QPalette::Mid }, { "Text", QPalette::Text }, { "BrightText", QPalette::BrightText }, { "Base", QPalette::Base }, { "AlternateBase", QPalette::AlternateBase }, { "Shadow", QPalette::Shadow }, { "Highlight", QPalette::Highlight }, { "HighlightedText", QPalette::HighlightedText }, { "Link", QPalette::Link }, { "LinkVisited", QPalette::LinkVisited }, { "ToolTipBase", QPalette::ToolTipBase }, { "ToolTipText", QPalette::ToolTipText }, #if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) { "PlaceholderText", QPalette::PlaceholderText }, #endif { "NoRole", QPalette::NoRole }, { nullptr, QPalette::NoRole } }; //------------------------------------------------------------------------- // qjackctlPaletteForm qjackctlPaletteForm::qjackctlPaletteForm ( QWidget *parent, const QPalette& pal ) : QDialog(parent), p_ui(new Ui::qjackctlPaletteForm), m_ui(*p_ui) { m_ui.setupUi(this); m_settings = nullptr; m_owner = false; m_modelUpdated = false; m_paletteUpdated = false; m_dirtyCount = 0; m_dirtyTotal = 0; updateGenerateButton(); m_paletteModel = new PaletteModel(this); m_ui.paletteView->setModel(m_paletteModel); ColorDelegate *delegate = new ColorDelegate(this); m_ui.paletteView->setItemDelegate(delegate); m_ui.paletteView->setEditTriggers(QAbstractItemView::AllEditTriggers); // m_ui.paletteView->setAlternatingRowColors(true); m_ui.paletteView->setSelectionBehavior(QAbstractItemView::SelectRows); m_ui.paletteView->setDragEnabled(true); m_ui.paletteView->setDropIndicatorShown(true); m_ui.paletteView->setRootIsDecorated(false); m_ui.paletteView->setColumnHidden(2, true); m_ui.paletteView->setColumnHidden(3, true); QObject::connect(m_ui.nameCombo, SIGNAL(editTextChanged(const QString&)), SLOT(nameComboChanged(const QString&))); QObject::connect(m_ui.saveButton, SIGNAL(clicked()), SLOT(saveButtonClicked())); QObject::connect(m_ui.deleteButton, SIGNAL(clicked()), SLOT(deleteButtonClicked())); QObject::connect(m_ui.generateButton, SIGNAL(changed()), SLOT(generateButtonChanged())); QObject::connect(m_ui.resetButton, SIGNAL(clicked()), SLOT(resetButtonClicked())); QObject::connect(m_ui.detailsCheck, SIGNAL(clicked()), SLOT(detailsCheckClicked())); QObject::connect(m_ui.importButton, SIGNAL(clicked()), SLOT(importButtonClicked())); QObject::connect(m_ui.exportButton, SIGNAL(clicked()), SLOT(exportButtonClicked())); QObject::connect(m_paletteModel, SIGNAL(paletteChanged(const QPalette&)), SLOT(paletteChanged(const QPalette&))); QObject::connect(m_ui.dialogButtons, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.dialogButtons, SIGNAL(rejected()), SLOT(reject())); setPalette(pal, pal); QDialog::adjustSize(); } qjackctlPaletteForm::~qjackctlPaletteForm (void) { setSettings(nullptr); } void qjackctlPaletteForm::setPalette ( const QPalette& pal ) { m_palette = pal; #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) const uint mask = pal.resolveMask(); #else const uint mask = pal.resolve(); #endif for (int i = 0; g_colorRoles[i].key; ++i) { if ((mask & (1 << i)) == 0) { const QPalette::ColorRole cr = g_colorRoles[i].value; m_palette.setBrush(QPalette::Active, cr, m_parentPalette.brush(QPalette::Active, cr)); m_palette.setBrush(QPalette::Inactive, cr, m_parentPalette.brush(QPalette::Inactive, cr)); m_palette.setBrush(QPalette::Disabled, cr, m_parentPalette.brush(QPalette::Disabled, cr)); } } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) m_palette.setResolveMask(mask); #else m_palette.resolve(mask); #endif updateGenerateButton(); m_paletteUpdated = true; if (!m_modelUpdated) m_paletteModel->setPalette(m_palette, m_parentPalette); m_paletteUpdated = false; } void qjackctlPaletteForm::setPalette ( const QPalette& pal, const QPalette& parentPal ) { m_parentPalette = parentPal; setPalette(pal); } const QPalette& qjackctlPaletteForm::palette (void) const { return m_palette; } void qjackctlPaletteForm::setSettings ( QSettings *settings, bool owner ) { if (m_settings && m_owner) delete m_settings; m_settings = settings; m_owner = owner; m_ui.detailsCheck->setChecked(isShowDetails()); updateNamedPaletteList(); updateDialogButtons(); } QSettings *qjackctlPaletteForm::settings (void) const { return m_settings; } void qjackctlPaletteForm::nameComboChanged ( const QString& name ) { if (m_dirtyCount > 0 && m_ui.nameCombo->findText(name) < 0) { updateDialogButtons(); } else { resetButtonClicked(); setPaletteName(name); ++m_dirtyTotal; } } void qjackctlPaletteForm::saveButtonClicked (void) { const QString& name = m_ui.nameCombo->currentText(); if (name.isEmpty()) return; QString filename = namedPaletteConf(name); if (filename.isEmpty() || !QFileInfo(filename).isWritable()) { const QString& title = tr("Save Palette - %1").arg(QDialog::windowTitle()); QStringList filters; filters.append(tr("Palette files (*.%1)").arg(DefaultSuffix)); filters.append(tr("All files (*.*)")); QString dirname = defaultDir(); if (!dirname.isEmpty()) dirname.append(QDir::separator()); dirname.append(paletteName() + '.' + DefaultSuffix); filename = QFileDialog::getSaveFileName(this, title, dirname, filters.join(";;")); } if (!filename.isEmpty() && saveNamedPaletteConf(name, filename, m_palette)) { addNamedPaletteConf(name, filename); setPalette(m_palette, m_palette); updateNamedPaletteList(); resetButtonClicked(); } } void qjackctlPaletteForm::deleteButtonClicked (void) { const QString& name = m_ui.nameCombo->currentText(); if (m_ui.nameCombo->findText(name) >= 0) { deleteNamedPaletteConf(name); updateNamedPaletteList(); updateDialogButtons(); } } void qjackctlPaletteForm::generateButtonChanged (void) { const QColor& color = m_ui.generateButton->brush().color(); const QPalette& pal = QPalette(color); setPalette(pal); ++m_dirtyCount; updateDialogButtons(); } void qjackctlPaletteForm::resetButtonClicked (void) { const bool blocked = blockSignals(true); for (int i = 0; g_colorRoles[i].key; ++i) { const QPalette::ColorRole cr = g_colorRoles[i].value; const QModelIndex& index = m_paletteModel->index(cr, 0); m_paletteModel->setData(index, false, Qt::EditRole); } m_dirtyCount = 0; updateDialogButtons(); blockSignals(blocked); } void qjackctlPaletteForm::detailsCheckClicked (void) { const int cw = (m_ui.paletteView->viewport()->width() >> 2); QHeaderView *header = m_ui.paletteView->header(); header->resizeSection(0, cw); if (m_ui.detailsCheck->isChecked()) { m_ui.paletteView->setColumnHidden(2, false); m_ui.paletteView->setColumnHidden(3, false); header->resizeSection(1, cw); header->resizeSection(2, cw); header->resizeSection(3, cw); m_paletteModel->setGenerate(false); } else { m_ui.paletteView->setColumnHidden(2, true); m_ui.paletteView->setColumnHidden(3, true); header->resizeSection(1, cw * 3); m_paletteModel->setGenerate(true); } } void qjackctlPaletteForm::importButtonClicked (void) { const QString& title = tr("Import File - %1").arg(QDialog::windowTitle()); QStringList filters; filters.append(tr("Palette files (*.%1)").arg(DefaultSuffix)); filters.append(tr("All files (*.*)")); const QString& filename = QFileDialog::getOpenFileName(this, title, defaultDir(), filters.join(";;")); if (filename.isEmpty()) return; QSettings conf(filename, QSettings::IniFormat); conf.beginGroup(ColorThemesGroup); const QStringList names = conf.childGroups(); conf.endGroup(); int imported = 0; QStringListIterator name_iter(names); while (name_iter.hasNext()) { const QString& name = name_iter.next(); if (!name.isEmpty()) { addNamedPaletteConf(name, filename); setPaletteName(name); ++imported; } } if (imported > 0) { updateNamedPaletteList(); resetButtonClicked(); setDefaultDir(QFileInfo(filename).absolutePath()); } else { QMessageBox::warning(this, tr("Warning - %1").arg(QDialog::windowTitle()), tr("Could not import from file:\n\n" "%1\n\nSorry.").arg(filename)); } } void qjackctlPaletteForm::exportButtonClicked (void) { const QString& title = tr("Export File - %1").arg(QDialog::windowTitle()); QStringList filters; filters.append(tr("Palette files (*.%1)").arg(DefaultSuffix)); filters.append(tr("All files (*.*)")); QString dirname = defaultDir(); if (!dirname.isEmpty()) dirname.append(QDir::separator()); dirname.append(paletteName() + '.' + DefaultSuffix); const QString& filename = QFileDialog::getSaveFileName(this, title, dirname, filters.join(";;")); if (filename.isEmpty()) return; const QFileInfo fi(filename); const QString& name = fi.baseName(); if (saveNamedPaletteConf(name, filename, m_palette)) { // addNamedPaletteConf(name, filename); setDefaultDir(fi.absolutePath()); } } void qjackctlPaletteForm::paletteChanged ( const QPalette& pal ) { m_modelUpdated = true; if (!m_paletteUpdated) setPalette(pal); m_modelUpdated = false; ++m_dirtyCount; updateDialogButtons(); } void qjackctlPaletteForm::setPaletteName ( const QString& name ) { const bool blocked = m_ui.nameCombo->blockSignals(true); m_ui.nameCombo->setEditText(name); QPalette pal; if (namedPalette(m_settings, name, pal, true)) setPalette(pal, pal); m_dirtyCount = 0; updateDialogButtons(); m_ui.nameCombo->blockSignals(blocked); } QString qjackctlPaletteForm::paletteName (void) const { return m_ui.nameCombo->currentText(); } void qjackctlPaletteForm::updateNamedPaletteList (void) { const bool blocked = m_ui.nameCombo->blockSignals(true); const QString old_name = m_ui.nameCombo->currentText(); m_ui.nameCombo->clear(); m_ui.nameCombo->insertItems(0, namedPaletteList()); // m_ui.nameCombo->model()->sort(0); const int i = m_ui.nameCombo->findText(old_name); if (i >= 0) m_ui.nameCombo->setCurrentIndex(i); else m_ui.nameCombo->setEditText(old_name); m_ui.nameCombo->blockSignals(blocked); } void qjackctlPaletteForm::updateGenerateButton (void) { m_ui.generateButton->setBrush( m_palette.brush(QPalette::Active, QPalette::Button)); } void qjackctlPaletteForm::updateDialogButtons (void) { const QString& name = m_ui.nameCombo->currentText(); const QString& filename = namedPaletteConf(name); const int i = m_ui.nameCombo->findText(name); m_ui.saveButton->setEnabled(!name.isEmpty() && (m_dirtyCount > 0 || i < 0)); m_ui.deleteButton->setEnabled(i >= 0); m_ui.resetButton->setEnabled(m_dirtyCount > 0); m_ui.exportButton->setEnabled(!name.isEmpty() || i >= 0); m_ui.dialogButtons->button(QDialogButtonBox::Ok)->setEnabled(i >= 0); } bool qjackctlPaletteForm::namedPalette ( const QString& name, QPalette& pal ) const { return namedPalette(m_settings, name, pal); } bool qjackctlPaletteForm::namedPalette ( QSettings *settings, const QString& name, QPalette& pal, bool fixup ) { int result = 0; if (!name.isEmpty() && loadNamedPalette(settings, name, pal)) { ++result; } else { const QString& filename = namedPaletteConf(settings, name); if (!filename.isEmpty() && QFileInfo(filename).isReadable() && loadNamedPaletteConf(name, filename, pal)) { ++result; } } // Dark themes grayed/disabled color group fix... if (!fixup && pal.base().color().value() < 0x7f) { const QColor& color = pal.window().color(); const int groups = int(QPalette::Active | QPalette::Inactive) + 1; for (int i = 0; i < groups; ++i) { const QPalette::ColorGroup cg = QPalette::ColorGroup(i); pal.setBrush(cg, QPalette::Light, color.lighter(140)); pal.setBrush(cg, QPalette::Midlight, color.lighter(100)); pal.setBrush(cg, QPalette::Mid, color.lighter(90)); pal.setBrush(cg, QPalette::Dark, color.darker(160)); pal.setBrush(cg, QPalette::Shadow, color.darker(180)); } pal.setColorGroup(QPalette::Disabled, pal.windowText().color().darker(), pal.button(), pal.light(), pal.dark(), pal.mid(), pal.text().color().darker(), pal.text().color().lighter(), pal.base(), pal.window()); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) pal.setColor(QPalette::Disabled, QPalette::Highlight, pal.mid().color()); pal.setColor(QPalette::Disabled, QPalette::ButtonText, pal.mid().color()); #endif ++result; } return (result > 0); } QStringList qjackctlPaletteForm::namedPaletteList (void) const { return namedPaletteList(m_settings); } QStringList qjackctlPaletteForm::namedPaletteList ( QSettings *settings ) { QStringList list; if (settings) { settings->beginGroup(ColorThemesGroup); list.append(settings->childKeys()); list.append(settings->childGroups()); // legacy... settings->endGroup(); } return list; } QString qjackctlPaletteForm::namedPaletteConf ( const QString& name ) const { return namedPaletteConf(m_settings, name); } QString qjackctlPaletteForm::namedPaletteConf ( QSettings *settings, const QString& name ) { QString ret; if (settings && !name.isEmpty()) { settings->beginGroup(ColorThemesGroup); ret = settings->value(name).toString(); settings->endGroup(); } return ret; } void qjackctlPaletteForm::addNamedPaletteConf ( const QString& name, const QString& filename ) { addNamedPaletteConf(m_settings, name, filename); ++m_dirtyTotal; } void qjackctlPaletteForm::addNamedPaletteConf ( QSettings *settings, const QString& name, const QString& filename ) { if (settings) { settings->beginGroup(ColorThemesGroup); settings->remove(name); // remove legacy keys! settings->setValue(name, filename); settings->endGroup(); } } void qjackctlPaletteForm::deleteNamedPaletteConf ( const QString& name ) { if (m_settings) { m_settings->beginGroup(ColorThemesGroup); m_settings->remove(name); m_settings->endGroup(); ++m_dirtyTotal; } } bool qjackctlPaletteForm::loadNamedPaletteConf ( const QString& name, const QString& filename, QPalette& pal ) { QSettings conf(filename, QSettings::IniFormat); return loadNamedPalette(&conf, name, pal); } bool qjackctlPaletteForm::saveNamedPaletteConf ( const QString& name, const QString& filename, const QPalette& pal ) { QSettings conf(filename, QSettings::IniFormat); return saveNamedPalette(&conf, name, pal); } bool qjackctlPaletteForm::loadNamedPalette ( QSettings *settings, const QString& name, QPalette& pal ) { if (settings == nullptr) return false; int result = 0; settings->beginGroup(ColorThemesGroup); QStringListIterator name_iter(settings->childGroups()); while (name_iter.hasNext() && !result) { const QString& name2 = name_iter.next(); if (name2 == name) { #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) uint mask = pal.resolve(); #endif settings->beginGroup(name + '/'); QStringListIterator iter(settings->childKeys()); while (iter.hasNext()) { const QString& key = iter.next(); const QPalette::ColorRole cr = qjackctlPaletteForm::colorRole(key); const QStringList& clist = settings->value(key).toStringList(); if (clist.count() == 3) { pal.setColor(QPalette::Active, cr, QColor(clist.at(0))); pal.setColor(QPalette::Inactive, cr, QColor(clist.at(1))); pal.setColor(QPalette::Disabled, cr, QColor(clist.at(2))); #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) mask &= ~(1 << int(cr)); #endif ++result; } } #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) pal.resolve(mask); #endif settings->endGroup(); } } settings->endGroup(); return (result > 0); } bool qjackctlPaletteForm::saveNamedPalette ( QSettings *settings, const QString& name, const QPalette& pal ) { if (settings == nullptr) return false; settings->beginGroup(ColorThemesGroup); settings->beginGroup(name + '/'); for (int i = 0; g_colorRoles[i].key; ++i) { const QString& key = QString::fromLatin1(g_colorRoles[i].key); const QPalette::ColorRole cr = g_colorRoles[i].value; QStringList clist; clist.append(pal.color(QPalette::Active, cr).name()); clist.append(pal.color(QPalette::Inactive, cr).name()); clist.append(pal.color(QPalette::Disabled, cr).name()); settings->setValue(key, clist); } settings->endGroup(); settings->endGroup(); return true; } QPalette::ColorRole qjackctlPaletteForm::colorRole ( const QString& name ) { static QHash s_colorRoles; if (s_colorRoles.isEmpty()) { for (int i = 0; g_colorRoles[i].key; ++i) { const QString& key = QString::fromLatin1(g_colorRoles[i].key); const QPalette::ColorRole value = g_colorRoles[i].value; s_colorRoles.insert(key, value); } } return s_colorRoles.value(name, QPalette::NoRole); } bool qjackctlPaletteForm::isDirty (void) const { return (m_dirtyTotal > 0); } void qjackctlPaletteForm::accept (void) { setShowDetails(m_ui.detailsCheck->isChecked()); if (m_dirtyCount > 0) saveButtonClicked(); QDialog::accept(); } void qjackctlPaletteForm::reject (void) { if (m_dirtyCount > 0) { const QString& name = paletteName(); if (name.isEmpty()) { if (QMessageBox::warning(this, tr("Warning - %1").arg(QDialog::windowTitle()), tr("Some settings have been changed.\n\n" "Do you want to discard the changes?"), QMessageBox::Discard | QMessageBox::Cancel) == QMessageBox::Cancel) return; } else { switch (QMessageBox::warning(this, tr("Warning - %1").arg(QDialog::windowTitle()), tr("Some settings have been changed:\n\n" "\"%1\".\n\nDo you want to save the changes?") .arg(name), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) { case QMessageBox::Save: saveButtonClicked(); // Fall thru... case QMessageBox::Discard: break; default: // Cancel... return; } } } QDialog::reject(); } void qjackctlPaletteForm::setDefaultDir ( const QString& dir ) { if (m_settings) { m_settings->beginGroup(PaletteEditorGroup); m_settings->setValue(DefaultDirKey, dir); m_settings->endGroup(); } } QString qjackctlPaletteForm::defaultDir (void) const { QString dir; if (m_settings) { m_settings->beginGroup(PaletteEditorGroup); dir = m_settings->value(DefaultDirKey).toString(); m_settings->endGroup(); } return dir; } void qjackctlPaletteForm::setShowDetails ( bool on ) { if (m_settings) { m_settings->beginGroup(PaletteEditorGroup); m_settings->setValue(ShowDetailsKey, on); m_settings->endGroup(); } } bool qjackctlPaletteForm::isShowDetails (void) const { bool on = false; if (m_settings) { m_settings->beginGroup(PaletteEditorGroup); on = m_settings->value(ShowDetailsKey).toBool(); m_settings->endGroup(); } return on; } void qjackctlPaletteForm::showEvent ( QShowEvent *event ) { QDialog::showEvent(event); detailsCheckClicked(); } void qjackctlPaletteForm::resizeEvent ( QResizeEvent *event ) { QDialog::resizeEvent(event); detailsCheckClicked(); } //------------------------------------------------------------------------- // qjackctlPaletteForm::PaletteModel qjackctlPaletteForm::PaletteModel::PaletteModel ( QObject *parent ) : QAbstractTableModel(parent) { for (m_nrows = 0; g_colorRoles[m_nrows].key; ++m_nrows) { const QPalette::ColorRole value = g_colorRoles[m_nrows].value; const QString& key = QString::fromLatin1(g_colorRoles[m_nrows].key); m_roleNames.insert(value, key); } m_generate = true; } int qjackctlPaletteForm::PaletteModel::rowCount ( const QModelIndex& ) const { return m_nrows; } int qjackctlPaletteForm::PaletteModel::columnCount ( const QModelIndex& ) const { return 4; } QVariant qjackctlPaletteForm::PaletteModel::data ( const QModelIndex& index, int role ) const { if (!index.isValid()) return QVariant(); if (index.row() < 0 || index.row() >= m_nrows) return QVariant(); if (index.column() < 0 || index.column() >= 4) return QVariant(); if (index.column() == 0) { if (role == Qt::DisplayRole) return m_roleNames.value(QPalette::ColorRole(index.row())); if (role == Qt::EditRole) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) const uint mask = m_palette.resolveMask(); #else const uint mask = m_palette.resolve(); #endif return bool(mask & (1 << index.row())); } } else if (role == Qt::BackgroundRole) { return m_palette.color( columnToGroup(index.column()), QPalette::ColorRole(index.row())); } return QVariant(); } bool qjackctlPaletteForm::PaletteModel::setData ( const QModelIndex& index, const QVariant& value, int role ) { if (!index.isValid()) return false; if (index.column() != 0 && role == Qt::BackgroundRole) { const QColor& color = value.value(); const QPalette::ColorRole cr = QPalette::ColorRole(index.row()); const QPalette::ColorGroup cg = columnToGroup(index.column()); m_palette.setBrush(cg, cr, color); QModelIndex index_begin = PaletteModel::index(cr, 0); QModelIndex index_end = PaletteModel::index(cr, 3); if (m_generate) { m_palette.setBrush(QPalette::Inactive, cr, color); switch (cr) { case QPalette::WindowText: case QPalette::Text: case QPalette::ButtonText: case QPalette::Base: break; case QPalette::Dark: m_palette.setBrush(QPalette::Disabled, QPalette::WindowText, color); m_palette.setBrush(QPalette::Disabled, QPalette::Dark, color); m_palette.setBrush(QPalette::Disabled, QPalette::Text, color); m_palette.setBrush(QPalette::Disabled, QPalette::ButtonText, color); index_begin = PaletteModel::index(0, 0); index_end = PaletteModel::index(m_nrows - 1, 3); break; case QPalette::Window: m_palette.setBrush(QPalette::Disabled, QPalette::Base, color); m_palette.setBrush(QPalette::Disabled, QPalette::Window, color); index_begin = PaletteModel::index(QPalette::Base, 0); break; case QPalette::Highlight: m_palette.setBrush(QPalette::Disabled, QPalette::Highlight, color.darker(120)); break; default: m_palette.setBrush(QPalette::Disabled, cr, color); break; } } emit paletteChanged(m_palette); emit dataChanged(index_begin, index_end); return true; } if (index.column() == 0 && role == Qt::EditRole) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) uint mask = m_palette.resolveMask(); #else uint mask = m_palette.resolve(); #endif const bool masked = value.value(); const int i = index.row(); if (masked) { mask |= (1 << i); } else { const QPalette::ColorRole cr = QPalette::ColorRole(i); m_palette.setBrush(QPalette::Active, cr, m_parentPalette.brush(QPalette::Active, cr)); m_palette.setBrush(QPalette::Inactive, cr, m_parentPalette.brush(QPalette::Inactive, cr)); m_palette.setBrush(QPalette::Disabled, cr, m_parentPalette.brush(QPalette::Disabled, cr)); mask &= ~(1 << i); } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) m_palette.setResolveMask(mask); #else m_palette.resolve(mask); #endif emit paletteChanged(m_palette); const QModelIndex& index_end = PaletteModel::index(i, 3); emit dataChanged(index, index_end); return true; } return false; } Qt::ItemFlags qjackctlPaletteForm::PaletteModel::flags ( const QModelIndex& index ) const { if (!index.isValid()) return Qt::ItemIsEnabled; else return Qt::ItemIsEditable | Qt::ItemIsEnabled; } QVariant qjackctlPaletteForm::PaletteModel::headerData ( int section, Qt::Orientation orientation, int role ) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { if (section == 0) return tr("Color Role"); else if (section == groupToColumn(QPalette::Active)) return tr("Active"); else if (section == groupToColumn(QPalette::Inactive)) return tr("Inactive"); else if (section == groupToColumn(QPalette::Disabled)) return tr("Disabled"); } return QVariant(); } const QPalette& qjackctlPaletteForm::PaletteModel::palette(void) const { return m_palette; } void qjackctlPaletteForm::PaletteModel::setPalette ( const QPalette& palette, const QPalette& parentPalette ) { m_palette = palette; m_parentPalette = parentPalette; const QModelIndex& index_begin = index(0, 0); const QModelIndex& index_end = index(m_nrows - 1, 3); emit dataChanged(index_begin, index_end); } QPalette::ColorGroup qjackctlPaletteForm::PaletteModel::columnToGroup ( int index ) const { if (index == 1) return QPalette::Active; else if (index == 2) return QPalette::Inactive; return QPalette::Disabled; } int qjackctlPaletteForm::PaletteModel::groupToColumn ( QPalette::ColorGroup group ) const { if (group == QPalette::Active) return 1; else if (group == QPalette::Inactive) return 2; return 3; } //------------------------------------------------------------------------- // qjackctlPaletteForm::ColorDelegate QWidget *qjackctlPaletteForm::ColorDelegate::createEditor ( QWidget *parent, const QStyleOptionViewItem&, const QModelIndex& index ) const { QWidget *editor = nullptr; if (index.column() == 0) { RoleEditor *ed = new RoleEditor(parent); QObject::connect(ed, SIGNAL(changed(QWidget *)), SIGNAL(commitData(QWidget *))); // ed->setFocusPolicy(Qt::NoFocus); // ed->installEventFilter(const_cast(this)); editor = ed; } else { ColorEditor *ed = new ColorEditor(parent); QObject::connect(ed, SIGNAL(changed(QWidget *)), SIGNAL(commitData(QWidget *))); ed->setFocusPolicy(Qt::NoFocus); ed->installEventFilter(const_cast(this)); editor = ed; } return editor; } void qjackctlPaletteForm::ColorDelegate::setEditorData ( QWidget *editor, const QModelIndex& index ) const { if (index.column() == 0) { const bool masked = index.model()->data(index, Qt::EditRole).value(); RoleEditor *ed = static_cast(editor); ed->setEdited(masked); const QString& colorName = index.model()->data(index, Qt::DisplayRole).value(); ed->setLabel(colorName); } else { const QColor& color = index.model()->data(index, Qt::BackgroundRole).value(); ColorEditor *ed = static_cast(editor); ed->setColor(color); } } void qjackctlPaletteForm::ColorDelegate::setModelData ( QWidget *editor, QAbstractItemModel *model, const QModelIndex& index ) const { if (index.column() == 0) { RoleEditor *ed = static_cast(editor); const bool masked = ed->edited(); model->setData(index, masked, Qt::EditRole); } else { ColorEditor *ed = static_cast(editor); if (ed->changed()) { const QColor& color = ed->color(); model->setData(index, color, Qt::BackgroundRole); } } } void qjackctlPaletteForm::ColorDelegate::updateEditorGeometry ( QWidget *editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const { QItemDelegate::updateEditorGeometry(editor, option, index); editor->setGeometry(editor->geometry().adjusted(0, 0, -1, -1)); } void qjackctlPaletteForm::ColorDelegate::paint ( QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { QStyleOptionViewItem opt = option; const bool masked = index.model()->data(index, Qt::EditRole).value(); if (index.column() == 0 && masked) opt.font.setBold(true); QItemDelegate::paint(painter, opt, index); // painter->setPen(opt.palette.midlight().color()); painter->setPen(Qt::darkGray); painter->drawLine(opt.rect.right(), opt.rect.y(), opt.rect.right(), opt.rect.bottom()); painter->drawLine(opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom()); } QSize qjackctlPaletteForm::ColorDelegate::sizeHint ( const QStyleOptionViewItem& option, const QModelIndex &index) const { return QItemDelegate::sizeHint(option, index) + QSize(4, 4); } //------------------------------------------------------------------------- // qjackctlPaletteForm::ColorButton qjackctlPaletteForm::ColorButton::ColorButton ( QWidget *parent ) : QPushButton(parent), m_brush(Qt::darkGray) { QPushButton::setMinimumWidth(48); QObject::connect(this, SIGNAL(clicked()), SLOT(chooseColor())); } const QBrush& qjackctlPaletteForm::ColorButton::brush (void) const { return m_brush; } void qjackctlPaletteForm::ColorButton::setBrush ( const QBrush& brush ) { m_brush = brush; update(); } void qjackctlPaletteForm::ColorButton::paintEvent ( QPaintEvent *event ) { QPushButton::paintEvent(event); QStyleOptionButton opt; opt.initFrom(this); const QRect& rect = style()->subElementRect(QStyle::SE_PushButtonContents, &opt, this); QPainter paint(this); paint.setBrush(QBrush(m_brush.color())); paint.drawRect(rect.adjusted(+1, +1, -2, -2)); } void qjackctlPaletteForm::ColorButton::chooseColor (void) { const QColor color = QColorDialog::getColor(m_brush.color(), this); if (color.isValid()) { m_brush.setColor(color); emit changed(); } } //------------------------------------------------------------------------- // qjackctlPaletteForm::ColorEditor qjackctlPaletteForm::ColorEditor::ColorEditor ( QWidget *parent ) : QWidget(parent) { QLayout *layout = new QHBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); m_button = new qjackctlPaletteForm::ColorButton(this); layout->addWidget(m_button); QObject::connect(m_button, SIGNAL(changed()), SLOT(colorChanged())); setFocusProxy(m_button); m_changed = false; } void qjackctlPaletteForm::ColorEditor::setColor ( const QColor& color ) { m_button->setBrush(color); m_changed = false; } QColor qjackctlPaletteForm::ColorEditor::color (void) const { return m_button->brush().color(); } void qjackctlPaletteForm::ColorEditor::colorChanged (void) { m_changed = true; emit changed(this); } bool qjackctlPaletteForm::ColorEditor::changed (void) const { return m_changed; } //------------------------------------------------------------------------- // qjackctlPaletteForm::RoleEditor qjackctlPaletteForm::RoleEditor::RoleEditor ( QWidget *parent ) : QWidget(parent) { m_edited = false; QHBoxLayout *layout = new QHBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); m_label = new QLabel(this); layout->addWidget(m_label); m_label->setAutoFillBackground(true); m_label->setIndent(3); // HACK: it should have the same value of textMargin in QItemDelegate setFocusProxy(m_label); m_button = new QToolButton(this); m_button->setToolButtonStyle(Qt::ToolButtonIconOnly); m_button->setIcon(QPixmap(":/images/itemReset.png")); m_button->setIconSize(QSize(8, 8)); m_button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding)); layout->addWidget(m_button); QObject::connect(m_button, SIGNAL(clicked()), SLOT(resetProperty())); } void qjackctlPaletteForm::RoleEditor::setLabel ( const QString& label ) { m_label->setText(label); } void qjackctlPaletteForm::RoleEditor::setEdited ( bool on ) { QFont font; if (on) font.setBold(on); m_label->setFont(font); m_button->setEnabled(on); m_edited = on; } bool qjackctlPaletteForm::RoleEditor::edited (void) const { return m_edited; } void qjackctlPaletteForm::RoleEditor::resetProperty (void) { setEdited(false); emit changed(this); } // end of qjackctlPaletteForm.cpp qjackctl-1.0.4/src/PaxHeaders/CMakeLists.txt0000644000000000000000000000012414771215054015724 xustar0028 mtime=1743067692.3182779 28 atime=1743067692.3182779 28 ctime=1743067692.3182779 qjackctl-1.0.4/src/CMakeLists.txt0000644000175000001440000001702514771215054015720 0ustar00rncbcusers# project (qjackctl) set (CMAKE_INCLUDE_CURRENT_DIR ON) set (CMAKE_AUTOUIC ON) set (CMAKE_AUTOMOC ON) set (CMAKE_AUTORCC ON) if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/config.h) file (REMOVE ${CMAKE_CURRENT_SOURCE_DIR}/config.h) endif () configure_file (config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) set (HEADERS qjackctl.h qjackctlAbout.h qjackctlAlsaConnect.h qjackctlAlsaGraph.h qjackctlConnect.h qjackctlAliases.h qjackctlGraph.h qjackctlGraphCommand.h qjackctlInterfaceComboBox.h qjackctlJackConnect.h qjackctlJackGraph.h qjackctlPatchbay.h qjackctlPatchbayFile.h qjackctlPatchbayRack.h qjackctlSession.h qjackctlSetup.h qjackctlStatus.h qjackctlSystemTray.h qjackctlAboutForm.h qjackctlConnectionsForm.h qjackctlGraphForm.h qjackctlMainForm.h qjackctlMessagesStatusForm.h qjackctlPatchbayForm.h qjackctlSessionForm.h qjackctlSessionSaveForm.h qjackctlSetupForm.h qjackctlPaletteForm.h qjackctlSocketForm.h ) set (SOURCES qjackctl.cpp qjackctlAlsaConnect.cpp qjackctlAlsaGraph.cpp qjackctlConnect.cpp qjackctlAliases.cpp qjackctlGraph.cpp qjackctlGraphCommand.cpp qjackctlInterfaceComboBox.cpp qjackctlJackConnect.cpp qjackctlJackGraph.cpp qjackctlPatchbay.cpp qjackctlPatchbayFile.cpp qjackctlPatchbayRack.cpp qjackctlSession.cpp qjackctlSetup.cpp qjackctlSystemTray.cpp qjackctlAboutForm.cpp qjackctlConnectionsForm.cpp qjackctlGraphForm.cpp qjackctlMainForm.cpp qjackctlMessagesStatusForm.cpp qjackctlPatchbayForm.cpp qjackctlSessionForm.cpp qjackctlSessionSaveForm.cpp qjackctlSetupForm.cpp qjackctlPaletteForm.cpp qjackctlSocketForm.cpp ) set (FORMS qjackctlAboutForm.ui qjackctlConnectionsForm.ui qjackctlGraphForm.ui qjackctlMainForm.ui qjackctlMessagesStatusForm.ui qjackctlPatchbayForm.ui qjackctlSessionForm.ui qjackctlSessionSaveForm.ui qjackctlSetupForm.ui qjackctlPaletteForm.ui qjackctlSocketForm.ui ) set (RESOURCES qjackctl.qrc ) set (TRANSLATIONS translations/qjackctl_cs.ts translations/qjackctl_de.ts translations/qjackctl_es.ts translations/qjackctl_fr.ts translations/qjackctl_it.ts translations/qjackctl_ja.ts translations/qjackctl_ko.ts translations/qjackctl_nl.ts translations/qjackctl_pt_BR.ts translations/qjackctl_ru.ts translations/qjackctl_sk.ts translations/qjackctl_tr.ts translations/qjackctl_uk.ts ) if (QT_VERSION VERSION_LESS 5.15.0) qt5_add_translation (QM_FILES ${TRANSLATIONS}) else () qt_add_translation (QM_FILES ${TRANSLATIONS}) endif () add_custom_target (translations ALL DEPENDS ${QM_FILES}) add_executable (${PROJECT_NAME} ${HEADERS} ${SOURCES} ${FORMS} ${RESOURCES} ) # Add some debugger flags. if (CONFIG_DEBUG AND UNIX AND NOT APPLE) set (CONFIG_DEBUG_OPTIONS -g -fsanitize=address -fno-omit-frame-pointer) target_compile_options (${PROJECT_NAME} PRIVATE ${CONFIG_DEBUG_OPTIONS}) target_link_options (${PROJECT_NAME} PRIVATE ${CONFIG_DEBUG_OPTIONS}) endif () set_target_properties (${PROJECT_NAME} PROPERTIES CXX_STANDARD 17) if (WIN32) set_target_properties (${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE true) target_compile_definitions (${PROJECT_NAME} PUBLIC _USE_MATH_DEFINES) endif () if (APPLE) set_target_properties (${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE true) endif () target_link_libraries (${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Xml Qt${QT_VERSION_MAJOR}::Svg) if (CONFIG_XUNIQUE) target_link_libraries (${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Network) endif () if (CONFIG_DBUS) target_link_libraries (${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::DBus) endif () if (CONFIG_JACK) target_link_libraries (${PROJECT_NAME} PRIVATE PkgConfig::JACK) endif () if (CONFIG_ALSA_SEQ) target_link_libraries (${PROJECT_NAME} PRIVATE ALSA::ALSA) endif () if (CONFIG_PORTAUDIO) target_link_libraries (${PROJECT_NAME} PRIVATE PortAudio::PortAudio) endif () if (CONFIG_COREAUDIO) target_link_libraries (${PROJECT_NAME} PRIVATE ${CORE_FOUNDATION_LIBRARY} ${CORE_AUDIO_LIBRARY}) endif () if (MINGW OR (UNIX AND NOT APPLE)) install (TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install (FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/translations) install (FILES images/${PROJECT_NAME}.png RENAME org.rncbc.${PROJECT_NAME}.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/32x32/apps) install (FILES images/${PROJECT_NAME}.svg RENAME org.rncbc.${PROJECT_NAME}.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps) install (FILES appdata/org.rncbc.${PROJECT_NAME}.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) install (FILES appdata/org.rncbc.${PROJECT_NAME}.metainfo.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo) install (FILES man1/${PROJECT_NAME}.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) install (FILES man1/${PROJECT_NAME}.fr.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/fr/man1 RENAME ${PROJECT_NAME}.1) install (FILES palette/KXStudio.conf palette/Wonton\ Soup.conf DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/palette) elseif (APPLE) # Generate bundle on MacOS with QjackCtl.icns as the icon and a custom Info.plist file. target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/images/QjackCtl.icns) set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/images/QjackCtl.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE True OUTPUT_NAME QjackCtl MACOSX_RPATH ON INSTALL_RPATH @executable_path/../Frameworks MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/appdata/Info.plist ) install (TARGETS ${PROJECT_NAME} BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}) elseif (WIN32) install (TARGETS ${PROJECT_NAME} RUNTIME DESTINATION .) # Use same path as windeployqt for translations install (FILES ${QM_FILES} DESTINATION translations) endif () if (WIN32 AND CONFIG_INSTALL_QT) get_target_property (_qt_qmake_location Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION) get_filename_component (_qt_bin_dir "${_qt_qmake_location}" DIRECTORY) set (QT_WINDEPLOYQT "${_qt_bin_dir}/windeployqt.exe") if (EXISTS ${QT_WINDEPLOYQT}) # execute windeployqt in a tmp directory after build if (QT_VERSION_MAJOR MATCHES "5") # These options are not available with Qt6 set (WINDEPLOYQT_EXTRA_OPTIONS --no-webkit2 --no-angle) endif () add_custom_command (TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/windeployqt" COMMAND set PATH=${_qt_bin_dir}$%PATH% COMMAND "${QT_WINDEPLOYQT}" --dir "${CMAKE_CURRENT_BINARY_DIR}/windeployqt" --no-quick-import --no-opengl-sw --no-virtualkeyboard --no-svg ${WINDEPLOYQT_EXTRA_OPTIONS} "$" USES_TERMINAL ) # copy deployment directory during installation install ( DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/windeployqt/" DESTINATION . ) endif () endif () if (APPLE AND CONFIG_INSTALL_QT) get_target_property (_qt_qmake_location Qt${QT_VERSION_MAJOR}::qmake IMPORTED_LOCATION) get_filename_component (_qt_bin_dir "${_qt_qmake_location}" DIRECTORY) find_program(QT_MACDEPLOYQT macdeployqt HINTS "${_qt_bin_dir}") if (EXISTS ${QT_MACDEPLOYQT}) add_custom_command (TARGET ${PROJECT_NAME} POST_BUILD COMMAND "${QT_MACDEPLOYQT}" "$/../.." USES_TERMINAL ) endif () endif () qjackctl-1.0.4/src/PaxHeaders/qjackctlSetupForm.cpp0000644000000000000000000000013214771215054017330 xustar0030 mtime=1743067692.329636565 30 atime=1743067692.329636565 30 ctime=1743067692.329636565 qjackctl-1.0.4/src/qjackctlSetupForm.cpp0000644000175000001440000022224614771215054017330 0ustar00rncbcusers// qjackctlSetupForm.cpp // /**************************************************************************** Copyright (C) 2003-2024, rncbc aka Rui Nuno Capela. All rights reserved. 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 (at your option) 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *****************************************************************************/ #include "qjackctlSetupForm.h" #include "qjackctlMainForm.h" #include "qjackctlPaletteForm.h" #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_SYSTEM_TRAY #include #endif #ifdef CONFIG_COREAUDIO #include #include #include #include #include #endif #ifdef CONFIG_PORTAUDIO #include #include #include #endif #ifdef CONFIG_ALSA_SEQ #include #endif //---------------------------------------------------------------------------- // qjackctlSetupForm -- UI wrapper form. // Constructor. qjackctlSetupForm::qjackctlSetupForm ( QWidget *pParent ) : QDialog(pParent) { // Setup UI struct... m_ui.setupUi(this); // No settings descriptor initially (the caller will set it). m_pSetup = nullptr; QMessageBox mbox; mbox.setIcon(QMessageBox::Warning); m_ui.AdvancedIconLabel->setPixmap( mbox.iconPixmap().scaledToHeight(16, Qt::SmoothTransformation)); // Setup time-display radio-button group. m_pTimeDisplayButtonGroup = new QButtonGroup(this); m_pTimeDisplayButtonGroup->addButton(m_ui.TransportTimeRadioButton, 0); m_pTimeDisplayButtonGroup->addButton(m_ui.TransportBBTRadioButton, 1); m_pTimeDisplayButtonGroup->addButton(m_ui.ElapsedResetRadioButton, 2); m_pTimeDisplayButtonGroup->addButton(m_ui.ElapsedXrunRadioButton, 3); m_pTimeDisplayButtonGroup->setExclusive(true); // Setup clock-source combo-box. const QString& sDefName = qjackctlSetup::defName(); m_ui.ClockSourceComboBox->clear(); m_ui.ClockSourceComboBox->addItem(sDefName, uint(0)); m_ui.ClockSourceComboBox->addItem(tr("System"), uint('s')); m_ui.ClockSourceComboBox->addItem(tr("Cycle"), uint('c')); m_ui.ClockSourceComboBox->addItem(tr("HPET"), uint('h')); // Setup self-connect-mode combo-box. m_ui.SelfConnectModeComboBox->clear(); m_ui.SelfConnectModeComboBox->addItem( tr("Don't restrict self connect requests (default)"), QVariant::fromValue (' ')); m_ui.SelfConnectModeComboBox->addItem( tr("Fail self connect requests to external ports only"), QVariant::fromValue ('E')); m_ui.SelfConnectModeComboBox->addItem( tr("Ignore self connect requests to external ports only"), QVariant::fromValue ('e')); m_ui.SelfConnectModeComboBox->addItem( tr("Fail all self connect requests"), QVariant::fromValue ('A')); m_ui.SelfConnectModeComboBox->addItem( tr("Ignore all self connect requests"), QVariant::fromValue ('a')); // Initialize dirty control state. m_iDirtySetup = 0; m_iDirtyPreset = 0; m_iDirtyBuffSize = 0; m_iDirtySettings = 0; m_iDirtyOptions = 0; #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__APPLE__) // Remove useless drivers for some systems for (int i = m_ui.DriverComboBox->count(); --i >= 0;) { const QString itemText = m_ui.DriverComboBox->itemText(i); if (itemText == "dummy") continue; #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) if (itemText == "portaudio") continue; #endif #ifdef __APPLE__ if (itemText == "coreaudio") continue; #endif if (itemText == "net") continue; if (itemText == "netone") continue; m_ui.DriverComboBox->removeItem(i); } #endif // Save original hard-coded driver names, only really // useful when (changing (dis)enabling JACK D-BUS... m_drivers.clear(); const int iDriverCount = m_ui.DriverComboBox->count(); for (int i = 0; i < iDriverCount; ++i) m_drivers.append(m_ui.DriverComboBox->itemText(i)); // Set dialog validators... m_ui.PresetComboBox->setValidator( new QRegularExpressionValidator(QRegularExpression("[\\w-]+"), m_ui.PresetComboBox)); m_ui.FramesComboBox->setValidator( new QIntValidator(m_ui.FramesComboBox)); m_ui.SampleRateComboBox->setValidator( new QIntValidator(m_ui.SampleRateComboBox)); m_ui.WaitComboBox->setValidator( new QIntValidator(m_ui.WaitComboBox)); m_ui.WordLengthComboBox->setValidator( new QIntValidator(m_ui.WordLengthComboBox)); m_ui.TimeoutComboBox->setValidator( new QIntValidator(m_ui.TimeoutComboBox)); m_ui.PortMaxComboBox->setValidator( new QIntValidator(m_ui.PortMaxComboBox)); m_ui.MessagesLimitLinesComboBox->setValidator( new QIntValidator(m_ui.MessagesLimitLinesComboBox)); m_ui.PresetComboBox->setCompleter(nullptr); m_ui.ServerNameComboBox->setCompleter(nullptr); m_ui.ServerPrefixComboBox->setCompleter(nullptr); m_ui.ServerSuffixComboBox->setCompleter(nullptr); m_ui.PrioritySpinBox->setSpecialValueText(sDefName); m_ui.SampleRateComboBox->insertItem(0, sDefName); m_ui.FramesComboBox->insertItem(0, sDefName); m_ui.PeriodsSpinBox->setSpecialValueText(sDefName); m_ui.PortMaxComboBox->insertItem(0, sDefName); m_ui.TimeoutComboBox->insertItem(0, sDefName); m_ui.WaitComboBox->insertItem(0, sDefName); m_ui.WordLengthComboBox->insertItem(0, sDefName); m_ui.ChanSpinBox->setSpecialValueText(sDefName); m_ui.InChannelsSpinBox->setSpecialValueText(sDefName); m_ui.OutChannelsSpinBox->setSpecialValueText(sDefName); m_ui.InLatencySpinBox->setSpecialValueText(sDefName); m_ui.OutLatencySpinBox->setSpecialValueText(sDefName); updatePalette(); // UI connections... QObject::connect(m_ui.PresetComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(changeCurrentPreset(const QString&))); QObject::connect(m_ui.PresetClearPushButton, SIGNAL(clicked()), SLOT(clearCurrentPreset())); QObject::connect(m_ui.PresetSavePushButton, SIGNAL(clicked()), SLOT(saveCurrentPreset())); QObject::connect(m_ui.PresetDeletePushButton, SIGNAL(clicked()), SLOT(deleteCurrentPreset())); QObject::connect(m_ui.DriverComboBox, SIGNAL(activated(int)), SLOT(changeDriver(int))); QObject::connect(m_ui.AudioComboBox, SIGNAL(activated(int)), SLOT(changeAudio(int))); QObject::connect(m_ui.ServerPrefixComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.ServerNameComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.DriverComboBox, SIGNAL(activated(int)), SLOT(settingsChanged())); QObject::connect(m_ui.RealtimeCheckBox, SIGNAL(stateChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.NoMemLockCheckBox, SIGNAL(stateChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.SoftModeCheckBox, SIGNAL(stateChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.MonitorCheckBox, SIGNAL(stateChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.ShortsCheckBox, SIGNAL(stateChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.HWMeterCheckBox, SIGNAL(stateChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.IgnoreHWCheckBox, SIGNAL(stateChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.UnlockMemCheckBox, SIGNAL(stateChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.ClockSourceComboBox, SIGNAL(activated(int)), SLOT(settingsChanged())); QObject::connect(m_ui.SelfConnectModeComboBox, SIGNAL(activated(int)), SLOT(settingsChanged())); QObject::connect(m_ui.SyncCheckBox, SIGNAL(stateChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.VerboseCheckBox, SIGNAL(stateChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.PrioritySpinBox, SIGNAL(valueChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.FramesComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(buffSizeChanged())); QObject::connect(m_ui.SampleRateComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.PeriodsSpinBox, SIGNAL(valueChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.WordLengthComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.WaitComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.ChanSpinBox, SIGNAL(valueChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.InterfaceComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.AudioComboBox, SIGNAL(activated(int)), SLOT(settingsChanged())); QObject::connect(m_ui.DitherComboBox, SIGNAL(activated(int)), SLOT(settingsChanged())); QObject::connect(m_ui.TimeoutComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.InDeviceComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.OutDeviceComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.InChannelsSpinBox, SIGNAL(valueChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.OutChannelsSpinBox, SIGNAL(valueChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.InLatencySpinBox, SIGNAL(valueChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.OutLatencySpinBox, SIGNAL(valueChanged(int)), SLOT(settingsChanged())); #ifdef CONFIG_JACK_MIDI QObject::connect(m_ui.MidiDriverComboBox, SIGNAL(activated(int)), SLOT(settingsChanged())); #endif QObject::connect(m_ui.StartDelaySpinBox, SIGNAL(valueChanged(int)), SLOT(settingsChanged())); QObject::connect(m_ui.PortMaxComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.ServerSuffixComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(settingsChanged())); QObject::connect(m_ui.StartupScriptCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.StartupScriptShellComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(optionsChanged())); QObject::connect(m_ui.PostStartupScriptCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.PostStartupScriptShellComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(optionsChanged())); QObject::connect(m_ui.ShutdownScriptCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.ShutdownScriptShellComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(optionsChanged())); QObject::connect(m_ui.PostShutdownScriptCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.PostShutdownScriptShellComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(optionsChanged())); QObject::connect(m_ui.StartupScriptBrowseToolButton, SIGNAL(clicked()), SLOT(browseStartupScript())); QObject::connect(m_ui.PostStartupScriptBrowseToolButton, SIGNAL(clicked()), SLOT(browsePostStartupScript())); QObject::connect(m_ui.ShutdownScriptBrowseToolButton, SIGNAL(clicked()), SLOT(browseShutdownScript())); QObject::connect(m_ui.PostShutdownScriptBrowseToolButton, SIGNAL(clicked()), SLOT(browsePostShutdownScript())); QObject::connect(m_ui.StartupScriptSymbolToolButton, SIGNAL(clicked()), SLOT(symbolStartupScript())); QObject::connect(m_ui.PostStartupScriptSymbolToolButton, SIGNAL(clicked()), SLOT(symbolPostStartupScript())); QObject::connect(m_ui.ShutdownScriptSymbolToolButton, SIGNAL(clicked()), SLOT(symbolShutdownScript())); QObject::connect(m_ui.PostShutdownScriptSymbolToolButton, SIGNAL(clicked()), SLOT(symbolPostShutdownScript())); QObject::connect(m_ui.StdoutCaptureCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.XrunRegexComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(optionsChanged())); QObject::connect(m_ui.ActivePatchbayCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.ActivePatchbayPathComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(optionsChanged())); QObject::connect(m_ui.ActivePatchbayPathToolButton, SIGNAL(clicked()), SLOT(browseActivePatchbayPath())); QObject::connect(m_ui.ActivePatchbayResetCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.QueryDisconnectCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.MessagesLogCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.MessagesLogPathComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(optionsChanged())); QObject::connect(m_ui.MessagesLogPathToolButton, SIGNAL(clicked()), SLOT(browseMessagesLogPath())); QObject::connect(m_ui.TransportTimeRadioButton, SIGNAL(toggled(bool)), SLOT(optionsChanged())); QObject::connect(m_ui.TransportBBTRadioButton, SIGNAL(toggled(bool)), SLOT(optionsChanged())); QObject::connect(m_ui.ElapsedResetRadioButton, SIGNAL(toggled(bool)), SLOT(optionsChanged())); QObject::connect(m_ui.ElapsedXrunRadioButton, SIGNAL(toggled(bool)), SLOT(optionsChanged())); QObject::connect(m_ui.DisplayBlinkCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.CustomColorThemeComboBox, SIGNAL(activated(int)), SLOT(optionsChanged())); QObject::connect(m_ui.CustomColorThemeToolButton, SIGNAL(clicked()), SLOT(editCustomColorThemes())); QObject::connect(m_ui.CustomStyleThemeComboBox, SIGNAL(activated(int)), SLOT(optionsChanged())); QObject::connect(m_ui.DisplayFont1PushButton, SIGNAL(clicked()), SLOT(chooseDisplayFont1())); QObject::connect(m_ui.DisplayFont2PushButton, SIGNAL(clicked()), SLOT(chooseDisplayFont2())); QObject::connect(m_ui.MessagesFontPushButton, SIGNAL(clicked()), SLOT(chooseMessagesFont())); QObject::connect(m_ui.ConnectionsFontPushButton, SIGNAL(clicked()), SLOT(chooseConnectionsFont())); QObject::connect(m_ui.MessagesLimitCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.MessagesLimitLinesComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(optionsChanged())); QObject::connect(m_ui.ConnectionsIconSizeComboBox, SIGNAL(activated(int)), SLOT(optionsChanged())); QObject::connect(m_ui.AliasesEnabledCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.AliasesEditingCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); #ifdef CONFIG_JACK_PORT_ALIASES QObject::connect(m_ui.JackClientPortAliasComboBox, SIGNAL(activated(int)), SLOT(optionsChanged())); QObject::connect(m_ui.JackClientPortMetadataCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); #endif QObject::connect(m_ui.StartJackCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.StopJackCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.QueryCloseCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.QueryShutdownCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.KeepOnTopCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); #ifdef CONFIG_SYSTEM_TRAY QObject::connect(m_ui.SystemTrayCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.SystemTrayQueryCloseCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.StartMinimizedCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); #endif #ifdef CONFIG_XUNIQUE QObject::connect(m_ui.SingletonCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); #endif QObject::connect(m_ui.ServerConfigCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.ServerConfigNameComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(optionsChanged())); #ifdef CONFIG_ALSA_SEQ QObject::connect(m_ui.AlsaSeqEnabledCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); #endif #ifdef CONFIG_DBUS QObject::connect(m_ui.DBusEnabledCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.JackDBusEnabledCheckBox, SIGNAL(stateChanged(int)), SLOT(changeDrivers())); #endif QObject::connect(m_ui.LeftButtonsCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.RightButtonsCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.TransportButtonsCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.TextLabelsCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.GraphButtonCheckBox, SIGNAL(stateChanged(int)), SLOT(optionsChanged())); QObject::connect(m_ui.BaseFontSizeComboBox, SIGNAL(editTextChanged(const QString&)), SLOT(optionsChanged())); #if 0 QObject::connect(m_ui.DialogButtonBox, SIGNAL(accepted()), SLOT(accept())); QObject::connect(m_ui.DialogButtonBox, SIGNAL(rejected()), SLOT(reject())); #else QObject::connect(m_ui.DialogButtonBox, SIGNAL(clicked(QAbstractButton *)), SLOT(buttonClicked(QAbstractButton *))); #endif // Try to restore old window positioning. adjustSize(); } // Destructor. qjackctlSetupForm::~qjackctlSetupForm (void) { delete m_pTimeDisplayButtonGroup; } // A combo-box text item setter helper. void qjackctlSetupForm::setComboBoxCurrentText ( QComboBox *pComboBox, const QString& sText ) const { if (pComboBox->isEditable()) { pComboBox->setEditText(sText); } else { int iIndex = pComboBox->findText(sText); if (iIndex < 0) { iIndex = 0; if (!sText.isEmpty()) pComboBox->insertItem(0, sText); } pComboBox->setCurrentIndex(iIndex); } } // A combo-box text data setter helper. void qjackctlSetupForm::setComboBoxCurrentData ( QComboBox *pComboBox, const QVariant& data ) const { if (pComboBox->isEditable()) { pComboBox->setEditText(data.toString()); } else { int iIndex = pComboBox->findData(data); if (iIndex < 0) iIndex = 0; pComboBox->setCurrentIndex(iIndex); } } // Populate (setup) dialog controls from settings descriptors. void qjackctlSetupForm::setup ( qjackctlSetup *pSetup ) { // Set reference descriptor. m_pSetup = pSetup; // Avoid dirty this all up. ++m_iDirtySetup; // Load combo box history... m_pSetup->loadComboBoxHistory(m_ui.ServerPrefixComboBox); m_pSetup->loadComboBoxHistory(m_ui.ServerNameComboBox); m_pSetup->loadComboBoxHistory(m_ui.ServerSuffixComboBox); m_pSetup->loadComboBoxHistory(m_ui.StartupScriptShellComboBox); m_pSetup->loadComboBoxHistory(m_ui.PostStartupScriptShellComboBox); m_pSetup->loadComboBoxHistory(m_ui.ShutdownScriptShellComboBox); m_pSetup->loadComboBoxHistory(m_ui.PostShutdownScriptShellComboBox); m_pSetup->loadComboBoxHistory(m_ui.XrunRegexComboBox); m_pSetup->loadComboBoxHistory(m_ui.ActivePatchbayPathComboBox); m_pSetup->loadComboBoxHistory(m_ui.MessagesLogPathComboBox); m_pSetup->loadComboBoxHistory(m_ui.ServerConfigNameComboBox); const QString& sDefName = qjackctlSetup::defName(); m_ui.InterfaceComboBox->setup( m_ui.DriverComboBox, QJACKCTL_DUPLEX, sDefName); m_ui.InDeviceComboBox->setup( m_ui.DriverComboBox, QJACKCTL_CAPTURE, sDefName); m_ui.OutDeviceComboBox->setup( m_ui.DriverComboBox, QJACKCTL_PLAYBACK, sDefName); // Load Options... m_ui.StartupScriptCheckBox->setChecked(m_pSetup->bStartupScript); setComboBoxCurrentText(m_ui.StartupScriptShellComboBox, m_pSetup->sStartupScriptShell); m_ui.PostStartupScriptCheckBox->setChecked(m_pSetup->bPostStartupScript); setComboBoxCurrentText(m_ui.PostStartupScriptShellComboBox, m_pSetup->sPostStartupScriptShell); m_ui.ShutdownScriptCheckBox->setChecked(m_pSetup->bShutdownScript); setComboBoxCurrentText(m_ui.ShutdownScriptShellComboBox, m_pSetup->sShutdownScriptShell); m_ui.PostShutdownScriptCheckBox->setChecked(m_pSetup->bPostShutdownScript); setComboBoxCurrentText(m_ui.PostShutdownScriptShellComboBox, m_pSetup->sPostShutdownScriptShell); m_ui.StdoutCaptureCheckBox->setChecked(m_pSetup->bStdoutCapture); setComboBoxCurrentText(m_ui.XrunRegexComboBox, m_pSetup->sXrunRegex); m_ui.ActivePatchbayCheckBox->setChecked(m_pSetup->bActivePatchbay); setComboBoxCurrentText(m_ui.ActivePatchbayPathComboBox, m_pSetup->sActivePatchbayPath); m_ui.ActivePatchbayResetCheckBox->setChecked(m_pSetup->bActivePatchbayReset); m_ui.QueryDisconnectCheckBox->setChecked(m_pSetup->bQueryDisconnect); m_ui.MessagesLogCheckBox->setChecked(m_pSetup->bMessagesLog); setComboBoxCurrentText(m_ui.MessagesLogPathComboBox, m_pSetup->sMessagesLogPath); // Load some other defaults... QRadioButton *pRadioButton = static_cast ( m_pTimeDisplayButtonGroup->button(m_pSetup->iTimeDisplay)); if (pRadioButton) pRadioButton->setChecked(true); // Load font chooser samples... const QString sSansSerif = "Sans Serif"; QFont font; if (m_pSetup->sDisplayFont1.isEmpty() || !font.fromString(m_pSetup->sDisplayFont1)) font = QFont(sSansSerif, 12, QFont::Bold); m_ui.DisplayFont1TextLabel->setFont(font); m_ui.DisplayFont1TextLabel->setText( font.family() + ' ' + QString::number(font.pointSize())); if (m_pSetup->sDisplayFont2.isEmpty() || !font.fromString(m_pSetup->sDisplayFont2)) font = QFont(sSansSerif, 6, QFont::Bold); m_ui.DisplayFont2TextLabel->setFont(font); m_ui.DisplayFont2TextLabel->setText( font.family() + ' ' + QString::number(font.pointSize())); if (m_pSetup->sMessagesFont.isEmpty() || !font.fromString(m_pSetup->sMessagesFont)) font = QFont("Monospace", 8); m_ui.MessagesFontTextLabel->setFont(font); m_ui.MessagesFontTextLabel->setText( font.family() + ' ' + QString::number(font.pointSize())); if (m_pSetup->sConnectionsFont.isEmpty() || !font.fromString(m_pSetup->sConnectionsFont)) font = QFont(sSansSerif, 10); m_ui.ConnectionsFontTextLabel->setFont(font); m_ui.ConnectionsFontTextLabel->setText( font.family() + ' ' + QString::number(font.pointSize())); // The main display shiny effect option. m_ui.DisplayBlinkCheckBox->setChecked(m_pSetup->bDisplayBlink); toggleDisplayEffect(m_pSetup->bDisplayEffect); // Connections view icon size. m_ui.ConnectionsIconSizeComboBox->setCurrentIndex( m_pSetup->iConnectionsIconSize); // and this JACK specialities... m_ui.JackClientPortAliasComboBox->setCurrentIndex( m_pSetup->iJackClientPortAlias); m_ui.JackClientPortMetadataCheckBox->setChecked( m_pSetup->bJackClientPortMetadata); // Messages limit option. m_ui.MessagesLimitCheckBox->setChecked(m_pSetup->bMessagesLimit); setComboBoxCurrentText(m_ui.MessagesLimitLinesComboBox, QString::number(m_pSetup->iMessagesLimitLines)); // Other misc options... m_ui.StartJackCheckBox->setChecked(m_pSetup->bStartJack); m_ui.StopJackCheckBox->setChecked(m_pSetup->bStopJack); m_ui.QueryCloseCheckBox->setChecked(m_pSetup->bQueryClose); m_ui.QueryShutdownCheckBox->setChecked(m_pSetup->bQueryShutdown); m_ui.KeepOnTopCheckBox->setChecked(m_pSetup->bKeepOnTop); #ifdef CONFIG_SYSTEM_TRAY m_ui.SystemTrayCheckBox->setChecked(m_pSetup->bSystemTray); m_ui.SystemTrayQueryCloseCheckBox->setChecked(m_pSetup->bSystemTrayQueryClose); m_ui.StartMinimizedCheckBox->setChecked(m_pSetup->bStartMinimized); #endif m_ui.SingletonCheckBox->setChecked(m_pSetup->bSingleton); m_ui.ServerConfigCheckBox->setChecked(m_pSetup->bServerConfig); setComboBoxCurrentText(m_ui.ServerConfigNameComboBox, m_pSetup->sServerConfigName); m_ui.AlsaSeqEnabledCheckBox->setChecked(m_pSetup->bAlsaSeqEnabled); m_ui.DBusEnabledCheckBox->setChecked(m_pSetup->bDBusEnabled); m_ui.JackDBusEnabledCheckBox->setChecked(m_pSetup->bJackDBusEnabled); m_ui.AliasesEnabledCheckBox->setChecked(m_pSetup->bAliasesEnabled); m_ui.AliasesEditingCheckBox->setChecked(m_pSetup->bAliasesEditing); m_ui.LeftButtonsCheckBox->setChecked(!m_pSetup->bLeftButtons); m_ui.RightButtonsCheckBox->setChecked(!m_pSetup->bRightButtons); m_ui.TransportButtonsCheckBox->setChecked(!m_pSetup->bTransportButtons); m_ui.TextLabelsCheckBox->setChecked(!m_pSetup->bTextLabels); m_ui.GraphButtonCheckBox->setChecked(m_pSetup->bGraphButton); if (m_pSetup->iBaseFontSize > 0) m_ui.BaseFontSizeComboBox->setEditText(QString::number(m_pSetup->iBaseFontSize)); else m_ui.BaseFontSizeComboBox->setCurrentIndex(0); // Custom display options... resetCustomColorThemes(m_pSetup->sCustomColorTheme); resetCustomStyleThemes(m_pSetup->sCustomStyleTheme); #ifdef CONFIG_SYSTEM_TRAY const bool bSystemTray = QSystemTrayIcon::isSystemTrayAvailable(); #else const bool bSystemTray = false; #endif if (!bSystemTray) { m_ui.SystemTrayCheckBox->setChecked(false); m_ui.SystemTrayCheckBox->setEnabled(false); m_ui.SystemTrayQueryCloseCheckBox->setChecked(false); m_ui.SystemTrayQueryCloseCheckBox->setEnabled(false); m_ui.StartMinimizedCheckBox->setChecked(false); m_ui.StartMinimizedCheckBox->setEnabled(false); } #ifndef CONFIG_JACK_MIDI m_ui.MidiDriverComboBox->setCurrentIndex(0); m_ui.MidiDriverTextLabel->setEnabled(false); m_ui.MidiDriverComboBox->setEnabled(false); #endif #ifndef CONFIG_JACK_PORT_ALIASES m_ui.JackClientPortAliasComboBox->setCurrentIndex(0); m_ui.JackClientPortAliasTextLabel->setEnabled(false); m_ui.JackClientPortAliasComboBox->setEnabled(false); #endif #ifndef CONFIG_JACK_METADATA m_ui.JackClientPortMetadataCheckBox->setChecked(false); m_ui.JackClientPortMetadataCheckBox->setEnabled(false); #endif #ifndef CONFIG_ALSA_SEQ m_ui.AlsaSeqEnabledCheckBox->setEnabled(false); #endif #ifndef CONFIG_DBUS m_ui.DBusEnabledCheckBox->setEnabled(false); m_ui.JackDBusEnabledCheckBox->setEnabled(false); #endif // Load preset list... resetPresets(); updateCurrentPreset(); updateBuffSize(); // Make sure initial preset is not dirty... m_iDirtyPreset = 0; // We're clean now. --m_iDirtySetup; stabilizeForm(); } // Set form widgets from preset values... void qjackctlSetupForm::setCurrentPreset ( const qjackctlPreset& preset ) { const QString& sDefName = qjackctlSetup::defName(); setComboBoxCurrentText(m_ui.ServerPrefixComboBox, preset.sServerPrefix); setComboBoxCurrentText(m_ui.ServerNameComboBox, preset.sServerName.isEmpty() ? sDefName : preset.sServerName); m_ui.RealtimeCheckBox->setChecked(preset.bRealtime); m_ui.SoftModeCheckBox->setChecked(preset.bSoftMode); m_ui.MonitorCheckBox->setChecked(preset.bMonitor); m_ui.ShortsCheckBox->setChecked(preset.bShorts); m_ui.NoMemLockCheckBox->setChecked(preset.bNoMemLock); m_ui.UnlockMemCheckBox->setChecked(preset.bUnlockMem); m_ui.HWMeterCheckBox->setChecked(preset.bHWMeter); m_ui.IgnoreHWCheckBox->setChecked(preset.bIgnoreHW); m_ui.PrioritySpinBox->setValue(preset.iPriority); setComboBoxCurrentText(m_ui.FramesComboBox, preset.iFrames > 0 ? QString::number(preset.iFrames) : sDefName); setComboBoxCurrentText(m_ui.SampleRateComboBox, preset.iSampleRate > 0 ? QString::number(preset.iSampleRate) : sDefName); m_ui.PeriodsSpinBox->setValue(preset.iPeriods); setComboBoxCurrentText(m_ui.WordLengthComboBox, preset.iWordLength > 0 && preset.iWordLength != 16 ? QString::number(preset.iWordLength) : sDefName); setComboBoxCurrentText(m_ui.WaitComboBox, preset.iWait > 0 && preset.iWait != 21333 ? QString::number(preset.iWait) : sDefName); m_ui.ChanSpinBox->setValue(preset.iChan); setComboBoxCurrentText(m_ui.DriverComboBox, preset.sDriver); setComboBoxCurrentText(m_ui.InterfaceComboBox, preset.sInterface.isEmpty() ? sDefName : preset.sInterface); m_ui.AudioComboBox->setCurrentIndex(preset.iAudio); m_ui.DitherComboBox->setCurrentIndex(preset.iDither); setComboBoxCurrentText(m_ui.TimeoutComboBox, preset.iTimeout > 0 && preset.iTimeout != 500 ? QString::number(preset.iTimeout) : sDefName); setComboBoxCurrentData(m_ui.ClockSourceComboBox, QVariant::fromValue (preset.ucClockSource)); setComboBoxCurrentText(m_ui.InDeviceComboBox, preset.sInDevice.isEmpty() ? sDefName : preset.sInDevice); setComboBoxCurrentText(m_ui.OutDeviceComboBox, preset.sOutDevice.isEmpty() ? sDefName : preset.sOutDevice); m_ui.InChannelsSpinBox->setValue(preset.iInChannels); m_ui.OutChannelsSpinBox->setValue(preset.iOutChannels); m_ui.InLatencySpinBox->setValue(preset.iInLatency); m_ui.OutLatencySpinBox->setValue(preset.iOutLatency); m_ui.StartDelaySpinBox->setValue(preset.iStartDelay); m_ui.SyncCheckBox->setChecked(preset.bSync); setComboBoxCurrentData(m_ui.SelfConnectModeComboBox, QVariant::fromValue (preset.ucSelfConnectMode)); m_ui.VerboseCheckBox->setChecked(preset.bVerbose); setComboBoxCurrentText(m_ui.PortMaxComboBox, preset.iPortMax > 0 && preset.iPortMax != 256 ? QString::number(preset.iPortMax) : sDefName); #ifdef CONFIG_JACK_MIDI setComboBoxCurrentText(m_ui.MidiDriverComboBox, preset.sMidiDriver); #endif setComboBoxCurrentText(m_ui.ServerSuffixComboBox, preset.sServerSuffix); } // Get preset values from form widgets... bool qjackctlSetupForm::getCurrentPreset ( qjackctlPreset& preset ) { preset.sServerPrefix = m_ui.ServerPrefixComboBox->currentText(); preset.sServerName = m_ui.ServerNameComboBox->currentText(); preset.bRealtime = m_ui.RealtimeCheckBox->isChecked(); preset.bSoftMode = m_ui.SoftModeCheckBox->isChecked(); preset.bMonitor = m_ui.MonitorCheckBox->isChecked(); preset.bShorts = m_ui.ShortsCheckBox->isChecked(); preset.bNoMemLock = m_ui.NoMemLockCheckBox->isChecked(); preset.bUnlockMem = m_ui.UnlockMemCheckBox->isChecked(); preset.bHWMeter = m_ui.HWMeterCheckBox->isChecked(); preset.bIgnoreHW = m_ui.IgnoreHWCheckBox->isChecked(); preset.iPriority = m_ui.PrioritySpinBox->value(); preset.iFrames = m_ui.FramesComboBox->currentText().toInt(); preset.iSampleRate = m_ui.SampleRateComboBox->currentText().toInt(); preset.iPeriods = m_ui.PeriodsSpinBox->value(); preset.iWordLength = m_ui.WordLengthComboBox->currentText().toInt(); preset.iWait = m_ui.WaitComboBox->currentText().toInt(); preset.iChan = m_ui.ChanSpinBox->value(); preset.sDriver = m_ui.DriverComboBox->currentText(); preset.sInterface = m_ui.InterfaceComboBox->currentText(); preset.iAudio = m_ui.AudioComboBox->currentIndex(); preset.iDither = m_ui.DitherComboBox->currentIndex(); preset.iTimeout = m_ui.TimeoutComboBox->currentText().toInt(); preset.sInDevice = m_ui.InDeviceComboBox->currentText(); preset.sOutDevice = m_ui.OutDeviceComboBox->currentText(); preset.iInChannels = m_ui.InChannelsSpinBox->value(); preset.iOutChannels = m_ui.OutChannelsSpinBox->value(); preset.iInLatency = m_ui.InLatencySpinBox->value(); preset.iOutLatency = m_ui.OutLatencySpinBox->value(); preset.iStartDelay = m_ui.StartDelaySpinBox->value(); preset.bSync = m_ui.SyncCheckBox->isChecked(); preset.bVerbose = m_ui.VerboseCheckBox->isChecked(); preset.iPortMax = m_ui.PortMaxComboBox->currentText().toInt(); #ifdef CONFIG_JACK_MIDI preset.sMidiDriver = m_ui.MidiDriverComboBox->currentText(); #endif preset.sServerSuffix = m_ui.ServerSuffixComboBox->currentText(); const QString& sDefName = qjackctlSetup::defName(); if (preset.sServerName == sDefName) preset.sServerName.clear(); if (preset.sInterface == sDefName) preset.sInterface.clear(); if (preset.sInDevice == sDefName) preset.sInDevice.clear(); if (preset.sOutDevice == sDefName) preset.sOutDevice.clear(); preset.ucClockSource = 0; int iIndex = m_ui.ClockSourceComboBox->currentIndex(); if (iIndex >= 0) preset.ucClockSource = m_ui.ClockSourceComboBox->itemData(iIndex).value (); preset.ucSelfConnectMode = 0; iIndex = m_ui.SelfConnectModeComboBox->currentIndex(); if (iIndex >= 0) preset.ucSelfConnectMode = m_ui.SelfConnectModeComboBox->itemData(iIndex).value (); return true; } void qjackctlSetupForm::changePreset ( const QString& sPreset ) { if (sPreset.isEmpty()) return; // Load settings... qjackctlPreset preset; if (m_pSetup->loadPreset(preset, sPreset)) { setCurrentPreset(preset); // Reset dirty flags? m_iDirtySettings = 0; ++m_iDirtyPreset; } // Set current preset name.. m_sPreset = sPreset; } bool qjackctlSetupForm::savePreset ( const QString& sPreset ) { if (sPreset.isEmpty()) return false; // Unload settings. qjackctlPreset preset; if (getCurrentPreset(preset)) m_pSetup->savePreset(preset, sPreset); return true; } bool qjackctlSetupForm::deletePreset ( const QString& sPreset ) { if (sPreset.isEmpty()) return false; // Just remove the preset item... m_pSetup->deletePreset(sPreset); return true; } void qjackctlSetupForm::resetPresets (void) { m_ui.PresetComboBox->clear(); m_ui.PresetComboBox->addItems(m_pSetup->presets); m_ui.PresetComboBox->addItem(qjackctlSetup::defName()); } void qjackctlSetupForm::updateCurrentPreset (void) { // Have current preset changed anyhow? if (m_pSetup && m_pSetup->sDefPreset != m_sPreset) { ++m_iDirtySetup; setComboBoxCurrentText(m_ui.PresetComboBox, m_pSetup->sDefPreset); changePreset(m_ui.PresetComboBox->currentText()); --m_iDirtySetup; } } void qjackctlSetupForm::changeCurrentPreset ( const QString& sPreset ) { if (m_iDirtySetup > 0) return; // Check if there's any pending changes... if (m_iDirtySettings > 0 && !m_sPreset.isEmpty()) { switch (QMessageBox::warning(isVisible() ? this : parentWidget(), tr("Warning") + " - " QJACKCTL_TITLE, tr("Some settings have been changed:\n\n" "\"%1\"\n\nDo you want to save the changes?") .arg(m_sPreset), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) { case QMessageBox::Save: savePreset(m_sPreset); ++m_iDirtySetup; resetPresets(); setComboBoxCurrentText(m_ui.PresetComboBox, sPreset); --m_iDirtySetup; // Fall thru... case QMessageBox::Discard: m_iDirtySettings = 0; break; default: // Cancel... ++m_iDirtySetup; resetPresets(); setComboBoxCurrentText(m_ui.PresetComboBox, m_sPreset); --m_iDirtySetup; return; } } changePreset(sPreset); optionsChanged(); } void qjackctlSetupForm::clearCurrentPreset (void) { // Clear current settings... qjackctlPreset preset; setCurrentPreset(preset); settingsChanged(); } void qjackctlSetupForm::saveCurrentPreset (void) { const QString sPreset = m_ui.PresetComboBox->currentText(); if (savePreset(sPreset)) { // Reset preset combobox list. ++m_iDirtySetup; resetPresets(); setComboBoxCurrentText(m_ui.PresetComboBox, sPreset); --m_iDirtySetup; // Reset dirty flag. m_iDirtySettings = 0; stabilizeForm(); } } void qjackctlSetupForm::deleteCurrentPreset (void) { const QString sPreset = m_ui.PresetComboBox->currentText(); // Try to prompt user if he/she really wants this... if (QMessageBox::warning(isVisible() ? this : parentWidget(), tr("Warning") + " - " QJACKCTL_TITLE, tr("Delete preset:\n\n" "\"%1\"\n\nAre you sure?") .arg(sPreset), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) return; if (deletePreset(sPreset)) { // Reset preset combobox list, // and load a new available preset.. ++m_iDirtySetup; int iItem = m_ui.PresetComboBox->currentIndex(); resetPresets(); m_ui.PresetComboBox->setCurrentIndex(iItem); changePreset(m_ui.PresetComboBox->currentText()); --m_iDirtySetup; // Take care that maybe it was the default one... if (m_pSetup->sDefPreset == sPreset) m_pSetup->sDefPreset = m_sPreset; // Make this stable now. optionsChanged(); } } void qjackctlSetupForm::computeLatency (void) { const int p = m_ui.FramesComboBox->currentText().toInt(); const int r = m_ui.SampleRateComboBox->currentText().toInt(); const int n = m_ui.PeriodsSpinBox->value(); float lat = 0.0f; if (r > 0) lat = float(1000.0f * p * n) / float(r); if (lat > 0.0f) m_ui.LatencyTextValue->setText(QString::number(lat, 'g', 3) + " " + tr("msec")); else m_ui.LatencyTextValue->setText(tr("n/a")); } void qjackctlSetupForm::changeDriverAudio ( const QString& sDriver, int iAudio ) { const bool bSun = (sDriver == "sun"); const bool bOss = (sDriver == "oss"); const bool bAlsa = (sDriver == "alsa"); const bool bCoreaudio = (sDriver == "coreaudio"); const bool bPortaudio = (sDriver == "portaudio"); const bool bFirewire = (sDriver == "firewire"); const bool bNet = (sDriver == "net" || sDriver == "netone"); bool bInEnabled = false; bool bOutEnabled = false; bool bEnabled = false;; switch (iAudio) { case QJACKCTL_DUPLEX: bInEnabled = (bSun || bOss || bAlsa || bCoreaudio || bPortaudio || bNet); bOutEnabled = (bSun || bOss || bAlsa || bCoreaudio || bPortaudio || bNet); break; case QJACKCTL_CAPTURE: bInEnabled = (bSun || bOss || bCoreaudio || bPortaudio || bNet); break; case QJACKCTL_PLAYBACK: bOutEnabled = (bSun || bOss || bCoreaudio || bPortaudio || bNet); break; } bEnabled = (bInEnabled && (bAlsa || bSun || bOss || bCoreaudio || bPortaudio)); m_ui.InDeviceTextLabel->setEnabled(bEnabled); m_ui.InDeviceComboBox->setEnabled(bEnabled); if (!bEnabled) setComboBoxCurrentText(m_ui.InDeviceComboBox, qjackctlSetup::defName()); bEnabled = (bOutEnabled && (bAlsa || bSun || bOss || bCoreaudio || bPortaudio)); m_ui.OutDeviceTextLabel->setEnabled(bEnabled); m_ui.OutDeviceComboBox->setEnabled(bEnabled); if (!bEnabled) setComboBoxCurrentText(m_ui.OutDeviceComboBox, qjackctlSetup::defName()); m_ui.InOutChannelsTextLabel->setEnabled(bInEnabled || (bAlsa || bFirewire)); m_ui.InChannelsSpinBox->setEnabled(bInEnabled || ((bAlsa || bFirewire) && iAudio != QJACKCTL_PLAYBACK)); m_ui.OutChannelsSpinBox->setEnabled(bOutEnabled || ((bAlsa || bFirewire) && iAudio != QJACKCTL_CAPTURE)); m_ui.InOutLatencyTextLabel->setEnabled((bInEnabled && !bNet) || (bAlsa || bFirewire)); m_ui.InLatencySpinBox->setEnabled((bInEnabled && !bNet) || ((bAlsa || bFirewire) && iAudio != QJACKCTL_PLAYBACK)); m_ui.OutLatencySpinBox->setEnabled((bOutEnabled && !bNet) || ((bAlsa || bFirewire) && iAudio != QJACKCTL_CAPTURE)); computeLatency(); } void qjackctlSetupForm::changeAudio ( int iAudio ) { changeDriverAudio(m_ui.DriverComboBox->currentText(), iAudio); } void qjackctlSetupForm::changeDriver ( int iDriver ) { changeDriverUpdate(m_ui.DriverComboBox->itemText(iDriver), true); } void qjackctlSetupForm::changeDriverUpdate ( const QString& sDriver, bool bUpdate ) { const bool bDummy = (sDriver == "dummy"); const bool bSun = (sDriver == "sun"); const bool bOss = (sDriver == "oss"); const bool bAlsa = (sDriver == "alsa"); const bool bPortaudio = (sDriver == "portaudio"); const bool bCoreaudio = (sDriver == "coreaudio"); const bool bFirewire = (sDriver == "firewire"); const bool bNet = (sDriver == "net" || sDriver == "netone"); #ifdef CONFIG_DBUS const bool bJackDBus = m_ui.JackDBusEnabledCheckBox->isChecked(); #else const bool bJackDBus = false; #endif // m_ui.SyncCheckBox->setEnabled(bJackDBus); // m_ui.ClockSourceTextLabel->setEnabled(bJackDBus); // m_ui.ClockSourceComboBox->setEnabled(bJackDBus); // m_ui.SelfConnectModeTextLabel->setEnabled(bJackDBus); // m_ui.SelfConnectModeComboBox->setEnabled(bJackDBus); m_ui.NoMemLockCheckBox->setEnabled(!bCoreaudio && !bJackDBus); m_ui.UnlockMemCheckBox->setEnabled(!bCoreaudio && !bJackDBus && !m_ui.NoMemLockCheckBox->isChecked()); m_ui.SoftModeCheckBox->setEnabled(bAlsa); m_ui.MonitorCheckBox->setEnabled(bAlsa); m_ui.ShortsCheckBox->setEnabled(bAlsa); m_ui.HWMeterCheckBox->setEnabled(bAlsa); m_ui.IgnoreHWCheckBox->setEnabled((bSun || bOss) && !bJackDBus); if (bCoreaudio || bPortaudio) { m_ui.PriorityTextLabel->setEnabled(false); m_ui.PrioritySpinBox->setEnabled(false); } else { const bool bPriorityEnabled = m_ui.RealtimeCheckBox->isChecked(); m_ui.PriorityTextLabel->setEnabled(bPriorityEnabled); m_ui.PrioritySpinBox->setEnabled(bPriorityEnabled); } m_ui.SampleRateTextLabel->setEnabled(!bNet); m_ui.SampleRateComboBox->setEnabled(!bNet); m_ui.FramesTextLabel->setEnabled(!bNet); m_ui.FramesComboBox->setEnabled(!bNet); m_ui.PeriodsTextLabel->setEnabled(bAlsa || bSun || bOss || bFirewire); m_ui.PeriodsSpinBox->setEnabled(bAlsa || bSun || bOss || bFirewire); if (bUpdate && bFirewire && m_ui.PeriodsSpinBox->value() < 3) m_ui.PeriodsSpinBox->setValue(3); m_ui.WordLengthTextLabel->setEnabled((bSun || bOss) && !bJackDBus); m_ui.WordLengthComboBox->setEnabled((bSun || bOss) && !bJackDBus); m_ui.WaitTextLabel->setEnabled(bDummy); m_ui.WaitComboBox->setEnabled(bDummy); m_ui.ChanTextLabel->setEnabled(bPortaudio); m_ui.ChanSpinBox->setEnabled(bPortaudio); const int iAudio = m_ui.AudioComboBox->currentIndex(); bool bEnabled = (bAlsa || bPortaudio); if (bEnabled && iAudio == QJACKCTL_DUPLEX) { const QString& sInDevice = m_ui.InDeviceComboBox->currentText(); const QString& sOutDevice = m_ui.OutDeviceComboBox->currentText(); bEnabled = (sInDevice.isEmpty() || sInDevice == qjackctlSetup::defName() || sOutDevice.isEmpty() || sOutDevice == qjackctlSetup::defName()); } const bool bInterface = (bEnabled || bCoreaudio || bFirewire); m_ui.InterfaceTextLabel->setEnabled(bInterface); m_ui.InterfaceComboBox->setEnabled(bInterface); if (!bInterface) setComboBoxCurrentText(m_ui.InterfaceComboBox, qjackctlSetup::defName()); m_ui.DitherTextLabel->setEnabled(bAlsa || bPortaudio); m_ui.DitherComboBox->setEnabled(bAlsa || bPortaudio); #ifdef CONFIG_JACK_MIDI m_ui.MidiDriverTextLabel->setEnabled(bAlsa); m_ui.MidiDriverComboBox->setEnabled(bAlsa); #endif m_ui.ServerNameTextLabel->setEnabled(!bJackDBus); m_ui.ServerNameComboBox->setEnabled(!bJackDBus); m_ui.ServerPrefixTextLabel->setEnabled(!bJackDBus); m_ui.ServerPrefixComboBox->setEnabled(!bJackDBus); m_ui.ServerSuffixTextLabel->setEnabled(!bJackDBus); m_ui.ServerSuffixComboBox->setEnabled(!bJackDBus); changeDriverAudio(sDriver, iAudio); } // Stabilize current form state. void qjackctlSetupForm::stabilizeForm (void) { bool bValid = (m_iDirtySettings > 0 || m_iDirtyOptions > 0); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm && !pMainForm->isJackDetach()) { m_ui.PresetTextLabel->setEnabled(true); m_ui.PresetComboBox->setEnabled(true); m_ui.PresetClearPushButton->setEnabled(true); const QString& sPreset = m_ui.PresetComboBox->currentText(); if (!sPreset.isEmpty()) { const bool bPreset = (m_pSetup->presets.contains(sPreset)); m_ui.PresetSavePushButton->setEnabled(m_iDirtySettings > 0 || (!bPreset && sPreset != qjackctlSetup::defName())); m_ui.PresetDeletePushButton->setEnabled(bPreset); } else { m_ui.PresetSavePushButton->setEnabled(false); m_ui.PresetDeletePushButton->setEnabled(false); } m_ui.DriverTextLabel->setEnabled(true); m_ui.DriverComboBox->setEnabled(true); m_ui.RealtimeCheckBox->setEnabled(true); m_ui.InterfaceTextLabel->setEnabled(true); m_ui.InterfaceComboBox->setEnabled(true); m_ui.SampleRateTextLabel->setEnabled(true); m_ui.SampleRateComboBox->setEnabled(true); // m_ui.FramesTextLabel->setEnabled(true); // m_ui.FramesComboBox->setEnabled(true); m_ui.PeriodsTextLabel->setEnabled(true); m_ui.PeriodsSpinBox->setEnabled(true); m_ui.MidiDriverTextLabel->setEnabled(true); m_ui.MidiDriverComboBox->setEnabled(true); m_ui.SyncCheckBox->setEnabled(true); m_ui.VerboseCheckBox->setEnabled(true); // m_ui.LatencyTextLabel->setEnabled(true); // m_ui.LatencyTextValue->setEnabled(true); m_ui.AdvancedTab->setEnabled(true); changeDriverUpdate(m_ui.DriverComboBox->currentText(), false); } else { m_ui.PresetTextLabel->setEnabled(false); m_ui.PresetComboBox->setEnabled(false); m_ui.PresetClearPushButton->setEnabled(false); m_ui.PresetSavePushButton->setEnabled(false); m_ui.PresetDeletePushButton->setEnabled(false); m_ui.DriverTextLabel->setEnabled(false); m_ui.DriverComboBox->setEnabled(false); m_ui.RealtimeCheckBox->setEnabled(false); m_ui.InterfaceTextLabel->setEnabled(false); m_ui.InterfaceComboBox->setEnabled(false); m_ui.SampleRateTextLabel->setEnabled(false); m_ui.SampleRateComboBox->setEnabled(false); // m_ui.FramesTextLabel->setEnabled(false); // m_ui.FramesComboBox->setEnabled(false); m_ui.PeriodsTextLabel->setEnabled(false); m_ui.PeriodsSpinBox->setEnabled(false); m_ui.MidiDriverTextLabel->setEnabled(false); m_ui.MidiDriverComboBox->setEnabled(false); m_ui.SyncCheckBox->setEnabled(false); m_ui.VerboseCheckBox->setEnabled(false); // m_ui.LatencyTextLabel->setEnabled(false); // m_ui.LatencyTextValue->setEnabled(false); m_ui.AdvancedTab->setEnabled(false); m_ui.InterfaceComboBox->setCurrentIndex(0); m_ui.PeriodsSpinBox->setValue(0); computeLatency(); } bool bEnabled = m_ui.StartupScriptCheckBox->isChecked(); m_ui.StartupScriptShellComboBox->setEnabled(bEnabled); m_ui.StartupScriptSymbolToolButton->setEnabled(bEnabled); m_ui.StartupScriptBrowseToolButton->setEnabled(bEnabled); bEnabled = m_ui.PostStartupScriptCheckBox->isChecked(); m_ui.PostStartupScriptShellComboBox->setEnabled(bEnabled); m_ui.PostStartupScriptSymbolToolButton->setEnabled(bEnabled); m_ui.PostStartupScriptBrowseToolButton->setEnabled(bEnabled); bEnabled = m_ui.ShutdownScriptCheckBox->isChecked(); m_ui.ShutdownScriptShellComboBox->setEnabled(bEnabled); m_ui.ShutdownScriptSymbolToolButton->setEnabled(bEnabled); m_ui.ShutdownScriptBrowseToolButton->setEnabled(bEnabled); bEnabled = m_ui.PostShutdownScriptCheckBox->isChecked(); m_ui.PostShutdownScriptShellComboBox->setEnabled(bEnabled); m_ui.PostShutdownScriptSymbolToolButton->setEnabled(bEnabled); m_ui.PostShutdownScriptBrowseToolButton->setEnabled(bEnabled); bEnabled = m_ui.StdoutCaptureCheckBox->isChecked(); m_ui.XrunRegexTextLabel->setEnabled(bEnabled); m_ui.XrunRegexComboBox->setEnabled(bEnabled); bEnabled = m_ui.ActivePatchbayCheckBox->isChecked(); m_ui.ActivePatchbayPathComboBox->setEnabled(bEnabled); m_ui.ActivePatchbayPathToolButton->setEnabled(bEnabled); m_ui.ActivePatchbayResetCheckBox->setEnabled(bEnabled); m_ui.QueryDisconnectCheckBox->setEnabled(bEnabled); if (bEnabled && bValid) { const QString& sPath = m_ui.ActivePatchbayPathComboBox->currentText(); bValid = (!sPath.isEmpty() && QFileInfo(sPath).exists()); } bEnabled = m_ui.MessagesLogCheckBox->isChecked(); m_ui.MessagesLogPathComboBox->setEnabled(bEnabled); m_ui.MessagesLogPathToolButton->setEnabled(bEnabled); if (bEnabled && bValid) { const QString& sPath = m_ui.MessagesLogPathComboBox->currentText(); bValid = !sPath.isEmpty(); } m_ui.MessagesLimitLinesComboBox->setEnabled( m_ui.MessagesLimitCheckBox->isChecked()); #ifdef CONFIG_JACK_METADATA #ifdef CONFIG_JACK_PORT_ALIASES bEnabled = !m_ui.JackClientPortMetadataCheckBox->isChecked(); m_ui.JackClientPortAliasTextLabel->setEnabled(bEnabled); m_ui.JackClientPortAliasComboBox->setEnabled(bEnabled); if (bEnabled) { m_ui.JackClientPortMetadataCheckBox->setEnabled( m_ui.JackClientPortAliasComboBox->currentIndex() == 0); } #endif #endif #ifdef CONFIG_SYSTEM_TRAY bEnabled = m_ui.SystemTrayCheckBox->isChecked(); m_ui.SystemTrayQueryCloseCheckBox->setEnabled(bEnabled); m_ui.StartMinimizedCheckBox->setEnabled(bEnabled); #endif bEnabled = !m_ui.JackDBusEnabledCheckBox->isChecked(); m_ui.ServerConfigCheckBox->setEnabled(bEnabled); if (bEnabled) bEnabled = m_ui.ServerConfigCheckBox->isChecked(); m_ui.ServerConfigNameComboBox->setEnabled(bEnabled); m_ui.AliasesEditingCheckBox->setEnabled( m_ui.AliasesEnabledCheckBox->isChecked()); #ifndef CONFIG_XUNIQUE m_ui.SingletonCheckBox->setEnabled(false); #endif m_ui.TransportButtonsCheckBox->setEnabled( m_ui.LeftButtonsCheckBox->isChecked()); m_ui.GraphButtonCheckBox->setEnabled( !m_ui.LeftButtonsCheckBox->isChecked()); bEnabled = (bValid || m_iDirtyBuffSize > 0); m_ui.DialogButtonBox->button(QDialogButtonBox::Apply)->setEnabled(bEnabled); m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(bEnabled); } // Meta-symbol menu executive. void qjackctlSetupForm::symbolMenu( QLineEdit *pLineEdit, QToolButton *pToolButton ) { const QString s = " "; QMenu menu(this); menu.addAction("%P" + s + tr("&Preset Name")); menu.addSeparator(); menu.addAction("%N" + s + tr("&Server Name")); menu.addAction("%s" + s + tr("&Server Path")); menu.addAction("%d" + s + tr("&Driver")); menu.addAction("%i" + s + tr("&Interface")); menu.addSeparator(); menu.addAction("%r" + s + tr("Sample &Rate")); menu.addAction("%p" + s + tr("&Frames/Period")); menu.addAction("%n" + s + tr("Periods/&Buffer")); QAction *pAction = menu.exec(pToolButton->mapToGlobal(QPoint(0,0))); if (pAction) { const QString sText = pAction->text(); int iMetaChar = sText.indexOf('%'); if (iMetaChar >= 0) { pLineEdit->insert('%' + sText[iMetaChar + 1]); // optionsChanged(); } } } // Startup script meta-symbol button slot. void qjackctlSetupForm::symbolStartupScript (void) { symbolMenu(m_ui.StartupScriptShellComboBox->lineEdit(), m_ui.StartupScriptSymbolToolButton); } // Post-startup script meta-symbol button slot. void qjackctlSetupForm::symbolPostStartupScript (void) { symbolMenu(m_ui.PostStartupScriptShellComboBox->lineEdit(), m_ui.PostStartupScriptSymbolToolButton); } // Shutdown script meta-symbol button slot. void qjackctlSetupForm::symbolShutdownScript (void) { symbolMenu(m_ui.ShutdownScriptShellComboBox->lineEdit(), m_ui.ShutdownScriptSymbolToolButton); } // Post-shutdown script meta-symbol button slot. void qjackctlSetupForm::symbolPostShutdownScript (void) { symbolMenu(m_ui.PostShutdownScriptShellComboBox->lineEdit(), m_ui.PostShutdownScriptSymbolToolButton); } // Startup script browse slot. void qjackctlSetupForm::browseStartupScript (void) { QString sFileName = QFileDialog::getOpenFileName( this, // Parent. tr("Startup Script"), // Caption. m_ui.StartupScriptShellComboBox->currentText() // Start here. ); if (!sFileName.isEmpty()) { setComboBoxCurrentText(m_ui.StartupScriptShellComboBox, sFileName); m_ui.StartupScriptShellComboBox->setFocus(); optionsChanged(); } } // Post-startup script browse slot. void qjackctlSetupForm::browsePostStartupScript (void) { QString sFileName = QFileDialog::getOpenFileName( this, // Parent. tr("Post-Startup Script"), // Caption. m_ui.PostStartupScriptShellComboBox->currentText() // Start here. ); if (!sFileName.isEmpty()) { setComboBoxCurrentText(m_ui.PostStartupScriptShellComboBox, sFileName); m_ui.PostStartupScriptShellComboBox->setFocus(); optionsChanged(); } } // Shutdown script browse slot. void qjackctlSetupForm::browseShutdownScript (void) { QString sFileName = QFileDialog::getOpenFileName( this, // Parent. tr("Shutdown Script"), // Caption. m_ui.ShutdownScriptShellComboBox->currentText() // Start here. ); if (!sFileName.isEmpty()) { setComboBoxCurrentText(m_ui.ShutdownScriptShellComboBox, sFileName); m_ui.ShutdownScriptShellComboBox->setFocus(); optionsChanged(); } } // Post-shutdown script browse slot. void qjackctlSetupForm::browsePostShutdownScript (void) { QString sFileName = QFileDialog::getOpenFileName( this, // Parent. tr("Post-Shutdown Script"), // Caption. m_ui.PostShutdownScriptShellComboBox->currentText() // Start here. ); if (!sFileName.isEmpty()) { setComboBoxCurrentText(m_ui.PostShutdownScriptShellComboBox, sFileName); m_ui.PostShutdownScriptShellComboBox->setFocus(); optionsChanged(); } } // Active Patchbay path browse slot. void qjackctlSetupForm::browseActivePatchbayPath (void) { QString sFileName = QFileDialog::getOpenFileName( this, // Parent. tr("Active Patchbay Definition"), // Caption. m_ui.ActivePatchbayPathComboBox->currentText(), // Start here. tr("Patchbay Definition files") + " (*.xml)" // Filter (XML files) ); if (!sFileName.isEmpty()) { setComboBoxCurrentText(m_ui.ActivePatchbayPathComboBox, sFileName); m_ui.ActivePatchbayPathComboBox->setFocus(); optionsChanged(); } } // Messages log path browse slot. void qjackctlSetupForm::browseMessagesLogPath (void) { QString sFileName = QFileDialog::getSaveFileName( this, // Parent. tr("Messages Log"), // Caption. m_ui.MessagesLogPathComboBox->currentText(), // Start here. tr("Log files") + " (*.log)" // Filter (log files) ); if (!sFileName.isEmpty()) { setComboBoxCurrentText(m_ui.MessagesLogPathComboBox, sFileName); m_ui.MessagesLogPathComboBox->setFocus(); optionsChanged(); } } // The display font 1 (big time) selection dialog. void qjackctlSetupForm::chooseDisplayFont1 (void) { bool bOk = false; QFont font = QFontDialog::getFont(&bOk, m_ui.DisplayFont1TextLabel->font(), this); if (bOk) { m_ui.DisplayFont1TextLabel->setFont(font); m_ui.DisplayFont1TextLabel->setText(font.family() + ' ' + QString::number(font.pointSize())); optionsChanged(); } } // The display font 2 (normal time et al.) selection dialog. void qjackctlSetupForm::chooseDisplayFont2 (void) { bool bOk = false; QFont font = QFontDialog::getFont(&bOk, m_ui.DisplayFont2TextLabel->font(), this); if (bOk) { m_ui.DisplayFont2TextLabel->setFont(font); m_ui.DisplayFont2TextLabel->setText(font.family() + ' ' + QString::number(font.pointSize())); optionsChanged(); } } // The channel display effect demo changer. void qjackctlSetupForm::toggleDisplayEffect ( bool bOn ) { QPalette pal; pal.setColor(QPalette::WindowText, Qt::green); if (bOn) { QPixmap pm(":/images/displaybg1.png"); pal.setBrush(QPalette::Window, QBrush(pm)); } else { pal.setColor(QPalette::Window, Qt::black); } m_ui.DisplayFont1TextLabel->setPalette(pal); m_ui.DisplayFont2TextLabel->setPalette(pal); optionsChanged(); } // The messages font selection dialog. void qjackctlSetupForm::chooseMessagesFont (void) { bool bOk = false; QFont font = QFontDialog::getFont(&bOk, m_ui.MessagesFontTextLabel->font(), this); if (bOk) { m_ui.MessagesFontTextLabel->setFont(font); m_ui.MessagesFontTextLabel->setText(font.family() + ' ' + QString::number(font.pointSize())); optionsChanged(); } } // The connections font selection dialog. void qjackctlSetupForm::chooseConnectionsFont (void) { bool bOk = false; QFont font = QFontDialog::getFont(&bOk, m_ui.ConnectionsFontTextLabel->font(), this); if (bOk) { m_ui.ConnectionsFontTextLabel->setFont(font); m_ui.ConnectionsFontTextLabel->setText(font.family() + ' ' + QString::number(font.pointSize())); optionsChanged(); } } // Custom color palette theme manager. void qjackctlSetupForm::editCustomColorThemes (void) { qjackctlPaletteForm form(this); form.setSettings(&m_pSetup->settings()); QString sCustomColorTheme; int iDirtyCustomColorTheme = 0; const int iCustomColorTheme = m_ui.CustomColorThemeComboBox->currentIndex(); if (iCustomColorTheme > 0) { sCustomColorTheme = m_ui.CustomColorThemeComboBox->itemText( iCustomColorTheme); form.setPaletteName(sCustomColorTheme); } if (form.exec() == QDialog::Accepted) { sCustomColorTheme = form.paletteName(); ++iDirtyCustomColorTheme; } if (iDirtyCustomColorTheme > 0 || form.isDirty()) { resetCustomColorThemes(sCustomColorTheme); optionsChanged(); } } // Custom color palette themes settler. void qjackctlSetupForm::resetCustomColorThemes ( const QString& sCustomColorTheme ) { m_ui.CustomColorThemeComboBox->clear(); m_ui.CustomColorThemeComboBox->addItem( qjackctlSetup::defName()); m_ui.CustomColorThemeComboBox->addItems( qjackctlPaletteForm::namedPaletteList(&m_pSetup->settings())); int iCustomColorTheme = 0; if (!sCustomColorTheme.isEmpty()) { iCustomColorTheme = m_ui.CustomColorThemeComboBox->findText( sCustomColorTheme); if (iCustomColorTheme < 0) iCustomColorTheme = 0; } m_ui.CustomColorThemeComboBox->setCurrentIndex(iCustomColorTheme); } // Custom widget style themes settler. void qjackctlSetupForm::resetCustomStyleThemes ( const QString& sCustomStyleTheme ) { m_ui.CustomStyleThemeComboBox->clear(); m_ui.CustomStyleThemeComboBox->addItem( qjackctlSetup::defName()); m_ui.CustomStyleThemeComboBox->addItems(QStyleFactory::keys()); int iCustomStyleTheme = 0; if (!sCustomStyleTheme.isEmpty()) { iCustomStyleTheme = m_ui.CustomStyleThemeComboBox->findText( sCustomStyleTheme); if (iCustomStyleTheme < 0) iCustomStyleTheme = 0; } m_ui.CustomStyleThemeComboBox->setCurrentIndex(iCustomStyleTheme); } void qjackctlSetupForm::updatePalette (void) { QPalette pal; pal.setColor(QPalette::Window, pal.base().color()); m_ui.MessagesFontTextLabel->setPalette(pal); m_ui.ConnectionsFontTextLabel->setPalette(pal); } // Brag about any buffer-size (frames/period) changes... void qjackctlSetupForm::buffSizeChanged (void) { if (m_iDirtySetup > 0) return; ++m_iDirtyBuffSize; stabilizeForm(); } // Get actual sample-rate and buffer-size when in pure-client mode... void qjackctlSetupForm::updateBuffSize (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr || pMainForm->isJackDetach()) { ++m_iDirtySetup; m_ui.InterfaceComboBox->setCurrentIndex(0); jack_client_t *pJackClient = nullptr; if (pMainForm) pJackClient = pMainForm->jackClient(); if (pJackClient) { m_ui.SampleRateComboBox->setCurrentText( QString::number(jack_get_sample_rate(pJackClient))); m_ui.FramesComboBox->setCurrentText( QString::number(jack_get_buffer_size(pJackClient))); } else { m_ui.SampleRateComboBox->setCurrentIndex(0); m_ui.FramesComboBox->setCurrentIndex(0); } m_ui.PeriodsSpinBox->setValue(0); m_iDirtySettings = 0; m_iDirtyBuffSize = 0; --m_iDirtySetup; } } // Mark that JACK D-BUS has been (dis)enabled. void qjackctlSetupForm::updateDrivers (void) { const bool bBlockSignals = m_ui.DriverComboBox->blockSignals(true); const QString sDriver = m_ui.DriverComboBox->currentText(); m_ui.DriverComboBox->clear(); QStringList drivers; #ifdef CONFIG_DBUS if (m_ui.JackDBusEnabledCheckBox->isChecked()) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) drivers = pMainForm->getDBusEngineDrivers(); } #endif if (drivers.isEmpty()) drivers = m_drivers; // Restore the original list... m_ui.DriverComboBox->addItems(drivers); setComboBoxCurrentText(m_ui.DriverComboBox, sDriver); m_ui.DriverComboBox->blockSignals(bBlockSignals); } void qjackctlSetupForm::changeDrivers (void) { updateDrivers(); optionsChanged(); } // Mark that some server preset settings have changed. void qjackctlSetupForm::settingsChanged (void) { if (m_iDirtySetup > 0) return; ++m_iDirtySettings; stabilizeForm(); } // Mark that some program options have changed. void qjackctlSetupForm::optionsChanged (void) { if (m_iDirtySetup > 0) return; ++m_iDirtyOptions; stabilizeForm(); } // Apply settings (Apply button slot). void qjackctlSetupForm::apply (void) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm == nullptr) return; if (m_iDirtyBuffSize > 0) { // Change JACK buffer size immediately... if (!pMainForm->resetBuffSize(jack_nframes_t( m_ui.FramesComboBox->currentText().toUInt()))) { // Make up a settings change instead... ++m_iDirtySettings; } } if (m_iDirtySettings > 0 || m_iDirtyPreset > 0 || m_iDirtyBuffSize > 0) { // Save current preset selection. m_pSetup->sDefPreset = m_ui.PresetComboBox->currentText(); // Always save current settings... savePreset(m_pSetup->sDefPreset); } if (m_iDirtyOptions > 0) { // To track down deferred or immediate changes. const bool bOldMessagesLog = m_pSetup->bMessagesLog; const QString sOldMessagesLogPath = m_pSetup->sMessagesLogPath; const QString sOldMessagesFont = m_pSetup->sMessagesFont; const QString sOldDisplayFont1 = m_pSetup->sDisplayFont1; const QString sOldDisplayFont2 = m_pSetup->sDisplayFont2; const QString sOldConnectionsFont = m_pSetup->sConnectionsFont; const int iOldConnectionsIconSize = m_pSetup->iConnectionsIconSize; const int iOldJackClientPortAlias = m_pSetup->iJackClientPortAlias; const bool bOldJackClientPortMetadata = m_pSetup->bJackClientPortMetadata; const int iOldTimeDisplay = m_pSetup->iTimeDisplay; const bool bOldActivePatchbay = m_pSetup->bActivePatchbay; const QString sOldActivePatchbayPath = m_pSetup->sActivePatchbayPath; const bool bOldStdoutCapture = m_pSetup->bStdoutCapture; const bool bOldKeepOnTop = m_pSetup->bKeepOnTop; #ifdef CONFIG_SYSTEM_TRAY const bool bOldSystemTray = m_pSetup->bSystemTray; #endif const int bOldMessagesLimit = m_pSetup->bMessagesLimit; const int iOldMessagesLimitLines = m_pSetup->iMessagesLimitLines; const bool bOldAlsaSeqEnabled = m_pSetup->bAlsaSeqEnabled; #ifdef CONFIG_DBUS const bool bOldDBusEnabled = m_pSetup->bDBusEnabled; const bool bOldJackDBusEnabled = m_pSetup->bJackDBusEnabled; #endif const bool bOldAliasesEnabled = m_pSetup->bAliasesEnabled; const bool bOldAliasesEditing = m_pSetup->bAliasesEditing; const bool bOldLeftButtons = m_pSetup->bLeftButtons; const bool bOldRightButtons = m_pSetup->bRightButtons; const bool bOldTransportButtons = m_pSetup->bTransportButtons; const bool bOldTextLabels = m_pSetup->bTextLabels; const bool bOldGraphButton = m_pSetup->bGraphButton; const int iOldBaseFontSize = m_pSetup->iBaseFontSize; // Save Options... m_pSetup->bStartupScript = m_ui.StartupScriptCheckBox->isChecked(); m_pSetup->sStartupScriptShell = m_ui.StartupScriptShellComboBox->currentText(); m_pSetup->bPostStartupScript = m_ui.PostStartupScriptCheckBox->isChecked(); m_pSetup->sPostStartupScriptShell = m_ui.PostStartupScriptShellComboBox->currentText(); m_pSetup->bShutdownScript = m_ui.ShutdownScriptCheckBox->isChecked(); m_pSetup->sShutdownScriptShell = m_ui.ShutdownScriptShellComboBox->currentText(); m_pSetup->bPostShutdownScript = m_ui.PostShutdownScriptCheckBox->isChecked(); m_pSetup->sPostShutdownScriptShell = m_ui.PostShutdownScriptShellComboBox->currentText(); m_pSetup->bStdoutCapture = m_ui.StdoutCaptureCheckBox->isChecked(); m_pSetup->sXrunRegex = m_ui.XrunRegexComboBox->currentText(); m_pSetup->bActivePatchbay = m_ui.ActivePatchbayCheckBox->isChecked(); m_pSetup->sActivePatchbayPath = m_ui.ActivePatchbayPathComboBox->currentText(); m_pSetup->bActivePatchbayReset = m_ui.ActivePatchbayResetCheckBox->isChecked(); m_pSetup->bQueryDisconnect = m_ui.QueryDisconnectCheckBox->isChecked(); m_pSetup->bMessagesLog = m_ui.MessagesLogCheckBox->isChecked(); m_pSetup->sMessagesLogPath = m_ui.MessagesLogPathComboBox->currentText(); // Save Defaults... m_pSetup->iTimeDisplay = m_pTimeDisplayButtonGroup->checkedId(); m_pSetup->sMessagesFont = m_ui.MessagesFontTextLabel->font().toString(); m_pSetup->bMessagesLimit = m_ui.MessagesLimitCheckBox->isChecked(); m_pSetup->iMessagesLimitLines = m_ui.MessagesLimitLinesComboBox->currentText().toInt(); m_pSetup->sDisplayFont1 = m_ui.DisplayFont1TextLabel->font().toString(); m_pSetup->sDisplayFont2 = m_ui.DisplayFont2TextLabel->font().toString(); m_pSetup->bDisplayBlink = m_ui.DisplayBlinkCheckBox->isChecked(); m_pSetup->iJackClientPortAlias = m_ui.JackClientPortAliasComboBox->currentIndex(); m_pSetup->bJackClientPortMetadata = m_ui.JackClientPortMetadataCheckBox->isChecked(); m_pSetup->iConnectionsIconSize = m_ui.ConnectionsIconSizeComboBox->currentIndex(); m_pSetup->sConnectionsFont = m_ui.ConnectionsFontTextLabel->font().toString(); m_pSetup->bStartJack = m_ui.StartJackCheckBox->isChecked(); m_pSetup->bStopJack = m_ui.StopJackCheckBox->isChecked(); m_pSetup->bQueryClose = m_ui.QueryCloseCheckBox->isChecked(); m_pSetup->bQueryShutdown = m_ui.QueryShutdownCheckBox->isChecked(); m_pSetup->bKeepOnTop = m_ui.KeepOnTopCheckBox->isChecked(); #ifdef CONFIG_SYSTEM_TRAY m_pSetup->bSystemTray = m_ui.SystemTrayCheckBox->isChecked(); m_pSetup->bSystemTrayQueryClose = m_ui.SystemTrayQueryCloseCheckBox->isChecked(); m_pSetup->bStartMinimized = m_ui.StartMinimizedCheckBox->isChecked(); #endif m_pSetup->bSingleton = m_ui.SingletonCheckBox->isChecked(); m_pSetup->bServerConfig = m_ui.ServerConfigCheckBox->isChecked(); m_pSetup->sServerConfigName = m_ui.ServerConfigNameComboBox->currentText(); m_pSetup->bAlsaSeqEnabled = m_ui.AlsaSeqEnabledCheckBox->isChecked(); #ifdef CONFIG_DBUS m_pSetup->bDBusEnabled = m_ui.DBusEnabledCheckBox->isChecked(); m_pSetup->bJackDBusEnabled = m_ui.JackDBusEnabledCheckBox->isChecked(); #endif m_pSetup->bAliasesEnabled = m_ui.AliasesEnabledCheckBox->isChecked(); m_pSetup->bAliasesEditing = m_ui.AliasesEditingCheckBox->isChecked(); m_pSetup->bLeftButtons = !m_ui.LeftButtonsCheckBox->isChecked(); m_pSetup->bRightButtons = !m_ui.RightButtonsCheckBox->isChecked(); m_pSetup->bTransportButtons = !m_ui.TransportButtonsCheckBox->isChecked(); m_pSetup->bTextLabels = !m_ui.TextLabelsCheckBox->isChecked(); m_pSetup->bGraphButton = m_ui.GraphButtonCheckBox->isChecked(); m_pSetup->iBaseFontSize = m_ui.BaseFontSizeComboBox->currentText().toInt(); // Custom color/style theme options... const QString sOldCustomStyleTheme = m_pSetup->sCustomStyleTheme; if (m_ui.CustomStyleThemeComboBox->currentIndex() > 0) m_pSetup->sCustomStyleTheme = m_ui.CustomStyleThemeComboBox->currentText(); else m_pSetup->sCustomStyleTheme.clear(); const QString sOldCustomColorTheme = m_pSetup->sCustomColorTheme; if (m_ui.CustomColorThemeComboBox->currentIndex() > 0) m_pSetup->sCustomColorTheme = m_ui.CustomColorThemeComboBox->currentText(); else m_pSetup->sCustomColorTheme.clear(); // Check whether restart is needed or whether // custom options maybe set up immediately... int iNeedRestart = 0; if (m_pSetup->sCustomStyleTheme != sOldCustomStyleTheme) { if (m_pSetup->sCustomStyleTheme.isEmpty()) { ++iNeedRestart; } else { QApplication::setStyle( QStyleFactory::create(m_pSetup->sCustomStyleTheme)); } } if (m_pSetup->sCustomColorTheme != sOldCustomColorTheme) { if (m_pSetup->sCustomColorTheme.isEmpty()) { ++iNeedRestart; } else { QPalette pal; if (qjackctlPaletteForm::namedPalette( &m_pSetup->settings(), m_pSetup->sCustomColorTheme, pal)) { QApplication::setPalette(pal); pMainForm->updatePalette(); updatePalette(); } } } // Show restart message if needed... if (iNeedRestart > 0) { QMessageBox::information(this, tr("Information"), tr("Some settings may be only effective\n" "next time you start this application.")); } // Check wheather something immediate has changed. if (( bOldMessagesLog && !m_pSetup->bMessagesLog) || (!bOldMessagesLog && m_pSetup->bMessagesLog) || (sOldMessagesLogPath != m_pSetup->sMessagesLogPath)) pMainForm->updateMessagesLogging(); if (iOldJackClientPortAlias != m_pSetup->iJackClientPortAlias) pMainForm->updateJackClientPortAlias(); if (( bOldJackClientPortMetadata && !m_pSetup->bJackClientPortMetadata) || (!bOldJackClientPortMetadata && m_pSetup->bJackClientPortMetadata)) pMainForm->updateJackClientPortMetadata(); if (iOldConnectionsIconSize != m_pSetup->iConnectionsIconSize) pMainForm->updateConnectionsIconSize(); if (sOldConnectionsFont != m_pSetup->sConnectionsFont) pMainForm->updateConnectionsFont(); if (sOldMessagesFont != m_pSetup->sMessagesFont) pMainForm->updateMessagesFont(); if (( bOldMessagesLimit && !m_pSetup->bMessagesLimit) || (!bOldMessagesLimit && m_pSetup->bMessagesLimit) || (iOldMessagesLimitLines != m_pSetup->iMessagesLimitLines)) pMainForm->updateMessagesLimit(); if (sOldDisplayFont1 != m_pSetup->sDisplayFont1 || sOldDisplayFont2 != m_pSetup->sDisplayFont2) pMainForm->updateTimeDisplayFonts(); if (iOldTimeDisplay != m_pSetup->iTimeDisplay) pMainForm->updateTimeDisplayToolTips(); if ((!bOldActivePatchbay && m_pSetup->bActivePatchbay) || (sOldActivePatchbayPath != m_pSetup->sActivePatchbayPath)) pMainForm->updateActivePatchbay(); #ifdef CONFIG_SYSTEM_TRAY if (( bOldSystemTray && !m_pSetup->bSystemTray) || (!bOldSystemTray && m_pSetup->bSystemTray)) pMainForm->updateSystemTray(); #endif if (( bOldAliasesEnabled && !m_pSetup->bAliasesEnabled) || (!bOldAliasesEnabled && m_pSetup->bAliasesEnabled) || ( bOldAliasesEditing && !m_pSetup->bAliasesEditing) || (!bOldAliasesEditing && m_pSetup->bAliasesEditing)) pMainForm->updateAliases(); if (( bOldLeftButtons && !m_pSetup->bLeftButtons) || (!bOldLeftButtons && m_pSetup->bLeftButtons) || ( bOldRightButtons && !m_pSetup->bRightButtons) || (!bOldRightButtons && m_pSetup->bRightButtons) || ( bOldTransportButtons && !m_pSetup->bTransportButtons) || (!bOldTransportButtons && m_pSetup->bTransportButtons) || ( bOldTextLabels && !m_pSetup->bTextLabels) || (!bOldTextLabels && m_pSetup->bTextLabels) || ( bOldGraphButton && !m_pSetup->bGraphButton) || (!bOldGraphButton && m_pSetup->bGraphButton)) pMainForm->updateButtons(); #ifdef CONFIG_DBUS if (( bOldJackDBusEnabled && !m_pSetup->bJackDBusEnabled) || (!bOldJackDBusEnabled && m_pSetup->bJackDBusEnabled)) pMainForm->updateJackDBus(); #endif // Warn if something will be only effective on next run. if (( bOldStdoutCapture && !m_pSetup->bStdoutCapture) || (!bOldStdoutCapture && m_pSetup->bStdoutCapture) || ( bOldKeepOnTop && !m_pSetup->bKeepOnTop) || (!bOldKeepOnTop && m_pSetup->bKeepOnTop) || ( bOldAlsaSeqEnabled && !m_pSetup->bAlsaSeqEnabled) || (!bOldAlsaSeqEnabled && m_pSetup->bAlsaSeqEnabled) || #ifdef CONFIG_DBUS ( bOldDBusEnabled && !m_pSetup->bDBusEnabled) || (!bOldDBusEnabled && m_pSetup->bDBusEnabled) || #endif (iOldBaseFontSize != m_pSetup->iBaseFontSize)) pMainForm->showDirtySetupWarning(); } // Save combobox history... m_pSetup->saveComboBoxHistory(m_ui.ServerPrefixComboBox); m_pSetup->saveComboBoxHistory(m_ui.ServerNameComboBox); m_pSetup->saveComboBoxHistory(m_ui.ServerSuffixComboBox); m_pSetup->saveComboBoxHistory(m_ui.StartupScriptShellComboBox); m_pSetup->saveComboBoxHistory(m_ui.PostStartupScriptShellComboBox); m_pSetup->saveComboBoxHistory(m_ui.ShutdownScriptShellComboBox); m_pSetup->saveComboBoxHistory(m_ui.PostShutdownScriptShellComboBox); m_pSetup->saveComboBoxHistory(m_ui.XrunRegexComboBox); m_pSetup->saveComboBoxHistory(m_ui.ActivePatchbayPathComboBox); m_pSetup->saveComboBoxHistory(m_ui.MessagesLogPathComboBox); m_pSetup->saveComboBoxHistory(m_ui.ServerConfigNameComboBox); // Save/commit to disk. m_pSetup->saveSetup(); // If server is currently running, warn user... if (m_iDirtySettings > 0 || m_iDirtyPreset > 0) { // Maybe whether to restart the server, who knows? pMainForm->restartJack(); // Maybe something changed on the way up?... m_ui.QueryShutdownCheckBox->setChecked(m_pSetup->bQueryShutdown); } // Reset all dirty flags... m_iDirtyPreset = 0; m_iDirtySettings = 0; m_iDirtyBuffSize = 0; m_iDirtyOptions = 0; // Make it stable anyway... stabilizeForm(); } // Discard/revert settings (Discard button slot). void qjackctlSetupForm::discard (void) { // Load settings... qjackctlPreset preset; if (m_pSetup->loadPreset(preset, m_sPreset)) { setCurrentPreset(preset); // Reset dirty flags? m_iDirtySettings = 0; } } // Accept settings (OK button slot). void qjackctlSetupForm::accept (void) { // Just go with dialog acceptance. apply(); QDialog::accept(); } // Reject settings (Cancel button slot). void qjackctlSetupForm::reject (void) { if (queryClose()) QDialog::reject(); } // Dialog bos button slot. void qjackctlSetupForm::buttonClicked ( QAbstractButton *pButton ) { switch (m_ui.DialogButtonBox->buttonRole(pButton)) { case QDialogButtonBox::AcceptRole: accept(); break; case QDialogButtonBox::ApplyRole: apply(); break; case QDialogButtonBox::RejectRole: reject(); // Fall-thru... default: break; } } // Check whether we're clear to close. bool qjackctlSetupForm::queryClose (void) { bool bQueryClose = true; // Check if there's any pending changes... if (m_iDirtySettings > 0 || m_iDirtyOptions > 0 || m_iDirtyBuffSize > 0) { switch (QMessageBox::warning(isVisible() ? this : parentWidget(), tr("Warning") + " - " QJACKCTL_TITLE, tr("Some settings have been changed.\n\n" "Do you want to apply the changes?"), QMessageBox::Apply | QMessageBox::Discard | QMessageBox::Cancel)) { case QMessageBox::Apply: apply(); break; case QMessageBox::Discard: discard(); break; default: // Cancel. bQueryClose = false; break; } } return bQueryClose; } // Notify our parent that we're emerging. void qjackctlSetupForm::showEvent ( QShowEvent *pShowEvent ) { qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); updateBuffSize(); updateDrivers(); stabilizeForm(); QDialog::showEvent(pShowEvent); } // Notify our parent that we're closing. void qjackctlSetupForm::hideEvent ( QHideEvent *pHideEvent ) { QDialog::hideEvent(pHideEvent); qjackctlMainForm *pMainForm = qjackctlMainForm::getInstance(); if (pMainForm) pMainForm->stabilizeFormEx(); } // end of qjackctlSetupForm.cpp qjackctl-1.0.4/src/PaxHeaders/palette0000644000000000000000000000013214771215054014544 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323701235 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/palette/0000755000175000001440000000000014771215054014611 5ustar00rncbcusersqjackctl-1.0.4/src/palette/PaxHeaders/KXStudio.conf0000644000000000000000000000013214771215054017202 xustar0030 mtime=1743067692.323701235 30 atime=1743067692.323701235 30 ctime=1743067692.323701235 qjackctl-1.0.4/src/palette/KXStudio.conf0000644000175000001440000000165514771215054017201 0ustar00rncbcusers[ColorThemes] KXStudio\AlternateBase=#0e0e0e, #0e0e0e, #0c0c0c KXStudio\Base=#070707, #070707, #060606 KXStudio\BrightText=#ffffff, #ffffff, #ffffff KXStudio\Button=#1c1c1c, #1c1c1c, #181818 KXStudio\ButtonText=#f0f0f0, #f0f0f0, #5a5a5a KXStudio\Dark=#818181, #818181, #818181 KXStudio\Highlight=#3c3c3c, #222222, #0e0e0e KXStudio\HighlightedText=#ffffff, #f0f0f0, #535353 KXStudio\Light=#bfbfbf, #bfbfbf, #bfbfbf KXStudio\Link=#6464e6, #6464e6, #22224a KXStudio\LinkVisited=#e664e6, #e664e6, #4a224a KXStudio\Mid=#5e5e5e, #5e5e5e, #5e5e5e KXStudio\Midlight=#9b9b9b, #9b9b9b, #9b9b9b KXStudio\NoRole=#000000, #000000, #000000 KXStudio\PlaceholderText=#000000, #000000, #000000 KXStudio\Shadow=#9b9b9b, #9b9b9b, #9b9b9b KXStudio\Text=#e6e6e6, #e6e6e6, #4a4a4a KXStudio\ToolTipBase=#040404, #040404, #040404 KXStudio\ToolTipText=#e6e6e6, #e6e6e6, #e6e6e6 KXStudio\Window=#111111, #111111, #0e0e0e KXStudio\WindowText=#f0f0f0, #f0f0f0, #535353 qjackctl-1.0.4/src/palette/PaxHeaders/Wonton Soup.conf0000644000000000000000000000013214771215054017663 xustar0030 mtime=1743067692.323773797 30 atime=1743067692.323701235 30 ctime=1743067692.323773797 qjackctl-1.0.4/src/palette/Wonton Soup.conf0000644000175000001440000000202614771215054017653 0ustar00rncbcusers[ColorThemes] Wonton%20Soup\AlternateBase=#434750, #434750, #3b3e46 Wonton%20Soup\Base=#3c4048, #3c4048, #34383f Wonton%20Soup\BrightText=#ffffff, #ffffff, #ffffff Wonton%20Soup\Button=#525863, #525863, #484d57 Wonton%20Soup\ButtonText=#d2def0, #d2def0, #6f7682 Wonton%20Soup\Dark=#282b31, #282b31, #23262b Wonton%20Soup\Highlight=#78889c, #515a67, #40444d Wonton%20Soup\HighlightedText=#d1e1f4, #b6c1d0, #616872 Wonton%20Soup\Light=#5f6572, #5f6572, #565c68 Wonton%20Soup\Link=#9cd4ff, #9cd4ff, #526677 Wonton%20Soup\LinkVisited=#4080ff, #4080ff, #364c77 Wonton%20Soup\Mid=#3f444c, #3f444c, #383b43 Wonton%20Soup\Midlight=#545a65, #545a65, #4b515b Wonton%20Soup\NoRole=#000000, #000000, #000000 Wonton%20Soup\PlaceholderText=#000000, #000000, #000000 Wonton%20Soup\Shadow=#1d1f23, #1d1f23, #191b1e Wonton%20Soup\Text=#d2def0, #d2def0, #636973 Wonton%20Soup\ToolTipBase=#b6c1d0, #b6c1d0, #b6c1d0 Wonton%20Soup\ToolTipText=#2a2c30, #2a2c30, #2a2c30 Wonton%20Soup\Window=#494e58, #494e58, #40444d Wonton%20Soup\WindowText=#b6c1d0, #b6c1d0, #616872