Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bringing back prior (and new) button long-press actions (+extended documentation) #1406

Merged
merged 10 commits into from
May 15, 2021

Conversation

T0bi79
Copy link
Contributor

@T0bi79 T0bi79 commented May 10, 2021

This brings back prior (and adds new) features to the GPIO control module - especially different modes for long-press actions.

Long version:
This PR finally closes issue #1377 that was inadvertently already closed with my previous, preparatory PR #1397.

  • The boolean button option "hold_repeat" was upgraded to a textual "hold_mode" with several options. This brings back postponed as well as secondary actions and introduces some new variants.
  • I wrote an extensive component documentation for the GPIO module with many examples (previous one was way too short IMHO)
  • I tested and optimized the ShutDown button class with the integrated LED support. For example, it had some timing options which were mostly ignored in favor of hardcoded values. Now the config values get effective.
  • I also tested the TwoButtonControl class (with minor updates) and the LED class.
  • Since I do not have a rotary encoder, I did neither test but also not touch the related code. (I just removed some lines from respective ini examples that are not evaluated by this component)
  • Also, I added more available functions to the function_calls.py. This includes the new random track/folder playout commands added by my earlier PR Additional commands to play random cards/folders or tracks #1365.
  • On my breadboards I encountered double/unwanted actions especially when releasing buttons, especially when they haven't just been tipped very shortly. Though I did not experience similar effects on older Phoniebox versions, such effects seem to be a well-known behavior of the GPIO library, as I found in the forums. I added a workaround which works fine for me, but left it disabled by default. It can be activated using a config file option described in the manual.

Even longer version:
See the single commit notes in my repo for some more (but less relevant) details ;-)

T0bi79 added 8 commits May 10, 2021 21:46
(can be switched on via the config);
Enhanced verbosity of Button status on console output.
- Optimized control logic (iteration_time was formerly forced to 200ms ignoring the config value)
- Renamed time_pressed to hold_time to match the corresponding name in SimpleButton base class
- Pass-through of antibounce feature
- Enhanced verbosity of ShutdownButton status on console output.
Changed hold_repeat flag (True/False) to hold_mode (textual). "hold_repeat = True" is "hold_mode = Repeat" now.
Added new hold_mode "Postpone" (as possible in earlier PhonieBox versions)
…me (as possible in earlier PhonieBox versions)
- Pass-through of all relevant SimpleButton base parameters
- Enhanced verbosity of TwoButtonControl status on console output
- Updated VolumeControl.py (though this file is completely superfluous / redundant IMHO)
Fixed several typos and issues in several ini files
Extended documentation, e.g. more example configurations.
@s-martin s-martin added this to the 2.3 milestone May 10, 2021
Copy link
Collaborator

@s-martin s-martin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR and improving GPIO control!

Is the renaming of the parameters working in existing installations?
If not would it make sense to update the ini file, while reading it, if necessary?

PinUp: 5
PinDown: 6
pull_up: True
Pin1: 5
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does renaming these parameters work with existing installations, i.e. ini-files which use the old parameter names?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @s-martin s-martin. See PR #1406 for my response.

@T0bi79
Copy link
Contributor Author

T0bi79 commented May 14, 2021

Thank you for the PR and improving GPIO control!

Is the renaming of the parameters working in existing installations?
If not would it make sense to update the ini file, while reading it, if necessary?

Hi @s-martin!

My answer has two parts:

  1. I already found the code with existing insonsistencies among all these ini files and how it is implemented/evaluated in the python scripts.
    Typical examples were pull_up_down (new scheme) vs. pull_up (old scheme), Pin1/Pin2 (new?) vs. PinUp/PinDown (old?), functionCallUp/Down (old?) vs. functionCall1/2 (new?). or enable(typo? found several times) vs. enabled.

    In your example, the ini file defines a control of type TwoButtonControl which defines the GPIOs as PinUp and PinDown and the actions as functionCallUp and functionCallDown. However, if gpio_control.py finds a control of Type TwoButtonControl it actually expects Pin1 / Pin2 and functionCall1 / functionCall2.

    The funny thing is that this particular ini entry actually still worked because gpio_control.py has a special treatment for TwoButtonControl if (and only if) the ini section is named "VolumeControl". In this case it actually did the same thing just by querying the old(?) names.
    But if the user would rename the ini section to something else (e.g. "Primary VolumeControl" or whatever) it would suddenly stop working and probably no user could understand why.

    My first tought was that all of these inconsistencies evolved unintentionally so I cleaned up / unified everything I found. Maybe the special treatment of entries named VolumeControl was somehow intentional for backward compatibility. In this case I somehow broke it ;-) This special treatment is actually still contained in my PR with the updated ini naming - but is more or less redundant now and could be removed. The only (remaining) difference is that TwoButtonControls named VolumeControl have the auto-repeat feature (old: hold_repeat, new: hold mode: Repeat") enabled by default / as fallback (which does not apply to the ini sample entry which defines auto-repeat itself).

2.) It might be a good idea to make a list or approach how old GPIO entries/parameters could be updated by automatic conversions. I consider this a good idea which is a cleaner style than some special constructs in the code (which even do not work for arbitrary entries but only for such with one reserved name). I'm quite confident that this will not be very complex. I'll think about it soon and post it here...

@T0bi79
Copy link
Contributor Author

T0bi79 commented May 14, 2021

@s-martin

I just tested it and it is quite easy to add a new function that checks the ini file for deprecated syntax after loading it and upgrades it to the current format. This obviously works quite well. I could finish it (after testing it a bit further) and add it to my source branch so it will be added to this PR.

