diff -Nru ubuntustudio-controls-1.12.6/AUTHORS ubuntustudio-controls-1.13/AUTHORS --- ubuntustudio-controls-1.12.6/AUTHORS 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/AUTHORS 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -Authors: Kaj Ailomaa - Len Ovens - Erich Eickmeyer -Copyright: Andrew Hunter, Luis de Bethencourt Guimera 2007 - Kaj Ailomaa 2012 - Len Ovens 2012-2020 - Erich Eickmeyer 2020 diff -Nru ubuntustudio-controls-1.12.6/COPYING ubuntustudio-controls-1.13/COPYING --- ubuntustudio-controls-1.12.6/COPYING 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/COPYING 1970-01-01 00:00:00.000000000 +0000 @@ -1,280 +0,0 @@ - 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 diff -Nru ubuntustudio-controls-1.12.6/debian/changelog ubuntustudio-controls-1.13/debian/changelog --- ubuntustudio-controls-1.12.6/debian/changelog 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/debian/changelog 2020-05-13 15:14:19.000000000 +0000 @@ -1,3 +1,9 @@ +ubuntustudio-controls (1.13) groovy; urgency=medium + + * Replaced by Studio Controls + + -- Erich Eickmeyer Wed, 13 May 2020 08:14:19 -0700 + ubuntustudio-controls (1.12.6) groovy; urgency=medium [ Len Ovens ] diff -Nru ubuntustudio-controls-1.12.6/debian/control ubuntustudio-controls-1.13/debian/control --- ubuntustudio-controls-1.12.6/debian/control 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/debian/control 2020-05-13 15:14:19.000000000 +0000 @@ -10,22 +10,8 @@ Package: ubuntustudio-controls Architecture: all -Depends: a2jmidid, - jackd2, - pulseaudio-module-jack, - python3-dbus, - python3-gi, - python3, - python3-jack-client, - zita-ajbridge, - qasmixer, - pavucontrol, - ${misc:Depends} -Suggests: carla -Conflicts: cadence -Description: Ubuntu Studio Controls - Ubuntu Studio Controls is a small application that enables/disables realtime - privilege for users and controls jackdbus. It allows Jackdbus to be run from - session start. It also will detect USB audio devices getting plugged in after - session start and optionally connect them to jackdbus as a client or switch - them in as jackdbus master. +Depends: studio-controls, ${misc:Depends} +Conflicts: ubuntstudio-controls (<< 1.13) +Replaces: ubuntustudio-controls (<< 1.13) +Description: Transitional Dummy Package for studio-controls + Transitional Dummy Package. This package is safe to remove. diff -Nru ubuntustudio-controls-1.12.6/debian/docs ubuntustudio-controls-1.13/debian/docs --- ubuntustudio-controls-1.12.6/debian/docs 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/debian/docs 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -AUTHORS -COPYING -notes.txt -README -ROADMAP diff -Nru ubuntustudio-controls-1.12.6/debian/ubuntustudio-controls.install ubuntustudio-controls-1.13/debian/ubuntustudio-controls.install --- ubuntustudio-controls-1.12.6/debian/ubuntustudio-controls.install 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/debian/ubuntustudio-controls.install 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -usr/ -lib/ diff -Nru ubuntustudio-controls-1.12.6/debian/ubuntustudio-controls.postinst ubuntustudio-controls-1.13/debian/ubuntustudio-controls.postinst --- ubuntustudio-controls-1.12.6/debian/ubuntustudio-controls.postinst 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/debian/ubuntustudio-controls.postinst 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/bin/sh - if [ -f "/etc/xdg/autostart/autojack.desktop" ]; then - rm /etc/xdg/autostart/autojack.desktop - fi -#Remove systemd service file for non-Ubuntu systems -rm /lib/systemd/system/studio-controls.service -#DEBHELPER# diff -Nru ubuntustudio-controls-1.12.6/lib/systemd/system/ondemand.service.d/ubuntustudio.conf ubuntustudio-controls-1.13/lib/systemd/system/ondemand.service.d/ubuntustudio.conf --- ubuntustudio-controls-1.12.6/lib/systemd/system/ondemand.service.d/ubuntustudio.conf 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/lib/systemd/system/ondemand.service.d/ubuntustudio.conf 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -[Service] - -ExecStart= -ExecStart=/lib/systemd/ubuntustudio diff -Nru ubuntustudio-controls-1.12.6/lib/systemd/system/studio-system.service ubuntustudio-controls-1.13/lib/systemd/system/studio-system.service --- ubuntustudio-controls-1.12.6/lib/systemd/system/studio-system.service 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/lib/systemd/system/studio-system.service 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -[Unit] -Description=Studio System CPU Governor Setting - -[Service] -Type=oneshot -ExecStart=/lib/systemd/ubuntustudio - -[Install] -WantedBy=multi-user.target diff -Nru ubuntustudio-controls-1.12.6/lib/systemd/ubuntustudio ubuntustudio-controls-1.13/lib/systemd/ubuntustudio --- ubuntustudio-controls-1.12.6/lib/systemd/ubuntustudio 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/lib/systemd/ubuntustudio 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -#!/bin/sh - -set -eu - -DESC="Ubuntustudio Controls" - -PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin - -ENABLE="true" -NO_TURBO="0" -GOVERNOR="ondemand" - -# we should check for the availablity of any setting we wish to change -check_turbo_avail() { - info="/sys/devices/system/cpu/intel_pstate/no_turbo" - if [ -f $info ]; then - return 0; - fi - return 1; -} - -# any setting in this file will override the above defaults. -# ubuntustudio-controls will normally write the defaults file -if [ -f /etc/default/ubuntustudio ] ; then - . /etc/default/ubuntustudio -fi - -# if not enabled then exit gracefully -[ "$ENABLE" = "true" ] || exit 0 -RETVAL=0 - -logger "${DESC}: Setting system settings" -if check_turbo_avail ; then - logger "${DESC}: Set no_turbo ${NO_TURBO}" - echo "${NO_TURBO}" | tee /sys/devices/system/cpu/intel_pstate/no_turbo || \ - RETVAL=$? - logger "${DESC}: ${RETVAL} " -else - logger "${DESC}: turbo/boost not available" -fi - -AVAILABLE="/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors" -[ -f $AVAILABLE ] || exit 0 -read governors < $AVAILABLE - -case "$GOVERNOR" in - performance) - case $governors in - *performance*) - GOVERNOR="performance" - ;; - *) - exit 0 - ;; - esac - ;; - *) - case $governors in - *ondemand*) - GOVERNOR="ondemand" - ;; - *powersave*) - GOVERNOR="powersave" - ;; - *) - exit 0 - ;; - esac - ;; -esac - -logger "${DESC}: Using ${GOVERNOR} governor" - -for CPUFREQ in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor - do - logger "${DESC}: setting ${GOVERNOR} for ${CPUFREQ}" - [ -f $CPUFREQ ] || continue - echo -n $GOVERNOR > $CPUFREQ - done -logger "${DESC}: Governor set finished" -exit 0 - diff -Nru ubuntustudio-controls-1.12.6/notes.txt ubuntustudio-controls-1.13/notes.txt --- ubuntustudio-controls-1.12.6/notes.txt 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/notes.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -Ubuntustudio-controls version 1.11.3 - -New for this version -- Bug fixes: check if device removed signal is true - Save last valid internal device so removing USB device - allows controls to switch to something sane. -- moved config file to it's own directory so that we can add - more files like post start scripts. -- Converted config file to use configparser for less accident prone - maintenance. -- Declutter audio setup GUI by splitting it into three tabs -- Pulse bridges can have custom names -- pulse bridges can have custom auto connects diff -Nru ubuntustudio-controls-1.12.6/README ubuntustudio-controls-1.13/README --- ubuntustudio-controls-1.12.6/README 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -UbuntuStudio Controls - -This is a small application to allow setting up audio for (semi)pro -audio work. - -The application first checks to see if application will have access to -memory locking and real time priorities. If not, a warning is displayed -and a checkbox allows repairing this. After repairing this the user needs -to log out and back in for the new setting to have effect, there is -a warning to this effect. - -It is assumed that jack will run at session start and not be stopped till -session end. However, it is possible to override this. - -USB mics have started to make their way into bedroom studios and have been -a problem with jack or ALSA oriented audio applications which expect -to work with only one audio device. The user expects to use their USB -mic for input and internal audio for monitoring. These two devices have -no way of being in sync with each other and in most cases can not be -used together. This application allows setting one jack device and adding -a second device as a jack client via zita-ajbridge. diff -Nru ubuntustudio-controls-1.12.6/ROADMAP ubuntustudio-controls-1.13/ROADMAP --- ubuntustudio-controls-1.12.6/ROADMAP 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/ROADMAP 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ - - This is Notes about developing this application, known bugs and - features to add. It is generally in order of importance... or at - least order to be worked on. (some later things rely on sooner - things) - -Bugs: - Fixed - Backends All use different commands to do the same things - fixed - zita needs to read in all rates - -Features: - - logrotate for shorter log files - - jack client should start once and detect jack stop callback - check DSP regularly and add xruns. - - jack detection when jack is stopped should only happen once - when entering audio settings page. - - add pre/post jack start/stop scripting - - add usb bridge and pulse bridge tabs - - USB bridge tab should have a way to set devices - not to bridge. - - pulse bridge should allow for naming bridges - - add drawing tablet support - - start with setting size and setting buttons - - add the rest of the supported backends - - add button to system page to select between lowlatency or generic - kernel as default. - - monitor headphone plug status if PCH is being used for output - switch to headphones or speakers in alsa. use alsa level/mute - controls but add hook for user script. This will involve - moving autojackrc into .config/autojack/ so new V3 for ping. - So two commits. - - add use of internals (net manager, audio and net adapters) - option to use audioadapter instead of zita bridge? - that may only work for one device, zita can do many. - - remove Cadence from autostart and Cadences pulseaudio config - Cadence will reinsert these if the user decides to use it again - but at least if controls is used PA should get set to stock. - Will also have to restart PA as Cadence disables respawn so - one start is needed to re-enable that. - - adding in stuff from https://github.com/jhernberg/udev-rtirq so that - hot plugged USB devices get higher priority. - - pulse profiles for multi-channels devices. (including jack) - This is really pulse related not -controls diff -Nru ubuntustudio-controls-1.12.6/testing ubuntustudio-controls-1.13/testing --- ubuntustudio-controls-1.12.6/testing 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/testing 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -TESTING Controls: -================= - -At present, controls should be tested for: - - defaults are correct (no config file) - both in running instance (autojack autostarts) - - check pavucontrol shows devices and sends sound through - and in GUI - - not in performance - - boost (if available) is on - Audio should show correct defaults - - config file in ~/.config/autojackrc is read and used. - in running instance - In GUI - when gui saves this file should vanish - - config file in ~/.config/autojack/autojackrc - in running instance - start jack - change everything make sure whats actually runnig echoes config - in GUI - Gui should show last config change diff -Nru ubuntustudio-controls-1.12.6/usr/bin/autojack ubuntustudio-controls-1.13/usr/bin/autojack --- ubuntustudio-controls-1.12.6/usr/bin/autojack 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/bin/autojack 1970-01-01 00:00:00.000000000 +0000 @@ -1,966 +0,0 @@ -#!/usr/bin/python3 -u - -# autojack - Monitors dbus for added audio devices (hot plugged USB audio intefaces) -# on detect it does one of three things: -# makes it the jack device -# makes it a jack client (via zita-ajbridge) -# nothing -# -# The mode is chosen from either the USBAUTO setting or if the device -# name is present in XDEV then slave mode is assumed. If DEV has the -# device name, then master is chosen. -# -# autojack also monitors dbus for messages from ubuntustudio-controls to: -# - stop jack -# - re/start jack -# - remove a USB device as jack master to allow safe device removal -# - reread ~/.config/autojackrc and apply any changes - -import os -from os.path import expanduser -import re -import time -from gi.repository import GLib -import dbus -import dbus.mainloop.glib -import subprocess -import signal -import configparser -import logging - -def get_dev_info(x): - '''uses audio device number to make a device structure with device - info. The layout is: - device[0] = device name as a string - device[1] = bool true is USB device - device[2] = number of sub devices (0 means MIDI only) - device[3 to n] = subdevice info as a list: - device[n][0] = sub device number (some devices skip...) - device[n][1] = bool has playback - device[n][2] = PID of playback user - device[n][3] = bool has capture - device[n][4] = PID of capture user - This structure is returned. If the device does not - exist, a minimal structure is still returned ["", False, 0]''' - device = [] - cname = "" - l_usb = False - sub = 0 - if os.path.exists(f"/proc/asound/card{str(x)}"): - if os.path.isfile(f"/proc/asound/card{str(x)}/id"): - with open(f"/proc/asound/card{str(x)}/id", "r") as card_file: - for line in card_file: - # only need one line - cname = line.rstrip() - else: - cname = str(x) - - if os.path.exists(f"/proc/asound/card{str(x)}/usbbus"): - l_usb = True - - device.append(cname) - device.append(l_usb) - device.append(sub) - - for y in range(0, 10): - subdevice = [] - cap = False - cap_pid = 0 - play = False - play_pid = 0 - if os.path.exists(f"/proc/asound/card{str(x)}/pcm{str(y)}p"): - play = True - if os.path.exists(f"/proc/asound/card{str(x)}/pcm{str(y)}p/sub0"): - with open(f"/proc/asound/card{str(x)}/pcm{str(y)}p/sub0/status", "r") as info_file: - for line in info_file: - if re.match("^owner_pid", line.rstrip()): - play_pid = int(line.rstrip().split(": ", 1)[1]) - - if os.path.exists(f"/proc/asound/card{str(x)}/pcm{str(y)}c"): - cap = True - if os.path.exists(f"/proc/asound/card{str(x)}/pcm{str(y)}c/sub0"): - with open(f"/proc/asound/card{str(x)}/pcm{str(y)}c/sub0/status", "r") as info_file: - for line in info_file: - if re.match("^owner_pid", line.rstrip()): - cap_pid = int(line.rstrip().split(": ", 1)[1]) - - if play or cap: - device[2] = device[2] + 1 - subdevice.append(y) - subdevice.append(play) - subdevice.append(play_pid) - subdevice.append(cap) - subdevice.append(cap_pid) - device.append(subdevice) - # change this to create a list, USB cards may have devices and subdevices - logging.debug(f"Device list: {str(device)}") - return device - - -def import_device_array(): - '''creates an array of device structures as per get_dev_info(), from - device 0 to the highest number device currently on the system. Missing - device numbers will still save a space in the case a USB device has - been removed and there is still a higher number so that array index - can be the same as the device number.''' - global devices - devices = [] - ndevs = 0 - - if os.path.exists("/proc/asound/cards"): - with open("/proc/asound/cards", "r") as cards_file: - for line in cards_file: - # need to find lines with:space/int/space[ - # ndevs = int from above - # last one is highest dev number - sub = line.rstrip()[1:] - sub2 = sub.split(" ") - if sub2[0].isdigit(): - ndevs = int(sub2[0]) - ndevs += 1 - for x in range(0, ndevs): - # card loop - device = [] - device = get_dev_info(x) - devices.append(device) - del device - - -def import_config(): - ''' sets default parmeters, then reads values from configuration file''' - global config - global def_config - global tab_conf - global config_path - global config_file - global zdev - global pulse_in - global pulse_out - global p_in_con - global p_out_con - zdev = [] - pulse_in = [] - pulse_out = [] - p_in_con = [] - p_out_con = [] - - config = configparser.ConfigParser() - def_config = config['DEFAULT'] - #tab_conf = config['TABLET'] - config_path = "~/.config/autojack" - config_file = "{path}/autojackrc".format(path=config_path) - old_config_file = "~/.config/autojackrc" - - # first set defaults - config['DEFAULT'] = { - 'JACK': "False", - 'DRIVER': "alsa", - 'CHAN-IN': "0", - 'CHAN-OUT': "0", - 'RATE': "48000", - 'FRAME': "1024", - 'PERIOD': "2", - 'ZFRAME': "512", - 'XDEV': "", - 'PULSE-IN': "pulse_in", - 'PULSE-OUT': "pulse_out", - 'PJ-IN-CON': '1', - 'PJ-OUT-CON': '1', - 'A2J': "True", - 'DEV': "0,0,0", - 'USBAUTO': "True", - 'USB-SINGLE': "False", - 'USBDEV': "", - "PULSE": "True", - "LOG-LEVEL": "15", - } - - config['TABLET'] = { - 'DEVICE': "", - 'BUTTON1': "", - 'BUTTON2': "", - 'BUTTON3': "", - 'BUTTON8': "", - 'BUTTON9': "", - 'BUTTON10': "", - 'BUTTON11': "", - 'BUTTON12': "", - 'BUTTON13': "", - 'BUTTON14': "", - 'BUTTON15': "", - 'BUTTON16': "", - 'POSITION': "", - 'PEN': "", - } - tab_conf = config['TABLET'] - - # read in autojack config file - c_file = expanduser(config_file) - if os.path.isfile(c_file): - # New config file exists, read it in - config.read(c_file) - else: - # New file did not exist, let's check for a legacy file - c_file = expanduser(old_config_file) - if os.path.isfile(c_file): - # Found the legacy config, let's load it - with open(c_file, "r") as rc_file: - for line in rc_file: - if re.match("^#", line): - continue - lsplit = line.rstrip().split("=", 1) - if lsplit[0] == "JACK": - def_config['JACK'] = lsplit[1] - elif lsplit[0] == "DRIVER": - def_config['DRIVER'] = lsplit[1] - elif lsplit[0] == "DEV": - def_config['DEV'] = lsplit[1] - elif lsplit[0] == "CHAN-IN": - def_config['CHAN-IN'] = lsplit[1] - elif lsplit[0] == "CHAN-OUT": - def_config['CHAN-OUT'] = lsplit[1] - elif lsplit[0] == "RATE": - def_config['RATE'] = lsplit[1] - elif lsplit[0] == "FRAME": - def_config['FRAME'] = lsplit[1] - elif lsplit[0] == "ZFRAME": - def_config['ZFRAME'] = lsplit[1] - elif lsplit[0] == "PERIOD": - def_config['PERIOD'] = lsplit[1] - elif lsplit[0] == "PULSE": - pulse = lsplit[1] - if pulse == 'True': - def_config['PULSE-IN'] = 'pulse_in' - def_config['PULSE-OUT'] = 'pulse_out' - else: - def_config['PULSE-IN'] = '' - def_config['PULSE-OUT'] = '' - elif lsplit[0] == "PULSE-IN": - pin = lsplit[1] - if pin: - def_config['PULSE-IN'] = 'pulse_in' - elif lsplit[0] == "PULSE-OUT": - pout = lsplit[1] - if pout: - def_config['PULSE-OUT'] = 'pulse_out' - elif lsplit[0] == "A2J": - def_config['A2J'] = lsplit[1] - elif lsplit[0] == "OUTPUT": - def_config['PJ-IN-CON'] = "1" - def_config['PJ-OUT-CON'] = "1" - elif lsplit[0] == "PORTS": - def_config['PJ-OUT-CON'] = f"{lsplit[1]}" - elif lsplit[0] == "XDEV": - def_config['XDEV'] = lsplit[1].strip('"') - zdev = def_config['XDEV'].strip('"').split() - elif lsplit[0] == "USBAUTO": - def_config['USBAUTO'] = lsplit[1] - elif lsplit[0] == "USB-SINGLE": - def_config['USB-SINGLE'] = lsplit[1] - elif lsplit[0] == "USBDEV": - def_config['USBDEV'] = lsplit[1] - - if def_config['DEV'] == "default": - def_config['DEV'] = "0,0,0" - zdev = def_config['XDEV'].strip('"').split() - pulse_in = def_config['PULSE-IN'].strip('"').split() - pulse_out = def_config['PULSE-OUT'].strip('"').split() - p_in_con = def_config['PJ-IN-CON'].strip('"').split() - p_out_con = def_config['PJ-OUT-CON'].strip('"').split() - if pulse_in == [] and pulse_out == []: - def_config['PULSE'] = "False" - - -def reconfig(): - '''reads values from configuration file and changes run to match. This tries - to do this without stopping jack if not needed''' - global devices - global zdev - global pulse_in - global pulse_out - global config - global def_config - - old_config = configparser.ConfigParser() - old_def_config = old_config['DEFAULT'] - old_config.read_dict(config) - oldzdev = zdev - oldpulse_in = pulse_in - oldpulse_out = pulse_out - import_config() - if def_config['LOG-LEVEL'] != old_def_config['LOG-LEVEL']: - logger = logging.getLogger() - logger.setLevel(int(def_config['LOG-LEVEL'])) - logging.debug(f"log level: {def_config['LOG-LEVEL']}") - - newlist = [def_config['JACK'], def_config['DRIVER'], def_config['CHAN-IN'], def_config['CHAN-OUT'], - def_config['RATE'], def_config['FRAME'], def_config['PERIOD'], def_config['DEV'], def_config['USBDEV']] - oldlist = [old_def_config['JACK'], old_def_config['DRIVER'], old_def_config['CHAN-IN'], old_def_config['CHAN-OUT'], - old_def_config['RATE'], old_def_config['FRAME'], old_def_config['PERIOD'], old_def_config['DEV'], - old_def_config['USBDEV']] - if newlist != oldlist: - config_start() - return - # if we got this far all the above params have not changed - if def_config['JACK'] == "False": - return - # no use checking anything else - - pulse_dirty = False - if def_config['PULSE-IN'] != old_def_config['PULSE-IN']: - pulse_dirty = True - disconnect_pa(old_def_config) - cp = subprocess.run(["/usr/bin/pactl", "unload-module", "module-jack-source"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"remove jackd_source: {cp.stdout.strip()}") - for piname in pulse_in: - def_config['PULSE'] = "True" - cp = subprocess.run(["/usr/bin/pactl", "load-module", "module-jack-source", f"client_name={piname}", - "channels=2", "connect=no"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Load jackd_source: {cp.stdout.strip()}") - - if def_config['PULSE-OUT'] != old_def_config['PULSE-OUT']: - if not pulse_dirty: - pulse_dirty = True - disconnect_pa(old_def_config) - cp = subprocess.run(["/usr/bin/pactl", "unload-module", "module-jack-sink"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"PA unload jack-sink: {cp.stdout.strip()}") - for poname in pulse_out: - def_config['PULSE'] = "True" - cp = subprocess.run(["/usr/bin/pactl", "load-module", "module-jack-sink", f"client_name={poname}", "channels=2", - "connect=no"], universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"PA load jack-sink: {cp.stdout.strip()}") - - if [def_config['PJ-IN-CON'], def_config['PJ-OUT-CON']] != [old_def_config['PJ-IN-CON'], old_def_config['PJ-OUT-CON']]: - # need to pass old_def_config - if not pulse_dirty: - pulse_dirty = True - disconnect_pa(old_def_config) - - if pulse_dirty: - connect_pa() - - if old_def_config['A2J'] != def_config['A2J']: - cp = subprocess.run(["/usr/bin/killall", "-9", "a2jmidid"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"kill old a2j: {cp.stdout.strip()}") - if def_config['A2J'] == "True": - # Can't add logging for background processes. Will show up in syslog - subprocess.Popen(["/usr/bin/a2jmidid", "-e"], shell=False).pid - - if [def_config['USBAUTO'], def_config['USB-SINGLE'], zdev] != [old_def_config['USBAUTO'], - old_def_config['USB-SINGLE'], - oldzdev]: - import_device_array() - for device in devices: - if device[3][2] and device[3][2] == device[3][4]: - # in and out are same PID this is jack master skip or device in use - continue - if device[1]: - # USB device - if def_config['USBAUTO'] != old_def_config['USBAUTO'] or def_config['USB-SINGLE'] != old_def_config[ - 'USB-SINGLE']: - kill_slave(f"{device[0]},0,0") - if def_config['USBAUTO'] == "True": - start_slave(f"{device[0]},0,0") - else: - # not USB device - if zdev != oldzdev: - tempname = "nothing" - dev_has_pid = False - for i in range(3, (device[2] + 3)): - tempname = f"{device[0]},{str(device[i][0])},0" - if device[i][2]: - dev_has_pid = True - if tempname in zdev: - if not dev_has_pid: - start_slave(tempname) - else: - kill_slave(tempname) - - -def config_start(): - ''' Pulls configuration and force restarts the world ''' - global last_master - global zdev - global pulse_in - global pulse_out - global def_config - - logging.info("Running: config_start()") - - import_config() - logger = logging.getLogger() - logger.setLevel(int(def_config['LOG-LEVEL'])) - logging.debug(f"log level: {def_config['LOG-LEVEL']}") - - # if at session start we should wait a few seconds for pulse - # to be fully running - time.sleep(2) - # Stop jack if running - cp = subprocess.run(["/usr/bin/killall", "-q", "-9", "jackdbus", "jackd", "a2jmidid"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Kill old Procs: {cp.stdout.strip()}") - if def_config['JACK'] == "False": - # restart Pulse - cp = subprocess.run(["/usr/bin/pulseaudio", "-k"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"JACK == {def_config['JACK']} restart pulse: {cp.stdout.strip()}") - return - - # Assume start of session where pulse may be fully loaded - # get rid of anything that can automatically interfere - cp = subprocess.run(["/usr/bin/pactl", "unload-module", "module-jackdbus-detect"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"remove jackdbus_detect: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/pactl", "unload-module", "module-udev-detect"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"remove module-udev-detect: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/pactl", "unload-module", "module-alsa-card"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"remove module-alsa-card: {cp.stdout.strip()}") - if os.path.exists(f"/proc/asound/{def_config['USBDEV'].split(',')[0]}") and def_config['USBDEV'] != "": - mdev = def_config['USBDEV'] - else: - mdev = def_config['DEV'] - # Now start jackdbus with the configured device - # the commands are all different so... - if def_config['DRIVER'] == "alsa": - cp = subprocess.run(["/usr/bin/jack_control", "ds", "alsa", "dps", "capture", "none", "dps", "playback", "none"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jackdbus: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/jack_control", "dps", "device", f"hw:{mdev}", "dps", "rate", def_config['RATE']], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jackdbus: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/jack_control", "dps", "period", def_config['FRAME'], "dps", "nperiods", - def_config['PERIOD'], "start"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jackdbus: {cp.stdout.strip()}") - elif def_config['DRIVER'] == "firewire": - cp = subprocess.run(["/usr/bin/jack_control", "ds", "firewire"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jackdbus: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/jack_control", "dps", "device", f"hw:{mdev}", "dps", "rate", def_config['RATE']], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jackdbus: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/jack_control", "dps", "period", def_config['FRAME'], "dps", "nperiods", - def_config['PERIOD'], "start"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jackdbus: {cp.stdout.strip()}") - elif def_config['DRIVER'] == "dummy": - cp = subprocess.run(["/usr/bin/jack_control", "ds", "dummy"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jackdbus: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/jack_control", "dps", "rate", def_config['RATE'], "dps" "period", def_config['FRAME']], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jackdbus: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/jack_control", "dps", "capture", def_config['CHAN-IN'], "dps", "playback", - def_config['CHAN-OUT'], "start"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jackdbus: {cp.stdout.strip()}") - else: - # we should never get here - logging.error("programming error! if you find this in your log file please file" + - "a bug report about: Driver not found") - last_master = mdev - # maybe check for jack up (need function?) - time.sleep(2) - - for piname in pulse_in: - def_config['PULSE'] = "True" - cp = subprocess.run(["/usr/bin/pactl", "load-module", "module-jack-source", f"client_name={piname}", - "channels=2", "connect=no"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Pulseaudio: {cp.stdout.strip()}") - for poname in pulse_out: - def_config['PULSE'] = "True" - cp = subprocess.run(["/usr/bin/pactl", "load-module", "module-jack-sink", f"client_name={poname}", "channels=2", - "connect=no"], universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Pulseaudio: {cp.stdout.strip()}") - - for cname in zdev: - if cname != "": - start_slave(cname) - - # not sure all these delays need to be here. Was checking with old pulse. - time.sleep(2) - - connect_pa() - if def_config['USBAUTO'] == "True": - import_device_array() - for device in devices: - if device[1]: - # this is a USB device - if f"{device[0]},0,0" != def_config['USBDEV']: - start_slave(f"{device[0]},0,0") - - if def_config['A2J'] == "True": - # Can't set up logging - subprocess.Popen(["/usr/bin/a2jmidid", "-e"], shell=False).pid - - -def connect_pa(): - '''connects pulse ports to the correct device ports. May have to - use zita-ajbridge to first make the correct device available.''' - global pulse_in - global pulse_out - global p_in_con - global p_out_con - - if (p_in_con == []) and (p_out_con == []): - return - - for i, pj_name in enumerate(pulse_in): - port2 = "" - port = p_in_con[i] - if port == "none" or port == "0": - continue - elif "left" in port: - port2 = f"{port[0-(len(port)-5)]}right" - elif port.isnumeric(): - p = int(port) - port = f"system:capture_{str(p)}" - port2 = f"system:capture_{str(p + 1)}" - else: - p = int(port[(port.rfind("_") + 1):]) + 1 - port2 = f"{port[0:port.rfind('_') + 1]}{p}" - cp = subprocess.run(["/usr/bin/jack_connect", port, f"{pj_name}:front-left"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jack connect to pulse in left: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/jack_connect", port2, f"{pj_name}:front-right"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Jack connect to pulse in right: {cp.stdout.strip()}") - - - for i, pj_name in enumerate(pulse_out): - port2 = "" - port = p_out_con[i] - if port == "none" or port == "0": - continue - elif "left" in port: - port2 = f"{port[0:(len(port)-5)]}right" - elif port.isnumeric(): - p = int(port) - port = f"system:playback_{str(p)}" - port2 = f"system:playback_{str(p + 1)}" - else: - p = int(port[(port.rfind("_") + 1):]) + 1 - port2 = f"{port[0:port.rfind('_') + 1]}{p}" - cp = subprocess.run(["/usr/bin/jack_connect", port, f"{pj_name}:front-left"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Pulse out left connect to jack: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/jack_connect", port2, f"{pj_name}:front-right"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Pulse out right connect to jack: {cp.stdout.strip()}") - - -def disconnect_pa(our_config): - '''disconnect Pulse ports we know we have connected. - The pa-jack bridge is left running.''' - p_in_con = our_config['PJ-IN-CON'].strip('"').split() - p_out_con = our_config['PJ-OUT-CON'].strip('"').split() - for i, name in enumerate(our_config['PULSE-IN'].strip('"').split()): - if int(p_in_con[i]): - cp = subprocess.run(["/usr/bin/jack_disconnect", f"{name}:front-left", - f"system:capture_{p_in_con[i]}"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"jack dissconnect PA: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/jack_disconnect", f"{name}:front-right", - f"system:capture_{str(int(p_in_con[i]) + 1)}"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"jack dissconnect PA: {cp.stdout.strip()}") - - for i, name in enumerate(our_config['PULSE-OUT'].strip('"').split()): - if int(p_out_con[i]): - cp = subprocess.run(["/usr/bin/jack_disconnect", f"{name}:front-left", - f"system:playback_{p_out_con[i]}"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"jack dissconnect PA: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/jack_disconnect", f"{name}:front-right", - f"system:playback_{str(int(p_out_con[i]) + 1)}"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"jack dissconnect PA: {cp.stdout.strip()}") - - -def msg_cb_new(*args, **kwargs): - '''call back for udev sensing new device. checks if device is audio. - checks if device is USB. If both are true and configuration is to - use this device, the device is either connected with zita-ajbridge - or becomes jack's master device''' - global devices - global last_master - global def_config - - if def_config['JACK'] == "False": - # then we don't care - return - - import_config() - - if args[0].find("sound-card") >= 0: - # remake database - import_device_array() - a_if = args[0].split("sound-card", 1) - audio_if = a_if[1].split(".", 1)[0] - device = devices[int(audio_if)] - # make sure device is USB and is not midi only - if device[1] and device[2]: - # tell gui devicelist has changed so it can up date device dropdowns - subprocess.run(["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.usb_signal"], - shell=False) - - cid = f"{device[0]},0,0" - logging.info(f" device = {cid} play:{str(device[3][1])} capture:{str(device[3][3])}") - if cid == last_master: - # spurious indication, ignore - logging.debug(f" We already have that device - spurious signal, ignoring") - return - if def_config['JACK'] == "True" and def_config['DRIVER'] == "alsa": - if def_config['USBDEV'] == cid: - # change_jack_master(cid, "sm") - logging.debug(f"Changing jack master to: {cid}") - config_start() - last_master = cid - time.sleep(1) - start_slave(def_config['DEV']) - time.sleep(1) - # connect_pa() - elif def_config['USBAUTO'] == "True": - start_slave(cid) - - -def msg_cb_removed(*args, **kwargs): - ''' dbus call back when a USB device removal has been detected by udev ''' - global devices - global last_master - global def_config - - if def_config['JACK'] == "False": - # then we don't care - return - - import_config() - - if args[0].find("sound-card") >= 0: - # tell gui devicelist has changed - subprocess.run(["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.usb_signal"], - shell=False) - - a_if = args[0].split("sound-card", 1) - audio_if = a_if[1].split(".", 1)[0] - logging.info(f"sound card: hw:{audio_if} removed") - if os.path.exists(f"/proc/asound/card{str(audio_if)}"): - # Hmm, I guess it hasn't really gone, false alarm - logging.debug(f"Device is still here - signal ignored") - return - - device = devices[int(audio_if)] - cid = f"{device[0]},0,0" - if def_config['JACK'] == "True": - if not device[1]: - # not a usb device - return - if def_config['USBDEV'] == cid: - if last_master == def_config['USBDEV']: - kill_slave(def_config['DEV']) - time.sleep(1) - config_start() - elif def_config['USBAUTO'] == "True": - kill_slave(cid) - import_device_array() - - -def get_card_rate(filename, l_usb): - ''' Takes a filename and searches for lines that include the word: - Rates or rates. From each of those lines any numbers are takes and - compared to the list of rates already found and added to that list if - it is not already there. The return is the closest rate to jack - master sample rate''' - global def_config - - dsr = def_config['RATE'] - full_list = [] - if os.path.isfile(filename): - with open(filename, "r") as card_file: - for line in card_file: - srlist = [] - if 'Rates' in line: - srlist = line.rstrip().split() - elif 'rates' in line: - srlist = line.rstrip().split() - if srlist != []: - for word in srlist: - word = word.strip(',') - if word.isdigit(): - if word not in full_list: - full_list.append(word) - # full_list should have a list of all sample rates - esr = lsr = 0 - hsr = 1000000 - if not l_usb: - hsr = 48000 - lsr = 44100 - for word in full_list: - if int(word) > hsr: - continue - if int(word) < lsr: - continue - if int(word) < int(def_config['RATE']): - if int(word) > lsr: - lsr = int(word) - elif int(word) > int(def_config['RATE']): - if int(word) < hsr: - hsr = int(word) - elif int(word) == int(def_config['RATE']): - esr = int(word) - if not esr: - if hsr < int(def_config['RATE']): - dsr = str(hsr) - elif lsr > int(def_config['RATE']): - dsr = str(lsr) - elif (hsr - int(def_config['RATE'])) < (int(def_config['RATE']) - lsr): - dsr = str(hsr) - else: - dsr = str(lsr) - return dsr - - -def start_slave(ldev): - ''' takes the audio device as a parameter and starts a bridge - from that device to jack ''' - global devices - global def_config - global procs - - dsr = def_config['RATE'] - import_device_array() - dname, l_dev, sub = ldev.split(",", 2) - for device in devices: - if device[0] == dname and device[2] > int(l_dev): - if device[3 + int(l_dev)][1]: - if device[1]: - # this is usb devices we should find /proc/dname/stream? - if os.path.isfile(f"/proc/asound/{dname}/stream0"): - dsr = get_card_rate(f"/proc/asound/{dname}/stream0", True) - logging.info(f"Got {dsr} as the closest rate to {def_config['RATE']}") - if def_config['USB-SINGLE'] == "False": - procout = subprocess.Popen( - ["/usr/bin/zita-j2a", "-j", f"{ldev}-out", "-d", f"hw:{ldev}", "-r", dsr, "-p", - def_config['ZFRAME'], "-n", def_config['PERIOD'], "-c", "100"], shell=False) - pidout = procout.pid - procs.append(procout) - device[3 + int(l_dev)][2] = pidout - else: - # this is internal and so we look at /proc/dname/codec* if it is a file - if os.path.isfile(f"/proc/asound/{dname}/codec#0"): - dsr = get_card_rate(f"/proc/asound/{dname}/codec#0", False) - logging.info(f"Got {dsr} as the closest rate to {def_config['RATE']}") - procout = subprocess.Popen( - ["/usr/bin/zita-j2a", "-j", f"{ldev}-out", "-d", f"hw:{ldev}", "-r", dsr, "-p", - def_config['ZFRAME'], "-n", def_config['PERIOD'], "-c", "100"], shell=False) - pidout = procout.pid - procs.append(procout) - device[3 + int(l_dev)][2] = pidout - if device[3 + int(l_dev)][3]: - procin = subprocess.Popen( - ["/usr/bin/zita-a2j", "-j", f"{ldev}-in", "-d", f"hw:{ldev}", "-r", dsr, "-p", def_config['ZFRAME'], - "-n", def_config['PERIOD'], "-c", "100"], shell=False) - pidin = procin.pid - procs.append(procin) - device[3 + int(l_dev)][4] = pidin - - -def kill_slave(ldev): - ''' takes the device as a parameter and if the device exists - and is bridged to jack, stops the bridge ''' - global devices - global procs - # XXXX need to separate out dev and subdev like above. - dname, l_dev, sub = ldev.split(",", 2) - for device in devices: - if device[0] == dname and device[2]: - if device[3 + int(l_dev)][2]: - for i, pr in enumerate(procs): - if pr.pid == device[3 + int(l_dev)][2]: - logging.debug(f"kill {str(dname)} sub: {str(l_dev)} PID: {str(device[3 + int(l_dev)][2])}") - pr.send_signal(signal.SIGINT) - try: - rt = pr.wait(timeout=15) - except TimeoutExpired: - logging.debug(f"kill PID: {str(device[3 + int(l_dev)][2])} failed") - pr.terminate() - outs, errs = pr.communicate() - del procs[i] - if device[3 + int(l_dev)][4]: - for i, pr in enumerate(procs): - if pr.pid == device[3 + int(l_dev)][4]: - logging.info(f"kill {str(dname)} sub: {str(l_dev)} PID: {str(device[3 + int(l_dev)][4])}") - pr.send_signal(signal.SIGINT) - try: - rt = pr.wait(timeout=15) - except TimeoutExpired: - logging.debug(f"kill PID: {str(device[3 + int(l_dev)][4])} failed") - pr.terminate() - outs, errs = pr.communicate() - del procs[i] - - -def ses_cb_quit(*args, **kwargs): - ''' dbus call back when quit signal caught. This is for use in - testing and the GUI never sends this. ''' - logging.warning("Got quit signal.") - cp = subprocess.run(["/usr/bin/killall", "-9", "jackdbus", "jackd", "a2jmidid"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Kill jack and friends: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/pulseaudio", "-k"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Restart PA: {cp.stdout.strip()}") - os._exit(0) - - -def handler(signum, frame): - ''' a handler for system signals that may be sent by the system. - we want to trap sigint, sigkill and sigterm and do the same as - above. ''' - logging.warning(f"Got signal number: {str(signum)} - Dying.") - cp = subprocess.run(["/usr/bin/killall", "-9", "jackdbus", "jackd", "a2jmidid"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Kill jack and friends: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/pulseaudio", "-k"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Restart PA: {cp.stdout.strip()}") - os._exit(0) - - -def ses_cb_stop(*args, **kwargs): - ''' dbus call back when stop signal caught. This stops jack. ''' - logging.info("Got stop signal.") - cp = subprocess.run(["/usr/bin/killall", "-9", "jackdbus", "jackd", "a2jmidid"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Kill jack and friends: {cp.stdout.strip()}") - cp = subprocess.run(["/usr/bin/pulseaudio", "-k"], - universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) - logging.debug(f"Restart PA: {cp.stdout.strip()}") - - -def ses_cb_start(*args, **kwargs): - ''' dbus call back when (re)start signal caught''' - logging.info("Got start signal.") - config_start() - - -def ses_cb_config(*args, **kwargs): - ''' dbus call back when config signal caught ''' - logging.info("Got config signal.") - reconfig() - - -def ses_cb_tablet(*args, **kwargs): - ''' dbus call back when tablet signal caught - This reads the config file and sets the tablet - buttons, pen and size/position''' - global tab_conf - logging.info("Got tablet signal.") - import_config() - ''' - 'DEVICE': "", - device is a dual number like 256c:006e - for setting it becomes: 'HID 256c:006e Pad pad' - how we save it will depend on how it gets listed - 'BUTTON1': "", normally the top button 'undo' - 'BUTTON2': "", - 'BUTTON3': "", - buttons 4,5,6,7 extra - 'BUTTON8': "", - 'BUTTON9': "", - 'BUTTON10': "", - 'BUTTON11': "", - 'BUTTON12': "", - 'BUTTON13': "", - 'BUTTON14': "", - 'BUTTON15': "", - 'BUTTON16': "", - ''' - position = tab_conf['POSITION'].strip('"').split() - pen = tab_conf['PEN'].strip('"').split() - - -def ses_cb_ping(*args, **kwargs): - ''' dbus call back when config signal caught ''' - logging.info("Got ping signal.") - time.sleep(3) - subprocess.run(["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.V3_1_signal"], - shell=False) - - -def main(): - ''' Autojack runs at session start and manages audio for the session. - this is the daemon for ubuntustudio-controls''' - global last_master - global procs - procs = [] - last_master = "" - # set up logging - logpath = expanduser("~/.log") - # make sure the logfile directory exists - if not os.path.exists(logpath): - os.makedirs(logpath) - logfile = expanduser("~/.log/autojack.log") - if os.path.isfile(logfile): - os.replace(logfile, f"{logfile}.old") - - logging.basicConfig(filename=logfile, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.DEBUG) - logging.info('logging online') - dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) - signal.signal(signal.SIGHUP, handler) - signal.signal(signal.SIGINT, handler) - signal.signal(signal.SIGQUIT, handler) - signal.signal(signal.SIGILL, handler) - signal.signal(signal.SIGTRAP, handler) - signal.signal(signal.SIGABRT, handler) - signal.signal(signal.SIGBUS, handler) - signal.signal(signal.SIGFPE, handler) - #signal.signal(signal.SIGKILL, handler) - signal.signal(signal.SIGUSR1, handler) - signal.signal(signal.SIGSEGV, handler) - signal.signal(signal.SIGUSR2, handler) - signal.signal(signal.SIGPIPE, handler) - signal.signal(signal.SIGALRM, handler) - signal.signal(signal.SIGTERM, handler) - subprocess.run(["/usr/bin/dbus-send", "--type=signal", "/", - "org.ubuntustudio.control.event.quit_signal"], shell=False) - logging.info('kill other autojack intances') - time.sleep(3) - - config_start() - import_device_array() - system_bus = dbus.SystemBus() - system_bus.add_signal_receiver(msg_cb_new, dbus_interface='org.freedesktop.systemd1.Manager', signal_name='UnitNew') - system_bus.add_signal_receiver(msg_cb_removed, dbus_interface='org.freedesktop.systemd1.Manager', - signal_name='UnitRemoved') - - user_bus = dbus.SessionBus() - user_bus.add_signal_receiver(ses_cb_stop, dbus_interface='org.ubuntustudio.control.event', - signal_name='stop_signal') - user_bus.add_signal_receiver(ses_cb_start, dbus_interface='org.ubuntustudio.control.event', - signal_name='start_signal') - user_bus.add_signal_receiver(ses_cb_config, dbus_interface='org.ubuntustudio.control.event', - signal_name='config_signal') - user_bus.add_signal_receiver(ses_cb_ping, dbus_interface='org.ubuntustudio.control.event', - signal_name='ping_signal') - user_bus.add_signal_receiver(ses_cb_tablet, dbus_interface='org.ubuntustudio.control.event', - signal_name='tablet_signal') - user_bus.add_signal_receiver(ses_cb_quit, dbus_interface='org.ubuntustudio.control.event', - signal_name='quit_signal') - - subprocess.run(["/usr/bin/dbus-send", "--type=signal", "/", - "org.ubuntustudio.control.event.V3_1_signal"], shell=False) - - loop = GLib.MainLoop() - loop.run() - - -if __name__ == '__main__': - main() diff -Nru ubuntustudio-controls-1.12.6/usr/bin/ubuntustudio-controls ubuntustudio-controls-1.13/usr/bin/ubuntustudio-controls --- ubuntustudio-controls-1.12.6/usr/bin/ubuntustudio-controls 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/bin/ubuntustudio-controls 1970-01-01 00:00:00.000000000 +0000 @@ -1,988 +0,0 @@ -#!/usr/bin/python3 - -import gi - -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk, GLib, Gdk -import os -from os.path import expanduser -import getpass -import pwd -import re -import resource -import shutil -import subprocess -import glob -import dbus -from dbus.mainloop.glib import DBusGMainLoop -import time -import jack -import configparser - -DBusGMainLoop(set_as_default=True) - - -class SysInfo: - """Get information about the system""" - - # get info about if rtaccess is setup right - def user_audio(self): - """Checks if current user is in the audio group, or not""" - # create a list of users who are members of audio group: - with open("/etc/group", "r") as groups_file: - for line in groups_file: - if re.match("^audio:", line): - audio_users = line.split(':')[3].rstrip().split(',') - - user = getpass.getuser() - audio_group = False - if user in audio_users: - audio_group = True - - return audio_group - - def check_pam_files(self): - '''Checks for the existence of two files''' - jack_file_exists = False - if os.path.isfile("/etc/security/limits.d/audio.conf"): - jack_file_exists = True - return jack_file_exists - - def check_rlimits(self): - """returns hard rlimit values for RTPRIO and MEMLOCK""" - return resource.getrlimit(resource.RLIMIT_RTPRIO)[1], resource.getrlimit(resource.RLIMIT_MEMLOCK)[1] - - # System tweaks - def get_performance(self): - '''Checks for current cpu governor''' - in_performance = False - if os.path.isfile("/sys/devices/system/cpu/cpufreq/policy0/scaling_governor"): - with open("/sys/devices/system/cpu/cpufreq/policy0/scaling_governor", "r") as perform_file_test: - for line in perform_file_test: - if re.match("performance", line.rstrip()): - in_performance = True - return in_performance - - def get_boosted(self): - '''Checks for Intel boost state''' - boosted = False - boost_path = "/sys/devices/system/cpu/intel_pstate/no_turbo" - if os.path.exists(boost_path): - with open(boost_path, "r") as boost_test: - for line in boost_test: - if re.match("0", line.rstrip()): - boosted = True - return boosted - - # Audio stuff - - -class RTSetup: - # defs for doing things - def __init__(self): - self.enabled_path = "/etc/security/limits.d/audio.conf" - self.disabled_path = "/etc/security/limits.d/audio.conf.disabled" - self.backup_file = "/usr/share/ubuntustudio-controls/audio.conf" - - def set_governor(self, enable): - if enable == True: - gov = "performance" - else: - if os.path.exists("/sys/devices/system/cpu/intel_pstate"): - gov = "powersave" - else: - gov = "ondemand" - subprocess.run(["/usr/bin/pkexec", "/usr/sbin/ubuntustudio-system", gov], shell=False) - - def set_boost(self, enable): - boost_path = "/sys/devices/system/cpu/intel_pstate/no_turbo" - if os.path.exists(boost_path): - if enable == True: - subprocess.run(["/usr/bin/pkexec", "/usr/sbin/ubuntustudio-system", "boost"], shell=False) - else: - subprocess.run(["/usr/bin/pkexec", "/usr/sbin/ubuntustudio-system", "noboost"], shell=False) - - -class UbuntuStudioControls: - config = configparser.ConfigParser() - def_config = config['DEFAULT'] - #tab_conf = config['TABLET'] - config_path = "~/.config/autojack" - config_file = "{path}/autojackrc".format(path=config_path) - old_config_file = "~/.config/autojackrc" - - def __init__(self): - '''Activate the SysInfo class''' - # this is a long chunk of code that initializes every thing - # it should probably be split into tabs at least - self.sysinfo = SysInfo() - '''Create the GUI''' - builder = Gtk.Builder() - builder.add_from_file("/usr/share/ubuntustudio-controls/ubuntustudio-controls.glade") - '''Get windows''' - self.window_main = builder.get_object('window_main') - self.window_help = builder.get_object('window_help') - self.message_dialog_changes_info = builder.get_object('message_dialog_changes_info') - self.message_dialog_rt_info = builder.get_object('message_dialog_rt_info') - self.message_dialog_changes_info.set_transient_for(self.window_main) - self.message_dialog_rt_info.set_transient_for(self.window_main) - self.button_msg_ok = builder.get_object('button_msg_ok') - '''Get buttons for system tab''' - self.rt_button = builder.get_object('rt_button') - self.rt_warning = builder.get_object('rt_warning') - self.combo_governor = builder.get_object('combo_governor') - self.combo_boost = builder.get_object('combo_boost') - self.logging_comb = builder.get_object('logging_comb') - '''audio tab stuff''' - '''master tab''' - self.jack_device_combo = builder.get_object('jack_device_combo') - self.jack_usb_dev_combo = builder.get_object('jack_usb_dev_combo') - self.chan_in_spin = builder.get_object('chan_in_spin') - self.chan_out_spin = builder.get_object('chan_out_spin') - self.jack_rate_combo = builder.get_object('jack_rate_combo') - self.combobox_late = builder.get_object('combobox_late') - self.combo_periods = builder.get_object('combo_periods') - self.combo_backend = builder.get_object('combo_backend') - self.jack_midi_check = builder.get_object('jack_midi_check') - self.jack_ind = builder.get_object('jack_ind') - self.jack_state = builder.get_object('jack_state') - self.dsp_label = builder.get_object('dsp_label') - self.xrun_lab = builder.get_object('xrun_lab') - - '''extra tab''' - self.usb_plug_check = builder.get_object('usb_plug_check') - self.usb_single_ck = builder.get_object('usb_single_ck') - self.combo_zita_add = builder.get_object('combo_zita_add') - self.combo_zita_remove = builder.get_object('combo_zita_remove') - - '''pulse tab''' - self.pj_in_combo = builder.get_object('pj_in_combo') - self.pj_out_combo = builder.get_object('pj_out_combo') - self.pj_in_name = builder.get_object('pj_in_name') - self.pj_out_name = builder.get_object('pj_out_name') - self.pj_in_con = builder.get_object('pj_in_con') - self.pj_out_con = builder.get_object('pj_out_con') - - '''Dbus monitoring''' - user_bus = dbus.SessionBus() - user_bus.add_signal_receiver(self.db_ses_cb, dbus_interface='org.ubuntustudio.control.event', - signal_name='V3_1_signal') - user_bus.add_signal_receiver(self.db_new_usb, dbus_interface='org.ubuntustudio.control.event', - signal_name='usb_signal') - - '''Check if audio.conf and/or audio.conf.disabled exists, returns are true or false''' - self.rt_file = False - self.jack_file_exists = self.sysinfo.check_pam_files() - if self.jack_file_exists and self.sysinfo.user_audio(): - rtprio, memlock = self.sysinfo.check_rlimits() - if rtprio == 0: - self.rt_button.set_label("Logout required") - self.rt_button.set_sensitive(False) - self.message_dialog_rt_info.show() - self.rt_warning.set_text("Session restart required for Real Time Permissions") - else: - # turn off warning text, check on, deactivate - self.rt_warning.set_text("") - self.rt_button.set_label("Real Time Permissions Enabled") - self.rt_button.set_sensitive(False) - - # show current CPU Governor - self.combo_governor.append_text("Performance") - if os.path.exists("/sys/devices/system/cpu/intel_pstate/"): - self.combo_governor.append_text("Powersave") - else: - self.combo_governor.append_text("Ondemand") - self.in_performance = self.sysinfo.get_performance() - if self.in_performance: - self.combo_governor.set_active(0) - else: - self.combo_governor.set_active(1) - - # show boost state - if os.path.exists("/sys/devices/system/cpu/intel_pstate/no_turbo"): - self.boosted = self.sysinfo.get_boosted() - if self.boosted: - self.combo_boost.set_active(1) - else: - self.combo_boost.set_active(0) - else: - self.combo_boost.set_sensitive(False) - - # Audio stuff - - # first set defaults - self.config['DEFAULT'] = { - 'JACK': 'False', - 'DRIVER': "alsa", - 'CHAN-IN': '0', - 'CHAN-OUT': '0', - 'RATE': "48000", - 'FRAME': "1024", - 'PERIOD': "2", - 'ZFRAME': "512", - 'XDEV': "", - 'PULSE-IN': 'pulse_in', - 'PULSE-OUT': 'pulse_out', - 'PJ-IN-CON': '1', - 'PJ-OUT-CON': '1', - 'A2J': "True", - 'DEV': "0,0,0", - 'USBAUTO': "True", - 'USB-SINGLE': "False", - 'USBDEV': "", - 'LOG-LEVEL': "19", - } - - global autojack - global newusb - global jack_alive - global jack_died - global xrun_count - global max_in - global max_out - max_in = 18 - max_out = 18 - xrun_count = 0 - autojack = False - newusb = False - jack_alive = False - jack_died = False - self.dirty = False - - # read in autojack config file - c_file = expanduser(self.config_file) - if os.path.isfile(c_file): - # New config file exists, read it in - self.config.read(c_file) - else: - # New file did not exist, let's check for a legacy file - c_file = expanduser(self.old_config_file) - if os.path.isfile(c_file): - # Found the legacy config, let's load it - with open(c_file, "r") as rc_file: - for line in rc_file: - if re.match("^#", line): - continue - lsplit = line.rstrip().split("=", 1) - if lsplit[0] == "JACK": - self.def_config['JACK'] = lsplit[1] - elif lsplit[0] == "DRIVER": - self.def_config['DRIVER'] = lsplit[1] - elif lsplit[0] == "DEV": - self.def_config['DEV'] = self.dev_desc = lsplit[1] - elif lsplit[0] == "CHAN-IN": - self.def_config['CHAN-IN'] = lsplit[1] - elif lsplit[0] == "CHAN-OUT": - self.def_config['CHAN-OUT'] = lsplit[1] - elif lsplit[0] == "RATE": - self.def_config['RATE'] = lsplit[1] - elif lsplit[0] == "FRAME": - self.def_config['FRAME'] = lsplit[1] - elif lsplit[0] == "ZFRAME": - self.def_config['ZFRAME'] = lsplit[1] - elif lsplit[0] == "PERIOD": - self.def_config['PERIOD'] = lsplit[1] - elif lsplit[0] == "PULSE": - pulse = lsplit[1] - if pulse == 'True': - self.def_config['PULSE-IN'] = 'pulse_in' - self.def_config['PULSE-OUT'] = 'pulse_out' - elif lsplit[0] == "PULSE-IN": - pin = lsplit[1] - if pin: - self.def_config['PULSE-IN'] = 'pulse_in' - elif lsplit[0] == "PULSE-OUT": - pout = lsplit[1] - if pout: - self.def_config['PULSE-OUT'] = 'pulse_out' - elif lsplit[0] == "A2J": - self.def_config['A2J'] = lsplit[1] - elif lsplit[0] == "OUTPUT": - self.def_config['PJ-IN-CON'] = "1" - self.def_config['PJ-OUT-CON'] = "1" - elif lsplit[0] == "PORTS": - self.def_config['PJ-OUT-CON'] = lsplit[1] - elif lsplit[0] == "XDEV": - self.def_config['XDEV'] = lsplit[1].strip('"') - self.zdev = self.def_config['XDEV'].strip('"').split() - elif lsplit[0] == "USBAUTO": - self.def_config['USBAUTO'] = lsplit[1] - elif lsplit[0] == "USB-SINGLE": - self.def_config['USB-SINGLE'] = lsplit[1] - elif lsplit[0] == "USBDEV": - self.def_config['USBDEV'] = lsplit[1] - self.zdev = self.def_config['XDEV'].strip('"').split() - self.pulse_in = self.def_config['PULSE-IN'].strip('"').split() - self.pulse_out = self.def_config['PULSE-OUT'].strip('"').split() - self.p_in_con = self.def_config['PJ-IN-CON'].strip('"').split() - self.p_out_con = self.def_config['PJ-OUT-CON'].strip('"').split() - - # Find out if jack is running - try: - client = jack.Client('controls', False, True) - self.def_config['JACK'] = "True" - client.close() - except jack.JackError: - self.def_config['JACK'] = "False" - - self.logging_comb.set_active_id(self.def_config['LOG-LEVEL']) - # fill in Jack master widgets - self.jack_rate_combo.set_active_id(self.def_config['RATE']) - self.combobox_late.set_active_id(self.def_config['FRAME']) - self.combo_periods.set_active_id(self.def_config['PERIOD']) - self.combo_backend.set_active_id(self.def_config['DRIVER']) - self.chan_in_spin.set_range(0, 128) - self.chan_out_spin.set_range(0, 128) - self.chan_in_spin.set_value(self.def_config.getint('CHAN-IN')) - self.chan_out_spin.set_value(self.def_config.getint('CHAN-OUT')) - self.jack_midi_check.set_active(self.def_config['A2J'] == "True") - # Fill Extra devices widgets - self.usb_plug_check.set_active(self.def_config['USBAUTO'] == "True") - if self.def_config['USBAUTO'] == "True": - self.usb_single_ck.set_sensitive(True) - self.usb_single_ck.set_active(self.def_config['USB-SINGLE'] == "True") - else: - self.usb_single_ck.set_sensitive(False) - self.usb_single_ck.set_active(self.def_config['USB-SINGLE'] == "True") - - - self.refresh_dropdowns() - self.i_in = 0 - self.i_out = 0 - self.refresh_pulse_tab(self.i_in, self.i_out) - - handlers = { - "on_window_main_delete_event": self.on_window_main_delete_event, - "on_window_help_delete_event": self.on_window_help_delete_event, - "on_main_button_cancel_clicked": self.on_main_button_cancel_clicked, - "on_main_button_help_clicked": self.on_main_button_help_clicked, - "combo_governor_changed_cb": self.combo_governor_changed_cb, - "combo_boost_changed_cb": self.combo_boost_changed_cb, - "logging_change": self.logging_changed, - "rt_button_hit": self.rt_button_hit, - "on_button_msg_ok_clicked": self.on_button_msg_ok_clicked, - "on_button_rt_info_ok_clicked": self.on_button_rt_info_ok_clicked, - "on_button_help_ok_clicked": self.on_button_help_ok_clicked, - - "jack_device_changed": self.jack_device_changed, - "usb_master_changed": self.usb_master_changed, - "jack_driver_changed": self.jack_driver_changed, - "xrun_reset": self.xrun_reset, - "cb_jack_start": self.cb_jack_start, - "cb_jack_stop": self.cb_jack_stop, - "cb_audio_apply": self.cb_audio_apply, - "mixer_cb": self.mixer_cb, - "pavucontrol_cb": self.pavucontrol_cb, - "carla_cb": self.carla_cb, - - "cb_zita_add": self.cb_zita_add, - "cb_zita_remove": self.cb_zita_remove, - "usb_plug_cb": self.usb_plug_cb, - - "pj_in_combo_cb": self.pj_in_combo_cb, - "pj_out_combo_cb": self.pj_out_combo_cb, - "pj_in_add_cb": self.pj_in_add_cb, - "pj_out_add_cb": self.pj_out_add_cb, - "pj_in_rem_cb": self.pj_in_rem_cb, - "pj_out_rem_cb": self.pj_out_rem_cb, - "pj_in_name_cb": self.pj_in_name_cb, - "pj_out_name_cb": self.pj_out_name_cb, - - } - builder.connect_signals(handlers) - - self.rtsetup = RTSetup() - self.timeout_id = GLib.timeout_add(500, self.check_jack_status, None) - - def db_ses_cb(*args, **kwargs): - ''' this means we got a responce from autojack, Good''' - global autojack - autojack = True - print("autojack is running") - - def db_new_usb(*args, **kwargs): - ''' Autojack tells us a USB audio device has been plugged in or - unplugged. ''' - global newusb - newusb = True - print("autojack sees usb change") - - def check_jack_status(self, user_data): - '''Check if jack has died and the client needs to be - closed. Check if jack is running then set jack status indicator. - Check to see if the device lists have changed - and update the gui if so. Updating GUI prevents race with - secondary updates caused by updating''' - # these variables need to be global as they are used by callbacks - global newusb - global jack_client - global jack_alive - global jack_died - global xrun_count - global max_in - global max_out - - # sent by jackdied() callback - if jack_died: - jack_client.deactivate() - jack_client.close() - max_in = 18 - max_out = 18 - self.dirty = True - jack_died = False - jack_alive = False - - # device changed, update GUI - if self.dirty or newusb: - self.refresh_dropdowns() - self.dirty = False - newusb = False - - if jack_alive: - load = jack_client.cpu_load() - self.dsp_label.set_text(f"DSP: {str(load)[0:4]}%") - self.xrun_lab.set_text(f" {str(xrun_count)}") - else: - self.dsp_label.set_text("DSP: 0%") - self.xrun_lab.set_text(" 0") - xrun_count = 0 - try: - jack_client = jack.Client('controls', False, True) - except jack.JackError: - self.jack_state.set_text(" Stopped") - self.jack_ind.set_from_icon_name("gtk-stop", 0) - self.xrun_lab.set_text(" 0") - xrun_count = 0 - return True - self.jack_state.set_text(" Running") - self.jack_ind.set_from_icon_name("gtk-apply", 0) - jack_client.set_shutdown_callback(self.jackdied) - jack_client.set_xrun_callback(self.jackxrun) - jack_client.activate() - jack_alive = True - max_in = len(jack_client.get_ports('system.*', is_audio=True, is_output=True)) - max_out = len(jack_client.get_ports('system.*', is_audio=True, is_input=True)) - self.refresh_pulse_tab(self.i_in, self.i_out) - return True - - def jackdied(state, why, extra): - '''gets called by jack if it is exiting, we can't clean up - here... so tell the world jack died with a flag instead''' - global jack_alive - global jack_died - jack_died = True - jack_alive = False - - def jackxrun(xruntime, extra): - global xrun_count - xrun_count = xrun_count + 1 - - def xrun_reset(self, button): - global xrun_count - xrun_count = 0 - - def refresh_dropdowns(self): - '''this call refreshes the device lists for all drop downs - that use devices. If backend is not "alsa" then the jack master - and USB master are set to default and no usb master. However, - all all alsa devices will still be available for bridging and - as output device.''' - - if self.def_config['DRIVER'] == "alsa": - self.jack_device_combo.set_sensitive(True) - self.jack_usb_dev_combo.set_sensitive(True) - self.chan_in_spin.set_sensitive(False) - self.chan_out_spin.set_sensitive(False) - self.combo_periods.set_sensitive(True) - elif self.def_config['DRIVER'] == "firewire": - self.jack_device_combo.set_sensitive(False) - self.jack_usb_dev_combo.set_sensitive(False) - self.chan_in_spin.set_sensitive(False) - self.chan_out_spin.set_sensitive(False) - self.combo_periods.set_sensitive(True) - elif self.def_config['DRIVER'] == "dummy": - self.jack_device_combo.set_sensitive(False) - self.jack_usb_dev_combo.set_sensitive(False) - self.chan_in_spin.set_sensitive(True) - self.chan_out_spin.set_sensitive(True) - self.combo_periods.set_sensitive(False) - self.jack_device_combo.get_model().clear() - self.jack_device_combo.append("0,0,0", "default") - if self.def_config['DEV'] == "0,0,0": - self.jack_device_combo.set_active_id("0,0,0") - - self.jack_usb_dev_combo.get_model().clear() - self.jack_usb_dev_combo.append("", "No USB Master") - - if self.def_config['DRIVER'] == "alsa": - if self.def_config['USBDEV'] == "": - self.jack_usb_dev_combo.set_active_id("") - else: - self.jack_usb_dev_combo.append(self.def_config['USBDEV'], self.def_config['USBDEV']) - self.jack_usb_dev_combo.set_active_id(self.def_config['USBDEV']) - self.jack_device_combo.append("200,0,0", "USB Jack Master") - self.jack_device_combo.set_active_id("200,0,0") - - self.combo_zita_remove.get_model().clear() - self.combo_zita_remove.append("label", "Remove (connected)") - self.combo_zita_remove.set_active_id("label") - - self.combo_zita_add.get_model().clear() - self.combo_zita_add.append("label", "Add (available)") - self.combo_zita_add.set_active_id("label") - - usb_save = "" - pci_save = "" - for x in range(0, 10): - # card loop - cname = "" - next_id = "" - next_d = "" - is_usb = False - if os.path.exists(f"/proc/asound/card{str(x)}"): - if os.path.isfile(f"/proc/asound/card{str(x)}/id"): - with open(f"/proc/asound/card{str(x)}/id", "r") as card_file: - for line in card_file: - # only need one line - cname = line.rstrip() - else: - cname = str(x) - if os.path.exists(f"/proc/asound/card{str(x)}/usbbus"): - is_usb = True - for y in range(0, 10): - d_type = "" - d_desc = "" - if os.path.exists(f"/proc/asound/card{str(x)}/pcm{str(y)}p"): - d_type = "playback" - if os.path.exists(f"/proc/asound/card{str(x)}/pcm{str(y)}c"): - if d_type == "": - d_type = "capture" - else: - d_type = f"{d_type} and capture" - if d_type != "": - for z in range(0, 10): - if os.path.exists(f"/proc/asound/card{str(x)}/pcm{str(y)}{d_type[0]}/sub{str(z)}"): - with open(f"/proc/asound/card{str(x)}/pcm{str(y)}{d_type[0]}/sub{str(z)}/info", - "r") as info_file: - for line in info_file: - clean_line = line.rstrip() - if re.match("^name:", clean_line): - line_list = clean_line.split(": ", 1) - dname = "" - if len(line_list) > 1: - dname = line_list[1] - next_id = f"{cname},{str(y)},{str(z)}" - next_d = f"{next_id} {d_type} ({dname})" - # Have everything we need now - - # this block will fit where ever we know sub-ids and description - if is_usb: - if usb_save == "": - usb_save = next_id - if next_id != self.def_config['USBDEV'] and self.def_config['DRIVER'] == "alsa": - self.jack_usb_dev_combo.append(next_id, next_d) - - else: - if pci_save == "": - pci_save = next_id - if self.def_config['DRIVER'] == "alsa": - self.jack_device_combo.append(next_id, next_d) - if self.def_config['USBDEV'] == "" and self.def_config['DEV'] == next_id: - self.jack_device_combo.set_active_id(next_id) - self.dev_desc = next_d - if self.def_config['DEV'] != next_id and self.zdev.count(next_id) > 0: - self.combo_zita_remove.append(next_id, next_d) - else: - if self.def_config['DEV'] != next_id: - self.combo_zita_add.append(next_id, next_d) - - if pci_save == "" and self.def_config['USBDEV'] == "": - self.def_config['USBDEV'] = usb_save - self.jack_usb_dev_combo.set_active_id(usb_save) - self.jack_device_combo.append("200,0,0", "USB device below") - self.jack_device_combo.set_active_id("200,0,0") - - '''Functions for all the gui controls''' - - def on_window_main_delete_event(self, *args): - Gtk.main_quit(*args) - - def on_window_help_delete_event(self, window, event): - self.window_help.hide_on_delete() - return True - - def on_main_button_cancel_clicked(self, button): - global jack_alive - global jack_client - if jack_alive: - jack_client.close() - Gtk.main_quit() - - def on_main_button_help_clicked(self, button): - self.window_help.show() - - def rt_button_hit(self, button): - subprocess.run(["/usr/bin/pkexec", "/usr/sbin/ubuntustudio-system", "fix"], shell=False) - self.rt_button.set_label("Logout required") - self.rt_button.set_sensitive(False) - self.message_dialog_rt_info.show() - self.rt_warning.set_text("Session restart required for Real Time Permissions") - - # system tweaks - def combo_governor_changed_cb(self, button): - if button.get_active_text() == "Performance": - self.rtsetup.set_governor(True) - else: - self.rtsetup.set_governor(False) - - def combo_boost_changed_cb(self, button): - if button.get_active_text() == "on": - self.rtsetup.set_boost(True) - else: - self.rtsetup.set_boost(False) - self.boosted = self.sysinfo.get_boosted() - if self.boosted: - self.combo_boost.set_active(1) - else: - self.combo_boost.set_active(0) - - def logging_changed(self, widget): - newval = widget.get_active_id() - if self.def_config['LOG-LEVEL'] != newval: - self.def_config['LOG-LEVEL'] = newval - self.cb_audio_apply(widget) - - - # Audio setup call backs - def cb_zita_add(self, button): - a_id = str(button.get_active_id()) - if a_id != "None" and a_id != "label": - self.zdev.append(str(a_id)) - if not self.dirty: - self.dirty = True - - def cb_zita_remove(self, button): - a_id = str(button.get_active_id()) - if a_id != "None" and a_id != "label": - self.zdev.remove(str(a_id)) - if not self.dirty: - self.dirty = True - - def jack_device_changed(self, button): - a_id = str(button.get_active_id()) - a_desc = str(button.get_active_text()) - if a_id != "None" and a_id != "200,0,0": - self.def_config['DEV'] = a_id - self.dev_desc = a_desc - if not self.dirty: - self.dirty = True - - def jack_driver_changed(self, button): - a_driver = str(button.get_active_text()) - self.def_config['DRIVER'] = a_driver - if not self.dirty: - self.dirty = True - - def usb_master_changed(self, button): - a_id = str(button.get_active_id()) - if a_id != "None": - self.def_config['USBDEV'] = a_id - if not self.dirty: - self.dirty = True - - def usb_plug_cb(self, widget): - a_id = widget.get_active() - self.usb_single_ck.set_sensitive(a_id) - - - def refresh_pulse_tab(self, i_in, i_out): - ''' Fill in all pulse related widgets ''' - '''self.combo_out_ports.set_active_id(self.def_config['PORTS'])''' - global jack_alive - global max_in - global max_out - self.pj_in_con.set_sensitive(False) - self.pj_in_combo.set_sensitive(False) - self.pj_in_name.set_sensitive(False) - self.pj_out_con.set_sensitive(False) - self.pj_out_combo.set_sensitive(False) - self.pj_out_name.set_sensitive(False) - - self.pj_in_con.get_model().clear() - self.pj_in_con.append("0", "no connection") - self.pj_in_con.set_active(0) - for i in range(1, max_in, 2): - self.pj_in_con.append(f"{str(i)}", f"{str(i)} and {str(i + 1)}") - self.pj_in_combo.get_model().clear() - for i, pj_name in enumerate(self.pulse_in): - self.pj_in_combo.append(str(i), pj_name) - if len(self.pulse_in): - self.pj_in_combo.set_active(i_in) - self.pj_in_name.set_text(self.pulse_in[i_in]) - if (int(self.p_in_con[i_in]) > max_in) and (jack_alive): - self.pj_in_con.append(self.p_in_con[i_in], - f"{self.p_in_con[i_in]} and {str(int(self.p_in_con[i_in]) + 1)} (invalid)") - self.pj_in_con.set_active_id(self.p_in_con[i_in]) - else: - self.pj_in_name.set_text("") - - self.pj_out_con.get_model().clear() - self.pj_out_con.append("0", "no connection") - self.pj_out_con.set_active(0) - for i in range(1, max_out, 2): - self.pj_out_con.append(f"{str(i)}", f"{str(i)} and {str(i + 1)}") - self.pj_out_combo.get_model().clear() - for i, pj_name in enumerate(self.pulse_out): - self.pj_out_combo.append(str(i), pj_name) - if len(self.pulse_out): - self.pj_out_combo.set_active(i_out) - self.pj_out_name.set_text(self.pulse_out[i_out]) - if (int(self.p_out_con[i_out]) > max_out) and (jack_alive): - self.pj_out_con.append(self.p_out_con[i_out], - f"{self.p_out_con[i_out]} and {str(int(self.p_out_con[i_out]) + 1)} (invalid)") - self.pj_out_con.set_active_id(self.p_out_con[i_out]) - else: - self.pj_out_name.set_text("") - - self.pj_in_con.set_sensitive(True) - self.pj_in_combo.set_sensitive(True) - self.pj_in_name.set_sensitive(True) - self.pj_out_con.set_sensitive(True) - self.pj_out_combo.set_sensitive(True) - self.pj_out_name.set_sensitive(True) - - - def pj_in_name_cb(self, widget): - ''' call back for any pulse bridge input name or connect change - to current values ''' - if not widget.get_sensitive(): - return - if len(self.pulse_in): - self.pulse_in[self.i_in] = "".join(str(self.pj_in_name.get_text()).split()) - self.pj_in_name.set_text(self.pulse_in[self.i_in]) - self.p_in_con[self.i_in] = str(self.pj_in_con.get_active_id()) - self.refresh_pulse_tab(self.i_in, self.i_out) - - - def pj_out_name_cb(self, widget): - ''' call back for any pulse bridge output name or connect change - to current values ''' - if not widget.get_sensitive(): - return - if len(self.pulse_out): - self.pulse_out[self.i_out] = "".join(str(self.pj_out_name.get_text()).split()) - self.pj_out_name.set_text(self.pulse_out[self.i_out]) - self.p_out_con[self.i_out] = str(self.pj_out_con.get_active_id()) - self.refresh_pulse_tab(self.i_in, self.i_out) - - - def pj_in_combo_cb(self, widget): - ''' callback to look at different pa bridge. - need to save name and connection, then - refresh name and connections to match ''' - if not widget.get_sensitive(): - return - if widget.get_active() < 0: - return - self.i_in = self.pj_in_combo.get_active() - self.refresh_pulse_tab(self.i_in, self.i_out) - - - def pj_out_combo_cb(self, widget): - ''' callback to look at different pa bridge. - need to save name and connection, then - refresh name and connections to match ''' - if not widget.get_sensitive(): - return - if widget.get_active() < 0: - return - self.i_out = self.pj_out_combo.get_active() - self.refresh_pulse_tab(self.i_in, self.i_out) - - - def pj_in_add_cb(self, widget): - ''' need to create a name for the bridge and - assign connect as "none". Before switching - to display the new bridge we need to save the - current bridge info ''' - self.i_in = len(self.pulse_in) - self.i_out = 0 - if len(self.pulse_out): - self.i_out = int(self.pj_out_combo.get_active_id()) - self.pulse_in.append(f"pulse_in-{str(self.i_in + 1)}") - self.p_in_con.append("0") - self.refresh_pulse_tab(self.i_in, self.i_out) - - - def pj_out_add_cb(self, widget): - ''' need to create a name for the bridge and - assign connect as "none". Before switching - to display the new bridge we need to save the - current bridge info ''' - self.i_out = len(self.pulse_out) - self.i_in = 0 - if len(self.pulse_in): - self.i_in = int(self.pj_in_combo.get_active_id()) - self.pulse_out.append(f"pulse_out-{str(self.i_out + 1)}") - self.p_out_con.append("0") - self.refresh_pulse_tab(self.i_in, self.i_out) - - - def pj_in_rem_cb(self, widget): - ''' get index of current bridge - remove name from list by index - remove connection from list by index ''' - index = self.pj_in_combo.get_active() - del self.pulse_in[index] - del self.p_in_con[index] - self.i_in = 0 - self.i_out = 0 - if len(self.pulse_out): - self.i_out = int(self.pj_out_combo.get_active_id()) - self.refresh_pulse_tab(self.i_in, self.i_out) - - - def pj_out_rem_cb(self, widget): - ''' get index of current bridge - remove name from list by index - remove connection from list by index ''' - index = self.pj_out_combo.get_active() - del self.pulse_out[index] - del self.p_out_con[index] - self.i_out = 0 - self.i_in = 0 - if len(self.pulse_in): - self.i_in = int(self.pj_in_combo.get_active_id()) - self.refresh_pulse_tab(self.i_in, self.i_out) - - - def mixer_cb(self, button): - '''callback for mixer button. This starts QASMixer - with the device set to whatever is jack master''' - if self.def_config['USBDEV'] != "": - # must be hw:device not hw:device,0,0 - mixdevice = self.def_config['USBDEV'].split(',', 1)[0] - else: - mixdevice = self.def_config['DEV'].split(',', 1)[0] - subprocess.Popen(["/usr/bin/qasmixer", "-n", f"--device=hw:{str(mixdevice)}"], shell=False).pid - - def pavucontrol_cb(self, button): - '''callback for pulse control button, opens pavucontrol''' - subprocess.Popen(["/usr/bin/pavucontrol"], shell=False).pid - - def carla_cb(self, button): - '''callback for carla button, opens carla''' - if os.path.isfile("/usr/bin/carla") and os.access("/usr/bin/carla", os.X_OK): - subprocess.Popen(["/usr/bin/carla"], shell=False).pid - else: - button.set_label("Please Install Carla First") - - def cb_jack_start(self, button): - ''' call back for Jack (re)start button''' - global autojack - self.def_config['JACK'] = "True" - self.config_save() - if autojack: - subprocess.run(["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.start_signal"], - shell=False) - else: - time.sleep(5) - if autojack: - subprocess.run( - ["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.start_signal"], - shell=False) - else: - self.start_autojack() - - def cb_jack_stop(self, button): - global autojack - self.def_config['JACK'] = "False" - self.config_save() - if autojack: - subprocess.run(["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.stop_signal"], - shell=False) - else: - time.sleep(5) - if autojack: - subprocess.run( - ["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.stop_signal"], - shell=False) - else: - self.start_autojack() - - def cb_audio_apply(self, button): - '''callback for audio tab apply button''' - global autojack - self.config_save() - if autojack: - subprocess.run(["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.config_signal"], - shell=False) - else: - time.sleep(5) - if autojack: - subprocess.run( - ["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.config_signal"], - shell=False) - else: - self.start_autojack() - - def config_save(self): - ''' Write audio setting to ~/.config/autojack/autojackrc''' - c_file = expanduser(self.config_file) - if not os.path.isfile(c_file): - # either first run or old version - c_dir = expanduser(self.config_path) - if not os.path.isdir(c_dir): - os.makedirs(c_dir) - if os.path.isfile(expanduser(self.old_config_file)): - os.remove(expanduser(self.old_config_file)) - with open(expanduser(self.config_file), "w") as rc_file: - self.def_config['DRIVER'] = str(self.combo_backend.get_active_id()) - self.def_config['CHAN-IN'] = str(int(self.chan_in_spin.get_value())) - self.def_config['CHAN-OUT'] = str(int(self.chan_out_spin.get_value())) - self.def_config['RATE'] = str(self.jack_rate_combo.get_active_id()) - self.def_config['FRAME'] = str(self.combobox_late.get_active_id()) - zframe = str(int(int(self.combobox_late.get_active_id()) / 2)) - if int(zframe) < 128: - zframe = str(64) - self.def_config['ZFRAME'] = zframe - self.def_config['PERIOD'] = str(self.combo_periods.get_active_id()) - self.def_config['A2J'] = str(self.jack_midi_check.get_active()) - self.def_config['PULSE-IN'] = ' '.join(self.pulse_in) - self.def_config['PULSE-OUT'] = ' '.join(self.pulse_out) - self.def_config['PJ-IN-CON'] = ' '.join(self.p_in_con) - self.def_config['PJ-OUT-CON'] = ' '.join(self.p_out_con) - self.def_config['USBAUTO'] = str(self.usb_plug_check.get_active()) - self.def_config['USB-SINGLE'] = str(self.usb_single_ck.get_active()) - self.def_config['XDEV'] = ' '.join(self.zdev) - self.config.write(rc_file) - - def start_autojack(self): - '''start autojack as it has been detected as not running. - This should only happen directly after a fresh install of - -controls''' - print("Starting Autojack...") - # first tell any old autojack to die - subprocess.run(["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.quit_signal"], - shell=False) - # do it - subprocess.Popen(["/usr/bin/autojack"], stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, - stderr=subprocess.STDOUT, shell=False).pid - - def on_button_help_ok_clicked(self, button): - self.window_help.hide() - - def on_button_msg_ok_clicked(self, button): - Gtk.main_quit() - - def on_button_rt_info_ok_clicked(self, button): - self.message_dialog_rt_info.hide() - - subprocess.run(["/usr/bin/dbus-send", "--type=signal", "/", "org.ubuntustudio.control.event.ping_signal"], - shell=False) - - -us = UbuntuStudioControls() -us.window_main.show_all() - -Gtk.main() diff -Nru ubuntustudio-controls-1.12.6/usr/lib/systemd/user/default.target.wants/studio.service ubuntustudio-controls-1.13/usr/lib/systemd/user/default.target.wants/studio.service --- ubuntustudio-controls-1.12.6/usr/lib/systemd/user/default.target.wants/studio.service 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/lib/systemd/user/default.target.wants/studio.service 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -[Unit] -Description=Studio autojack session daemon - -# Runs autojack which starts Studio audio in the same way the session -# ended as well as providing a back end for ubuntustudio-controls for -# changing various settings. -BindsTo=default.target -Before=default.target - -[Service] -ExecStart=/usr/bin/autojack - - -[Install] -WantedBy=default.target diff -Nru ubuntustudio-controls-1.12.6/usr/lib/systemd/user/indicator-messages.service.wants/session-monitor.service ubuntustudio-controls-1.13/usr/lib/systemd/user/indicator-messages.service.wants/session-monitor.service --- ubuntustudio-controls-1.12.6/usr/lib/systemd/user/indicator-messages.service.wants/session-monitor.service 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/lib/systemd/user/indicator-messages.service.wants/session-monitor.service 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -[Unit] -Description=Studio - session monitor - -# Stops autojack which starts Studio audio in the same way the session -# ended as well as providing a back end for studio-controls for -# changing various settings. -BindsTo=indicator-messages.service -After=indicator-messages.service - -[Service] -Type=simple - -ExecStart=/bin/sleep infinity - -TimeoutStopSec=4 - -ExecStop=/bin/sleep 3 -ExecStopPost=/bin/systemctl --user start systemd-exit.service - - - -[Install] -WantedBy=indicator-messages.service diff -Nru ubuntustudio-controls-1.12.6/usr/lib/systemd/user/session-monitor.service ubuntustudio-controls-1.13/usr/lib/systemd/user/session-monitor.service --- ubuntustudio-controls-1.12.6/usr/lib/systemd/user/session-monitor.service 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/lib/systemd/user/session-monitor.service 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -[Unit] -Description=Studio - session monitor - -# Stops autojack which starts Studio audio in the same way the session -# ended as well as providing a back end for studio-controls for -# changing various settings. -BindsTo=indicator-messages.service -After=indicator-messages.service - -[Service] -Type=simple - -ExecStart=/bin/sleep infinity - -TimeoutStopSec=4 - -ExecStop=/bin/sleep 3 -ExecStopPost=/bin/systemctl --user start systemd-exit.service - - - -[Install] -WantedBy=indicator-messages.service diff -Nru ubuntustudio-controls-1.12.6/usr/lib/systemd/user/studio.service ubuntustudio-controls-1.13/usr/lib/systemd/user/studio.service --- ubuntustudio-controls-1.12.6/usr/lib/systemd/user/studio.service 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/lib/systemd/user/studio.service 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -[Unit] -Description=Studio autojack session daemon - -# Runs autojack which starts Studio audio in the same way the session -# ended as well as providing a back end for ubuntustudio-controls for -# changing various settings. -BindsTo=default.target -Before=default.target - -[Service] -ExecStart=/usr/bin/autojack - - -[Install] -WantedBy=default.target diff -Nru ubuntustudio-controls-1.12.6/usr/sbin/ubuntustudio-system ubuntustudio-controls-1.13/usr/sbin/ubuntustudio-system --- ubuntustudio-controls-1.12.6/usr/sbin/ubuntustudio-system 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/sbin/ubuntustudio-system 1970-01-01 00:00:00.000000000 +0000 @@ -1,115 +0,0 @@ -#! /bin/sh -# -# Script to change do system side things for ubuntustudio-controls -# -# -GOVERNOR="ondemand" -NO_TURBO="0" - -set_governors() { - # do this here in case we hit exit 0 before the end - echo "NO_TURBO=$NO_TURBO\n" > /etc/default/ubuntustudio - echo "GOVERNOR=${GOVERNOR}\n" >> /etc/default/ubuntustudio - AVAILABLE="/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors" - [ -f $AVAILABLE ] || exit 0 - read governors < $AVAILABLE - case "$GOVERNOR" in - performance) - case $governors in - *performance*) - GOVERNOR="performance" - ;; - *) - exit 0 - ;; - esac - ;; - *) - case $governors in - *ondemand*) - GOVERNOR="ondemand" - ;; - *powersave*) - GOVERNOR="powersave" - ;; - *) - exit 0 - ;; - esac - ;; - esac - - for CPUFREQ in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor - do - [ -f $CPUFREQ ] || continue - echo -n $GOVERNOR > $CPUFREQ - done - #reswrite just in case we corrected something - echo "NO_TURBO=$NO_TURBO\n" > /etc/default/ubuntustudio - echo "GOVERNOR=${GOVERNOR}\n" >> /etc/default/ubuntustudio - -} - -# any setting in this file will override the above defaults. -# ubuntustudio-controls will normally write the defaults file -if [ -f /etc/default/ubuntustudio ] ; then - . /etc/default/ubuntustudio -fi - -case "$1" in - performance) - GOVERNOR="performance" - set_governors - ;; - - ondemand) - GOVERNOR="ondemand" - set_governors - ;; - - powersave) - GOVERNOR="powersave" - set_governors - ;; - - fix) - if [ -f /etc/security/limits.d/audio.conf.disabled ]; then - mv /etc/security/limits.d/audio.conf.disabled /etc/security/limits.d/audio.conf - elif ! [ -f /etc/security/limits.d/audio.conf ]; then - cp /usr/share/ubuntustudio-controls/audio.conf /etc/security/limits.d/audio.conf - fi - if [ ${PKEXEC_UID} -gt 999 ]; then - /usr/sbin/usermod `id -nu ${PKEXEC_UID}` -aG audio - fi - ;; - - boost) - if [ -f /sys/devices/system/cpu/intel_pstate/no_turbo ]; then - echo "NO_TURBO=0\n" > /etc/default/ubuntustudio - echo "GOVERNOR=${GOVERNOR}" >> /etc/default/ubuntustudio - echo "0" | tee /sys/devices/system/cpu/intel_pstate/no_turbo - fi - ;; - - noboost) - if [ -f /sys/devices/system/cpu/intel_pstate/no_turbo ]; then - echo "NO_TURBO=1\n" > /etc/default/ubuntustudio - echo "GOVERNOR=${GOVERNOR}" >> /etc/default/ubuntustudio - echo "1" | tee /sys/devices/system/cpu/intel_pstate/no_turbo - fi - ;; - - - nosys) - /etc/init.d/cron stop - ;; - - sys) - /etc/init.d/cron start - ;; - - *) - exit 0 - ;; - - esac diff -Nru ubuntustudio-controls-1.12.6/usr/share/applications/ubuntustudio-controls.desktop ubuntustudio-controls-1.13/usr/share/applications/ubuntustudio-controls.desktop --- ubuntustudio-controls-1.12.6/usr/share/applications/ubuntustudio-controls.desktop 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/share/applications/ubuntustudio-controls.desktop 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -[Desktop Entry] -Name=Ubuntu Studio Controls -GenericName=Multimedia Controls -Comment=Setup Audio, Video and Graphics -Exec=ubuntustudio-controls -Icon=ubuntustudio-controls -Terminal=false -Type=Application -Categories=Settings;Audio -Keywords=Audio;Utility;Settings Binary files /tmp/tmp2YDgd6/eXvkqV9JyA/ubuntustudio-controls-1.12.6/usr/share/icons/hicolor/128x128/apps/ubuntustudio-controls.png and /tmp/tmp2YDgd6/MR_VrIvwAf/ubuntustudio-controls-1.13/usr/share/icons/hicolor/128x128/apps/ubuntustudio-controls.png differ Binary files /tmp/tmp2YDgd6/eXvkqV9JyA/ubuntustudio-controls-1.12.6/usr/share/icons/hicolor/16x16/apps/ubuntustudio-controls.png and /tmp/tmp2YDgd6/MR_VrIvwAf/ubuntustudio-controls-1.13/usr/share/icons/hicolor/16x16/apps/ubuntustudio-controls.png differ Binary files /tmp/tmp2YDgd6/eXvkqV9JyA/ubuntustudio-controls-1.12.6/usr/share/icons/hicolor/22x22/apps/ubuntustudio-controls.png and /tmp/tmp2YDgd6/MR_VrIvwAf/ubuntustudio-controls-1.13/usr/share/icons/hicolor/22x22/apps/ubuntustudio-controls.png differ Binary files /tmp/tmp2YDgd6/eXvkqV9JyA/ubuntustudio-controls-1.12.6/usr/share/icons/hicolor/24x24/apps/ubuntustudio-controls.png and /tmp/tmp2YDgd6/MR_VrIvwAf/ubuntustudio-controls-1.13/usr/share/icons/hicolor/24x24/apps/ubuntustudio-controls.png differ Binary files /tmp/tmp2YDgd6/eXvkqV9JyA/ubuntustudio-controls-1.12.6/usr/share/icons/hicolor/256x256/apps/ubuntustudio-controls.png and /tmp/tmp2YDgd6/MR_VrIvwAf/ubuntustudio-controls-1.13/usr/share/icons/hicolor/256x256/apps/ubuntustudio-controls.png differ Binary files /tmp/tmp2YDgd6/eXvkqV9JyA/ubuntustudio-controls-1.12.6/usr/share/icons/hicolor/48x48/apps/ubuntustudio-controls.png and /tmp/tmp2YDgd6/MR_VrIvwAf/ubuntustudio-controls-1.13/usr/share/icons/hicolor/48x48/apps/ubuntustudio-controls.png differ Binary files /tmp/tmp2YDgd6/eXvkqV9JyA/ubuntustudio-controls-1.12.6/usr/share/icons/hicolor/64x64/apps/ubuntustudio-controls.png and /tmp/tmp2YDgd6/MR_VrIvwAf/ubuntustudio-controls-1.13/usr/share/icons/hicolor/64x64/apps/ubuntustudio-controls.png differ diff -Nru ubuntustudio-controls-1.12.6/usr/share/man/man1/ubuntustudio-controls.1 ubuntustudio-controls-1.13/usr/share/man/man1/ubuntustudio-controls.1 --- ubuntustudio-controls-1.12.6/usr/share/man/man1/ubuntustudio-controls.1 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/share/man/man1/ubuntustudio-controls.1 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -.TH ubuntustudio-controls 1 "16 June 2018" "version 1.5" -.SH NAME -ubuntustudio-controls \- Is an audio setup utility for Ubuntu Studio -.SH SYNOPSIS -ubuntustudio-controls -.SH DESCRIPTION -Ubuntustudio-controls is an audio setup utility. It has a GUI that first -checks that the user has correct real time permissions to run professional -audio applications. The user is warned if real time permissions are not -correct and if the user desires, corrects permissions. The user will be -asked to log out and back in so these permissions can take effect. -.LP -The running of jackdbus and extra utilities is also set up with -ubuntustudio-controls. Along with jackdbus itself, extra audio devices -can be set up as jack clients, USB devices can become jack master when -plugged in or added as jack clients. A2jmidid can be started to bridge -ALSA MIDI devices and applications to jack. Pulseaudio can be bridged -and connected to the right outputs of an output device. -.LP -Ubuntustudio-controls tries to be non-invasive and when jack is turned off -the system should run normally using Pulseaudio for sound. -.SH OPTIONS -Ubuntustudio-controls does not take any options. -.SH SEE ALSO -autojack(2), ubuntustudio-system(2) -.SH BUGS -No known bugs. -.SH AUTHOR -Len Ovens (len@ubuntustudio.org) diff -Nru ubuntustudio-controls-1.12.6/usr/share/man/man2/autojack.2 ubuntustudio-controls-1.13/usr/share/man/man2/autojack.2 --- ubuntustudio-controls-1.12.6/usr/share/man/man2/autojack.2 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/share/man/man2/autojack.2 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -.TH autojack 2 "16 June 2018" "version 1.5" -.SH NAME -autojack \- a jackdbus manager -.SH SYNOPSIS -autojack -.SH DESCRIPTION -Autojack is run at session start and using a config file generated by -ubuntustudio-controls to run jackdbus and other audio utilities. -.LP -Autojack is meant to be run from /etc/xdg/autorun/ and will change -configuration according to dbus signals received from ubuntustudio-controls. -.SH OPTIONS -Autojack does not take any options. -.SH SEE ALSO -ubuntustudio-controls(1), ubuntustudio-system(2) -.SH BUGS -No known bugs. -.SH AUTHOR -Len Ovens (len@ubuntustudio.org) diff -Nru ubuntustudio-controls-1.12.6/usr/share/man/man2/ubuntustudio-system.2 ubuntustudio-controls-1.13/usr/share/man/man2/ubuntustudio-system.2 --- ubuntustudio-controls-1.12.6/usr/share/man/man2/ubuntustudio-system.2 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/share/man/man2/ubuntustudio-system.2 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -.TH ubuntustudio-system 2 "16 June 2018" "version 1.5" -.SH NAME -ubuntustudio-system \- The system end of ubuntustudio-controls -.SH SYNOPSIS -.BI "ubuntustudio-system " "command" -.SH DESCRIPTION -Ubuntustudio-system is the system half of ubuntustudio-controls. It runs -commands as system that the gui requires. Only one command can be sent at -a time. The commands are effective over reboot. -.LP -Security is ensured by not taking any random text as options or commands. -Rather commands are limited to those listed. -.SH COMMANDS -.B fix -- Fixes rt permissions for the user running ubuntustudio-controls -.LP -.B boost -- Turns CPU BOOST on -.LP -.B noboost -- Turns CPU BOOST off -.LP -.B powersave -- Sets CPU governor to powersave -.LP -.B ondemand -- Sets CPU governor to ondemand or powersave if ondemand is not supported -.LP -.B performance -- Sets CPU Governor to performance -.SH OPTIONS -ubuntustudio-system does not take any options. -.SH SEE ALSO -ubuntustudio-controls(1), autojack(2) -.SH BUGS -No known bugs. -.SH AUTHOR -Len Ovens (len@ubuntustudio.org) diff -Nru ubuntustudio-controls-1.12.6/usr/share/polkit-1/actions/com.ubuntustudio.pkexec.ubuntustudio-controls.policy ubuntustudio-controls-1.13/usr/share/polkit-1/actions/com.ubuntustudio.pkexec.ubuntustudio-controls.policy --- ubuntustudio-controls-1.12.6/usr/share/polkit-1/actions/com.ubuntustudio.pkexec.ubuntustudio-controls.policy 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/share/polkit-1/actions/com.ubuntustudio.pkexec.ubuntustudio-controls.policy 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ - - - - - - Authentication is required to run Ubuntu Studio Controls - ubuntustudio-controls - - yes - yes - yes - - /usr/sbin/ubuntustudio-system - - - - diff -Nru ubuntustudio-controls-1.12.6/usr/share/ubuntustudio-controls/audio.conf ubuntustudio-controls-1.13/usr/share/ubuntustudio-controls/audio.conf --- ubuntustudio-controls-1.12.6/usr/share/ubuntustudio-controls/audio.conf 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/share/ubuntustudio-controls/audio.conf 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -# Provided by the jackd package. -# -# Changes to this file will be preserved. -# -# If you want to enable/disable realtime permissions, run -# -# dpkg-reconfigure -p high jackd - -@audio - rtprio 95 -@audio - memlock unlimited -#@audio - nice -19 diff -Nru ubuntustudio-controls-1.12.6/usr/share/ubuntustudio-controls/ubuntustudio-controls.glade ubuntustudio-controls-1.13/usr/share/ubuntustudio-controls/ubuntustudio-controls.glade --- ubuntustudio-controls-1.12.6/usr/share/ubuntustudio-controls/ubuntustudio-controls.glade 2020-05-08 20:56:28.000000000 +0000 +++ ubuntustudio-controls-1.13/usr/share/ubuntustudio-controls/ubuntustudio-controls.glade 1970-01-01 00:00:00.000000000 +0000 @@ -1,1514 +0,0 @@ - - - - - - 100 - 1 - 10 - - - 100 - 1 - 10 - - - 100 - 1 - 10 - - - 100 - 1 - 10 - - - 400 - False - Ubuntu Studio Controls - center-always - 500 - center - - - - - - - True - False - 8 - 8 - 8 - 8 - True - True - vertical - - - True - False - 4 - 8 - Studio Set Up Utility - - - - - - False - True - 0 - - - - - True - False - 19 - 7 - vertical - - - False - Warning: Real time permissions have not been properly installed! - - - - - - - False - True - 6 - 0 - - - - - Fix Real Time Permissions - True - True - True - - - - False - True - 1 - - - - - False - True - 1 - - - - - True - True - end - - - True - False - vertical - - - True - False - These are system Settings that can be changed on the fly depending on the work being done. For low latency Audio work, The Governor should be set to performance and Boost should be off. For best battery life choose ondemand or powersave (depending on your CPU) - True - - - False - True - 0 - - - - - True - False - True - - - True - False - CPU Governor - - - 0 - 0 - - - - - True - False - Intel Boost - - - 0 - 1 - - - - - True - False - 0 - 0 - - - - 1 - 0 - - - - - True - False - 0 - 0 - - off - on - - - - - 1 - 1 - - - - - False - True - 1 - - - - - True - False - True - - - True - False - Logging level - - - False - True - 0 - - - - - True - False - 0 - - Warnings - Info - Debug - - - - - False - True - 1 - - - - - False - True - 2 - - - - - - - True - False - System Tweaks - 0.040000000000000001 - - - False - - - - - True - False - vertical - 1 - - - - - - True - True - - - True - False - True - - - True - False - end - Jack Master Device (no USB): - right - end - - - 0 - 0 - - - - - jack_device_combo - True - False - 0 - 0 - - - - 1 - 0 - 2 - - - - - True - False - end - USB device that should be Master: - start - - - 0 - 1 - - - - - True - False - 0 - on - 0 - - - - 1 - 1 - 2 - - - - - True - False - end - Channel Count (0 = default) input/output: - - - 0 - 2 - - - - - True - True - 1 - number - adjustment4 - True - if-valid - 1 - - - 2 - 2 - - - - - True - True - 1 - number - adjustment3 - True - 1 - - - 1 - 2 - - - - - True - False - end - Jack Sample Rate: - start - - - 0 - 3 - - - - - True - False - 3 - - 22050 - 32000 - 44100 - 48000 - 88200 - 96000 - 192000 - - - - 1 - 3 - 2 - - - - - True - False - end - Jack Buffer Size (Latency): - - - 0 - 4 - - - - - True - False - 6 - - 16 - 32 - 64 - 128 - 256 - 512 - 1024 - 2048 - 4096 - - - - 1 - 4 - 2 - - - - - True - False - end - Jack Periods: - - - 0 - 5 - - - - - True - False - 0 - - 2 - 3 - 15 - - - - 1 - 5 - 2 - - - - - True - False - end - Jack Backend: - right - - - 0 - 6 - - - - - True - False - 0 - - alsa - dummy - - - - - 1 - 6 - 2 - - - - - - - True - False - Jack Master Settings - 0.040000000000000001 - - - False - - - - - True - False - - - True - False - end - Connect Other Internal Audio Interfaces: - - - 0 - 0 - - - - - True - False - 0 - - Add (Available) - - - - - 1 - 0 - - - - - True - False - 0 - - Remove (connected) - - - - - 2 - 0 - - - - - Bridge USB Devices to Jack When Plugged In - True - True - False - start - True - True - - - - 0 - 2 - - - - - USB device bridge is input only - True - True - False - True - - - 1 - 2 - - - - - - - - - - - - - - - - - 1 - - - - - True - False - Extra Devices - - - 1 - False - - - - - True - False - True - True - - - True - False - - - 1 - 0 - - - - - True - False - center - Add A Pulse Jack Bridge - - - 1 - 1 - - - - - True - False - Bridge to Configure - - - 1 - 2 - - - - - True - True - Change this Bridge's Name. No spaces allowed - - - - 0 - 3 - - - - - True - True - Change this Bridge's Name. No spaces allowed - - - - 2 - 3 - - - - - True - False - Bridge Names must be unique. They cannot be the same for input and output. - Change Bridge's (unique) Name - - - 1 - 3 - - - - - Remove input Bridge - True - True - True - - - - 0 - 5 - - - - - Remove output Bridge - True - True - True - - - - 2 - 5 - - - - - True - False - Auto Connect Port - - - 1 - 4 - - - - - True - False - Bridge From Pulse To Jack (input to Jack) - - - 0 - 0 - - - - - True - False - Bridge From Jack To Pulse (output from Jack) - - - 2 - 0 - - - - - Add an input Bridge - True - True - False - True - - - - 0 - 1 - - - - - Add an Output Bridge - True - True - False - True - - - - 2 - 1 - - - - - True - False - True - - - True - False - end - system:capture_ - right - - - False - True - 0 - - - - - True - False - - - - False - True - 1 - - - - - 0 - 4 - - - - - True - False - True - - - True - False - end - system:playback_ - right - - - False - True - 0 - - - - - True - False - - - - False - True - 1 - - - - - 2 - 4 - - - - - True - False - Select a Bridge to edit - False - - - - 0 - 2 - - - - - True - False - Select a Bridge to edit - - - - 2 - 2 - - - - - - - - 2 - - - - - True - False - Pulse Bridging - - - 2 - False - - - - - - - - - - - - - - - - - False - True - 1 - - - - - True - False - 14 - True - - - True - False - end - - - True - False - gtk-stop - - - False - True - 0 - - - - - True - False - end - Jack status: - - - False - True - 1 - - - - - True - False - end - unknown - - - - - - False - True - 2 - - - - - True - False - DSP: - 10 - - - False - True - 3 - - - - - 1 - 0 - - - - - True - False - True - - - X-runs/reset: - True - True - True - end - - - - False - True - 0 - - - - - True - False - start - 0 - - - False - True - 1 - - - - - 2 - 0 - - - - - Bridge ALSA to Jack MIDI (turn on a2jmidid) - True - True - False - start - True - True - - - 0 - 0 - - - - - True - True - 2 - - - - - True - False - True - - - Start or Restart Jack - True - True - True - True - - - - 0 - 0 - - - - - Stop Jack - True - True - True - True - - - - 1 - 0 - - - - - Apply Audio Settings - True - True - True - True - - - - 2 - 0 - - - - - Open QASMixer - True - True - True - - - - 0 - 1 - - - - - Open Pulse Control - True - True - True - - - - 1 - 1 - - - - - Open Carla - True - True - True - - - - 2 - 1 - - - - - False - True - 3 - - - - - 1 - - - - - True - False - Audio Setup - - - 1 - False - - - - - - - - - - - - - - - - - - - - - - - False - True - 2 - - - - - True - False - - - False - True - 8 - 3 - - - - - True - False - - - True - True - 4 - - - - - True - False - 2 - - - Help - True - True - True - 4 - 4 - 4 - - - - 0 - 0 - - - - - Close - True - True - True - 5 - - - - 2 - 0 - - - - - True - False - True - - - 1 - 0 - - - - - False - True - 5 - - - - - - - False - 2 - 2 - 2 - 2 - Info - False - center-always - 400 - 115 - True - dialog - center - window_main - window_main - For changes to take effect, you need to do a fresh login. - - - - - - False - vertical - 2 - - - False - 10 - True - end - - - - - - Ok - True - True - True - - - - True - True - 1 - - - - - False - False - 0 - - - - - - - False - 2 - 2 - 2 - 2 - RT info - False - center-always - 200 - 115 - dialog - True - True - center - window_main - window_main - It seems you have made settings previously and not done a fresh login, or you already have realtime settings in effect, but you are not using the file supplied with the package jackd. -If you want to use this application for administering realtime settings, please remove any custom settings and reboot your computer. - - - - - - False - vertical - 2 - - - False - True - end - - - - - - Ok - True - True - True - - - - True - True - 1 - - - - - False - False - 0 - - - - - - - Default_Audio - - - For a user to be able to run the jack audio server in realtime mode, the system setting "Realtime Audio" needs to be enabled and the user needs to be a member of audio group. This utillity checks this and fixes it if requested. - - - CPU Governor settings can affect low latency audio. Audio works best if the CPU speed is constant. For this to happen, The cpu Governor should be set to "performance" and "boost" should be turned off. These settings can be turned on and off on the fly or be set to take effect from boot. Turning performance off while not using low latency audio may increase battery life on a laptop. - - - 500 - False - True - True - Ubuntu Studio Controls Help - False - True - - - - - - - True - False - vertical - - - True - False - 8 - GENERAL - - - False - True - 0 - - - - - True - True - 8 - 8 - 4 - False - word - 12 - 12 - help_general_text_buffer - - - False - False - 1 - - - - - True - True - 8 - 8 - 4 - False - word - 12 - 12 - help_system_text_buffer - - - False - False - 5 - - - - - True - False - - - Ok - 100 - True - True - True - 8 - 8 - - - - 1 - 0 - - - - - True - False - True - - - 0 - 0 - - - - - True - False - True - - - 2 - 0 - - - - - False - True - 6 - - - - - - - - - - - - - - - - - -