One question beforehand: I can integrate it in two ways:

  • Option1: Once we patched the ConfigParser object, we save the updated gpio_settings.ini to disk.

    • Advantages: Patches become permanent, no need for further patching. Patching function could be removed after 2 or 3 years when little old configs will have survived in the field,
    • Disadvantages: All potential user comments and (upper, lower) case of the option keys will be lost. Though this is a readability/convenience issue only, this might annoy some users. However, we could make a gpio_settings.bak backup of the previous version so that nothing will be lost completely.
  • Option 2: We apply the patches within the configparser object without saving it to disk.

    • Advantage: We don't touch the ini file and everthing will work correctly anyway.
    • Disadvantages: We have to invoke this function and repeat the patching at every startup (but this runs quickly). We encourage users to keep deprecated ini format so it will be less easy to remove this patcher after 2 or 3 years...

Which option is preferred?

@s-martin
Copy link
Collaborator

@T0bi79
I would go for option 1 with a bak file.

T0bi79 added 2 commits May 14, 2021 22:59
… entries.

Removed special (and redundant) handling for controls if (and only if) the corresponding config sections is named "VolumeControl"
@T0bi79
Copy link
Contributor Author

T0bi79 commented May 14, 2021

@s-martin : auto-correction feature is implemented :)

@s-martin s-martin merged commit 88931b1 into MiczFlor:develop May 15, 2021
s-martin added a commit that referenced this pull request Aug 11, 2021
* implemented shutdownwithreducingvolume

* implemented shutdownwithreducingvolume

* fixed type

* activation of shutdown button class in gpio_control

* update to next version number

* fixed date for 2.2 release

* go back for commit to master

* update to next release

* Minor changes

* Add version number to startup script

* Improve reading artist (#1166)

* Improve reading artist

Implement #1164

* Fix syntax

* Fix syntax

* More idiomatic check

* Feature/gpio debugging (#1165)

* change logging

* functionCall in case of invalid read of btn

* adjust behavior to fix strange behavior in case of button press is not stead
y

* Set Own Repo

* Fix volume of startup sound (#1169)

Fixes #1167

* missing savepos-command in "playerstopafter"

As there is a savepos-command in "playerstop" this should also be included in "playerstopafter".

* Update buster-install-default.sh (#1181)

Added spacing

* Revert "Set Own Repo"

This reverts commit 6d504e5.

* Add base functionality for Bluetooth headphone integration

* Add Discussions link to Readme

* Update Mopidy Iris to 3.54.2 (#1161)

* Integrate bluetooth headphone toggle into Web Interface

* Fix bugs and default configuration after testing

* (maint) Minor typos, whitespace issues (#1214)

* Add GPIO function call for bluetooth audio toggle

* Create codeql-analysis.yml

* Update codeql-analysis.yml

* Change path to gpio_settings.ini

* Add mopidy extensions versions to script

* Fixes bug in folder tree, related to special chars

Resolving #469 by simplifying collapse IDs in folder tree.
Make use of integers for collapse IDs rather than folder names to avoid
problem with any kind of non-allowed characters as ID value.

Simplifies corresponding code as no character replacement is required
for collapse IDs anymore.

* 2021 calendar

* 2021 calendar

* Added stop on removal functionality example (#1209)

See #1049

* feat: GPIO Buttons over USB Encoder (#1249)

* feat: Buttons USB Encoder

Closes #1156

* change usb to uppercase USB

* added support for pc/sc readers

* Web App settings for swipe or place rifd (#1130)

* web app settings for #1122

* web app settings for #1122

* Include @Toqqi's review comments

Co-authored-by: s-martin <[email protected]>

* fix: let function_calls.py work with python 3.5 (#1253)

* Shortcuts volume commands of playout control (#1235)

* Shortcuts volume commands of playout control

* Moves debug control out of shorcutted block

* Fixes indentation

* Ensure ALSA is installed (#1255)

* Ensure ALSA is installed

* Fixed typo

* Added alsa to tests also

* Update README.md

* Preparing new file structure

* Increase functional robustness and adapt file locations

* Add Readme

* Improve performance in player.php by avoiding system calls

* removed old code

* Added chapter exts and minduration to global conf

* Removed the old variables from .sh script

* Fixed Socket Read for long content

* Improved Error-Handling with folders that have wrong permission.

* shutdownreducingvolume webUI

* Updated settings.php

* configured lang.php-files

* Update inc.setShutdownReduceVolume.php

* Updated inc.setShutdownReduceVolume.php

* Renamed to ShutdownVolumeReduction

* Changed at queue name to "r"

* shutdown also in at queue "r"

* enabled debug.log

* separate at queue for the shutdown

* Fixed: disabling the planned shutdown

* fix2 for disabling shutdown

* fix3: disabling "at" for the scheduled volume change

* added 4 controls for RFID

* updated description

* Add Readme

* Fix some formatting issues in Readme

* Change default to be w/o LED

* Spotify url conversion (http to mopidy format) (#1203)

* Added spotify url conversion

* Improved and translated error message

* Fix typos

* Fix typo

* Revert missing lines in htdocs/lang-*

* Re-enable start-up sound

* feat: keep USB Button Encoder settings during update

* Fix tabbed indentation to whitespace

* fix: handle list of keycodes in buttons usb encoder (#1285)

* fix: handle keycode lists in buttons usb encoder

* fix: sort key before joining to guarantee order

* Add documentation Complete Install Guide

* Correct typos in Complete Install Guide

* FF and Rewind added to GPIO_SETTINGS.ini (#1291)

* FF and Rewind added to GPIO_SETTINGS.ini

* Update gpio_settings.ini

* updating install information

* -Added addtional output formats matching the printed Card Numbers for the RDM6300 Reader
-Added XOR Checksum for the RDM6300 Output format (Wiegand26)
-Tried to Address the dependencie Topic of #1105 (untested)

* refactoring gpio-control to class

* Webplayer: Time Played Interpolation, Improvements (#1200)

* add mission date of 2.2 release (#1160)

* update to next version number

* fixed date for 2.2 release

* go back for commit to master

* Set Own Repo

* Revert "Set Own Repo"

This reverts commit 6d504e5.

* Interpolate played time to improve UX feeling (something is happening/playing)

* Solved problems of parallel put and get request of player.php

Co-authored-by: s-martin <[email protected]>

* implementing stop on removal for RC522 (see #1097); implementation proposed by @Toqqi in 786ecf4: (#1122)

Description from @Toqqi:
I used the signal python library to detect when a RC522 RFID reader stops reading in a card ID for one second.
This then triggers the playerpauseforce action in playout_controls.sh.

I then configured the second swipe action to be "resume playback" to achieve the play/pause effect when moving an RFID card to/from the reader.

* - Fixed unecessary code line
- improved comment

* fixed logging

* Update gpio_control.py (#1310)

BugFix functionCallTwoBtns

* Added read-for-card status LED GPIO control

Adds a status LED GPIO control that lights up the LED if the phoniebox
is ready (finished startup scripts, checked via systemctl). Type called
`StartupScriptsStatusLED`.

Comparison to MPDStatusLED:
MPDStatusLED lights up the LED if MPD is started which is (on a RPi
zero seconds) before the phoniebox is actually ready for its first card.
Therefore, another status LED indicating whether startup completely
finished appears useful.

* Added example/test config for status LED

Add an example config for the startup script status LED using GPIO 14
(UART TX). This combines a side effect of flashing once when RPi is
powered on and staying one once startup script finished.
Same config added to the gpio test config.

* Fix missing import (#1312)

* Added switchable audio iFaces

Adds a feature to switch between two audio iFaces (e.g.
speaker/headphone). Audio iFaces to swap are stored in files
`settings/Audio_iFace_Name_[01]` and need to be set manually, if feature
should be activated. The correlating volumes are stored in files
`Audio_Volume_Level_[01]`. Currently active iFace "ID" (0 or 1) is
stored in file `settings/Audio_iFace_Active` (default 0).

Scenario: You have equipped your Pi with a sound card that provides a
separate output (and volume control) for speaker and headphone, like the
WM8960 Hi-Fi HAT. This feature enables you to switch between the two
output. It can be triggered by RFID card or (not implemented) via GPIO
(button or switched jack). Compare discussion in #786.

Many room for extension of features:
- setting audio iFaces via WebUI
- display current audio iFace in WebUI + trigger for switch
- trigger switch via GPIO (not needed in my case :-))
- generalisation for more than two audio iFaces (simple to implement if
needed)
- multi volume control in WebUI and via RFID (not sure if handy)

* Drops MPDStatusLED in favour of general StatusLED

For backward compatibility `gpio_control.generate_device` accepts both
`device_type` "StatusLED" as well as "MPDStatusLED".
To be reduced to only "StatusLED" at some point.

* Fix unit test and remove Python 3.5 check (#1319)

* Update test_gpio_control.py

* Update test_gpio_control.py

* Remove Python 3.5 in Actions

* Remove stretch

See #1163

* (bugfix) stop on removal, incorporate switch (#1324)

The merge of #1122 missed @Toqqi comment
#1122 (comment)
which provided an update
(Toqqi@4e1a6fc) that incorporates the global switch, merged with #1130.

Now, "stop on removal" is an option and no must.

* Bugfix #1320  of arne123/RPi-Jukebox-RFID/tree/gpio-control_to_class (#1323)

* Bugfix of arne123/RPi-Jukebox-RFID/tree/gpio-control_to_class

This update form @arne123 fixes #1320 .
There was still a Bug in the Import of the class function. and here is my commit.

* Bugfix #1328  i2c_lcd.py

Removed string function to remove newline. Type error because trake_time contains binary.

Therefore using subprocess.check_output setting to remove newline with  universal_newlines

This fixes issue  #1328

* fix flake8 warnings (#1332)

* Align folder naming scheme (#1340)

* Use gpio_settings.ini for LED configuration (#1342)

* fix: move path append command back up (#1346)

Script can only be executed if sys.path.append(".") is executed before imports.
This bug (#1249 (comment))
was introduced with change #1332.

* Fix for Issue 1347: fix regexp (#1354)

* Update README.md

* Update README.md

* Ignore settings/PhonieboxInstall.conf (#1360)

* organizeFiles: I added a small script for conveniently organizing audio folders, linking them to RFID cards, finding audio folders that are currently not bound to any RFID card, and fixing broken links.

* organizeFiles script: advanced features regarding linking folders to RFID cards

* cli-player.py: script to play audio folders from command line

* organizeFiles.py: small fix

* minor

* Extended commands (e.g. for special Cards) to play random (surprise!) cards/folders or tracks.

* Fix spelling error in en-UK (#1367)

* added documentation as requested.

* Delete SPOTIFY-INTEGRATION.md (#1366)

* Delete SPOTIFY-INTEGRATION.md

#1238

* Updated Links to Spotify FAQ

* Fix typos (#1370)

* Update README.md (#1375)

Due to sloppy reading and not realizing where this documentation was located it took me a while to figure out what this folder was referring to. I thought I would clarify.

* move helper scripts

* README for helper scripts

* Update phoniebox-rfid-reader.service.stretch-default.sample (#1388)

* Update phoniebox-rfid-reader.service.stretch-default.sample

reducing cpu-load

* Update phoniebox-rfid-reader.service.stretch-default.sample

* Update documentation (#1386)

* Add headless install to complete installation guide as an option

* Reorganize structure

* Fix anchor link

* Correcting a few more issues

* Remove instructions to install Phoniebox with Desktop

* Clean-up and partial repair of the GPIO component (#1397)

* Edit GPIO sanmple configs: Removed misleading attribute hold_time for all ("Simple-")Buttons that do not have hold_repeat configured at all (today, hold_time will be ignored if hold_repeat is unset).
I kept the hold_time where hold_repeat was explicitely set to False so it could be re-enabled when needed.

* Fixed ShutdownButton: shutdown_button.py needs additional config parameters time_pressed, iteration_time and led_pin which gpio_control.py did not read and pass (has been added).
Instead, it read hold_repeat and hold_time which is not used by ShutdownButton (has been removed).

* Deprecated config options replaced: Button and ShutdownButton do not evaluate pull_up any more, instead they use pull_up_down today.

* Tested and repaired shutdown_button class:
- fixed import of SimpleButton (as in shutdown_button.py and two_button_control.py) since it threw an error under python 3.
- removed input params hold_repeat and hold_time since they are not used by any instance of ShutdownButton.
- configure LED GPIO port on init (LED flah function threw an error since GPIO was still uninitalized)
- renamed "status" to "cancelled" for better understanding
- enforce final LED switch off if action was cancelled early (might have stayed on if button was released during flashing)

* Create future1.md

* Workflows for Future3

* Bringing back prior (and new) button long-press actions (+extended documentation) (#1406)

* Added an optional countermeasure against button bouncing effects
(can be switched on via the config);
Enhanced verbosity of Button status on console output.

* Updated ShutdownButton:
- Optimized control logic (iteration_time was formerly forced to 200ms ignoring the config value)
- Renamed time_pressed to hold_time to match the corresponding name in SimpleButton base class
- Pass-through of antibounce feature
- Enhanced verbosity of ShutdownButton status on console output.

* Introduced support for different modes on button hold:
Changed hold_repeat flag (True/False) to hold_mode (textual). "hold_repeat = True" is "hold_mode = Repeat" now.
Added new hold_mode "Postpone" (as possible in earlier PhonieBox versions)

* Added new hold_mode "SecondFunc" for a different action after hold_time (as possible in earlier PhonieBox versions)

* Added new hold_mode "SecondFuncRepeated" for repeated executions of a different action after hold_time

* Updated TwoButtonControl:
- Pass-through of all relevant SimpleButton base parameters
- Enhanced verbosity of TwoButtonControl status on console output
- Updated VolumeControl.py (though this file is completely superfluous / redundant IMHO)

* Added more detailed GPIO component documentation to README.MD
Fixed several typos and issues in several ini files

* Added more functions that can be called by GPIO controls like buttons.
Extended documentation, e.g. more example configurations.

* Added auto-conversion of old/deprecated syntax within gpiocontrol.ini entries.
Removed special (and redundant) handling for controls if (and only if) the corresponding config sections is named "VolumeControl"

* Added the __init__.py I just forgot...

* Align path of requirements.txt

* Fix in future3 github workflow

* Update README.md (#1452)

I struggled with this for the 4th time on new phoniebox installations and most pinout graphs for these card leave the cable for IRQ out and although you can read a card on python phoniebox does not read anything. With the cable in place on that pin it works like a charm from the beginning.

* Add lsof (#1457)

* Update buster-install-default.sh

* Add lsof and other missing packages

* fix-alsa on buster-lite (#1467)

* Update buster-install-default.sh

* update test for alsa-utils

* omit inapropriate version evdev==0.7.0 (#1468)

see https://pypi.org/project/evdev/

* Adding a boot volume settings to be set in startup script after reboot (#1177)

* Adding boot volume value to config and startup script #1169

* Adding boot volume value to config and startup script #1169

* startup changing to boot volume

* comment in web app changed to boot

* Prepare Readme for 2.3

* facilitate transition to bullseye (#1469)

* facilitate transition to bullseye

in order to easily support the debian upgrade path (replace `buster` with `bullseye` in `/etc/apt/sources.list` and `/etc/apt/sources.list.d/*`)
this change helps transition from `php7.3` on buster to `php7.4` on bullseye
and use python3 for python which is valid on bullseye

* Update buster-install-default.sh

* Update buster-install-default.sh

* small changes: head -n and file prefix (#1423)

* replace head -1 by head -n 1 since this notation is depricated

* replace head -1 by head -n 1 since this notation is depricated

* playout_controls: my mopidy version need "file://" prefix

* Update README.md

* Update README.md

* Update README.md

* Update version-number

Co-authored-by: manajoe <[email protected]>
Co-authored-by: Felix Bachmair <[email protected]>
Co-authored-by: veloxidSchweiz <[email protected]>
Co-authored-by: Schneelocke <[email protected]>
Co-authored-by: Micz Flor <[email protected]>
Co-authored-by: StefanMinke <[email protected]>
Co-authored-by: jrn <[email protected]>
Co-authored-by: Schneelocke <[email protected]>
Co-authored-by: ChrisSoc <[email protected]>
Co-authored-by: ChrisSoc <pi@exaberry>
Co-authored-by: miohna <[email protected]>
Co-authored-by: miohna <[email protected]>
Co-authored-by: jeripeierSBB <[email protected]>
Co-authored-by: Dominik Ach <[email protected]>
Co-authored-by: Florian Bachmann <[email protected]>
Co-authored-by: ChisSoc <[email protected]>
Co-authored-by: Patrick Beer <[email protected]>
Co-authored-by: Stefan Caliandro <[email protected]>
Co-authored-by: arne123 <[email protected]>
Co-authored-by: damaev <[email protected]>
Co-authored-by: DCH <[email protected]>
Co-authored-by: Varac <[email protected]>
Co-authored-by: [email protected] <[email protected]>
Co-authored-by: T0bi79 <[email protected]>
Co-authored-by: Tobias L. Maier <[email protected]>
Co-authored-by: Kiriakos Antoniadis <[email protected]>
Co-authored-by: Michael Weinrich <[email protected]>
Co-authored-by: bart1 <[email protected]>
Co-authored-by: Patrick Beer <[email protected]>
Co-authored-by: T0bi79 <[email protected]>
Co-authored-by: sebrep <[email protected]>
Co-authored-by: t0b3 <[email protected]>
Co-authored-by: TRO <[email protected]>
s-martin added a commit that referenced this pull request Dec 18, 2022
* Feature/gpio debugging (#1165)

* change logging

* functionCall in case of invalid read of btn

* adjust behavior to fix strange behavior in case of button press is not stead
y

* Set Own Repo

* Fix volume of startup sound (#1169)

Fixes #1167

* missing savepos-command in "playerstopafter"

As there is a savepos-command in "playerstop" this should also be included in "playerstopafter".

* Update buster-install-default.sh (#1181)

Added spacing

* Revert "Set Own Repo"

This reverts commit 6d504e5.

* Add base functionality for Bluetooth headphone integration

* Add Discussions link to Readme

* Update Mopidy Iris to 3.54.2 (#1161)

* Integrate bluetooth headphone toggle into Web Interface

* Fix bugs and default configuration after testing

* (maint) Minor typos, whitespace issues (#1214)

* Add GPIO function call for bluetooth audio toggle

* Create codeql-analysis.yml

* Update codeql-analysis.yml

* Change path to gpio_settings.ini

* Add mopidy extensions versions to script

* Fixes bug in folder tree, related to special chars

Resolving #469 by simplifying collapse IDs in folder tree.
Make use of integers for collapse IDs rather than folder names to avoid
problem with any kind of non-allowed characters as ID value.

Simplifies corresponding code as no character replacement is required
for collapse IDs anymore.

* 2021 calendar

* 2021 calendar

* Added stop on removal functionality example (#1209)

See #1049

* feat: GPIO Buttons over USB Encoder (#1249)

* feat: Buttons USB Encoder

Closes #1156

* change usb to uppercase USB

* added support for pc/sc readers

* Web App settings for swipe or place rifd (#1130)

* web app settings for #1122

* web app settings for #1122

* Include @Toqqi's review comments

Co-authored-by: s-martin <[email protected]>

* fix: let function_calls.py work with python 3.5 (#1253)

* Shortcuts volume commands of playout control (#1235)

* Shortcuts volume commands of playout control

* Moves debug control out of shorcutted block

* Fixes indentation

* Ensure ALSA is installed (#1255)

* Ensure ALSA is installed

* Fixed typo

* Added alsa to tests also

* Update README.md

* Preparing new file structure

* Increase functional robustness and adapt file locations

* Add Readme

* Improve performance in player.php by avoiding system calls

* removed old code

* Added chapter exts and minduration to global conf

* Removed the old variables from .sh script

* Fixed Socket Read for long content

* Improved Error-Handling with folders that have wrong permission.

* shutdownreducingvolume webUI

* Updated settings.php

* configured lang.php-files

* Update inc.setShutdownReduceVolume.php

* Updated inc.setShutdownReduceVolume.php

* Renamed to ShutdownVolumeReduction

* Changed at queue name to "r"

* shutdown also in at queue "r"

* enabled debug.log

* separate at queue for the shutdown

* Fixed: disabling the planned shutdown

* fix2 for disabling shutdown

* fix3: disabling "at" for the scheduled volume change

* added 4 controls for RFID

* updated description

* Add Readme

* Fix some formatting issues in Readme

* Change default to be w/o LED

* Spotify url conversion (http to mopidy format) (#1203)

* Added spotify url conversion

* Improved and translated error message

* Fix typos

* Fix typo

* Revert missing lines in htdocs/lang-*

* Re-enable start-up sound

* feat: keep USB Button Encoder settings during update

* Fix tabbed indentation to whitespace

* fix: handle list of keycodes in buttons usb encoder (#1285)

* fix: handle keycode lists in buttons usb encoder

* fix: sort key before joining to guarantee order

* Add documentation Complete Install Guide

* Correct typos in Complete Install Guide

* FF and Rewind added to GPIO_SETTINGS.ini (#1291)

* FF and Rewind added to GPIO_SETTINGS.ini

* Update gpio_settings.ini

* updating install information

* -Added addtional output formats matching the printed Card Numbers for the RDM6300 Reader
-Added XOR Checksum for the RDM6300 Output format (Wiegand26)
-Tried to Address the dependencie Topic of #1105 (untested)

* refactoring gpio-control to class

* Webplayer: Time Played Interpolation, Improvements (#1200)

* add mission date of 2.2 release (#1160)

* update to next version number

* fixed date for 2.2 release

* go back for commit to master

* Set Own Repo

* Revert "Set Own Repo"

This reverts commit 6d504e5.

* Interpolate played time to improve UX feeling (something is happening/playing)

* Solved problems of parallel put and get request of player.php

Co-authored-by: s-martin <[email protected]>

* implementing stop on removal for RC522 (see #1097); implementation proposed by @Toqqi in 786ecf4: (#1122)

Description from @Toqqi:
I used the signal python library to detect when a RC522 RFID reader stops reading in a card ID for one second.
This then triggers the playerpauseforce action in playout_controls.sh.

I then configured the second swipe action to be "resume playback" to achieve the play/pause effect when moving an RFID card to/from the reader.

* - Fixed unecessary code line
- improved comment

* fixed logging

* Update gpio_control.py (#1310)

BugFix functionCallTwoBtns

* Added read-for-card status LED GPIO control

Adds a status LED GPIO control that lights up the LED if the phoniebox
is ready (finished startup scripts, checked via systemctl). Type called
`StartupScriptsStatusLED`.

Comparison to MPDStatusLED:
MPDStatusLED lights up the LED if MPD is started which is (on a RPi
zero seconds) before the phoniebox is actually ready for its first card.
Therefore, another status LED indicating whether startup completely
finished appears useful.

* Added example/test config for status LED

Add an example config for the startup script status LED using GPIO 14
(UART TX). This combines a side effect of flashing once when RPi is
powered on and staying one once startup script finished.
Same config added to the gpio test config.

* Fix missing import (#1312)

* Added switchable audio iFaces

Adds a feature to switch between two audio iFaces (e.g.
speaker/headphone). Audio iFaces to swap are stored in files
`settings/Audio_iFace_Name_[01]` and need to be set manually, if feature
should be activated. The correlating volumes are stored in files
`Audio_Volume_Level_[01]`. Currently active iFace "ID" (0 or 1) is
stored in file `settings/Audio_iFace_Active` (default 0).

Scenario: You have equipped your Pi with a sound card that provides a
separate output (and volume control) for speaker and headphone, like the
WM8960 Hi-Fi HAT. This feature enables you to switch between the two
output. It can be triggered by RFID card or (not implemented) via GPIO
(button or switched jack). Compare discussion in #786.

Many room for extension of features:
- setting audio iFaces via WebUI
- display current audio iFace in WebUI + trigger for switch
- trigger switch via GPIO (not needed in my case :-))
- generalisation for more than two audio iFaces (simple to implement if
needed)
- multi volume control in WebUI and via RFID (not sure if handy)

* Drops MPDStatusLED in favour of general StatusLED

For backward compatibility `gpio_control.generate_device` accepts both
`device_type` "StatusLED" as well as "MPDStatusLED".
To be reduced to only "StatusLED" at some point.

* Fix unit test and remove Python 3.5 check (#1319)

* Update test_gpio_control.py

* Update test_gpio_control.py

* Remove Python 3.5 in Actions

* Remove stretch

See #1163

* (bugfix) stop on removal, incorporate switch (#1324)

The merge of #1122 missed @Toqqi comment
#1122 (comment)
which provided an update
(Toqqi@4e1a6fc) that incorporates the global switch, merged with #1130.

Now, "stop on removal" is an option and no must.

* Bugfix #1320  of arne123/RPi-Jukebox-RFID/tree/gpio-control_to_class (#1323)

* Bugfix of arne123/RPi-Jukebox-RFID/tree/gpio-control_to_class

This update form @arne123 fixes #1320 .
There was still a Bug in the Import of the class function. and here is my commit.

* Bugfix #1328  i2c_lcd.py

Removed string function to remove newline. Type error because trake_time contains binary.

Therefore using subprocess.check_output setting to remove newline with  universal_newlines

This fixes issue  #1328

* fix flake8 warnings (#1332)

* Align folder naming scheme (#1340)

* Use gpio_settings.ini for LED configuration (#1342)

* fix: move path append command back up (#1346)

Script can only be executed if sys.path.append(".") is executed before imports.
This bug (#1249 (comment))
was introduced with change #1332.

* Fix for Issue 1347: fix regexp (#1354)

* Update README.md

* Update README.md

* Ignore settings/PhonieboxInstall.conf (#1360)

* organizeFiles: I added a small script for conveniently organizing audio folders, linking them to RFID cards, finding audio folders that are currently not bound to any RFID card, and fixing broken links.

* organizeFiles script: advanced features regarding linking folders to RFID cards

* cli-player.py: script to play audio folders from command line

* organizeFiles.py: small fix

* minor

* Extended commands (e.g. for special Cards) to play random (surprise!) cards/folders or tracks.

* Fix spelling error in en-UK (#1367)

* added documentation as requested.

* Delete SPOTIFY-INTEGRATION.md (#1366)

* Delete SPOTIFY-INTEGRATION.md

#1238

* Updated Links to Spotify FAQ

* Fix typos (#1370)

* Update README.md (#1375)

Due to sloppy reading and not realizing where this documentation was located it took me a while to figure out what this folder was referring to. I thought I would clarify.

* move helper scripts

* README for helper scripts

* Update phoniebox-rfid-reader.service.stretch-default.sample (#1388)

* Update phoniebox-rfid-reader.service.stretch-default.sample

reducing cpu-load

* Update phoniebox-rfid-reader.service.stretch-default.sample

* Update documentation (#1386)

* Add headless install to complete installation guide as an option

* Reorganize structure

* Fix anchor link

* Correcting a few more issues

* Remove instructions to install Phoniebox with Desktop

* Clean-up and partial repair of the GPIO component (#1397)

* Edit GPIO sanmple configs: Removed misleading attribute hold_time for all ("Simple-")Buttons that do not have hold_repeat configured at all (today, hold_time will be ignored if hold_repeat is unset).
I kept the hold_time where hold_repeat was explicitely set to False so it could be re-enabled when needed.

* Fixed ShutdownButton: shutdown_button.py needs additional config parameters time_pressed, iteration_time and led_pin which gpio_control.py did not read and pass (has been added).
Instead, it read hold_repeat and hold_time which is not used by ShutdownButton (has been removed).

* Deprecated config options replaced: Button and ShutdownButton do not evaluate pull_up any more, instead they use pull_up_down today.

* Tested and repaired shutdown_button class:
- fixed import of SimpleButton (as in shutdown_button.py and two_button_control.py) since it threw an error under python 3.
- removed input params hold_repeat and hold_time since they are not used by any instance of ShutdownButton.
- configure LED GPIO port on init (LED flah function threw an error since GPIO was still uninitalized)
- renamed "status" to "cancelled" for better understanding
- enforce final LED switch off if action was cancelled early (might have stayed on if button was released during flashing)

* Create future1.md

* Workflows for Future3

* Bringing back prior (and new) button long-press actions (+extended documentation) (#1406)

* Added an optional countermeasure against button bouncing effects
(can be switched on via the config);
Enhanced verbosity of Button status on console output.

* Updated ShutdownButton:
- Optimized control logic (iteration_time was formerly forced to 200ms ignoring the config value)
- Renamed time_pressed to hold_time to match the corresponding name in SimpleButton base class
- Pass-through of antibounce feature
- Enhanced verbosity of ShutdownButton status on console output.

* Introduced support for different modes on button hold:
Changed hold_repeat flag (True/False) to hold_mode (textual). "hold_repeat = True" is "hold_mode = Repeat" now.
Added new hold_mode "Postpone" (as possible in earlier PhonieBox versions)

* Added new hold_mode "SecondFunc" for a different action after hold_time (as possible in earlier PhonieBox versions)

* Added new hold_mode "SecondFuncRepeated" for repeated executions of a different action after hold_time

* Updated TwoButtonControl:
- Pass-through of all relevant SimpleButton base parameters
- Enhanced verbosity of TwoButtonControl status on console output
- Updated VolumeControl.py (though this file is completely superfluous / redundant IMHO)

* Added more detailed GPIO component documentation to README.MD
Fixed several typos and issues in several ini files

* Added more functions that can be called by GPIO controls like buttons.
Extended documentation, e.g. more example configurations.

* Added auto-conversion of old/deprecated syntax within gpiocontrol.ini entries.
Removed special (and redundant) handling for controls if (and only if) the corresponding config sections is named "VolumeControl"

* Added the __init__.py I just forgot...

* Align path of requirements.txt

* Fix in future3 github workflow

* Update README.md (#1452)

I struggled with this for the 4th time on new phoniebox installations and most pinout graphs for these card leave the cable for IRQ out and although you can read a card on python phoniebox does not read anything. With the cable in place on that pin it works like a charm from the beginning.

* Add lsof (#1457)

* Update buster-install-default.sh

* Add lsof and other missing packages

* fix-alsa on buster-lite (#1467)

* Update buster-install-default.sh

* update test for alsa-utils

* omit inapropriate version evdev==0.7.0 (#1468)

see https://pypi.org/project/evdev/

* Adding a boot volume settings to be set in startup script after reboot (#1177)

* Adding boot volume value to config and startup script #1169

* Adding boot volume value to config and startup script #1169

* startup changing to boot volume

* comment in web app changed to boot

* Prepare Readme for 2.3

* facilitate transition to bullseye (#1469)

* facilitate transition to bullseye

in order to easily support the debian upgrade path (replace `buster` with `bullseye` in `/etc/apt/sources.list` and `/etc/apt/sources.list.d/*`)
this change helps transition from `php7.3` on buster to `php7.4` on bullseye
and use python3 for python which is valid on bullseye

* Update buster-install-default.sh

* Update buster-install-default.sh

* small changes: head -n and file prefix (#1423)

* replace head -1 by head -n 1 since this notation is depricated

* replace head -1 by head -n 1 since this notation is depricated

* playout_controls: my mopidy version need "file://" prefix

* Update README.md

* Update README.md

* Update README.md

* Update version-number

* Release 2.3 (#1476) (#1477)

* Fix Link in README.md

Fixes the installaion guide link in the README.md

* send mqtt data on swiped card event

actively watch for changes to Latest_RFID file and send out MQTT data

* Update README.md

* Update daemon_mqtt_client.py

* Update README.md

* Create requirements.txt

* Update README.md

* quickfix idle-watchdog with amixer

#1497

* Update gpio_settings.ini.sample

* Update gpio_settings.ini.sample

* Added sustainability notes in README

* adjust playerpauseforce

adjust playerpauseforce to only pauses when currently playing
see bug #1520

* Removed hard coded homedir from install script

* Enhanced automated tests

* Fixing permissions in docker image altuser

* Update future3.md

* Announce future3 Aplha 1 on develop branch Readme (#1547)

* Announce future3 Aplha 1

* Update version naming

* Increase server-side github flow checks for future3 branches

* Fix workflow file

* Indentation fix

* Dependency fix

* Add dependencies in future3 python + doc workflow

* Syntax fix in future3 python + doc workflow

* Path fix in future3 python + doc workflow

* Update readme: future3 is under active development and not stable yet

* [future3] Announce Alpha 2 Release

* Update README.md

The current README takes a long time to read until you understand that you should not use Version 3 in production yet. Which is why I added this link at the top - and left the version 3 part unchanged. Because it is the future and deserves presence, contributors, applause, testers and looooove

* move config settings to a dict

For more intuitive management of configuration settings, these reside in a global dict now. dict allows to comment out unused settings (like e.g. mqttCA, mqttCert, mqttKey) rather than having to set them to "".

* add "shutdownvolumereduction"

* calendar 2022

* calendar 2022

* #1309, #1451, #1691 Add user-agent to avoid 400-bad-requests from open.spotify.com.

* Readme update for future3 3.2 Beta release

* Fixed issue with reading podcasts xml including line breaks in the enclosure tag

* Fixed Comment

* Update broken 2.3 installation guide link

* fix after merge with dev

* fix(install): updates the URL and adds missing key (#1789)

* Split the line read from the deviceName.txt at ';'. (#1702)

The code snippet was copied over from Reader.py.experimental.Multi.

* Update README.md (#1626)

Fixed wrong path for 2.3 installation guide

Co-authored-by: Micz Flor <[email protected]>

* GPIO-Documentation in /docs is deprecated (#1525)

Article in the wiki has been updated, this one is deprecated -> maybe remove entirely?

* Fix git protocol for pip (#1791)

* Fix #1721

* Fix also spi installation

* Add french language to our favorite jukebox (#1793)

* fix(install): mopidy for spotify install (#1792)

* fix(install): mopidy for spotify install

* applying mopidy install fix here as well

* Create dependabot.yml

* Update dependabot.yml

* Bump actions/setup-python from 1 to 3 (#1821)

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 1 to 3.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](actions/setup-python@v1...v3)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump actions/checkout from 2 to 3 (#1822)

Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump github/codeql-action from 1 to 2 (#1820)

Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@v1...v2)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix reported duration attribute via mqtt (#1787)

* fix reportet duration via mqtt

this adjusts the regex to get  the duration attribute from the status object.

* feat: use for duration the fallback time attribute

In some cases mpd does not report the duration of a track in
the mpd status response but usually a rounded value in the time
attribute. So lets use this as fallback value.

* Update README.md

* Update README.md

* Bump actions/setup-python from 3 to 4 (#1856)

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 4.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](actions/setup-python@v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* flexible php version in variable php_ini (#1849)

Follow-up for commit "facilitate transition to bullseye".
Bug: Since bullseye uses php7.4, php.ini will not be replaced by the sample
Solution: Read folder name in /etc/php and use it in variable php_ini, keeping compatibility with buster

* Run CI also on PRs (#1845)

* Update dockerimage.yml

* Update pythonpackage.yml

* Linting markdown and Python  (#1830)

* fix flake8 warnings

* fix markdownlint

* Fix code scanning alert (#1802)

Fixes https://github.com/MiczFlor/RPi-Jukebox-RFID/security/code-scanning/1

* Update version to 2.4

* Fix Command Injection and XSS vulnerabilities in trackEdit.php (#1862)

Signed-off-by: AL-KASSAR <[email protected]>

* feature: add repeat mode attribute to mqtt (#1807)

* feat: add repeat mode to mqtt attributes

* refactor: removes duplicated function

* docs: adds repeat_mode attribute to README

* refactor: extract method outside of main function

* chore: remove more duplicated code

* Bump php-mock/php-mock-phpunit from 2.5.0 to 2.6.1 (#1891)

Bumps [php-mock/php-mock-phpunit](https://github.com/php-mock/php-mock-phpunit) from 2.5.0 to 2.6.1.
- [Release notes](https://github.com/php-mock/php-mock-phpunit/releases)
- [Commits](php-mock/php-mock-phpunit@2.5.0...2.6.1)

---
updated-dependencies:
- dependency-name: php-mock/php-mock-phpunit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump phpunit/phpunit from 8.5.30 to 9.5.25 (#1899)

Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 8.5.30 to 9.5.25.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/main/ChangeLog-8.5.md)
- [Commits](sebastianbergmann/phpunit@8.5.30...9.5.25)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Fix missing ps package

* Fix badges

* fix markdown warnings (#1902)

* fix flake8 warnings

* fix markdownlint

* fix markdown lint warnings

* Bump phpunit/phpunit from 9.5.25 to 9.5.26 (#1905)

Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.5.25 to 9.5.26.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/main/ChangeLog-9.5.md)
- [Commits](sebastianbergmann/phpunit@9.5.25...9.5.26)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update README.md for 2.4 (#1904)

* fix flake8 warnings

* fix markdownlint

* fix markdown lint warnings

* merge recent updates in install script buster-install-default-with-autohotspot.sh

* fix flake8 warnings

* prepare README.md for 2.4 release and little cleanup

* update buster-install-default-with-autohotspot.sh to recent changes (#1903)

* fix flake8 warnings

* fix markdownlint

* fix markdown lint warnings

* merge recent updates in install script buster-install-default-with-autohotspot.sh

* fix flake8 warnings

* dont use pytest-pythonpath anymore (obsolete)

* revert last commit

* Update README.md

Signed-off-by: AL-KASSAR <[email protected]>
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: veloxidSchweiz <[email protected]>
Co-authored-by: Schneelocke <[email protected]>
Co-authored-by: Micz Flor <[email protected]>
Co-authored-by: StefanMinke <[email protected]>
Co-authored-by: jrn <[email protected]>
Co-authored-by: Schneelocke <[email protected]>
Co-authored-by: ChrisSoc <[email protected]>
Co-authored-by: ChrisSoc <pi@exaberry>
Co-authored-by: miohna <[email protected]>
Co-authored-by: miohna <[email protected]>
Co-authored-by: jeripeierSBB <[email protected]>
Co-authored-by: Dominik Ach <[email protected]>
Co-authored-by: Florian Bachmann <[email protected]>
Co-authored-by: manajoe <[email protected]>
Co-authored-by: ChisSoc <[email protected]>
Co-authored-by: Patrick Beer <[email protected]>
Co-authored-by: Stefan Caliandro <[email protected]>
Co-authored-by: arne123 <[email protected]>
Co-authored-by: damaev <[email protected]>
Co-authored-by: DCH <[email protected]>
Co-authored-by: Varac <[email protected]>
Co-authored-by: [email protected] <[email protected]>
Co-authored-by: T0bi79 <[email protected]>
Co-authored-by: Tobias L. Maier <[email protected]>
Co-authored-by: Kiriakos Antoniadis <[email protected]>
Co-authored-by: Michael Weinrich <[email protected]>
Co-authored-by: bart1 <[email protected]>
Co-authored-by: Patrick Beer <[email protected]>
Co-authored-by: T0bi79 <[email protected]>
Co-authored-by: sebrep <[email protected]>
Co-authored-by: t0b3 <[email protected]>
Co-authored-by: TRO <[email protected]>
Co-authored-by: robinjoerke <[email protected]>
Co-authored-by: Andreas Brett <[email protected]>
Co-authored-by: Philipp <[email protected]>
Co-authored-by: tobiasb <tobiasb@tobias-pc>
Co-authored-by: lenlennart <[email protected]>
Co-authored-by: Groovylein <[email protected]>
Co-authored-by: Groovylein <[email protected]>
Co-authored-by: pabera <[email protected]>
Co-authored-by: Andreas Brett <[email protected]>
Co-authored-by: u230412 <[email protected]>
Co-authored-by: Stephan Kessler <[email protected]>
Co-authored-by: Charles Vestal <[email protected]>
Co-authored-by: Peter Grauvogel <[email protected]>
Co-authored-by: climbit <[email protected]>
Co-authored-by: Christian Erhardt <[email protected]>
Co-authored-by: guidjome <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: David K <[email protected]>
Co-authored-by: notapirate <[email protected]>
Co-authored-by: Feras Al-Kassar <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants