From 14552bd3da25a4957d8f4fa89c3fc2bd92f76cfb Mon Sep 17 00:00:00 2001
From: arne
Systembefehle gelöscht.
"; $lang['cardImportFileDeleteMessageAudio'] = "Audio Verknüpfungen gelöscht.
"; - -/* -* "Track bearbeiten"-Formular -*/ $lang['trackEditTitle'] = "Track-Management"; $lang['trackEditInformation'] = "Track-Informationen"; $lang['trackEditMove'] = "Track verschieben"; @@ -202,10 +175,6 @@ $lang['trackEditDeleteHelp'] = "Es gibt kein Rückgängigmachen für gelöschte Dateien. Sie sind weg! Bist du sicher?"; $lang['trackEditDeleteNo'] = "Diesen Track NICHT löschen"; $lang['trackEditDeleteYes'] = "Ja, diesen Track LÖSCHEN"; - -/* -* Einstellungen -*/ $lang['settingsVolChangePercent'] = "Lautst. Änderung"; $lang['settingsMaxVol'] = "Max. Lautstärke"; $lang['settingsStartupVol'] = "Start-Lautstärke"; @@ -238,17 +207,12 @@ $lang['settingsWlanSendEmail'] = "E-Mail Adr."; $lang['settingsWlanSendON'] = "Ja, E-Mail senden."; $lang['settingsWlanSendOFF'] = "Nein, E-Mail nicht senden."; - - +$lang['settingsVolumeManager'] = "Select volume manager"; $lang['settingsWlanReadNav'] = "Wlan IP vorlesen"; $lang['settingsWlanReadInfo'] = "Wlan IP bei jedem Systemstart vorlesen? (nützlich wenn du deine Phoniebox in ein neues Wlan-Netzwerk mit dynamischer IP verbindest)"; $lang['settingsWlanReadQuest'] = "Wlan IP vorlesen?"; $lang['settingsWlanReadON'] = "Ja, Wlan IP vorlesen."; $lang['settingsWlanReadOFF'] = "Nein, Wlan IP nicht vorlesen."; - -/* -* Systeminformationen -*/ $lang['infoOsDistrib'] = "Betriebssystem"; $lang['infoOsCodename'] = "Codename"; $lang['infoOsTemperature'] = "Temperatur"; @@ -259,10 +223,6 @@ $lang['infoDebugLogTail'] = "DEBUG Logdatei: Letzte 40 Zeilen"; $lang['infoDebugLogClear'] = "Lösche Inhalt von debug.log"; $lang['infoDebugLogSettings'] = "Debug Log Einstellungen"; - -/* -* Ordnerverwaltung und Dateien hochladen -*/ $lang['manageFilesFoldersTitle'] = "Ordner & Dateien"; $lang['manageFilesFoldersUploadFilesLabel'] = "Dateien von deinem Laufwerk auswählen"; $lang['manageFilesFoldersUploadLegend'] = "Dateien hochladen"; @@ -278,22 +238,13 @@ $lang['manageFilesFoldersErrorNewFolderNotParent'] = "Der übergeordnete Ordner existiert nicht.
"; $lang['manageFilesFoldersSuccessNewFolder'] = "Neuer Ordner erstellt: "; $lang['manageFilesFoldersSelectDefault'] = "--Wählen--, um einen Ordner auszuwählen und/oder einen neuen Unterordner zu erstellen"; - $lang['manageFilesFoldersRenewDB'] = "Datenbank erneuern"; $lang['manageFilesFoldersLocalScan'] = "Musikbibliothek scannen"; $lang['manageFilesFoldersRenewDBinfo'] = "Bitte scanne deine Musikbibliothek, nachdem du neue Dateien hochgeladen oder Ordner verschoben hast. Der Scan ist nicht notwendig, um Musik zu hören, aber es ist notwendig, um Track-Informationen in der Web-Oberfläche zu sehen. Es werden nur neue oder verschobene Dateien gescannt. Während der Scan läuft, wird Mopidy gestoppt. Nach Abschluss des Scans startet Mopidy automatisch neu. Den Serverstatus siehst du im Abschnitt Info."; - -/* -* Dateisuche -*/ $lang['searchTitle'] = "Audiodateien suchen"; $lang['searchExample'] = "z.B. Moonlight"; $lang['searchSend'] = "Suchen"; $lang['searchResult'] = "Suchergebnisse:"; - -/* -* Filter -*/ $lang['filterall'] = "Zeige alle"; $lang['filterfile'] = "Dateien"; $lang['filterlivestream'] = "Livestream"; diff --git a/htdocs/phpinfo.php b/htdocs/phpinfo.php new file mode 100644 index 000000000..554a22c8b --- /dev/null +++ b/htdocs/phpinfo.php @@ -0,0 +1,5 @@ + diff --git a/scripts/Reader.py b/scripts/Reader.py index 3b583da4b..1db4af167 100755 --- a/scripts/Reader.py +++ b/scripts/Reader.py @@ -1,63 +1,168 @@ #!/usr/bin/env python3 -# There are a variety of RFID readers out there, USB and non-USB variants. -# This might create problems in recognizing the reader you are using. -# We haven't found the silver bullet yet. If you can contribute to this -# quest, please comment in the issue thread or create pull requests. -# ALTERNATIVE SCRIPTS: -# If you encounter problems with this script Reader.py -# consider and test one of the alternatives in the same scripts folder. -# Replace the Reader.py file with one of the following files: -# * Reader.py.experimental -# This alternative Reader.py script was meant to cover not only USB readers but more. -# It can be used to replace Reader.py if you have readers such as -# MFRC522, RDM6300 or PN532. -# * Reader.py.kkmoonRFIDreader -# KKMOON RFID Reader which appears twice in the devices list as HID 413d:2107 -# and this required to check "if" the device is a keyboard. - -# import string -# import csv +# This alternative Reader.py script was meant to cover not only USB readers but more. +# It can be used to replace Reader.py if you have readers such as +# MFRC522, RDM6300 or PN532. +# Please use the github issue threads to share bugs and improvements +# or create pull requests. + import os.path import sys +import serial +import string +import RPi.GPIO as GPIO +import logging + +from evdev import InputDevice, categorize, ecodes, list_devices +# Workaround: when using RC522 reader with pirc522 pkg the py532lib pkg may not be installed and vice-versa +try: + import pirc522 + from py532lib.i2c import * + from py532lib.mifare import * +except ImportError: + pass -from evdev import InputDevice, ecodes, list_devices -from select import select +logger = logging.getLogger(__name__) def get_devices(): - return [InputDevice(fn) for fn in list_devices()] + devices = [InputDevice(fn) for fn in list_devices()] + devices.append(NonUsbDevice('MFRC522')) + devices.append(NonUsbDevice('RDM6300')) + devices.append(NonUsbDevice('PN532')) + return devices -class Reader: - reader = None +class NonUsbDevice(object): + name = None - def __init__(self): - self.reader = self - path = os.path.dirname(os.path.realpath(__file__)) + def __init__(self, name): + self.name = name + + +class UsbReader(object): + def __init__(self, device): self.keys = "X^1234567890XXXXqwertzuiopXXXXasdfghjklXXXXXyxcvbnmXXXXXXXXXXXXXXXXXXXXXXX" - if not os.path.isfile(path + '/deviceName.txt'): - sys.exit('Please run RegisterDevice.py first') - else: - with open(path + '/deviceName.txt', 'r') as f: - deviceName = f.read() - devices = get_devices() - for device in devices: - if device.name == deviceName: - self.dev = device - break - try: - self.dev - except: - sys.exit('Could not find the device %s\n. Make sure is connected' % deviceName) + self.dev = device def readCard(self): + from select import select stri = '' key = '' while key != 'KEY_ENTER': - r, w, x = select([self.dev], [], []) + select([self.dev], [], []) for event in self.dev.read(): if event.type == 1 and event.value == 1: stri += self.keys[event.code] - # print( keys[ event.code ] ) key = ecodes.KEY[event.code] return stri[:-1] + + +class Mfrc522Reader(object): + def __init__(self): + self.device = pirc522.RFID() + + def readCard(self): + # Scan for cards + self.device.wait_for_tag() + (error, tag_type) = self.device.request() + + if not error: + logger.info("Card detected.") + # Perform anti-collision detection to find card uid + (error, uid) = self.device.anticoll() + if not error: + card_id = ''.join((str(x) for x in uid)) + logger.info(card_id) + return card_id + logger.debug("No Device ID found.") + return None + + @staticmethod + def cleanup(): + GPIO.cleanup() + + +class Rdm6300Reader: + def __init__(self): + device = '/dev/ttyS0' + baudrate = 9600 + ser_timeout = 0.1 + self.last_card_id = '' + try: + self.rfid_serial = serial.Serial(device, baudrate, timeout=ser_timeout) + except serial.SerialException as e: + logger.error(e) + exit(1) + + def readCard(self): + byte_card_id = b'' + + try: + while True: + try: + read_byte = self.rfid_serial.read() + + if read_byte == b'\x02': # start byte + while read_byte != b'\x03': # end bye + read_byte = self.rfid_serial.read() + byte_card_id += read_byte + + card_id = byte_card_id.decode('utf-8') + byte_card_id = '' + card_id = ''.join(x for x in card_id if x in string.printable) + + # Only return UUIDs with correct length + if len(card_id) == 12 and card_id != self.last_card_id: + self.last_card_id = card_id + self.rfid_serial.reset_input_buffer() + return self.last_card_id + + else: # wrong UUID length or already send that UUID last time + self.rfid_serial.reset_input_buffer() + + except ValueError as ve: + logger.errror(ve) + + except serial.SerialException as se: + logger.error(se) + + def cleanup(self): + self.rfid_serial.close() + + +class Pn532Reader: + def __init__(self): + pn532 = Pn532_i2c() + self.device = Mifare() + self.device.SAMconfigure() + self.device.set_max_retries(MIFARE_WAIT_FOR_ENTRY) + + def readCard(self): + return str(+int('0x' + self.device.scan_field().hex(), 0)) + + def cleanup(self): + # Not sure if something needs to be done here. + logger.debug("PN532Reader clean up.") + + +class Reader(object): + def __init__(self): + path = os.path.dirname(os.path.realpath(__file__)) + if not os.path.isfile(path + '/deviceName.txt'): + sys.exit('Please run RegisterDevice.py first') + else: + with open(path + '/deviceName.txt', 'r') as f: + device_name = f.read() + + if device_name == 'MFRC522': + self.reader = Mfrc522Reader() + elif device_name == 'RDM6300': + self.reader = Rdm6300Reader() + elif device_name == 'PN532': + self.reader = Pn532Reader() + else: + try: + device = [device for device in get_devices() if device.name == device_name][0] + self.reader = UsbReader(device) + except IndexError: + sys.exit('Could not find the device %s.\n Make sure it is connected' % device_name) diff --git a/scripts/Reader.py.experimental b/scripts/Reader.py.experimental deleted file mode 100755 index 1db4af167..000000000 --- a/scripts/Reader.py.experimental +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env python3 -# This alternative Reader.py script was meant to cover not only USB readers but more. -# It can be used to replace Reader.py if you have readers such as -# MFRC522, RDM6300 or PN532. -# Please use the github issue threads to share bugs and improvements -# or create pull requests. - -import os.path -import sys -import serial -import string -import RPi.GPIO as GPIO -import logging - -from evdev import InputDevice, categorize, ecodes, list_devices -# Workaround: when using RC522 reader with pirc522 pkg the py532lib pkg may not be installed and vice-versa -try: - import pirc522 - from py532lib.i2c import * - from py532lib.mifare import * -except ImportError: - pass - -logger = logging.getLogger(__name__) - - -def get_devices(): - devices = [InputDevice(fn) for fn in list_devices()] - devices.append(NonUsbDevice('MFRC522')) - devices.append(NonUsbDevice('RDM6300')) - devices.append(NonUsbDevice('PN532')) - return devices - - -class NonUsbDevice(object): - name = None - - def __init__(self, name): - self.name = name - - -class UsbReader(object): - def __init__(self, device): - self.keys = "X^1234567890XXXXqwertzuiopXXXXasdfghjklXXXXXyxcvbnmXXXXXXXXXXXXXXXXXXXXXXX" - self.dev = device - - def readCard(self): - from select import select - stri = '' - key = '' - while key != 'KEY_ENTER': - select([self.dev], [], []) - for event in self.dev.read(): - if event.type == 1 and event.value == 1: - stri += self.keys[event.code] - key = ecodes.KEY[event.code] - return stri[:-1] - - -class Mfrc522Reader(object): - def __init__(self): - self.device = pirc522.RFID() - - def readCard(self): - # Scan for cards - self.device.wait_for_tag() - (error, tag_type) = self.device.request() - - if not error: - logger.info("Card detected.") - # Perform anti-collision detection to find card uid - (error, uid) = self.device.anticoll() - if not error: - card_id = ''.join((str(x) for x in uid)) - logger.info(card_id) - return card_id - logger.debug("No Device ID found.") - return None - - @staticmethod - def cleanup(): - GPIO.cleanup() - - -class Rdm6300Reader: - def __init__(self): - device = '/dev/ttyS0' - baudrate = 9600 - ser_timeout = 0.1 - self.last_card_id = '' - try: - self.rfid_serial = serial.Serial(device, baudrate, timeout=ser_timeout) - except serial.SerialException as e: - logger.error(e) - exit(1) - - def readCard(self): - byte_card_id = b'' - - try: - while True: - try: - read_byte = self.rfid_serial.read() - - if read_byte == b'\x02': # start byte - while read_byte != b'\x03': # end bye - read_byte = self.rfid_serial.read() - byte_card_id += read_byte - - card_id = byte_card_id.decode('utf-8') - byte_card_id = '' - card_id = ''.join(x for x in card_id if x in string.printable) - - # Only return UUIDs with correct length - if len(card_id) == 12 and card_id != self.last_card_id: - self.last_card_id = card_id - self.rfid_serial.reset_input_buffer() - return self.last_card_id - - else: # wrong UUID length or already send that UUID last time - self.rfid_serial.reset_input_buffer() - - except ValueError as ve: - logger.errror(ve) - - except serial.SerialException as se: - logger.error(se) - - def cleanup(self): - self.rfid_serial.close() - - -class Pn532Reader: - def __init__(self): - pn532 = Pn532_i2c() - self.device = Mifare() - self.device.SAMconfigure() - self.device.set_max_retries(MIFARE_WAIT_FOR_ENTRY) - - def readCard(self): - return str(+int('0x' + self.device.scan_field().hex(), 0)) - - def cleanup(self): - # Not sure if something needs to be done here. - logger.debug("PN532Reader clean up.") - - -class Reader(object): - def __init__(self): - path = os.path.dirname(os.path.realpath(__file__)) - if not os.path.isfile(path + '/deviceName.txt'): - sys.exit('Please run RegisterDevice.py first') - else: - with open(path + '/deviceName.txt', 'r') as f: - device_name = f.read() - - if device_name == 'MFRC522': - self.reader = Mfrc522Reader() - elif device_name == 'RDM6300': - self.reader = Rdm6300Reader() - elif device_name == 'PN532': - self.reader = Pn532Reader() - else: - try: - device = [device for device in get_devices() if device.name == device_name][0] - self.reader = UsbReader(device) - except IndexError: - sys.exit('Could not find the device %s.\n Make sure it is connected' % device_name) diff --git a/scripts/phonie_access_objects.py b/scripts/phonie_access_objects.py new file mode 100644 index 000000000..c3c34e056 --- /dev/null +++ b/scripts/phonie_access_objects.py @@ -0,0 +1,54 @@ +import zmq +import json + +class phoniebox_object_access_queue: + + def __init__(self): + #self.objects = objects + self.context = None + + def connect(self,addr= None): + if addr == None: + addr = "tcp://127.0.0.1:5555" + self.context = zmq.Context() + self.queue = self.context.socket(zmq.REQ) + self.queue.setsockopt(zmq.RCVTIMEO,200) + self.queue.setsockopt(zmq.LINGER, 200) + self.queue.connect(addr) + + def phonie_enqueue(self, request): + #todo check reqest + print (request) + self.queue.send_string(json.dumps(request)) + + print ("send:", request) + + try: + server_response = self.queue.recv() + except: + print ("somethng went wrong") + server_response = None + + return server_response + + +if __name__ == "__main__": + import time + test_objects = [{'obj':'volume','cmd':'get','param':None}, + {'obj':'volume','cmd':'set','param':{'volume':30}}, + {'obj':'volume','cmd':'set','param':{'volume':33}}, + {'obj':'volume','cmd':'set','param':{'volume':36}}] + + print ("Test Phonibox Object Acces Client") + queue = phoniebox_object_access_queue() + print ("connect") + queue.connect() + + print ("test") + for req in test_objects: + #print (req) + resp = queue.phonie_enqueue(req) + print (resp) + time.sleep(0.5) + + diff --git a/scripts/playout_controls.sh b/scripts/playout_controls.sh index 11517a065..483f1410f 100755 --- a/scripts/playout_controls.sh +++ b/scripts/playout_controls.sh @@ -10,6 +10,9 @@ # Set the date and time of now NOW=`date +%Y-%m-%d.%H:%M:%S` +mtime=`date +%s` + + # USAGE EXAMPLES: # # shutdown RPi: @@ -574,6 +577,7 @@ case $COMMAND in echo ${AUDIOVOLSTARTUP} ;; setvolumetostartup) + echo "setvolumetostartup $(expr `date +%s` - $mtime) s" if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi # check if startup-volume is disabled if [ "${AUDIOVOLSTARTUP}" == 0 ]; then @@ -582,13 +586,15 @@ case $COMMAND in # set volume level in percent if [ "${VOLUMEMANAGER}" == "amixer" ]; then # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' ${AUDIOVOLSTARTUP}% + amixer -q sset \'$AUDIOIFACENAME\' ${AUDIOVOLSTARTUP}% + echo "after amixer setvolumetostartup $(expr `date +%s` - $mtime) s" else # manage volume with mpd echo -e setvol ${AUDIOVOLSTARTUP}\\nclose | nc -w 1 localhost 6600 fi fi + echo "after setvolumetostartup $(expr `date +%s` - $mtime) s" ;; playerstop) # stop the player diff --git a/scripts/startup-scripts.sh b/scripts/startup-scripts.sh index 503c165cf..6de44f52b 100755 --- a/scripts/startup-scripts.sh +++ b/scripts/startup-scripts.sh @@ -1,5 +1,7 @@ #!/bin/bash +start_time=`date +%s` + # The absolute path to the folder whjch contains all the scripts. # Unless you are working with symlinks, leave the following line untouched. PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" @@ -12,43 +14,52 @@ if [ ! -f $PATHDATA/../settings/global.conf ]; then fi . $PATHDATA/../settings/global.conf ########################################################### -echo "Phoniebox is starting..." +echo "Phoniebox is starting...$(expr `date +%s` - $start_time) s" -cat $PATHDATA/../settings/version-number +#cat $PATHDATA/../settings/version-number -cat $PATHDATA/../settings/global.conf +#cat $PATHDATA/../settings/global.conf -echo "${AUDIOVOLSTARTUP} is the mpd startup volume" +#echo "${AUDIOVOLSTARTUP} is the mpd startup volume $(expr `date +%s` - $start_time) s" #################################### # make playists, files and folders # and shortcuts # readable and writable to all -sudo chmod -R 777 ${AUDIOFOLDERSPATH} -sudo chmod -R 777 ${PLAYLISTSFOLDERPATH} -sudo chmod -R 777 $PATHDATA/../shared/shortcuts +#sudo chmod -R 777 ${AUDIOFOLDERSPATH} +#sudo chmod -R 777 ${PLAYLISTSFOLDERPATH} +#sudo chmod -R 777 $PATHDATA/../shared/shortcuts + + +#echo "before mpd status $(expr `date +%s` - $start_time) s" ######################################### # wait until mopidy/MPD server is running STATUS=0 -while [ "$STATUS" != "ACTIVE" ]; do STATUS=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep 'OK MPD'| sed 's/^.*$/ACTIVE/'); done +while [ "$STATUS" != "ACTIVE" ]; do STATUS=$(echo -e status\\nclose | nc -w 0 localhost 6600 | grep 'OK MPD'| sed 's/^.*$/ACTIVE/'); done + + +#echo "before playout $(expr `date +%s` - $start_time) s" #################################### # check if and set volume on startup -/home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh -c=setvolumetostartup +#/home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh -c=setvolumetostartup + + +#echo "after vol $(expr `date +%s` - $start_time) s" #################### # play startup sound -mpgvolume=$((32768*${AUDIOVOLSTARTUP}/100)) -echo "${mpgvolume} is the mpg123 startup volume" -/usr/bin/mpg123 -f -${mpgvolume} /home/pi/RPi-Jukebox-RFID/shared/startupsound.mp3 +#mpgvolume=$((32768*${AUDIOVOLSTARTUP}/100)) +#echo "${mpgvolume} is the mpg123 startup volume" +#/usr/bin/mpg123 -f -${mpgvolume} /home/pi/RPi-Jukebox-RFID/shared/startupsound.mp3 ####################### # re-scan music library -mpc rescan +#mpc rescan ####################### # read out wifi config? -if [ "${READWLANIPYN}" == "ON" ]; then - /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh -c=readwifiipoverspeaker -fi +#if [ "${READWLANIPYN}" == "ON" ]; then +# /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh -c=readwifiipoverspeaker +#fi diff --git a/scripts/startup_sound.sh b/scripts/startup_sound.sh new file mode 100755 index 000000000..3ca5da787 --- /dev/null +++ b/scripts/startup_sound.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +#sleep 1.5 + +#################### +# play startup sound +mpgvolume=$((32768*50/100)) +echo "${mpgvolume} is the mpg123 startup volume" +/usr/bin/mpg123 -f -${mpgvolume} /home/pi/RPi-Jukebox-RFID/shared/startupsound.mp3 + +####################### diff --git a/scripts/test_zmq.py b/scripts/test_zmq.py new file mode 100644 index 000000000..c79df0614 --- /dev/null +++ b/scripts/test_zmq.py @@ -0,0 +1,160 @@ +import nanotime +import zmq +import json +import time + +import alsaaudio +from mpd import MPDClient + +class player_control: + def __init__(self): + self.mpd_client = MPDClient() # create client object + self.mpd_client.timeout = 0.5 # network timeout in seconds (floats allowed), default: None + self.mpd_client.idletimeout = 0.5 # timeout for fetching the result of the idle command is handled seperately, default: None + #self.mpd_client.connect("localhost", 6600) # connect to localhost:6600 + self.connect() + print("Connected to MPD Version: "+self.mpd_client.mpd_version) + + def connect(self): + self.mpd_client.connect("localhost", 6600) # connect to localhost:6600 + + def get_player_type_and_version(self, param): + return ({'tpye':'mpd','version':self.mpd_client.mpd_version}) + + def play(self, param): + try: + self.mpd_client.play() + except ConnectionError: + print ("MPD Connection Error, retry") + self.conncet() + self.mpd_client.play() + except Exception as e: + print(e) + song = self.mpd_client.currentsong() + return ({'song':song}) + + def get_current_song(self, param): + song = self.mpd_client.currentsong() + #resp = {'resp': self.mpd_client.currentsong()} + return song + +class volume_control_mpd: + def __init__(self): + print ("not yet implemented\n") + +class volume_control_alsa: + def __init__(self): + self.mixer = alsaaudio.Mixer('PCM', 0) + self.volume = 0 + #self.mixer.getvolume() + + def get(self, param): + return ({'volume':self.volume}) + + def set(self, param): + volume = param.get('volume') + if isinstance(volume, int): + if (volume < 0): volume = 0; + if (volume > 100): volume = 100; + self.volume = volume + self.mixer.setvolume(self.volume) + else: + volume = -1 + return ({'volume':volume}) + + def inc(self, param): + volume = self.volume +3 + if (volume > 100): volume = 100 + self.volume = volume + self.mixer.setvolume(self.volume) + return ({'volume':self.volume}) + + def dec(self, param): + volume = self.volume -3 + if (volume < 0): volume = 0 + self.volume = volume + self.mixer.setvolume(self.volume) + return ({'volume':self.volume}) + +class phoniebox_control: + + def __init__(self,objects): + self.objects = objects + self.context = None + + def connect(self,addr= None): + if addr == None: + addr = "tcp://127.0.0.1:5555" + self.context = zmq.Context() + self.socket = self.context.socket(zmq.REP) + self.socket.bind(addr) + self.socket.setsockopt(zmq.LINGER, 200) + + def run(self, obj, cmd, param): + run_obj = self.objects.get(obj) + + if (run_obj is not None): + run_func = getattr(run_obj,cmd,None) + if (run_func is not None): # is callable() ?? + resp = run_func(param) + print (resp) + else: + resp = {'resp': "no valid commad"} + print (resp) + else: + resp = {'resp': "no valid obj"} + print (resp) + return resp + + def process_queue(self): + #while True: + # Wait for next request from client + message = self.socket.recv() + nt = nanotime.now().nanoseconds() + + client_request=json.loads(message) + client_response = {} + + print (client_request) + + client_object = client_request.get('obj') + if (client_object != None): + client_command = client_request.get('cmd') + if (client_command != None): + client_param = client_request.get('param') + client_response['resp'] = self.run(client_object,client_command,client_param) + + client_tsp = client_request.get('tsp') + if (client_tsp != None): + client_response['total_processing_time'] = (nt - int(client_request['tsp'])) / 1000000 + print ("processing time: {:2.3f} ms".format(client_response['total_processing_time'])) + + print(client_response) + # Send reply back to client + self.socket.send_string(json.dumps(client_response)) + + return (1) + + +#def get(self): +# def func_not_found(): # just in case we dont have the function +# print 'No Function '+self.i+' Found!' +# func_name = 'function' + self.i +# func = getattr(self,func_name,func_not_found) +# func() # <-- this should work! + + +if __name__ == "__main__": + #initialize objcts + objects = {'volume':volume_control_alsa(), + 'player':player_control()} + + print ("Start Phonibox Control") + pc = phoniebox_control(objects) + pc.connect() + + print ("Start loop") + ret_ok = 1 + while (ret_ok): + ret_ok = pc.process_queue() + \ No newline at end of file diff --git a/shared/audiofolders/placeholder b/shared/audiofolders/placeholder deleted file mode 100755 index e69de29bb..000000000 From 6bb27511705d57c68c5d16b58f0bb9bd1e6898a4 Mon Sep 17 00:00:00 2001 From: arne"; print_r($rfidAvailArr); print ""; + $rfidAvailArr = parse_ini_string($rfidAvailRaw); //print "
"; print_r($rfidAvailArr); print "";*/ return $rfidAvailArr; } /******************************************/ @@ -35,7 +36,8 @@ function rfidAvailArr() { function rfidUsedArr() { $rfidUsedRaw = ""; - $fn = fopen("../settings/rfid_trigger_play.conf","r"); + + /*$fn = fopen("../settings/rfid_trigger_play.conf","r"); while(! feof($fn)) { $result = fgets($fn); // ignore commented and empty lines @@ -44,7 +46,7 @@ function rfidUsedArr() { } } fclose($fn); - $rfidUsedArr = parse_ini_string($rfidUsedRaw); //print "
"; print_r($rfidUsedArr); print ""; + $rfidUsedArr = parse_ini_string($rfidUsedRaw); //print "
"; print_r($rfidUsedArr); print "";*/ return $rfidUsedArr; } /******************************************/ From 82404b6353eee9141da4ef5c1f2b0dd1fc62da5b Mon Sep 17 00:00:00 2001 From: arne123
"; print_r($shortcutstemp); print ""; //??? -//print "
"; print_r($shortcuts); print ""; //??? - -$csv = "\"id\",\"value\"\n"; - -foreach($shortcuts as $id => $value) { - $csv .= "\"".$id."\",\"".$value."\"\n"; -} -file_put_contents($conf['path2csvtarget'], $csv); -?> \ No newline at end of file diff --git a/scripts/helperscripts/CreatePodcastsKidsDeutsch.sh b/scripts/helperscripts/CreatePodcastsKidsDeutsch.sh deleted file mode 100755 index a6cef104b..000000000 --- a/scripts/helperscripts/CreatePodcastsKidsDeutsch.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# Creates sample folders with files and streams -# inside the $AUDIOFOLDERSPATH directory - -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# ZZZ-Podcast-DLF-Kinderhoerspiele (dir) -# * podcast.txt (file) -# * http://www.kakadu.de/podcast-kinderhoerspiel.3420.de.podcast.xml (content) - -AUDIOFOLDERSPATH=`cat ../../settings/Audio_Folders_Path` - -mkdir $AUDIOFOLDERSPATH/PODCASTS - -mkdir $AUDIOFOLDERSPATH/PODCASTS/BR-Betthupferl -echo "https://feeds.br.de/betthupferl/feed.xml" > $AUDIOFOLDERSPATH/PODCASTS/BR-Betthupferl/podcast.txt - -mkdir $AUDIOFOLDERSPATH/PODCASTS/Kakadu -echo "http://www.kakadu.de/podcast-kakadu.2730.de.podcast.xml" > $AUDIOFOLDERSPATH/PODCASTS/Kakadu/podcast.txt - -mkdir $AUDIOFOLDERSPATH/PODCASTS/MDR-Figarino -echo "http://www.mdr.de/figarino/podcast/streiche102-podcast.xml" > $AUDIOFOLDERSPATH/PODCASTS/MDR-Figarino/podcast.txt - -mkdir $AUDIOFOLDERSPATH/PODCASTS/WDR-Baerenbude -echo "https://kinder.wdr.de/radio/kiraka/hoeren/podcast/baerenbude192.podcast" > $AUDIOFOLDERSPATH/PODCASTS/WDR-Baerenbude/podcast.txt - -mkdir $AUDIOFOLDERSPATH/PODCASTS/BR-Klaro-Nachrichten -echo "https://feeds.br.de/klaro-nachrichten-fuer-kinder/feed.xml" > $AUDIOFOLDERSPATH/PODCASTS/BR-Klaro-Nachrichten/podcast.txt - -mkdir $AUDIOFOLDERSPATH/PODCASTS/WDR-KiRaKa -echo "https://kinder.wdr.de/radio/kiraka/hoeren/podcast/kinderhoerspiel-podcast-108.podcast" > $AUDIOFOLDERSPATH/PODCASTS/WDR-KiRaKa/podcast.txt - -# chmod chown -sudo chown -R :www-data $AUDIOFOLDERSPATH/PODCASTS -sudo chmod -R 777 $AUDIOFOLDERSPATH/PODCASTS diff --git a/scripts/helperscripts/CreateSampleAudiofoldersStreams.sh b/scripts/helperscripts/CreateSampleAudiofoldersStreams.sh deleted file mode 100755 index e2f477873..000000000 --- a/scripts/helperscripts/CreateSampleAudiofoldersStreams.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/bash - -# Creates sample folders with files and streams -# inside the $AUDIOFOLDERSPATH directory - -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# move to this directory to make sure relative paths work -cd $PATHDATA - -# ZZZ-Podcast-DLF-Kinderhoerspiele (dir) -# * podcast.txt (file) -# * http://www.kakadu.de/podcast-kinderhoerspiel.3420.de.podcast.xml (content) - -AUDIOFOLDERSPATH=`cat ../../settings/Audio_Folders_Path` - -mkdir $AUDIOFOLDERSPATH/ZZZ/ - -mkdir $AUDIOFOLDERSPATH/ZZZ/Podcast-DLF-Kinderhoerspiele -echo "http://www.kakadu.de/podcast-kinderhoerspiel.3420.de.podcast.xml" > $AUDIOFOLDERSPATH/ZZZ/Podcast-DLF-Kinderhoerspiele/podcast.txt - -#mkdir $AUDIOFOLDERSPATH/ZZZ/Podcast-Kakadu -#echo "http://www.kakadu.de/podcast-kakadu.2730.de.podcast.xml" > $AUDIOFOLDERSPATH/ZZZ/Podcast-Kakadu/podcast.txt - -#mkdir $AUDIOFOLDERSPATH/ZZZ/Podcast-WDR-Hörspielspeicher -#echo "https://www1.wdr.de/mediathek/audio/hoerspiel-speicher/wdr_hoerspielspeicher150.podcast" > $AUDIOFOLDERSPATH/ZZZ/Podcast-WDR-Hörspielspeicher/podcast.txt - -mkdir $AUDIOFOLDERSPATH/ZZZ/This\ American\ Life\ Podcast -echo "http://feed.thisamericanlife.org/talpodcast" > $AUDIOFOLDERSPATH/ZZZ/This\ American\ Life\ Podcast/podcast.txt - -# ZZZ-LiveStream-Bayern2 (dir) -# * livestream.txt (file) -# * http://br-br2-nord.cast.addradio.de/br/br2/nord/mp3/56/stream.mp3 (content) - -mkdir $AUDIOFOLDERSPATH/ZZZ/LiveStream-Bayern2 -echo "http://br-br2-nord.cast.addradio.de/br/br2/nord/mp3/56/stream.mp3" > $AUDIOFOLDERSPATH/ZZZ/LiveStream-Bayern2/livestream.txt - -# ZZZ-MP3-StartUpSound (dir) -# * startupsound.mp3 (file) - -mkdir $AUDIOFOLDERSPATH/ZZZ/MP3-StartUpSound -cp $PATHDATA/../../misc/sampleconfigs/startupsound.mp3.sample $AUDIOFOLDERSPATH/ZZZ/MP3-StartUpSound/startupsound.mp3 - -# ZZZ MP3 Whitespace StartUpSound (dir) -# * startupsound.mp3 (file) - -mkdir $AUDIOFOLDERSPATH/ZZZ/MP3\ Whitespace\ StartUpSound -cp $PATHDATA/../../misc/sampleconfigs/startupsound.mp3.sample $AUDIOFOLDERSPATH/ZZZ/MP3\ Whitespace\ StartUpSound/startupsound.mp3 - -# ZZZ-AudioFormatsTest (dir) -# * startupsound.mp3 (file) - -mkdir $AUDIOFOLDERSPATH/ZZZ/Counting/ -cp $PATHDATA/../../misc/number* $AUDIOFOLDERSPATH/ZZZ/Counting/ - -mkdir $AUDIOFOLDERSPATH/ZZZ/ABC/ -cp $PATHDATA/../../misc/alphabet* $AUDIOFOLDERSPATH/ZZZ/ABC/ - -mkdir $AUDIOFOLDERSPATH/ZZZ/AudioFormatsTest -cp $PATHDATA/../../misc/audiofiletype* $AUDIOFOLDERSPATH/ZZZ/AudioFormatsTest/ - -########################################### -# Now doing the same with nested subfolders -mkdir $AUDIOFOLDERSPATH/ZZZ/SubMaster -cp $PATHDATA/../../misc/sampleconfigs/startupsound.mp3.sample $AUDIOFOLDERSPATH/ZZZ/SubMaster/startupsound.mp3 - -# start nested with jump back two levels -mkdir $AUDIOFOLDERSPATH/ZZZ/SubMaster/fff-threeSubs -cp $PATHDATA/../../misc/sampleconfigs/startupsound.mp3.sample $AUDIOFOLDERSPATH/ZZZ/SubMaster/fff-threeSubs/startupsound.mp3 -mkdir $AUDIOFOLDERSPATH/ZZZ/SubMaster/fff-threeSubs/twoSubs -cp $PATHDATA/../../misc/sampleconfigs/startupsound.mp3.sample $AUDIOFOLDERSPATH/ZZZ/SubMaster/fff-threeSubs/twoSubs/startupsound.mp3 -mkdir $AUDIOFOLDERSPATH/ZZZ/SubMaster/fff-threeSubs/twoSubs/oneSub -cp $PATHDATA/../../misc/sampleconfigs/startupsound.mp3.sample $AUDIOFOLDERSPATH/ZZZ/SubMaster/fff-threeSubs/twoSubs/oneSub/startupsound.mp3 - -mkdir $AUDIOFOLDERSPATH/ZZZ/SubMaster/1-LiveStream-Bayern2 -echo "http://br-br2-nord.cast.addradio.de/br/br2/nord/mp3/56/stream.mp3" > $AUDIOFOLDERSPATH/ZZZ/SubMaster/1-LiveStream-Bayern2/livestream.txt - -mkdir $AUDIOFOLDERSPATH/ZZZ/SubMaster/This\ American\ Life\ Podcast -echo "http://feed.thisamericanlife.org/talpodcast" > $AUDIOFOLDERSPATH/ZZZ/SubMaster/This\ American\ Life\ Podcast/podcast.txt - -mkdir $AUDIOFOLDERSPATH/ZZZ/SubMaster/100-MP3-StartUpSound -cp $PATHDATA/../../misc/sampleconfigs/startupsound.mp3.sample $AUDIOFOLDERSPATH/ZZZ/SubMaster/100-MP3-StartUpSound/startupsound.mp3 - -mkdir $AUDIOFOLDERSPATH/ZZZ/SubMaster/AAA\ MP3\ Whitespace\ StartUpSound -cp $PATHDATA/../../misc/sampleconfigs/startupsound.mp3.sample $AUDIOFOLDERSPATH/ZZZ/SubMaster/AAA\ MP3\ Whitespace\ StartUpSound/startupsound.mp3 - -mkdir $AUDIOFOLDERSPATH/ZZZ/SubMaster/bbb-AudioFormatsTest -cp $PATHDATA/../../misc/audiofiletype* $AUDIOFOLDERSPATH/ZZZ/SubMaster/bbb-AudioFormatsTest/ - -mkdir $AUDIOFOLDERSPATH/ZZZ/SubMaster\ Whitespaces -cp -R $AUDIOFOLDERSPATH/ZZZ/SubMaster/* $AUDIOFOLDERSPATH/ZZZ/SubMaster\ Whitespaces/ - -# chmod chown -sudo chown -R :www-data $AUDIOFOLDERSPATH/ZZZ* -sudo chmod -R 777 $AUDIOFOLDERSPATH/ZZZ* diff --git a/scripts/helperscripts/DeleteAllConfig.sh b/scripts/helperscripts/DeleteAllConfig.sh deleted file mode 100755 index dc73e08e2..000000000 --- a/scripts/helperscripts/DeleteAllConfig.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -echo "This script will delete all config files" -echo "including mpd.conf and the like." -read -r -p "Do you want to proceed? [y/N] " response -case "$response" in - [Yy][Ee][Ss]|[Yy]) - ;; - *) - echo "Exiting script." - exit - ;; -esac -echo "Proceeding and deleting." - -# these ones we MUST leave -#sudo rm /etc/sudoers -#sudo rm /etc/samba/smb.conf - -# these ones we will leave -#sudo rm /home/pi/RPi-Jukebox-RFID/htdocs/config.php -#sudo rm /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf - -# these ones we delete -sudo rm /etc/lighttpd/lighttpd.conf -sudo rm /etc/lighttpd/conf-available/15-fastcgi-php.conf -sudo rm /etc/php/7.0/fpm/php.ini -sudo rm /home/pi/RPi-Jukebox-RFID/settings/Audio_iFace_Name -sudo rm /home/pi/RPi-Jukebox-RFID/settings/Audio_Folders_Path -sudo rm /home/pi/RPi-Jukebox-RFID/settings/Audio_Volume_Change_Step -sudo rm /home/pi/RPi-Jukebox-RFID/settings/Max_Volume_Limit -sudo rm /home/pi/RPi-Jukebox-RFID/settings/Idle_Time_Before_Shutdown -sudo rm /home/pi/RPi-Jukebox-RFID/settings/Second_Swipe -sudo rm /home/pi/RPi-Jukebox-RFID/settings/Playlists_Folders_Path -sudo rm /home/pi/RPi-Jukebox-RFID/settings/ShowCover -sudo rm /home/pi/RPi-Jukebox-RFID/scripts/gpio-buttons.py -sudo rm /etc/systemd/system/phoniebox-rfid-reader.service -sudo rm /etc/systemd/system/phoniebox-startup-sound.service -sudo rm /etc/systemd/system/phoniebox-gpio-buttons.service -sudo rm /etc/systemd/system/phoniebox-idle-watchdog.service -sudo rm /etc/systemd/system/rfid-reader.service -sudo rm /etc/systemd/system/startup-sound.service -sudo rm /etc/systemd/system/gpio-buttons.service -sudo rm /etc/systemd/system/idle-watchdog.service -sudo rm /etc/mpd.conf -sudo rm /etc/locale.gen -sudo rm /etc/default/locale -sudo rm /etc/mopidy/mopidy.conf -sudo rm ~/.config/mopidy/mopidy.conf diff --git a/scripts/helperscripts/DeleteSampleAudiofoldersStreams.sh b/scripts/helperscripts/DeleteSampleAudiofoldersStreams.sh deleted file mode 100755 index 5ae62290c..000000000 --- a/scripts/helperscripts/DeleteSampleAudiofoldersStreams.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# Deletes sample folders with files and streams -# inside the $AUDIOFOLDERSPATH directory - -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -AUDIOFOLDERSPATH=`cat ../../settings/Audio_Folders_Path` - -sudo rm -rf $AUDIOFOLDERSPATH/ZZZ\ MP3\ Whitespace\ StartUpSound -sudo rm -rf $AUDIOFOLDERSPATH/ZZZ\ SubMaster\ Whitespaces -sudo rm -rf $AUDIOFOLDERSPATH/ZZZ\ This\ American\ Life\ Podcast -sudo rm -rf $AUDIOFOLDERSPATH/ZZZ-AudioFormatsTest -sudo rm -rf $AUDIOFOLDERSPATH/ZZZ-LiveStream-Bayern2 -sudo rm -rf $AUDIOFOLDERSPATH/ZZZ-MP3-StartUpSound -sudo rm -rf $AUDIOFOLDERSPATH/ZZZ-Podcast-DLF-Kinderhoerspiele -sudo rm -rf $AUDIOFOLDERSPATH/ZZZ-SubMaster diff --git a/scripts/helperscripts/autohotspot b/scripts/helperscripts/autohotspot deleted file mode 100755 index af64f1dbf..000000000 --- a/scripts/helperscripts/autohotspot +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/bash -#version 0.95-41-N/HS - -#You may share this script on the condition a reference to RaspberryConnect.com -#must be included in copies or derivatives of this script. - -#A script to switch between a wifi network and a non internet routed Hotspot -#Works at startup or with a seperate timer or manually without a reboot -#Other setup required find out more at -#http://www.raspberryconnect.com - -wifidev="wlan0" #device name to use. Default is wlan0. -#use the command: iw dev ,to see wifi interface name - -IFSdef=$IFS -cnt=0 -#These four lines capture the wifi networks the RPi is setup to use -wpassid=$(awk '/ssid="/{ print $0 }' /etc/wpa_supplicant/wpa_supplicant.conf | awk -F'ssid=' '{ print $2 }' ORS=',' | sed 's/\"/''/g' | sed 's/,$//') -wpassid=$(echo "${wpassid//[$'\r\n']}") -IFS="," -ssids=($wpassid) -IFS=$IFSdef #reset back to defaults - - -#Note:If you only want to check for certain SSIDs -#Remove the # in in front of ssids=('mySSID1'.... below and put a # infront of all four lines above -# separated by a space, eg ('mySSID1' 'mySSID2') -#ssids=('mySSID1' 'mySSID2' 'mySSID3') - -#Enter the Routers Mac Addresses for hidden SSIDs, seperated by spaces ie -#( '11:22:33:44:55:66' 'aa:bb:cc:dd:ee:ff' ) -mac=() - -ssidsmac=("${ssids[@]}" "${mac[@]}") #combines ssid and MAC for checking - -createAdHocNetwork() -{ - echo "Creating Hotspot" - ip link set dev "$wifidev" down - ip a add 10.0.0.5/24 brd + dev "$wifidev" - ip link set dev "$wifidev" up - dhcpcd -k "$wifidev" >/dev/null 2>&1 - systemctl start dnsmasq - systemctl start hostapd -} - -KillHotspot() -{ - echo "Shutting Down Hotspot" - ip link set dev "$wifidev" down - systemctl stop hostapd - systemctl stop dnsmasq - ip addr flush dev "$wifidev" - ip link set dev "$wifidev" up - dhcpcd -n "$wifidev" >/dev/null 2>&1 -} - -ChkWifiUp() -{ - echo "Checking WiFi connection ok" - sleep 20 #give time for connection to be completed to router - if ! wpa_cli -i "$wifidev" status | grep 'ip_address' >/dev/null 2>&1 - then #Failed to connect to wifi (check your wifi settings, password etc) - echo 'Wifi failed to connect, falling back to Hotspot.' - wpa_cli terminate "$wifidev" >/dev/null 2>&1 - createAdHocNetwork - fi -} - - -FindSSID() -{ -#Check to see what SSID's and MAC addresses are in range -ssidChk=('NoSSid') -i=0; j=0 -until [ $i -eq 1 ] #wait for wifi if busy, usb wifi is slower. -do - ssidreply=$((iw dev "$wifidev" scan ap-force | egrep "^BSS|SSID:") 2>&1) >/dev/null 2>&1 - echo "SSid's in range: " $ssidreply - echo "Device Available Check try " $j - if (($j >= 10)); then #if busy 10 times goto hotspot - echo "Device busy or unavailable 10 times, going to Hotspot" - ssidreply="" - i=1 - elif echo "$ssidreply" | grep "No such device (-19)" >/dev/null 2>&1; then - echo "No Device Reported, try " $j - NoDevice - elif echo "$ssidreply" | grep "Network is down (-100)" >/dev/null 2>&1 ; then - echo "Network Not available, trying again" $j - j=$((j + 1)) - sleep 2 - elif echo "$ssidreply" | grep "Read-only file system (-30)" >/dev/null 2>&1 ; then - echo "Temporary Read only file system, trying again" - j=$((j + 1)) - sleep 2 - elif echo "$ssidreply" | grep "Invalid exchange (-52)" >/dev/null 2>&1 ; then - echo "Temporary unavailable, trying again" - j=$((j + 1)) - sleep 2 - elif ! echo "$ssidreply" | grep "resource busy (-16)" >/dev/null 2>&1 ; then - echo "Device Available, checking SSid Results" - i=1 - else #see if device not busy in 2 seconds - echo "Device unavailable checking again, try " $j - j=$((j + 1)) - sleep 2 - fi -done - -for ssid in "${ssidsmac[@]}" -do - if (echo "$ssidreply" | grep "$ssid") >/dev/null 2>&1 - then - #Valid SSid found, passing to script - echo "Valid SSID Detected, assesing Wifi status" - ssidChk=$ssid - return 0 - else - #No Network found, NoSSid issued" - echo "No SSid found, assessing WiFi status" - ssidChk='NoSSid' - fi -done -} - -NoDevice() -{ - #if no wifi device,ie usb wifi removed, activate wifi so when it is - #reconnected wifi to a router will be available - echo "No wifi device connected" - wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 - exit 1 -} - -FindSSID - -#Create Hotspot or connect to valid wifi networks -if [ "$ssidChk" != "NoSSid" ] -then - if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 - then #hotspot running and ssid in range - KillHotspot - echo "Hotspot Deactivated, Bringing Wifi Up" - wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 - ChkWifiUp - elif { wpa_cli -i "$wifidev" status | grep 'ip_address'; } >/dev/null 2>&1 - then #Already connected - echo "Wifi already connected to a network" - else #ssid exists and no hotspot running connect to wifi network - echo "Connecting to the WiFi Network" - wpa_supplicant -B -i "$wifidev" -c /etc/wpa_supplicant/wpa_supplicant.conf >/dev/null 2>&1 - ChkWifiUp - fi -else #ssid or MAC address not in range - if systemctl status hostapd | grep "(running)" >/dev/null 2>&1 - then - echo "Hostspot already active" - elif { wpa_cli status | grep "$wifidev"; } >/dev/null 2>&1 - then - echo "Cleaning wifi files and Activating Hotspot" - wpa_cli terminate >/dev/null 2>&1 - ip addr flush "$wifidev" - ip link set dev "$wifidev" down - rm -r /var/run/wpa_supplicant >/dev/null 2>&1 - createAdHocNetwork - else #"No SSID, activating Hotspot" - createAdHocNetwork - fi -fi diff --git a/scripts/helperscripts/cli_ReadWifiIp.php b/scripts/helperscripts/cli_ReadWifiIp.php deleted file mode 100755 index 17ead8364..000000000 --- a/scripts/helperscripts/cli_ReadWifiIp.php +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/php - diff --git a/scripts/idle-watchdog-countdown.sh b/scripts/idle-watchdog-countdown.sh deleted file mode 100755 index ad3708ffd..000000000 --- a/scripts/idle-watchdog-countdown.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -# This is a mpd idle watchdog to shutdown the box. -# -# Phonieboxes without reliable system time can use this idle-watchdog-script to -# shutdown the box after a pre defined number of minutes. -# This script checks every 60 seconds if mpd is paying music with volume set to -# greater than 0. If not it decreases the pre-defined number of minutes and shut -# down the box if it reaches zero. -# Be aware that playing lots of short sequences (less than 60 seconds) could be -# undetected by this script and lead to an unwanted shutdown. - -# Check for idle time settings. Assume to disable automatic shudown if not set. -if [ ! -r ./settings/Idle_Time_Before_Shutdown ]; then - logger "Idle_Time_Before_Shutdown is not set. Disable idle watchdog!" - exit 0 -else - SHUTDOWNAFTER=$(cat ./settings/Idle_Time_Before_Shutdown | head -n 1) -fi - -# Check if setting is a numeric value; else warn and disable watchdog. -[ "$SHUTDOWNAFTER" -eq "$SHUTDOWNAFTER" ] 2>/dev/null -if [ $? -ne 0 ]; then - logger "Invalid settings for Idle_Time_Before_Shutdown (not numeric). Disable idle watchdog!" - exit 0 -fi - -COUNTDOWN=$SHUTDOWNAFTER # initialize countdown value - -# start the continuous loop -while [ $SHUTDOWNAFTER -gt 0 ]; do - # check if mpd is playing and volume is not 0 - if [ $(mpc | egrep -c '^\[playing\]') -eq 1 ] && [ $(mpc | egrep -c '^volume:\s+0%') -eq 0 ]; then - if [ $COUNTDOWN -ne $SHUTDOWNAFTER ]; then - logger "mpd is playing audible again. Stop countdown to shutdown." - fi - COUNTDOWN=$SHUTDOWNAFTER # re-init countdown - else - if [ $COUNTDOWN -gt 0 ]; then - logger "mpd is NOT playing audible. Shutdown in $COUNTDOWN minutes." - else - logger "mpd was NOT playing audible for $SHUTDOWNAFTER minutes. Shutdown system!" - ./scripts/playout_controls.sh -c=shutdownsilent - exit 0 - fi - COUNTDOWN=$(expr $COUNTDOWN - 1) - fi - sleep 60 -done - -exit 0 diff --git a/scripts/idle-watchdog.sh b/scripts/idle-watchdog.sh deleted file mode 100755 index c4e721474..000000000 --- a/scripts/idle-watchdog.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -#Remove old shutdown commands from all 'at' queues after boot to prevent immediate shutdown -for i in `sudo atq | awk '{print $1}'`;do sudo atrm $i;done -#Give the RPi enough time to get the correct time via network -#Otherwise there may be an immediate shutdown because this script may set a shutdown time dated in the past -#in the first loop. If the Pi gets a correct time via network, "at" suddenly detects a overdue job, which is: -#shutting down the Pi. -sleep 60 - -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -# Idle time after the RPi will be shut down. 0=turn off feature. -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Idle_Time_Before_Shutdown ]; then - echo "0" > $PATHDATA/../settings/Idle_Time_Before_Shutdown -fi -# 2. then|or read value from file -IDLETIME=`cat $PATHDATA/../settings/Idle_Time_Before_Shutdown` - -#Go into infinite loop if idle time is greater 0 -while [ $IDLETIME -gt 0 ] -do - #Read volume and player status - PLAYERSTATUS=$(mpc status) - VOLPERCENT=$(echo -e "status\nclose" | nc.openbsd -w 1 localhost 6600 | grep -o -P '(?<=volume: ).*') - sleep 1 - #Set shutdown time if box is not playing or volume is 0 and no idle shutdown time is set - if { [ "$(echo "$PLAYERSTATUS" | grep -c "\[playing\]")" == "0" ] || [ $VOLPERCENT -eq "0" ]; } && [ -z "$(sudo atq -q i)" ]; - then - # shutdown pi after idling for $IDLETIME minutes - for i in `sudo atq -q i | awk '{print $1}'`;do sudo atrm $i;done - sleep 1 - echo "$PATHDATA/playout_controls.sh -c=shutdownsilent" | at -q i now + $IDLETIME minute - fi - - # If box is playing and volume is greater 0, remove idle shutdown. Skip this if "at"-queue is already empty - if [ "$(echo "$PLAYERSTATUS" | grep -c "\[playing\]")" == "1" ] && [ $VOLPERCENT -ne "0" ] && [ -n "$(sudo atq -q i)" ]; - then - for i in `sudo atq -q i | awk '{print $1}'`;do sudo atrm $i;done - fi - - sleep 60 -done diff --git a/scripts/inc.readArgsFromCommandLine.sh b/scripts/inc.readArgsFromCommandLine.sh deleted file mode 100755 index 5ed3b09ac..000000000 --- a/scripts/inc.readArgsFromCommandLine.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -# this file is called inside -# - resume_play.sh -# - rfid_trigger_play.sh -# - playout_controls.sh -# - inc.writeFolderConfig.sh -# ... and possibly more by the time you read this. -# It is meant to unify the variables which can be -# passed on to a script via the command line. - -############################################################# -# Set the date and time of now -NOW=`date +%Y-%m-%d.%H:%M:%S` - -# The absolute path to the folder whjch contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -############################################################# -# $DEBUG TRUE|FALSE -# Read debug logging configuration file -. $PATHDATA/../settings/debugLogging.conf - -for i in "$@" -do - case $i in - -i=*|--cardid=*) - CARDID="${i#*=}" - ;; - -c=*|--command=*) - COMMAND="${i#*=}" - ;; - -d=*|--dir=*) - FOLDER="${i#*=}" - ;; - -v=*|--value=*) - VALUE="${i#*=}" - ;; - esac -done - -if [ "${DEBUG_inc_readArgsFromCommandLine_sh}" == "TRUE" ]; then echo " ######### SCRIPT inc.readArgsFromCommandLine.sh ($NOW) ##" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_inc_readArgsFromCommandLine_sh}" == "TRUE" ]; then echo " # VAR CARDID: $CARDID" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_inc_readArgsFromCommandLine_sh}" == "TRUE" ]; then echo " # VAR COMMAND: $COMMAND" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_inc_readArgsFromCommandLine_sh}" == "TRUE" ]; then echo " # VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_inc_readArgsFromCommandLine_sh}" == "TRUE" ]; then echo " # VAR VALUE: $VALUE" >> $PATHDATA/../logs/debug.log; fi diff --git a/scripts/inc.settingsFolderSpecific.sh b/scripts/inc.settingsFolderSpecific.sh deleted file mode 100755 index c04380054..000000000 --- a/scripts/inc.settingsFolderSpecific.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -# This script is called when something needs to be played -# from script: playout_controls.sh -# It then looks into the settings of the folder and changes -# settings if need be, such as single track play or shuffle - -NOW=`date +%Y-%m-%d.%H:%M:%S` - -# The absolute path to the folder whjch contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -############################################################# -# $DEBUG TRUE|FALSE -# Read debug logging configuration file -. $PATHDATA/../settings/debugLogging.conf - -if [ "${DEBUG_inc_settingsFolderSpecific_sh}" == "TRUE" ]; then echo " #START### SCRIPT inc.settingsFolderSpecific.sh ($NOW) ##" >> $PATHDATA/../logs/debug.log; fi - -# Get folder name of currently played audio -if [ "x${FOLDER}" == "x" ] -then - FOLDER=$(cat $PATHDATA/../settings/Latest_Folder_Played) - - if [ "${DEBUG_inc_settingsFolderSpecific_sh}" == "TRUE" ]; then echo " # VAR FOLDER from settings/Latest_Folder_Played: $FOLDER" >> $PATHDATA/../logs/debug.log; fi -fi - -if [ -e "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" ] -then - # Read the current config file (include will execute == read) - . "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" - - if [ "${DEBUG_inc_settingsFolderSpecific_sh}" == "TRUE" ]; then echo " # Folder exists: ${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_inc_settingsFolderSpecific_sh}" == "TRUE" ]; then cat "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" >> $PATHDATA/../logs/debug.log; fi - - # SINGLE TRACK PLAY (== shuffle can not be on, because single on will play one track after another) - if [ "${DEBUG_inc_settingsFolderSpecific_sh}" == "TRUE" ]; then echo " # SINGLE TRACK PLAY: $SINGLE" >> $PATHDATA/../logs/debug.log; fi - if [ $SINGLE == "ON" ] - then - if [ "${DEBUG_inc_settingsFolderSpecific_sh}" == "TRUE" ]; then echo " # # CHANGING: mpc single on" >> $PATHDATA/../logs/debug.log; fi - mpc single on - mpc random off - else - if [ "${DEBUG_inc_settingsFolderSpecific_sh}" == "TRUE" ]; then echo " # # CHANGING: mpc single off" >> $PATHDATA/../logs/debug.log; fi - mpc single off - fi - -fi - -if [ "${DEBUG_inc_settingsFolderSpecific_sh}" == "TRUE" ]; then echo " #END##### SCRIPT inc.settingsFolderSpecific.sh ($NOW) ##" >> $PATHDATA/../logs/debug.log; fi diff --git a/scripts/inc.writeFolderConfig.sh b/scripts/inc.writeFolderConfig.sh deleted file mode 100755 index 2077462ec..000000000 --- a/scripts/inc.writeFolderConfig.sh +++ /dev/null @@ -1,160 +0,0 @@ -#!/bin/bash - -# This script is important. -# This script manages the creation and changing of folder.conf -# folder.conf sits in the audio folder and will grow over time, -# containing all infos about how to play the content -# such as loop, resume play, shuffle, elapsed time, etc. -# -# The functionality seems weird (but makes total sense:). -# This is how it works: -# 1. Since this file will be called from another bash, we can assume that -# we have same variables that need saving: check each and make a copy -# under a different name. -# 2. Read the current folder config file - now we have the vars in memory. -# 3. Create a raw config file instead of the current folder config -# which allows to replace new vars and keep the old -# 4. For each var in the config file: -# IF new var available, write this one -# ELSE write the one we read in step 2. -# -# Why so complicated? Because we don't know what other vars will be in the -# folder config in the future. Editing only the sample config file and this -# file, we are future proof, because old config files will work and update -# gracefully when new stuff arrives in the sample file. - -# We start from a sample file that contains vars like these: -# CURRENTFILENAME="%CURRENTFILENAME%" -# ELAPSED="%ELAPSED%" -# ... -# -# For complete control, the creatin of this raw config sample -# is also kept in this script and write if from here. -# So that all new vars etc. only require changing this file. - -############################################################# -# VARIABLES - -# Set the date and time of now -NOW=`date +%Y-%m-%d.%H:%M:%S` - -# The absolute path to the folder whjch contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -############################################################# -# $DEBUG TRUE|FALSE -# Read debug logging configuration file -. $PATHDATA/../settings/debugLogging.conf - -# Get args from command line. Needed for "create default folder.conf" file -# see following file for details: -. $PATHDATA/inc.readArgsFromCommandLine.sh - -# IMPORTANT: the $FOLDER var does not need to be passed on if it was set in the master script -# that calls this one. For elegance, it might be better to pass it on. -# And for error checking this might mean: if $FOLDER is not passed on, exit, do not do anything. -# If this would be preferred by you, the users, please file a ticket to discuss it. - -# path to audio folders -AUDIOFOLDERSPATH=`cat $PATHDATA/../settings/Audio_Folders_Path` - -# some debug info -if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo "########### SCRIPT inc.writeFolderConfig.sh ($NOW) ##" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo "VAR COMMAND: $COMMAND" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo "VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo "VAR AUDIOFOLDERSPATH: $AUDIOFOLDERSPATH" >> $PATHDATA/../logs/debug.log; fi - - -if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo "CHECK FOLDER EXISTS: ${AUDIOFOLDERSPATH}/${FOLDER}" >> $PATHDATA/../logs/debug.log; fi -# Only continue if $FOLDER exists -if [ -d "${AUDIOFOLDERSPATH}/${FOLDER}" ] -then - - # IF we got given the command to create a default folder.conf file - # set default vars, write file, exit - if [ $COMMAND == "createDefaultFolderConf" ] - then - if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo " !!!setting default vars for raw create!!!" >> $PATHDATA/../logs/debug.log; fi - # set default vars - CURRENTFILENAME="filename" - ELAPSED="0" - PLAYSTATUS="Stopped" - RESUME="OFF" - SHUFFLE="OFF" - LOOP="OFF" - SINGLE="OFF" - fi - - ######################################################### - # KEEP NEW VARS IN MIND - # Go through all given vars - make copy with prefix if found - if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo " KEEP NEW VARS IN MIND" >> $PATHDATA/../logs/debug.log; fi - if [ "$CURRENTFILENAME" ]; then - NEWCURRENTFILENAME="$CURRENTFILENAME"; - if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo "VAR NEWCURRENTFILENAME: $NEWCURRENTFILENAME" >> $PATHDATA/../logs/debug.log; fi - fi - if [ "$ELAPSED" ]; then NEWELAPSED="$ELAPSED"; fi - if [ "$PLAYSTATUS" ]; then NEWPLAYSTATUS="$PLAYSTATUS"; fi - if [ "$RESUME" ]; then NEWRESUME="$RESUME"; fi - if [ "$SHUFFLE" ]; then NEWSHUFFLE="$SHUFFLE"; fi - if [ "$LOOP" ]; then NEWLOOP="$LOOP"; fi - if [ "$SINGLE" ]; then NEWSINGLE="$SINGLE"; fi - if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo " KEEP SINGLE $SINGLE IN MIND" >> $PATHDATA/../logs/debug.log; fi - - # Read the current config file (include will execute == read) - . "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo " content of ${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then cat "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" >> $PATHDATA/../logs/debug.log; fi - - ######################################################### - # RAW CONFIG FILE - # Replace current config with empty sample - # write "empty" config file with vars that will be replaced later - rm "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - echo "CURRENTFILENAME=\"%CURRENTFILENAME%\"" >> "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - echo "ELAPSED=\"%ELAPSED%\"" >> "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - echo "PLAYSTATUS=\"%PLAYSTATUS%\"" >> "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - echo "RESUME=\"%RESUME%\"" >> "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - echo "SHUFFLE=\"%SHUFFLE%\"" >> "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - echo "LOOP=\"%LOOP%\"" >> "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - echo "SINGLE=\"%SINGLE%\"" >> "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - - # Let the juggle begin - - ######################################################### - # REPLACE VALUES FROM THE CONFIG FILE WITH NEW ONES - # Walk through all vars and prefer new over existing to write to config - if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo " REPLACE VALUES FROM THE CONFIG FILE WITH NEW ONES" >> $PATHDATA/../logs/debug.log; fi - if [ "$NEWCURRENTFILENAME" ]; then - CURRENTFILENAME="$NEWCURRENTFILENAME"; - if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo "VAR CURRENTFILENAME: $CURRENTFILENAME" >> $PATHDATA/../logs/debug.log; fi - fi - if [ "$NEWELAPSED" ]; then ELAPSED="$NEWELAPSED"; fi - if [ "$NEWPLAYSTATUS" ]; then PLAYSTATUS="$NEWPLAYSTATUS"; fi - if [ "$NEWRESUME" ]; then RESUME="$NEWRESUME"; fi - if [ "$NEWSHUFFLE" ]; then SHUFFLE="$NEWSHUFFLE"; fi - if [ "$NEWLOOP" ]; then LOOP="$NEWLOOP"; fi - if [ "$NEWSINGLE" ]; then SINGLE="$NEWSINGLE"; fi - - ######################################################### - # WRITE THE VALUES INTO THE NEWLY CREATED RAW CONFIG - # for $CURRENTFILENAME using | as alternate regex delimiter because of the folder path slash - if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo " WRITE THE VALUES INTO THE NEWLY CREATED RAW CONFIG" >> $PATHDATA/../logs/debug.log; fi - sudo sed -i 's|%CURRENTFILENAME%|'"$CURRENTFILENAME"'|' "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - sudo sed -i 's/%ELAPSED%/'"$ELAPSED"'/' "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - sudo sed -i 's/%PLAYSTATUS%/'"$PLAYSTATUS"'/' "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - sudo sed -i 's/%RESUME%/'"$RESUME"'/' "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - sudo sed -i 's/%SHUFFLE%/'"$SHUFFLE"'/' "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - sudo sed -i 's/%LOOP%/'"$LOOP"'/' "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - sudo sed -i 's/%SINGLE%/'"$SINGLE"'/' "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - sudo chown pi:www-data "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - sudo chmod 777 "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" - -else - if [ "${DEBUG_inc_writeFolderConfig_sh}" == "TRUE" ]; then echo "NOT FOUND: Full path to folder '${AUDIOFOLDERSPATH}/${FOLDER}'" >> $PATHDATA/../logs/debug.log; fi -fi - - - - diff --git a/scripts/inc.writeGlobalConfig.sh b/scripts/inc.writeGlobalConfig.sh deleted file mode 100755 index 85aa4c224..000000000 --- a/scripts/inc.writeGlobalConfig.sh +++ /dev/null @@ -1,380 +0,0 @@ -#!/bin/bash - -# Creates a global config file from all the individual -# files in the `settings` folder at: -# settings/global.conf -# Should be called: -# 1. on startup (list startup sound) to create a latest -# version of all settings -# 2. each settings change done in the web UI -# 3. a new feature to be implemented: manually triggered -# in the web UI -# -# Why so complicated? Because we don't know what other vars will be in the -# config in the future. Editing only this file, we are future proof, -# because old config files will work and update -# gracefully when new stuff arrives in the sample file. -# -# To make sure that the global.conf file has EVERYTHING in it -# that could be, for each feature it does the following: -# a) checks if there is a config file -# a) 1) if not, make one with the default value -# b) read the value from the config file - -# Set the date and time of now -NOW=`date +%Y-%m-%d.%H:%M:%S` - -# The absolute path to the folder which contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -############################################################# -# $DEBUG TRUE|FALSE -# Read debug logging configuration file -. $PATHDATA/../settings/debugLogging.conf - -# The absolute path to the folder which contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -if [ "${DEBUG_inc_writeGlobalConfig_sh}" == "TRUE" ]; then echo "########### SCRIPT inc.writeGlobalConf.sh ($NOW) ##" >> $PATHDATA/../logs/debug.log; fi - -# create the configuration file from sample - if it does not exist -if [ ! -f $PATHDATA/../settings/rfid_trigger_play.conf ]; then - cp $PATHDATA/../settings/rfid_trigger_play.conf.sample $PATHDATA/../settings/rfid_trigger_play.conf - # change the read/write so that later this might also be editable through the web app - sudo chown -R pi:www-data $PATHDATA/../settings/rfid_trigger_play.conf - sudo chmod -R 775 $PATHDATA/../settings/rfid_trigger_play.conf -fi - -# Path to folder containing audio / streams -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Audio_Folders_Path ]; then - echo "/home/pi/RPi-Jukebox-RFID/shared/audiofolders" > $PATHDATA/../settings/Audio_Folders_Path - chmod 777 $PATHDATA/../settings/Audio_Folders_Path -fi -# 2. then|or read value from file -AUDIOFOLDERSPATH=`cat $PATHDATA/../settings/Audio_Folders_Path` - -# Path to folder containing playlists -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Playlists_Folders_Path ]; then - echo "/home/pi/RPi-Jukebox-RFID/playlists" > $PATHDATA/../settings/Playlists_Folders_Path - chmod 777 $PATHDATA/../settings/Playlists_Folders_Path -fi -# 2. then|or read value from file -PLAYLISTSFOLDERPATH=`cat $PATHDATA/../settings/Playlists_Folders_Path` - -############################################## -# General RFID player control SWIPE OR PLACE -# General decision on how the player operates -# SWIPENOTPLACE = Swiping starts the player -# PLACENOTSWIPE = Placing the card starts player, removal stops it -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Swipe_or_Place ]; then - echo "SWIPENOTPLACE" > $PATHDATA/../settings/Swipe_or_Place - chmod 777 $PATHDATA/../settings/Swipe_or_Place -fi -# 2. then|or read value from file -SWIPEORPLACE=`cat $PATHDATA/../settings/Swipe_or_Place` - -############################################## -# Second swipe -# What happens when the same card is swiped a second time? -# RESTART => start the playlist again vs. PAUSE => toggle pause and play current -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Second_Swipe ]; then - echo "RESTART" > $PATHDATA/../settings/Second_Swipe - chmod 777 $PATHDATA/../settings/Second_Swipe -fi -# 2. then|or read value from file -SECONDSWIPE=`cat $PATHDATA/../settings/Second_Swipe` - -############################################## -# Second swipe Pause -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Second_Swipe_Pause ]; then - echo "2" > $PATHDATA/../settings/Second_Swipe_Pause - chmod 777 $PATHDATA/../settings/Second_Swipe_Pause -fi -# 2. then|or read value from file -SECONDSWIPEPAUSE=`cat $PATHDATA/../settings/Second_Swipe_Pause` - -############################################## -# Second swipe Pause Controls -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Second_Swipe_Pause_Controls ]; then - echo "ON" > $PATHDATA/../settings/Second_Swipe_Pause_Controls - chmod 777 $PATHDATA/../settings/Second_Swipe_Pause_Controls -fi -# 2. then|or read value from file -SECONDSWIPEPAUSECONTROLS=`cat $PATHDATA/../settings/Second_Swipe_Pause_Controls` - -############################################## -# Audio_iFace_Name -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Audio_iFace_Name ]; then - echo "PCM" > $PATHDATA/../settings/Audio_iFace_Name - chmod 777 $PATHDATA/../settings/Audio_iFace_Name -fi -# 2. then|or read value from file -AUDIOIFACENAME=`cat $PATHDATA/../settings/Audio_iFace_Name` - -############################################## -# Volume_Manager (mpd or amixer) -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Volume_Manager ]; then - echo "mpd" > $PATHDATA/../settings/Volume_Manager - chmod 777 $PATHDATA/../settings/Volume_Manager -fi -# 2. then|or read value from file -VOLUMEMANAGER=`cat $PATHDATA/../settings/Volume_Manager` - -############################################## -# Audio_Volume_Change_Step -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Audio_Volume_Change_Step ]; then - echo "3" > $PATHDATA/../settings/Audio_Volume_Change_Step - chmod 777 $PATHDATA/../settings/Audio_Volume_Change_Step -fi -# 2. then|or read value from file -AUDIOVOLCHANGESTEP=`cat $PATHDATA/../settings/Audio_Volume_Change_Step` - -############################################## -# Max_Volume_Limit -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Max_Volume_Limit ]; then - echo "100" > $PATHDATA/../settings/Max_Volume_Limit - chmod 777 $PATHDATA/../settings/Max_Volume_Limit -fi -# 2. then|or read value from file -AUDIOVOLMAXLIMIT=`cat $PATHDATA/../settings/Max_Volume_Limit` - -############################################## -# Min_Volume_Limit -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Min_Volume_Limit ]; then - echo "1" > $PATHDATA/../settings/Min_Volume_Limit - chmod 777 $PATHDATA/../settings/Min_Volume_Limit -fi -# 2. then|or read value from file -AUDIOVOLMINLIMIT=`cat $PATHDATA/../settings/Min_Volume_Limit` - -############################################## -# Startup_Volume -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Startup_Volume ]; then - echo "30" > $PATHDATA/../settings/Startup_Volume - chmod 777 $PATHDATA/../settings/Startup_Volume -fi -# 2. then|or read value from file -AUDIOVOLSTARTUP=`cat $PATHDATA/../settings/Startup_Volume` - -############################################## -# Change_Volume_Idle -# Change volume during idle (or only change it during Play and in the WebApp) -#TRUE=Change Volume during all Time (Default; FALSE=Change Volume only during "Play"; OnlyDown=It is possible to decrease Volume during Idle; OnlyUp=It is possible to increase Volume during Idle -# 1. create a default if file does not exist (set default do TRUE - Volume Change is possible every time) -if [ ! -f $PATHDATA/../settings/Change_Volume_Idle ]; then - echo "TRUE" > $PATHDATA/../settings/Change_Volume_Idle -fi -# 2. then|or read value from file -VOLCHANGEIDLE=`cat $PATHDATA/../settings/Change_Volume_Idle` - -############################################## -# Idle_Time_Before_Shutdown -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Idle_Time_Before_Shutdown ]; then - echo "0" > $PATHDATA/../settings/Idle_Time_Before_Shutdown - chmod 777 $PATHDATA/../settings/Idle_Time_Before_Shutdown -fi -# 2. then|or read value from file -IDLETIMESHUTDOWN=`cat $PATHDATA/../settings/Idle_Time_Before_Shutdown` - -############################################## -# Poweroff_Command -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Poweroff_Command ]; then - echo "sudo poweroff" > $PATHDATA/../settings/Poweroff_Command - chmod 777 $PATHDATA/../settings/Poweroff_Command -fi -# 2. then|or read value from file -POWEROFFCMD=`cat $PATHDATA/../settings/Poweroff_Command` - -############################################## -# ShowCover -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/ShowCover ]; then - echo "ON" > $PATHDATA/../settings/ShowCover - chmod 777 $PATHDATA/../settings/ShowCover -fi -# 2. then|or read value from file -SHOWCOVER=`cat $PATHDATA/../settings/ShowCover` - -############################################## -# Mail Wlan Ip Address -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/WlanIpMailAddr ]; then - echo "" > $PATHDATA/../settings/WlanIpMailAddr - chmod 777 $PATHDATA/../settings/WlanIpMailAddr -fi -# 2. then|or read value from file -MAILWLANIPADDR=`cat $PATHDATA/../settings/WlanIpMailAddr` - -############################################## -# Mail Wlan Ip Email Address -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/MailWlanIpYN ]; then - echo "OFF" > $PATHDATA/../settings/MailWlanIpYN - chmod 777 $PATHDATA/../settings/MailWlanIpYN -fi -# 2. then|or read value from file -MAILWLANIPYN=`cat $PATHDATA/../settings/MailWlanIpYN` - -############################################## -# Read IP address of Wlan after boot? -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/WlanIpReadYN ]; then - echo "OFF" > $PATHDATA/../settings/WlanIpReadYN - chmod 777 $PATHDATA/../settings/WlanIpReadYN -fi -# 2. then|or read value from file -READWLANIPYN=`cat $PATHDATA/../settings/WlanIpReadYN` - -############################################## -# edition -# read this always, do not write default - -# 1. create a default if file does not exist -#if [ ! -f $PATHDATA/../settings/edition ]; then -# echo "classic" > $PATHDATA/../settings/edition -# chmod 777 $PATHDATA/../settings/edition -#fi -# 2. then|or read value from file -chmod 777 $PATHDATA/../settings/edition -EDITION=`cat $PATHDATA/../settings/edition` - -############################################## -# Lang -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/Lang ]; then - echo "en-UK" > $PATHDATA/../settings/Lang - chmod 777 $PATHDATA/../settings/Lang -fi -# 2. then|or read value from file -LANG=`cat $PATHDATA/../settings/Lang` - -############################################## -# version -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/version ]; then - echo "unknown" > $PATHDATA/../settings/version - chmod 777 $PATHDATA/../settings/version -fi -# 2. then|or read value from file -VERSION=`cat $PATHDATA/../settings/version` - -############################################## -# CHAPTEREXTENSIONS -# Only files with the extensions listed will be scanned for chapters -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/CHAPTEREXTENSIONS ]; then - echo "mp4,m4a,m4b,m4r" > $PATHDATA/../settings/CHAPTEREXTENSIONS - chmod 777 $PATHDATA/../settings/CHAPTEREXTENSIONS -fi -# 2. then|or read value from file -CHAPTEREXTENSIONS=`cat $PATHDATA/../settings/CHAPTEREXTENSIONS` - -############################################## -# CHAPTERMINDURATION -# Only files with play length bigger than minimum will be scanned for chapters -# 1. create a default if file does not exist -if [ ! -f $PATHDATA/../settings/CHAPTERMINDURATION ]; then - echo "600" > $PATHDATA/../settings/CHAPTERMINDURATION - chmod 777 $PATHDATA/../settings/CHAPTERMINDURATION -fi -# 2. then|or read value from file -CHAPTERMINDURATION=`cat $PATHDATA/../settings/CHAPTERMINDURATION` - -############################################## -# read control card ids -# 1. read all values from file -CMDVOLUP=`grep 'CMDVOLUP' $PATHDATA/../settings/rfid_trigger_play.conf|tail -1|sed 's/CMDVOLUP=//g'|sed 's/"//g'|tr -d "\n"|grep -o '[0-9]*'` -CMDVOLDOWN=`grep 'CMDVOLDOWN' $PATHDATA/../settings/rfid_trigger_play.conf|tail -1|sed 's/CMDVOLDOWN=//g'|sed 's/"//g'|tr -d "\n"|grep -o '[0-9]*'` -CMDNEXT=`grep 'CMDNEXT' $PATHDATA/../settings/rfid_trigger_play.conf|tail -1|sed 's/CMDNEXT=//g'|sed 's/"//g'|tr -d "\n"|grep -o '[0-9]*'` -CMDPREV=`grep 'CMDPREV' $PATHDATA/../settings/rfid_trigger_play.conf|tail -1|sed 's/CMDPREV=//g'|sed 's/"//g'|tr -d "\n"|grep -o '[0-9]*'` -CMDREWIND=`grep 'CMDREWIND' $PATHDATA/../settings/rfid_trigger_play.conf|tail -1|sed 's/CMDREWIND=//g'|sed 's/"//g'|tr -d "\n"|grep -o '[0-9]*'` -CMDSEEKFORW=`grep 'CMDSEEKFORW' $PATHDATA/../settings/rfid_trigger_play.conf|tail -1|sed 's/CMDSEEKFORW=//g'|sed 's/"//g'|tr -d "\n"|grep -o '[0-9]*'` -CMDSEEKBACK=`grep 'CMDSEEKBACK' $PATHDATA/../settings/rfid_trigger_play.conf|tail -1|sed 's/CMDSEEKBACK=//g'|sed 's/"//g'|tr -d "\n"|grep -o '[0-9]*'` - -# AUDIOFOLDERSPATH -# PLAYLISTSFOLDERPATH -# SWIPEORPLACE -# SECONDSWIPE -# SECONDSWIPEPAUSE -# SECONDSWIPEPAUSECONTROLS -# AUDIOIFACENAME -# VOLUMEMANAGER -# AUDIOVOLCHANGESTEP -# AUDIOVOLMAXLIMIT -# AUDIOVOLMINLIMIT -# AUDIOVOLSTARTUP -# VOLCHANGEIDLE -# IDLETIMESHUTDOWN -# POWEROFFCMD -# SHOWCOVER -# MAILWLANIPYN -# MAILWLANIPADDR -# READWLANIPYN -# EDITION -# LANG -# VERSION -# CHAPTEREXTENSIONS -# CHAPTERMINDURATION -# CMDVOLUP -# CMDVOLDOWN -# CMDNEXT -# CMDPREV -# CMDREWIND -# CMDSEEKFORW -# CMDSEEKBACK - -######################################################### -# WRITE CONFIG FILE -rm "${PATHDATA}/../settings/global.conf" -echo "AUDIOFOLDERSPATH=\"${AUDIOFOLDERSPATH}\"" >> "${PATHDATA}/../settings/global.conf" -echo "PLAYLISTSFOLDERPATH=\"${PLAYLISTSFOLDERPATH}\"" >> "${PATHDATA}/../settings/global.conf" -echo "SWIPEORPLACE=\"${SWIPEORPLACE}\"" >> "${PATHDATA}/../settings/global.conf" -echo "SECONDSWIPE=\"${SECONDSWIPE}\"" >> "${PATHDATA}/../settings/global.conf" -echo "SECONDSWIPEPAUSE=\"${SECONDSWIPEPAUSE}\"" >> "${PATHDATA}/../settings/global.conf" -echo "SECONDSWIPEPAUSECONTROLS=\"${SECONDSWIPEPAUSECONTROLS}\"" >> "${PATHDATA}/../settings/global.conf" -echo "AUDIOIFACENAME=\"${AUDIOIFACENAME}\"" >> "${PATHDATA}/../settings/global.conf" -echo "VOLUMEMANAGER=\"${VOLUMEMANAGER}\"" >> "${PATHDATA}/../settings/global.conf" -echo "AUDIOVOLCHANGESTEP=\"${AUDIOVOLCHANGESTEP}\"" >> "${PATHDATA}/../settings/global.conf" -echo "AUDIOVOLMAXLIMIT=\"${AUDIOVOLMAXLIMIT}\"" >> "${PATHDATA}/../settings/global.conf" -echo "AUDIOVOLMINLIMIT=\"${AUDIOVOLMINLIMIT}\"" >> "${PATHDATA}/../settings/global.conf" -echo "AUDIOVOLSTARTUP=\"${AUDIOVOLSTARTUP}\"" >> "${PATHDATA}/../settings/global.conf" -echo "VOLCHANGEIDLE=\"${VOLCHANGEIDLE}\"" >> "${PATHDATA}/../settings/global.conf" -echo "IDLETIMESHUTDOWN=\"${IDLETIMESHUTDOWN}\"" >> "${PATHDATA}/../settings/global.conf" -echo "POWEROFFCMD=\"${POWEROFFCMD}\"" >> "${PATHDATA}/../settings/global.conf" -echo "SHOWCOVER=\"${SHOWCOVER}\"" >> "${PATHDATA}/../settings/global.conf" -echo "READWLANIPYN=\"${READWLANIPYN}\"" >> "${PATHDATA}/../settings/global.conf" -echo "EDITION=\"${EDITION}\"" >> "${PATHDATA}/../settings/global.conf" -echo "LANG=\"${LANG}\"" >> "${PATHDATA}/../settings/global.conf" -echo "VERSION=\"${VERSION}\"" >> "${PATHDATA}/../settings/global.conf" -echo "CHAPTEREXTENSIONS=\"${CHAPTEREXTENSIONS}\"" >> "${PATHDATA}/../settings/global.conf" -echo "CHAPTERMINDURATION=\"${CHAPTERMINDURATION}\"" >> "${PATHDATA}/../settings/global.conf" -echo "CMDVOLUP=\"${CMDVOLUP}\"" >> "${PATHDATA}/../settings/global.conf" -echo "CMDVOLDOWN=\"${CMDVOLDOWN}\"" >> "${PATHDATA}/../settings/global.conf" -echo "CMDNEXT=\"${CMDNEXT}\"" >> "${PATHDATA}/../settings/global.conf" -echo "CMDPREV=\"${CMDPREV}\"" >> "${PATHDATA}/../settings/global.conf" -echo "CMDREWIND=\"${CMDREWIND}\"" >> "${PATHDATA}/../settings/global.conf" -echo "CMDSEEKFORW=\"${CMDSEEKFORW}\"" >> "${PATHDATA}/../settings/global.conf" -echo "CMDSEEKBACK=\"${CMDSEEKBACK}\"" >> "${PATHDATA}/../settings/global.conf" - -# Work in progress: -#echo "MAILWLANIPYN=\"${MAILWLANIPYN}\"" >> "${PATHDATA}/../settings/global.conf" -#echo "MAILWLANIPADDR=\"${MAILWLANIPADDR}\"" >> "${PATHDATA}/../settings/global.conf" - -# change the read/write so that later this might also be editable through the web app -sudo chown -R pi:www-data ${PATHDATA}/../settings/global.conf -sudo chmod -R 777 ${PATHDATA}/../settings/global.conf diff --git a/scripts/installscripts/buster-install-default-with-autohotspot.sh b/scripts/installscripts/buster-install-default-with-autohotspot.sh deleted file mode 100755 index c7e748ab1..000000000 --- a/scripts/installscripts/buster-install-default-with-autohotspot.sh +++ /dev/null @@ -1,1427 +0,0 @@ -#!/usr/bin/env bash -# -# see https://github.com/MiczFlor/RPi-Jukebox-RFID for details -# -# NOTE: Running automated install (without interaction): -# Each install creates a file called PhonieboxInstall.conf -# in the folder /home/pi/ -# You can install the Phoniebox using such a config file -# which means you don't need to run the interactive install: -# -# 1. download the install file from github -# https://github.com/MiczFlor/RPi-Jukebox-RFID/tree/develop/scripts/installscripts -# (note: currently only works for buster and newer OS) -# 2. make the file executable: chmod +x -# 3. place the PhonieboxInstall.conf in the folder /home/pi/ -# 4. run the installscript with option -a like this: -# buster-install-default.sh -a - -# The absolute path to the folder which contains this script -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -GIT_BRANCH=${GIT_BRANCH:-master} -GIT_URL=${GIT_URL:-https://github.com/MiczFlor/RPi-Jukebox-RFID.git} -echo GIT_BRANCH $GIT_BRANCH -echo GIT_URL $GIT_URL - -DATETIME=$(date +"%Y%m%d_%H%M%S") - -SCRIPTNAME="$(basename $0)" -JOB="${SCRIPTNAME}" - -HOME_DIR="/home/pi" - -JUKEBOX_HOME_DIR="${HOME_DIR}/RPi-Jukebox-RFID" -LOGDIR="${HOME_DIR}"/phoniebox_logs -JUKEBOX_BACKUP_DIR="${HOME_DIR}/BACKUP" - -INTERACTIVE=true - -usage() { - printf "Usage: ${SCRIPTNAME} [-a] [-h]\n" - printf " -a\tautomatic/non-interactive mode\n" - printf " -h\thelp\n" - exit 0 -} - -while getopts ":ah" opt; -do - case ${opt} in - a ) INTERACTIVE=false - ;; - h ) usage - ;; - \? ) usage - ;; - esac -done - - -# Setup logger functions -# Input from http://www.ludovicocaldara.net/dba/bash-tips-5-output-logfile/ -log_open() { - [[ -d "${LOGDIR}" ]] || mkdir -p "${LOGDIR}" - PIPE="${LOGDIR}"/"${JOB}"_"${DATETIME}".pipe - mkfifo -m 700 "${PIPE}" - LOGFILE="${LOGDIR}"/"${JOB}"_"${DATETIME}".log - exec 3>&1 - tee "${LOGFILE}" <"${PIPE}" >&3 & - TEEPID=$! - exec 1>"${PIPE}" 2>&1 - PIPE_OPENED=1 -} - -log_close() { - if [ "${PIPE_OPENED}" ]; then - exec 1<&3 - sleep 0.2 - ps --pid "${TEEPID}" >/dev/null - if [ $? -eq 0 ] ; then - # a wait ${TEEPID} whould be better but some - # commands leave file descriptors open - sleep 1 - kill "${TEEPID}" - fi - rm "${PIPE}" - unset PIPE_OPENED - fi -} - - -welcome() { - clear - echo "##################################################### -# ___ __ ______ _ __________ ____ __ _ _ # -# / _ \/ // / __ \/ |/ / _/ __/( _ \ / \( \/ ) # -# / ___/ _ / /_/ / // // _/ ) _ (( O )) ( # -# /_/ /_//_/\____/_/|_/___/____/ (____/ \__/(_/\_) # -# # -##################################################### - -You are turning your Raspberry Pi into a Phoniebox. Good choice. -This INTERACTIVE INSTALL script requires you to be online and -will guide you through the configuration. - -If you want to run the AUTOMATED INSTALL (non-interactive) from -an existing configuration file, do the following: -1. exit this install script (press n) -2. place your PhonieboxInstall.conf in the folder /home/pi/ -3. run the installscript with option -a. For example like this: - ./home/pi/buster-install-default.sh -a - " - read -rp "Continue interactive installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - exit - ;; - *) - echo "Installation continues..." - ;; - esac -} - -reset_install_config_file() { - ##################################################### - # CONFIG FILE - # This file will contain all the data given in the - # following dialogue - # At a later stage, the install should also be done - # from such a config file with no user input. - - # Remove existing config file - #rm "${HOME_DIR}/PhonieboxInstall.conf" - # Create empty config file - #touch "${HOME_DIR}/PhonieboxInstall.conf" - #echo "# Phoniebox config" > "${HOME_DIR}/PhonieboxInstall.conf" - echo "# Phoniebox config" -} - -config_wifi() { - ##################################################### - # Ask if wifi config - - clear - - echo "##################################################### -# -# CONFIGURE WIFI -# -# Requires SSID, WiFi password and the static IP you want -# to assign to your Phoniebox. -# (Note: can be done manually later, if you are unsure.) -" -read -rp "Do you want to configure your WiFi? [Y/n] " response -echo "" -case "$response" in - [nN][oO]|[nN]) - WIFIconfig=NO - echo "You want to configure WiFi later." - # append variables to config file - echo "WIFIconfig=$WIFIconfig" >> "${HOME_DIR}/PhonieboxInstall.conf" - # make a fallback for WiFi Country Code, because we need that even without WiFi config - echo "WIFIcountryCode=DE" >> "${HOME_DIR}/PhonieboxInstall.conf" - ;; - *) - WIFIconfig=YES - #Ask for SSID - read -rp "* Type SSID name: " WIFIssid - #Ask for wifi country code - read -rp "* WiFi Country Code (e.g. DE, GB, CZ or US): " WIFIcountryCode - #Ask for password - read -rp "* Type password: " WIFIpass - #Ask for IP - read -rp "* Static IP (e.g. 192.168.1.199): " WIFIip - #Ask for Router IP - read -rp "* Router IP (e.g. 192.168.1.1): " WIFIipRouter - echo "" - echo "Your WiFi config:" - echo "SSID : $WIFIssid" - echo "WiFi Country Code : $WIFIcountryCode" - echo "Password : $WIFIpass" - echo "Static IP : $WIFIip" - echo "Router IP : $WIFIipRouter" - read -rp "Are these values correct? [Y/n] " response - echo "" - case "$response" in - [nN][oO]|[nN]) - echo "The values are incorrect." - read -rp "Hit ENTER to exit and start over." INPUT; exit - ;; - *) - # append variables to config file - { - echo "WIFIconfig=\"$WIFIconfig\""; - echo "WIFIcountryCode=\"$WIFIcountryCode\""; - echo "WIFIssid=\"$WIFIssid\""; - echo "WIFIpass=\"$WIFIpass\""; - echo "WIFIip=\"$WIFIip\""; - echo "WIFIipRouter=\"$WIFIipRouter\""; - } >> "${HOME_DIR}/PhonieboxInstall.conf" - ;; - esac - ;; -esac -read -rp "Hit ENTER to proceed to the next step." INPUT -} - -check_existing() { - local jukebox_dir="$1" - local backup_dir="$2" - local home_dir="$3" - - ##################################################### - # Check for existing Phoniebox - # - # In case there is no existing install, - # set the var now for later use: - EXISTINGuse=NO - - # The install will be in the home dir of user pi - # Move to home directory now to check - cd ~ || exit - if [ -d "${jukebox_dir}" ]; then - # Houston, we found something! - clear - echo "##################################################### -# -# . . . * alert * alert * alert * alert * . . . -# -# WARNING: an existing Phoniebox installation was found. -# -" - # check if we find the version number - if [ -f "${jukebox_dir}"/settings/version ]; then - #echo "The version of your installation is: $(cat ${jukebox_dir}/settings/version)" - - # get the current short commit hash of the repo - CURRENT_REMOTE_COMMIT="$(git ls-remote ${GIT_URL} ${GIT_BRANCH} | cut -c1-7)" - fi - echo "IMPORTANT: you can use the existing content and configuration" - echo "files for your new install." - echo "Whatever you chose to keep will be moved to the new install." - echo "Everything else will remain in a folder called 'BACKUP'. - " - - ### - # See if we find the PhonieboxInstall.conf file - # We need to do this first, because if we re-use the .conf file, we need to append - # the variables regarding the found content to the also found configuration file. - # That way, reading the configuration file for the (potentially) non-interactive - # install procedure will: - # a) overwrite whatever variables regarding re-cycling existing content which might - # be stored in the config file - # b) if there are no variables for dealing with re-cycled context, we will append - # them - to have them for this install - if [ -f "${jukebox_dir}"/settings/PhonieboxInstall.conf ]; then - # ask for re-using the found configuration file - echo "The configuration of your last Phoniebox install was found." - read -rp "Use existing configuration for this installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGusePhonieboxInstall=NO - ;; - *) - EXISTINGusePhonieboxInstall=YES - # Copy PhonieboxInstall.conf configuration file to settings folder - sudo cp "${jukebox_dir}"/settings/PhonieboxInstall.conf "${home_dir}"/PhonieboxInstall.conf - sudo chown pi:www-data "${home_dir}"/PhonieboxInstall.conf - sudo chmod 775 "${home_dir}"/PhonieboxInstall.conf - echo "The existing configuration will be used." - echo "Just a few more questions to answer." - read -rp "Hit ENTER to proceed to the next step." INPUT - clear - ;; - esac - fi - - # Delete or use existing installation? - read -rp "Re-use config, audio and RFID codes for the new install? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuse=NO - echo "Phoniebox will be a fresh install. The existing version will be dropped." - sudo rm -rf "${jukebox_dir}" - read -rp "Hit ENTER to proceed to the next step." INPUT - ;; - *) - EXISTINGuse=YES - # CREATE BACKUP - # delete existing BACKUP dir if exists - if [ -d "${backup_dir}" ]; then - sudo rm -r "${backup_dir}" - fi - # move install to BACKUP dir - mv "${jukebox_dir}" "${backup_dir}" - # delete .git dir - if [ -d "${backup_dir}"/.git ]; then - sudo rm -r "${backup_dir}"/.git - fi - # delete placeholder files so moving the folder content back later will not create git pull conflicts - rm "${backup_dir}"/shared/audiofolders/placeholder - rm "${backup_dir}"/shared/shortcuts/placeholder - - # ask for things to use - echo "Ok. You want to use stuff from the existing installation." - echo "What would you want to keep? Answer now." - read -rp "RFID config for system control (e.g. 'volume up' etc.)? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseRfidConf=NO - ;; - *) - EXISTINGuseRfidConf=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseRfidConf=$EXISTINGuseRfidConf" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "RFID shortcuts to play audio folders? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseRfidLinks=NO - ;; - *) - EXISTINGuseRfidLinks=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseRfidLinks=$EXISTINGuseRfidLinks" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "Audio folders: use existing? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseAudio=NO - ;; - *) - EXISTINGuseAudio=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseAudio=$EXISTINGuseAudio" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "Sound effects: use existing startup / shutdown sounds? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseSounds=NO - ;; - *) - EXISTINGuseSounds=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseSounds=$EXISTINGuseSounds" >> "${HOME_DIR}/PhonieboxInstall.conf" - - if [ "$(printf '%s\n' "2.1" "$(cat ~/BACKUP/settings/version-number)" | sort -V | head -n1)" = "2.1" ]; then - read -rp "GPIO: use existing file? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseGpio=NO - ;; - *) - EXISTINGuseGpio=YES - ;; - esac - else - echo "" - echo "Warning! -The configuration of GPIO-Devices has changed in the new version -and needs to be reconfigured. For further info check out the wiki: -https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons" - read -rp "Hit ENTER to proceed to the next step." INPUT - config_gpio - fi - # append variables to config file - echo "EXISTINGuseGpio=$EXISTINGuseGpio" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "Button USB Encoder: use existing device and button mapping? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseButtonUSBEncoder=NO - ;; - *) - EXISTINGuseButtonUSBEncoder=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseButtonUSBEncoder=$EXISTINGuseButtonUSBEncoder" >> "${HOME_DIR}/PhonieboxInstall.conf" - - echo "Thanks. Got it." - echo "The existing install can be found in the BACKUP directory." - read -rp "Hit ENTER to proceed to the next step." INPUT - ;; - esac - fi - # append variables to config file - echo "EXISTINGuse=$EXISTINGuse" >> "${HOME_DIR}/PhonieboxInstall.conf" - - # Check if we found a Phoniebox install configuration earlier and ask if to run this now - if [ "${EXISTINGusePhonieboxInstall}" == "YES" ]; then - clear - echo "Using the existing configuration, you can run a non-interactive install." - echo "This will re-cycle found content (specified just now) as well as the" - echo "system information from last time (wifi, audio interface, spotify, etc.)." - read -rp "Do you want to run a non-interactive installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - ;; - *) - cd "${home_dir}" - clear - ./buster-install-default.sh -a - exit - ;; - esac - fi -} - -config_audio_interface() { - ##################################################### - # Audio iFace - - clear - - echo "##################################################### -# -# CONFIGURE AUDIO INTERFACE (iFace) -# -# The default RPi audio interface is 'Headphone'. -# But this does not work for every setup. Here a list of -# available iFace names: -" - amixer scontrols - echo " " - read -rp "Use Headphone as iFace? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - read -rp "Type the iFace name you want to use:" AUDIOiFace - ;; - *) - AUDIOiFace="Headphone" - ;; - esac - # append variables to config file - echo "AUDIOiFace=\"$AUDIOiFace\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - echo "Your iFace is called '$AUDIOiFace'" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -config_spotify() { - ##################################################### - # Configure spotify - - clear - - echo "##################################################### -# -# OPTIONAL: INCLUDE SPOTIFY -# -# Note: if this is your first time installing a phoniebox -# it might be best to do a test install without Spotify -# to make sure all your hardware works. -# -# If you want to include Spotify, MUST have your -# credentials ready: -# -# * username -# * password -# * client_id -# * client_secret - -" - read -rp "Do you want to enable Spotify? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - SPOTinstall=NO - echo "You don't want spotify support." - ;; - *) - SPOTinstall=YES - clear - echo "##################################################### -# -# CREDENTIALS for Spotify -# -# Requires Spotify username, password, client_id and client_secret -# to get connection to Spotify. -# -# (Note: You need a device with browser to generate ID and SECRET) -# -# Please go to this website: -# https://www.mopidy.com/authenticate/ -# and follow the instructions. -# -# Your credential will appear on the site below the login button. -# Please note your client_id and client_secret! -# -" - read -rp "Type your Spotify username: " SPOTIuser - read -rp "Type your Spotify password: " SPOTIpass - read -rp "Type your client_id: " SPOTIclientid - read -rp "Type your client_secret: " SPOTIclientsecret - ;; - esac - # append variables to config file - { - echo "SPOTinstall=\"$SPOTinstall\""; - echo "SPOTIuser=\"$SPOTIuser\""; - echo "SPOTIpass=\"$SPOTIpass\""; - echo "SPOTIclientid=\"$SPOTIclientid\""; - echo "SPOTIclientsecret=\"$SPOTIclientsecret\"" - } >> "${HOME_DIR}/PhonieboxInstall.conf" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -config_mpd() { - ##################################################### - # Configure MPD - - clear - - echo "##################################################### -# -# CONFIGURE MPD -# -# MPD (Music Player Daemon) runs the audio output and must -# be configured. Do it now, if you are unsure. -# (Note: can be done manually later.) -" - read -rp "Do you want to configure MPD? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - MPDconfig=NO - echo "You want to configure MPD later." - ;; - *) - MPDconfig=YES - echo "MPD will be set up with default values." - ;; - esac - # append variables to config file - echo "MPDconfig=\"$MPDconfig\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -config_audio_folder() { - local jukebox_dir="$1" - - ##################################################### - # Folder path for audio files - # default: /home/pi/RPi-Jukebox-RFID/shared/audiofolders - - clear - - echo "##################################################### -# -# FOLDER CONTAINING AUDIO FILES -# -# The default location for folders containing audio files: -# ${jukebox_dir}/shared/audiofolders -# -# If unsure, keep it like this. If your files are somewhere -# else, you can specify the folder in the next step. -# IMPORTANT: the folder will not be created, only the path -# will be remembered. If you use a custom folder, you must -# create it. -" - - read -rp "Do you want to use the default location? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - echo "Please type the absolute path here (no trailing slash)." - echo "Default would be for example: ${jukebox_dir}/shared/audiofolders" - read -r DIRaudioFolders - ;; - *) - DIRaudioFolders="${jukebox_dir}/shared/audiofolders" - ;; - esac - # append variables to config file - echo "DIRaudioFolders=\"$DIRaudioFolders\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - echo "Your audio folders live in this dir:" - echo "${DIRaudioFolders}" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -check_variable() { - local variable=${1} - # check if variable exist and if it's empty - test -z "${!variable+x}" && echo "ERROR: \$${variable} is missing!" && fail=true && return - test "${!variable}" == "" && echo "ERROR: \$${variable} is empty!" && fail=true -} - -config_gpio() { - ##################################################### - # Configure GPIO - - clear - - echo "##################################################### -# -# ACTIVATE GPIO-Control -# -# Activation of the GPIO-Control-Service, which mangages Buttons -# or a Rotary Encoder for Volume and/or Track control. -# To configure the controls please consult the wiki: -# https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons -# It's also possible to activate the service later (see wiki). -" - read -rp "Do you want to activate the GPIO-Control-Service? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - GPIOconfig=NO - echo "You don't want to activate GPIO-Controls now." - ;; - *) - GPIOconfig=YES - echo "GPIO-Control-Service will be activated and set to default values." - ;; - esac - # append variables to config file - echo "GPIOconfig=\"$GPIOconfig\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - echo "" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -check_config_file() { - local install_conf="${HOME_DIR}/PhonieboxInstall.conf" - echo "Checking PhonieboxInstall.conf..." - # check that PhonieboxInstall.conf exists and is not empty - - # check if config file exists - if [[ -f "${install_conf}" ]]; then - # Source config file - source "${install_conf}" - cat "${install_conf}" - echo "" - else - echo "ERROR: ${install_conf} does not exist!" - exit 1 - fi - - fail=false - if [[ -z "${WIFIconfig+x}" ]]; then - echo "ERROR: \$WIFIconfig is missing or not set!" && fail=true - else - if [[ "$WIFIconfig" == "YES" ]]; then - check_variable "WIFIcountryCode" - check_variable "WIFIssid" - check_variable "WIFIpass" - check_variable "WIFIip" - check_variable "WIFIipRouter" - fi - fi - check_variable "EXISTINGuse" - check_variable "AUDIOiFace" - - if [[ -z "${SPOTinstall+x}" ]]; then - echo "ERROR: \$SPOTinstall is missing or not set!" && fail=true - else - if [ "$SPOTinstall" == "YES" ]; then - check_variable "SPOTIuser" - check_variable "SPOTIpass" - check_variable "SPOTIclientid" - check_variable "SPOTIclientsecret" - fi - fi - check_variable "MPDconfig" - check_variable "DIRaudioFolders" - check_variable "GPIOconfig" - - if [ "${fail}" == "true" ]; then - exit 1 - fi - - echo "" -} - -samba_config() { - local smb_conf="/etc/samba/smb.conf" - echo "Configuring Samba..." - # Samba configuration settings - # -rw-r--r-- 1 root root 9416 Apr 30 09:02 /etc/samba/smb.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/smb.conf.buster-default.sample ${smb_conf} - sudo chown root:root "${smb_conf}" - sudo chmod 644 "${smb_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${smb_conf}" - # Samba: create user 'pi' with password 'raspberry' - (echo "raspberry"; echo "raspberry") | sudo smbpasswd -s -a pi -} - -web_server_config() { - local lighthttpd_conf="/etc/lighttpd/lighttpd.conf" - local fastcgi_php_conf="/etc/lighttpd/conf-available/15-fastcgi-php.conf" - local php_ini="/etc/php/7.3/cgi/php.ini" - local sudoers="/etc/sudoers" - - echo "Configuring web server..." - # Web server configuration settings - # -rw-r--r-- 1 root root 1040 Apr 30 09:19 /etc/lighttpd/lighttpd.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/lighttpd.conf.buster-default.sample "${lighthttpd_conf}" - sudo chown root:root "${lighthttpd_conf}" - sudo chmod 644 "${lighthttpd_conf}" - - # Web server PHP7 fastcgi conf - # -rw-r--r-- 1 root root 398 Apr 30 09:35 /etc/lighttpd/conf-available/15-fastcgi-php.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/15-fastcgi-php.conf.buster-default.sample ${fastcgi_php_conf} - sudo chown root:root "${fastcgi_php_conf}" - sudo chmod 644 "${fastcgi_php_conf}" - - # settings for php.ini to support upload - # -rw-r--r-- 1 root root 70999 Jun 14 13:50 /etc/php/7.3/cgi/php.ini - sudo cp "${jukebox_dir}"/misc/sampleconfigs/php.ini.buster-default.sample ${php_ini} - sudo chown root:root "${php_ini}" - sudo chmod 644 "${php_ini}" - - # SUDO users (adding web server here) - # -r--r----- 1 root root 703 Nov 17 21:08 /etc/sudoers - sudo cp "${jukebox_dir}"/misc/sampleconfigs/sudoers.buster-default.sample ${sudoers} - sudo chown root:root "${sudoers}" - sudo chmod 440 "${sudoers}" -} - -install_main() { - local jukebox_dir="$1" - local apt_get="sudo apt-get -qq --yes" - local allow_downgrades="--allow-downgrades --allow-remove-essential --allow-change-held-packages" - - clear - - echo "##################################################### -# -# START INSTALLATION -# -# Good news: you completed the input. -# Let the install begin. -# -# Get yourself a cup of something. The install takes -# between 15 minutes to half an hour, depending on -# your Raspberry Pi and Internet connectivity. -# -# You will be prompted later to complete the installation. -" - - if [[ ${INTERACTIVE} == "true" ]]; then - read -rp "Do you want to start the installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - echo "Exiting the installation." - echo "Your configuration data was saved in this file:" - echo "${HOME_DIR}/PhonieboxInstall.conf" - echo - exit - ;; - esac - fi - - # Start logging here - log_open - - # Add conffile into logfile for better debugging - echo "################################################" - grep -v -e "SPOTI" -e "WIFIpass" "${HOME_DIR}/PhonieboxInstall.conf" - echo "################################################" - - ##################################################### - # INSTALLATION - - # Read install config as written so far - # (this might look stupid so far, but makes sense once - # the option to install from config file is introduced.) - # shellcheck source=scripts/installscripts/tests/ShellCheck/PhonieboxInstall.conf - . "${HOME_DIR}/PhonieboxInstall.conf" - - # power management of wifi: switch off to avoid disconnecting - sudo iwconfig wlan0 power off - - # create backup of /etc/resolv.conf - sudo cp /etc/resolv.conf /etc/resolv.conf.orig - - # Generate locales - sudo locale-gen "${LANG}" - - # Install required packages - ${apt_get} ${allow_downgrades} install apt-transport-https - wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add - - sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list - - ${apt_get} update - ${apt_get} upgrade - ${apt_get} install libspotify-dev - - # some packages are only available on raspberry pi's but not on test docker containers running on x86_64 machines - if [[ $(uname -m) =~ ^armv.+$ ]]; then - ${apt_get} ${allow_downgrades} install raspberrypi-kernel-headers - fi - - ${apt_get} ${allow_downgrades} install samba samba-common-bin gcc lighttpd php7.3-common php7.3-cgi php7.3 at mpd mpc mpg123 git ffmpeg resolvconf spi-tools - - # restore backup of /etc/resolv.conf in case installation of resolvconf cleared it - sudo cp /etc/resolv.conf.orig /etc/resolv.conf - - # prepare python3 - ${apt_get} ${allow_downgrades} install python3 python3-dev python3-pip python3-mutagen python3-gpiozero python3-spidev - - # use python3.7 as default - sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.7 1 - - # Get github code - cd "${HOME_DIR}" || exit - git clone ${GIT_URL} --branch "${GIT_BRANCH}" - - # VERSION of installation - - # Get version number - VERSION_NO=`cat ${jukebox_dir}/settings/version-number` - - # add used git branch and commit hash to version file - USED_BRANCH="$(git --git-dir=${jukebox_dir}/.git rev-parse --abbrev-ref HEAD)" - - # add git commit hash to version file - COMMIT_NO="$(git --git-dir=${jukebox_dir}/.git describe --always)" - - echo "${VERSION_NO} - ${COMMIT_NO} - ${USED_BRANCH}" > ${jukebox_dir}/settings/version - chmod 777 ${jukebox_dir}/settings/version - - # Install required spotify packages - if [ "${SPOTinstall}" == "YES" ]; then - echo "Installing dependencies for Spotify support..." - # keep major verson 3 of mopidy - echo -e "Package: mopidy\nPin: version 3.*\nPin-Priority: 1001" | sudo tee /etc/apt/preferences.d/mopidy - - wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add - - sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list - ${apt_get} update - ${apt_get} upgrade - ${apt_get} ${allow_downgrades} install mopidy mopidy-mpd mopidy-local mopidy-spotify - ${apt_get} ${allow_downgrades} install libspotify12 python3-cffi python3-ply python3-pycparser python3-spotify - - # Install necessary Python packages - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements-spotify.txt - fi - - local raw_github="https://raw.githubusercontent.com/MiczFlor/RPi-Jukebox-RFID" - # I comment the following lines out for now. I think they come from splitti when he applied a hotfix in Feb 2020? - # Back then the master install script needed develop branch files. I think this is from that time...? - #sudo rm "${jukebox_dir}"/misc/sampleconfigs/phoniebox-rfid-reader.service.stretch-default.sample - #wget -P "${jukebox_dir}"/misc/sampleconfigs/ "${raw_github}"/develop/misc/sampleconfigs/phoniebox-rfid-reader.service.stretch-default.sample - #sudo rm "${jukebox_dir}"/scripts/RegisterDevice.py - #wget -P "${jukebox_dir}"/scripts/ "${raw_github}"/develop/scripts/RegisterDevice.py - - # Install more required packages - echo "Installing additional Python packages..." - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements.txt - - samba_config - - web_server_config - - # copy shell script for player - cp "${jukebox_dir}"/settings/rfid_trigger_play.conf.sample "${jukebox_dir}"/settings/rfid_trigger_play.conf - - # creating files containing editable values for configuration - echo "$AUDIOiFace" > "${jukebox_dir}"/settings/Audio_iFace_Name - echo "$DIRaudioFolders" > "${jukebox_dir}"/settings/Audio_Folders_Path - echo "3" > "${jukebox_dir}"/settings/Audio_Volume_Change_Step - echo "100" > "${jukebox_dir}"/settings/Max_Volume_Limit - echo "0" > "${jukebox_dir}"/settings/Idle_Time_Before_Shutdown - echo "RESTART" > "${jukebox_dir}"/settings/Second_Swipe - echo "${jukebox_dir}/playlists" > "${jukebox_dir}"/settings/Playlists_Folders_Path - echo "ON" > "${jukebox_dir}"/settings/ShowCover - - # sample file for debugging with all options set to FALSE - sudo cp "${jukebox_dir}"/settings/debugLogging.conf.sample "${jukebox_dir}"/settings/debugLogging.conf - sudo chmod 777 "${jukebox_dir}"/settings/debugLogging.conf - - # The new way of making the bash daemon is using the helperscripts - # creating the shortcuts and script from a CSV file. - # see scripts/helperscripts/AssignIDs4Shortcuts.php - - # create config file for web app from sample - sudo cp "${jukebox_dir}"/htdocs/config.php.sample "${jukebox_dir}"/htdocs/config.php - - # Starting web server and php7 - sudo lighttpd-enable-mod fastcgi - sudo lighttpd-enable-mod fastcgi-php - sudo service lighttpd force-reload - - # create copy of GPIO script - sudo cp "${jukebox_dir}"/misc/sampleconfigs/gpio-buttons.py.sample "${jukebox_dir}"/scripts/gpio-buttons.py - sudo chmod +x "${jukebox_dir}"/scripts/gpio-buttons.py - - # make sure bash scripts have the right settings - sudo chown pi:www-data "${jukebox_dir}"/scripts/*.sh - sudo chmod +x "${jukebox_dir}"/scripts/*.sh - sudo chown pi:www-data "${jukebox_dir}"/scripts/*.py - sudo chmod +x "${jukebox_dir}"/scripts/*.py - - # services to launch after boot using systemd - # -rw-r--r-- 1 root root 304 Apr 30 10:07 phoniebox-rfid-reader.service - # 1. delete old services (this is legacy, might throw errors but is necessary. Valid for versions < 1.1.8-beta) - local systemd_dir="/etc/systemd/system" - echo "### Deleting older versions of service daemons. This might throw errors, ignore them" - sudo systemctl disable idle-watchdog - sudo systemctl disable rfid-reader - sudo systemctl disable phoniebox-startup-sound - sudo systemctl disable gpio-buttons - sudo systemctl disable phoniebox-rotary-encoder - sudo systemctl disable phoniebox-gpio-buttons.service - sudo rm "${systemd_dir}"/rfid-reader.service - sudo rm "${systemd_dir}"/startup-sound.service - sudo rm "${systemd_dir}"/gpio-buttons.service - sudo rm "${systemd_dir}"/idle-watchdog.service - sudo rm "${systemd_dir}"/phoniebox-rotary-encoder.service - sudo rm "${systemd_dir}"/phoniebox-gpio-buttons.service - echo "### Done with erasing old daemons. Stop ignoring errors!" - # 2. install new ones - this is version > 1.1.8-beta - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-rfid-reader.service.stretch-default.sample "${systemd_dir}"/phoniebox-rfid-reader.service - #startup sound now part of phoniebox-startup-scripts - #sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-startup-sound.service.stretch-default.sample "${systemd_dir}"/phoniebox-startup-sound.service - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-startup-scripts.service.stretch-default.sample "${systemd_dir}"/phoniebox-startup-scripts.service - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-gpio-buttons.service.stretch-default.sample "${systemd_dir}"/phoniebox-gpio-buttons.service - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-idle-watchdog.service.sample "${systemd_dir}"/phoniebox-idle-watchdog.service - [[ "${GPIOconfig}" == "YES" ]] && sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-gpio-control.service.sample "${systemd_dir}"/phoniebox-gpio-control.service - sudo chown root:root "${systemd_dir}"/phoniebox-*.service - sudo chmod 644 "${systemd_dir}"/phoniebox-*.service - # enable the services needed - sudo systemctl enable phoniebox-idle-watchdog - sudo systemctl enable phoniebox-rfid-reader - #startup sound is part of phoniebox-startup-scripts now - #sudo systemctl enable phoniebox-startup-sound - sudo systemctl enable phoniebox-startup-scripts - sudo systemctl enable phoniebox-gpio-buttons - sudo systemctl enable phoniebox-rotary-encoder.service - - # copy mp3s for startup and shutdown sound to the right folder - cp "${jukebox_dir}"/misc/sampleconfigs/startupsound.mp3.sample "${jukebox_dir}"/shared/startupsound.mp3 - cp "${jukebox_dir}"/misc/sampleconfigs/shutdownsound.mp3.sample "${jukebox_dir}"/shared/shutdownsound.mp3 - - # Spotify config - if [ "${SPOTinstall}" == "YES" ]; then - local etc_mopidy_conf="/etc/mopidy/mopidy.conf" - local mopidy_conf="${HOME_DIR}/.config/mopidy/mopidy.conf" - echo "Configuring Spotify support..." - sudo systemctl disable mpd - sudo systemctl enable mopidy - # Install Config Files - sudo cp "${jukebox_dir}"/misc/sampleconfigs/locale.gen.sample /etc/locale.gen - sudo cp "${jukebox_dir}"/misc/sampleconfigs/locale.sample /etc/default/locale - sudo locale-gen - mkdir -p "${HOME_DIR}"/.config/mopidy - sudo cp "${jukebox_dir}"/misc/sampleconfigs/mopidy-etc.sample "${etc_mopidy_conf}" - cp "${jukebox_dir}"/misc/sampleconfigs/mopidy.sample "${mopidy_conf}" - # Change vars to match install config - sudo sed -i 's/%spotify_username%/'"$SPOTIuser"'/' "${etc_mopidy_conf}" - sudo sed -i 's/%spotify_password%/'"$SPOTIpass"'/' "${etc_mopidy_conf}" - sudo sed -i 's/%spotify_client_id%/'"$SPOTIclientid"'/' "${etc_mopidy_conf}" - sudo sed -i 's/%spotify_client_secret%/'"$SPOTIclientsecret"'/' "${etc_mopidy_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${etc_mopidy_conf}" - sed -i 's/%spotify_username%/'"$SPOTIuser"'/' "${mopidy_conf}" - sed -i 's/%spotify_password%/'"$SPOTIpass"'/' "${mopidy_conf}" - sed -i 's/%spotify_client_id%/'"$SPOTIclientid"'/' "${mopidy_conf}" - sed -i 's/%spotify_client_secret%/'"$SPOTIclientsecret"'/' "${mopidy_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${mopidy_conf}" - fi - - # GPIO-Control - if [[ "${GPIOconfig}" == "YES" ]]; then - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements-GPIO.txt - sudo systemctl enable phoniebox-gpio-control.service - if [[ ! -f ~/.config/phoniebox/gpio_settings.ini ]]; then - mkdir -p ~/.config/phoniebox - cp "${jukebox_dir}"/components/gpio_control/example_configs/gpio_settings.ini ~/.config/phoniebox/gpio_settings.ini - fi - fi - - if [ "${MPDconfig}" == "YES" ]; then - local mpd_conf="/etc/mpd.conf" - - echo "Configuring MPD..." - # MPD configuration - # -rw-r----- 1 mpd audio 14043 Jul 17 20:16 /etc/mpd.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/mpd.conf.buster-default.sample ${mpd_conf} - # Change vars to match install config - sudo sed -i 's/%AUDIOiFace%/'"$AUDIOiFace"'/' "${mpd_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${mpd_conf}" - sudo chown mpd:audio "${mpd_conf}" - sudo chmod 640 "${mpd_conf}" - fi - - # set which version has been installed - if [ "${SPOTinstall}" == "YES" ]; then - echo "plusSpotify" > "${jukebox_dir}"/settings/edition - else - echo "classic" > "${jukebox_dir}"/settings/edition - fi - - # update mpc / mpd DB - mpc update - - # / INSTALLATION - ##################################################### -} - -wifi_settings() { - local sample_configs_dir="$1" - local dhcpcd_conf="$2" - local wpa_supplicant_conf="$3" - - ############################### - # WiFi settings (SSID password) - # - # https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md - # - # $WIFIssid - # $WIFIpass - # $WIFIip - # $WIFIipRouter - if [ "${WIFIconfig}" == "YES" ]; then - # DHCP configuration settings - echo "Setting ${dhcpcd_conf}..." - #-rw-rw-r-- 1 root netdev 0 Apr 17 11:25 /etc/dhcpcd.conf - sudo cp "${sample_configs_dir}"/dhcpcd.conf.buster-default-noHotspot.sample "${dhcpcd_conf}" - # Change IP for router and Phoniebox - sudo sed -i 's/%WIFIip%/'"$WIFIip"'/' "${dhcpcd_conf}" - sudo sed -i 's/%WIFIipRouter%/'"$WIFIipRouter"'/' "${dhcpcd_conf}" - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' "${dhcpcd_conf}" - # Change user:group and access mod - sudo chown root:netdev "${dhcpcd_conf}" - sudo chmod 664 "${dhcpcd_conf}" - - # WiFi SSID & Password - echo "Setting ${wpa_supplicant_conf}..." - # -rw-rw-r-- 1 root netdev 137 Jul 16 08:53 /etc/wpa_supplicant/wpa_supplicant.conf - sudo cp "${sample_configs_dir}"/wpa_supplicant.conf.buster-default.sample "${wpa_supplicant_conf}" - sudo sed -i 's/%WIFIssid%/'"$WIFIssid"'/' "${wpa_supplicant_conf}" - sudo sed -i 's/%WIFIpass%/'"$WIFIpass"'/' "${wpa_supplicant_conf}" - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' "${wpa_supplicant_conf}" - sudo chown root:netdev "${wpa_supplicant_conf}" - sudo chmod 664 "${wpa_supplicant_conf}" - fi - - # start DHCP - echo "Starting dhcpcd service..." - sudo service dhcpcd start - sudo systemctl enable dhcpcd - -# / WiFi settings (SSID password) -############################### -} - -existing_assets() { - local jukebox_dir="$1" - local backup_dir="$2" - - ##################################################### - # EXISTING ASSETS TO USE FROM EXISTING INSTALL - - if [ "${EXISTINGuse}" == "YES" ]; then - # RFID config for system control - if [ "${EXISTINGuseRfidConf}" == "YES" ]; then - # read old values and write them into new file (copied above already) - # do not overwrite but use 'sed' in case there are new vars in new version installed - - # Read the existing RFID config file line by line and use - # only lines which are separated (IFS) by '='. - while IFS='=' read -r key val ; do - # $var should be stripped of possible leading or trailing " - val=${val%\"} - val=${val#\"} - key=${key} - # Additional error check: key should not start with a hash and not be empty. - if [ ! "${key:0:1}" == '#' ] && [ -n "$key" ]; then - # Replace the matching value in the newly created conf file - sed -i 's/%'"$key"'%/'"$val"'/' "${jukebox_dir}"/settings/rfid_trigger_play.conf - fi - done <"${backup_dir}"/settings/rfid_trigger_play.conf - fi - - # RFID shortcuts for audio folders - if [ "${EXISTINGuseRfidLinks}" == "YES" ]; then - # copy from backup to new install - cp -R "${backup_dir}"/shared/shortcuts/* "${jukebox_dir}"/shared/shortcuts/ - fi - - # Audio folders: use existing - if [ "${EXISTINGuseAudio}" == "YES" ]; then - # copy from backup to new install - cp -R "${backup_dir}"/shared/audiofolders/* "$DIRaudioFolders/" - fi - - # GPIO: use existing file - if [ "${EXISTINGuseGpio}" == "YES" ]; then - # copy from backup to new install - cp "${backup_dir}"/settings/gpio_settings.ini "${jukebox_dir}"/settings/gpio_settings.ini - fi - - # Button USB Encoder: use existing file - if [ "${EXISTINGuseButtonUSBEncoder}" == "YES" ]; then - # copy from backup to new install - cp "${backup_dir}"/components/controls/buttons_usb_encoder/deviceName.txt "${jukebox_dir}"/components/controls/buttons_usb_encoder/deviceName.txt - cp "${backup_dir}"/components/controls/buttons_usb_encoder/buttonMap.json "${jukebox_dir}"/components/controls/buttons_usb_encoder/buttonMap.json - # make buttons_usb_encoder.py ready to be use from phoniebox-buttons-usb-encoder service - sudo chmod +x "${jukebox_dir}"/components/controls/buttons_usb_encoder/buttons_usb_encoder.py - # make sure service is still enabled by registering again - sudo cp -v "${jukebox_dir}"/components/controls/buttons_usb_encoder/phoniebox-buttons-usb-encoder.service.sample /etc/systemd/system/phoniebox-buttons-usb-encoder.service - sudo systemctl start phoniebox-buttons-usb-encoder.service - sudo systemctl enable phoniebox-buttons-usb-encoder.service - fi - - # Sound effects: use existing startup / shutdown sounds - if [ "${EXISTINGuseSounds}" == "YES" ]; then - # copy from backup to new install - cp "${backup_dir}"/shared/startupsound.mp3 "${jukebox_dir}"/shared/startupsound.mp3 - cp "${backup_dir}"/shared/shutdownsound.mp3 "${jukebox_dir}"/shared/shutdownsound.mp3 - fi - - fi - - # / EXISTING ASSETS TO USE FROM EXISTING INSTALL - ################################################ -} - - -folder_access() { - local jukebox_dir="$1" - local user_group="$2" - local mod="$3" - - ##################################################### - # Folders and Access Settings - - echo "Setting owner and permissions for directories..." - - # create playlists folder - mkdir -p "${jukebox_dir}"/playlists - sudo chown -R "${user_group}" "${jukebox_dir}"/playlists - sudo chmod -R "${mod}" "${jukebox_dir}"/playlists - - # make sure the shared folder is accessible by the web server - sudo chown -R "${user_group}" "${jukebox_dir}"/shared - sudo chmod -R "${mod}" "${jukebox_dir}"/shared - - # make sure the htdocs folder can be changed by the web server - sudo chown -R "${user_group}" "${jukebox_dir}"/htdocs - sudo chmod -R "${mod}" "${jukebox_dir}"/htdocs - - sudo chown -R "${user_group}" "${jukebox_dir}"/settings - sudo chmod -R "${mod}" "${jukebox_dir}"/settings - - # logs dir accessible by pi and www-data - sudo chown "${user_group}" "${jukebox_dir}"/logs - sudo chmod "${mod}" "${jukebox_dir}"/logs - - # audio folders might be somewhere else, so treat them separately - sudo chown "${user_group}" "${DIRaudioFolders}" - sudo chmod "${mod}" "${DIRaudioFolders}" - - # make sure bash scripts have the right settings - sudo chown "${user_group}" "${jukebox_dir}"/scripts/*.sh - sudo chmod +x "${jukebox_dir}"/scripts/*.sh - sudo chown "${user_group}" "${jukebox_dir}"/scripts/*.py - sudo chmod +x "${jukebox_dir}"/scripts/*.py - - # set audio volume to 100% - # see: https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/54 - sudo amixer cset numid=1 100% - - # delete the global.conf file, in case somebody manually copied stuff back and forth - # this will be created the first time the Phoniebox is put to use by web app or RFID - GLOBAL_CONF="${jukebox_dir}"/settings/global.conf - if [ -f "${GLOBAL_CONF}" ]; then - echo "global.conf needs to be deleted." - rm "${GLOBAL_CONF}" - fi - - # / Access settings - ##################################################### -} - -autohotspot() { - local jukebox_dir="$1" - local apt_get="sudo apt-get -qq --yes" - - # adapted from https://www.raspberryconnect.com/projects/65-raspberrypi-hotspot-accesspoints/158-raspberry-pi-auto-wifi-hotspot-switch-direct-connection - - # required packages - ${apt_get} install dnsmasq hostapd - sudo systemctl unmask hostapd - sudo systemctl disable hostapd - sudo systemctl disable dnsmasq - - # configure DNS - if [ -f /etc/dnsmasq.conf ]; then - sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig - sudo touch /etc/dnsmasq.conf - else - sudo touch /etc/dnsmasq.conf - fi - sudo bash -c 'cat << EOF > /etc/dnsmasq.conf -#AutoHotspot Config -#stop DNSmasq from using resolv.conf -no-resolv -#Interface to use -interface=wlan0 -bind-interfaces -dhcp-range=10.0.0.50,10.0.0.150,12h -EOF' - - # configure hotspot - if [ -f /etc/hostapd/hostapd.conf ]; then - sudo mv /etc/hostapd/hostapd.conf /etc/hostapd/hostapd.conf.orig - sudo touch /etc/hostapd/hostapd.conf - else - sudo touch /etc/hostapd/hostapd.conf - fi - sudo bash -c 'cat << EOF > /etc/hostapd/hostapd.conf -#2.4GHz setup wifi 80211 b,g,n -interface=wlan0 -driver=nl80211 -ssid=phoniebox -hw_mode=g -channel=8 -wmm_enabled=0 -macaddr_acl=0 -auth_algs=1 -ignore_broadcast_ssid=0 -wpa=2 -wpa_passphrase=PlayItLoud -wpa_key_mgmt=WPA-PSK -wpa_pairwise=CCMP TKIP -rsn_pairwise=CCMP - -#80211n - Change DE to your WiFi country code -country_code=DE -ieee80211n=1 -ieee80211d=1 -EOF' - - # configure Hotspot daemon - if [ -f /etc/default/hostapd ]; then - sudo mv /etc/default/hostapd /etc/default/hostapd.orig - sudo touch /etc/default/hostapd - else - sudo touch /etc/default/hostapd - fi - sudo bash -c 'cat << EOF > /etc/default/hostapd -DAEMON_CONF="/etc/hostapd/hostapd.conf" -EOF' - - if [ $(grep -v '^$' /etc/network/interfaces |wc -l) -gt 5 ]; then - sudo cp /etc/network/interfaces /etc/network/interfaces-backup - fi - - # disable powermanagement of wlan0 device - sudo iw wlan0 set power_save off - - if [[ ! $(grep "nohook wpa_supplicant" /etc/dhcpcd.conf) ]]; then - sudo echo -e "nohook wpa_supplicant" >> /etc/dhcpcd.conf - fi - - # create service to trigger hotspot - sudo bash -c 'cat << EOF > /etc/systemd/system/autohotspot.service -[Unit] -Description=Automatically generates an internet Hotspot when a valid ssid is not in range -After=multi-user.target -[Service] -Type=oneshot -RemainAfterExit=yes -ExecStart=/usr/bin/autohotspot -[Install] -WantedBy=multi-user.target -EOF' - - sudo systemctl enable autohotspot.service - - sudo cp "${jukebox_dir}"/scripts/helperscripts/autohotspot /usr/bin/autohotspot - sudo chmod +x /usr/bin/autohotspot - - # create crontab entry - if [[ ! $(grep "autohotspot" /var/spool/cron/crontabs/pi) ]]; then - sudo bash -c 'cat << EOF >> /var/spool/cron/crontabs/pi -*/5 * * * * sudo /usr/bin/autohotspot >/dev/null 2>&1 -EOF' - fi - sudo chown pi:crontab /var/spool/cron/crontabs/pi - sudo chmod 600 /var/spool/cron/crontabs/pi - sudo /usr/bin/crontab /var/spool/cron/crontabs/pi - -} - -finish_installation() { - local jukebox_dir="$1" - echo " -# -# INSTALLATION FINISHED -# -##################################################### -" - - ##################################################### - # Register external device(s) - - echo "If you are using an RFID reader, connect it to your RPi." - echo "(In case your RFID reader required soldering, consult the manual.)" - # Use -e to display response of user in the logfile - read -e -r -p "Have you connected your RFID reader? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - ;; - *) - echo 'Please select the RFID reader you want to use' - options=("USB-Reader (e.g. Neuftech)" "RC522" "PN532" "Manual configuration" "Multiple RFID reader") - select opt in "${options[@]}"; do - case $opt in - "USB-Reader (e.g. Neuftech)") - cd "${jukebox_dir}"/scripts/ || exit - python3 RegisterDevice.py - sudo chown pi:www-data "${jukebox_dir}"/scripts/deviceName.txt - sudo chmod 644 "${jukebox_dir}"/scripts/deviceName.txt - break - ;; - "RC522") - bash "${jukebox_dir}"/components/rfid-reader/RC522/setup_rc522.sh - break - ;; - "PN532") - bash "${jukebox_dir}"/components/rfid-reader/PN532/setup_pn532.sh - break - ;; - "Manual configuration") - echo "Please configure your reader manually." - break - ;; - "Multiple RFID reader") - cd "${jukebox_dir}"/scripts/ || exit - sudo python3 RegisterDevice.py.Multi - break - ;; - *) - echo "This is not a number" - ;; - esac - done - esac - - echo - echo "DONE. Let the sounds begin." - echo "Find more information and documentation on the github account:" - echo "https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/" - - echo "Reboot is needed to activate all settings" - # Use -e to display response of user in the logfile - read -e -r -p "Would you like to reboot now? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - # Close logging - log_close - ;; - *) - # Close logging - log_close - sudo shutdown -r now - ;; - esac -} - -######## -# Main # -######## -main() { - if [[ ${INTERACTIVE} == "true" ]]; then - welcome - #reset_install_config_file - config_wifi - check_existing "${JUKEBOX_HOME_DIR}" "${JUKEBOX_BACKUP_DIR}" "${HOME_DIR}" - config_audio_interface - config_spotify - config_mpd - config_audio_folder "${JUKEBOX_HOME_DIR}" - config_gpio - else - echo "Non-interactive installation!" - check_config_file - # Skip interactive Samba WINS config dialog - echo "samba-common samba-common/dhcp boolean false" | sudo debconf-set-selections - fi - install_main "${JUKEBOX_HOME_DIR}" - wifi_settings "${JUKEBOX_HOME_DIR}/misc/sampleconfigs" "/etc/dhcpcd.conf" "/etc/wpa_supplicant/wpa_supplicant.conf" - existing_assets "${JUKEBOX_HOME_DIR}" "${JUKEBOX_BACKUP_DIR}" - folder_access "${JUKEBOX_HOME_DIR}" "pi:www-data" 775 - autohotspot "${JUKEBOX_HOME_DIR}" - - # Copy PhonieboxInstall.conf configuration file to settings folder - sudo cp "${HOME_DIR}/PhonieboxInstall.conf" "${JUKEBOX_HOME_DIR}/settings/" - sudo chown pi:www-data "${JUKEBOX_HOME_DIR}/settings/PhonieboxInstall.conf" - sudo chmod 775 "${JUKEBOX_HOME_DIR}/settings/PhonieboxInstall.conf" - - if [[ ${INTERACTIVE} == "true" ]]; then - finish_installation "${JUKEBOX_HOME_DIR}" - else - echo "Skipping USB device setup..." - echo "For manual registration of a USB card reader type:" - echo "python3 /home/pi/RPi-Jukebox-RFID/scripts/RegisterDevice.py" - echo " " - echo "Reboot is required to activate all settings!" - fi -} - -start=$(date +%s) - -main - -end=$(date +%s) -runtime=$((end-start)) -((h=${runtime}/3600)) -((m=(${runtime}%3600)/60)) -((s=${runtime}%60)) -echo "Done (in ${h}h ${m}m ${s}s)." - -##################################################### -# notes for things to do - -# CLEANUP -## remove dir BACKUP (possibly not, because we do this at the beginning after user confirms for latest config) -##################################################### diff --git a/scripts/installscripts/buster-install-default.sh b/scripts/installscripts/buster-install-default.sh deleted file mode 100755 index f0bf19944..000000000 --- a/scripts/installscripts/buster-install-default.sh +++ /dev/null @@ -1,1299 +0,0 @@ -#!/usr/bin/env bash -# -# see https://github.com/MiczFlor/RPi-Jukebox-RFID for details -# -# NOTE: Running automated install (without interaction): -# Each install creates a file called PhonieboxInstall.conf -# in the folder /home/pi/ -# You can install the Phoniebox using such a config file -# which means you don't need to run the interactive install: -# -# 1. download the install file from github -# https://github.com/MiczFlor/RPi-Jukebox-RFID/tree/develop/scripts/installscripts -# (note: currently only works for buster and newer OS) -# 2. make the file executable: chmod +x -# 3. place the PhonieboxInstall.conf in the folder /home/pi/ -# 4. run the installscript with option -a like this: -# buster-install-default.sh -a - -# The absolute path to the folder which contains this script -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -GIT_BRANCH=${GIT_BRANCH:-master} -GIT_URL=${GIT_URL:-https://github.com/MiczFlor/RPi-Jukebox-RFID.git} -echo GIT_BRANCH $GIT_BRANCH -echo GIT_URL $GIT_URL - -DATETIME=$(date +"%Y%m%d_%H%M%S") - -SCRIPTNAME="$(basename $0)" -JOB="${SCRIPTNAME}" - -HOME_DIR="/home/pi" - -JUKEBOX_HOME_DIR="${HOME_DIR}/RPi-Jukebox-RFID" -LOGDIR="${HOME_DIR}"/phoniebox_logs -JUKEBOX_BACKUP_DIR="${HOME_DIR}/BACKUP" - -INTERACTIVE=true - -usage() { - printf "Usage: ${SCRIPTNAME} [-a] [-h]\n" - printf " -a\tautomatic/non-interactive mode\n" - printf " -h\thelp\n" - exit 0 -} - -while getopts ":ah" opt; -do - case ${opt} in - a ) INTERACTIVE=false - ;; - h ) usage - ;; - \? ) usage - ;; - esac -done - - -# Setup logger functions -# Input from http://www.ludovicocaldara.net/dba/bash-tips-5-output-logfile/ -log_open() { - [[ -d "${LOGDIR}" ]] || mkdir -p "${LOGDIR}" - PIPE="${LOGDIR}"/"${JOB}"_"${DATETIME}".pipe - mkfifo -m 700 "${PIPE}" - LOGFILE="${LOGDIR}"/"${JOB}"_"${DATETIME}".log - exec 3>&1 - tee "${LOGFILE}" <"${PIPE}" >&3 & - TEEPID=$! - exec 1>"${PIPE}" 2>&1 - PIPE_OPENED=1 -} - -log_close() { - if [ "${PIPE_OPENED}" ]; then - exec 1<&3 - sleep 0.2 - ps --pid "${TEEPID}" >/dev/null - if [ $? -eq 0 ] ; then - # a wait ${TEEPID} whould be better but some - # commands leave file descriptors open - sleep 1 - kill "${TEEPID}" - fi - rm "${PIPE}" - unset PIPE_OPENED - fi -} - - -welcome() { - clear - echo "##################################################### -# ___ __ ______ _ __________ ____ __ _ _ # -# / _ \/ // / __ \/ |/ / _/ __/( _ \ / \( \/ ) # -# / ___/ _ / /_/ / // // _/ ) _ (( O )) ( # -# /_/ /_//_/\____/_/|_/___/____/ (____/ \__/(_/\_) # -# # -##################################################### - -You are turning your Raspberry Pi into a Phoniebox. Good choice. -This INTERACTIVE INSTALL script requires you to be online and -will guide you through the configuration. - -If you want to run the AUTOMATED INSTALL (non-interactive) from -an existing configuration file, do the following: -1. exit this install script (press n) -2. place your PhonieboxInstall.conf in the folder /home/pi/ -3. run the installscript with option -a. For example like this: - ./home/pi/buster-install-default.sh -a - " - read -rp "Continue interactive installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - exit - ;; - *) - echo "Installation continues..." - ;; - esac -} - -reset_install_config_file() { - ##################################################### - # CONFIG FILE - # This file will contain all the data given in the - # following dialogue - # At a later stage, the install should also be done - # from such a config file with no user input. - - # Remove existing config file - #rm "${HOME_DIR}/PhonieboxInstall.conf" - # Create empty config file - #touch "${HOME_DIR}/PhonieboxInstall.conf" - #echo "# Phoniebox config" > "${HOME_DIR}/PhonieboxInstall.conf" - echo "# Phoniebox config" -} - -config_wifi() { - ##################################################### - # Ask if wifi config - - clear - - echo "##################################################### -# -# CONFIGURE WIFI -# -# Requires SSID, WiFi password and the static IP you want -# to assign to your Phoniebox. -# (Note: can be done manually later, if you are unsure.) -" -read -rp "Do you want to configure your WiFi? [Y/n] " response -echo "" -case "$response" in - [nN][oO]|[nN]) - WIFIconfig=NO - echo "You want to configure WiFi later." - # append variables to config file - echo "WIFIconfig=$WIFIconfig" >> "${HOME_DIR}/PhonieboxInstall.conf" - # make a fallback for WiFi Country Code, because we need that even without WiFi config - echo "WIFIcountryCode=DE" >> "${HOME_DIR}/PhonieboxInstall.conf" - ;; - *) - WIFIconfig=YES - #Ask for SSID - read -rp "* Type SSID name: " WIFIssid - #Ask for wifi country code - read -rp "* WiFi Country Code (e.g. DE, GB, CZ or US): " WIFIcountryCode - #Ask for password - read -rp "* Type password: " WIFIpass - #Ask for IP - read -rp "* Static IP (e.g. 192.168.1.199): " WIFIip - #Ask for Router IP - read -rp "* Router IP (e.g. 192.168.1.1): " WIFIipRouter - echo "" - echo "Your WiFi config:" - echo "SSID : $WIFIssid" - echo "WiFi Country Code : $WIFIcountryCode" - echo "Password : $WIFIpass" - echo "Static IP : $WIFIip" - echo "Router IP : $WIFIipRouter" - read -rp "Are these values correct? [Y/n] " response - echo "" - case "$response" in - [nN][oO]|[nN]) - echo "The values are incorrect." - read -rp "Hit ENTER to exit and start over." INPUT; exit - ;; - *) - # append variables to config file - { - echo "WIFIconfig=\"$WIFIconfig\""; - echo "WIFIcountryCode=\"$WIFIcountryCode\""; - echo "WIFIssid=\"$WIFIssid\""; - echo "WIFIpass=\"$WIFIpass\""; - echo "WIFIip=\"$WIFIip\""; - echo "WIFIipRouter=\"$WIFIipRouter\""; - } >> "${HOME_DIR}/PhonieboxInstall.conf" - ;; - esac - ;; -esac -read -rp "Hit ENTER to proceed to the next step." INPUT -} - -check_existing() { - local jukebox_dir="$1" - local backup_dir="$2" - local home_dir="$3" - - ##################################################### - # Check for existing Phoniebox - # - # In case there is no existing install, - # set the var now for later use: - EXISTINGuse=NO - - # The install will be in the home dir of user pi - # Move to home directory now to check - cd ~ || exit - if [ -d "${jukebox_dir}" ]; then - # Houston, we found something! - clear - echo "##################################################### -# -# . . . * alert * alert * alert * alert * . . . -# -# WARNING: an existing Phoniebox installation was found. -# -" - # check if we find the version number - if [ -f "${jukebox_dir}"/settings/version ]; then - #echo "The version of your installation is: $(cat ${jukebox_dir}/settings/version)" - - # get the current short commit hash of the repo - CURRENT_REMOTE_COMMIT="$(git ls-remote ${GIT_URL} ${GIT_BRANCH} | cut -c1-7)" - fi - echo "IMPORTANT: you can use the existing content and configuration" - echo "files for your new install." - echo "Whatever you chose to keep will be moved to the new install." - echo "Everything else will remain in a folder called 'BACKUP'. - " - - ### - # See if we find the PhonieboxInstall.conf file - # We need to do this first, because if we re-use the .conf file, we need to append - # the variables regarding the found content to the also found configuration file. - # That way, reading the configuration file for the (potentially) non-interactive - # install procedure will: - # a) overwrite whatever variables regarding re-cycling existing content which might - # be stored in the config file - # b) if there are no variables for dealing with re-cycled context, we will append - # them - to have them for this install - if [ -f "${jukebox_dir}"/settings/PhonieboxInstall.conf ]; then - # ask for re-using the found configuration file - echo "The configuration of your last Phoniebox install was found." - read -rp "Use existing configuration for this installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGusePhonieboxInstall=NO - ;; - *) - EXISTINGusePhonieboxInstall=YES - # Copy PhonieboxInstall.conf configuration file to settings folder - sudo cp "${jukebox_dir}"/settings/PhonieboxInstall.conf "${home_dir}"/PhonieboxInstall.conf - sudo chown pi:www-data "${home_dir}"/PhonieboxInstall.conf - sudo chmod 775 "${home_dir}"/PhonieboxInstall.conf - echo "The existing configuration will be used." - echo "Just a few more questions to answer." - read -rp "Hit ENTER to proceed to the next step." INPUT - clear - ;; - esac - fi - - # Delete or use existing installation? - read -rp "Re-use config, audio and RFID codes for the new install? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuse=NO - echo "Phoniebox will be a fresh install. The existing version will be dropped." - sudo rm -rf "${jukebox_dir}" - read -rp "Hit ENTER to proceed to the next step." INPUT - ;; - *) - EXISTINGuse=YES - # CREATE BACKUP - # delete existing BACKUP dir if exists - if [ -d "${backup_dir}" ]; then - sudo rm -r "${backup_dir}" - fi - # move install to BACKUP dir - mv "${jukebox_dir}" "${backup_dir}" - # delete .git dir - if [ -d "${backup_dir}"/.git ]; then - sudo rm -r "${backup_dir}"/.git - fi - # delete placeholder files so moving the folder content back later will not create git pull conflicts - rm "${backup_dir}"/shared/audiofolders/placeholder - rm "${backup_dir}"/shared/shortcuts/placeholder - - # ask for things to use - echo "Ok. You want to use stuff from the existing installation." - echo "What would you want to keep? Answer now." - read -rp "RFID config for system control (e.g. 'volume up' etc.)? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseRfidConf=NO - ;; - *) - EXISTINGuseRfidConf=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseRfidConf=$EXISTINGuseRfidConf" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "RFID shortcuts to play audio folders? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseRfidLinks=NO - ;; - *) - EXISTINGuseRfidLinks=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseRfidLinks=$EXISTINGuseRfidLinks" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "Audio folders: use existing? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseAudio=NO - ;; - *) - EXISTINGuseAudio=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseAudio=$EXISTINGuseAudio" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "Sound effects: use existing startup / shutdown sounds? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseSounds=NO - ;; - *) - EXISTINGuseSounds=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseSounds=$EXISTINGuseSounds" >> "${HOME_DIR}/PhonieboxInstall.conf" - - if [ "$(printf '%s\n' "2.1" "$(cat ~/BACKUP/settings/version-number)" | sort -V | head -n1)" = "2.1" ]; then - read -rp "GPIO: use existing file? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseGpio=NO - ;; - *) - EXISTINGuseGpio=YES - ;; - esac - else - echo "" - echo "Warning! -The configuration of GPIO-Devices has changed in the new version -and needs to be reconfigured. For further info check out the wiki: -https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons" - read -rp "Hit ENTER to proceed to the next step." INPUT - config_gpio - fi - # append variables to config file - echo "EXISTINGuseGpio=$EXISTINGuseGpio" >> "${HOME_DIR}/PhonieboxInstall.conf" - - read -rp "Button USB Encoder: use existing device and button mapping? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseButtonUSBEncoder=NO - ;; - *) - EXISTINGuseButtonUSBEncoder=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseButtonUSBEncoder=$EXISTINGuseButtonUSBEncoder" >> "${HOME_DIR}/PhonieboxInstall.conf" - - echo "Thanks. Got it." - echo "The existing install can be found in the BACKUP directory." - read -rp "Hit ENTER to proceed to the next step." INPUT - ;; - esac - fi - # append variables to config file - echo "EXISTINGuse=$EXISTINGuse" >> "${HOME_DIR}/PhonieboxInstall.conf" - - # Check if we found a Phoniebox install configuration earlier and ask if to run this now - if [ "${EXISTINGusePhonieboxInstall}" == "YES" ]; then - clear - echo "Using the existing configuration, you can run a non-interactive install." - echo "This will re-cycle found content (specified just now) as well as the" - echo "system information from last time (wifi, audio interface, spotify, etc.)." - read -rp "Do you want to run a non-interactive installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - ;; - *) - cd "${home_dir}" - clear - ./buster-install-default.sh -a - exit - ;; - esac - fi -} - -config_audio_interface() { - ##################################################### - # Audio iFace - - clear - - echo "##################################################### -# -# CONFIGURE AUDIO INTERFACE (iFace) -# -# The default RPi audio interface is 'Headphone'. -# But this does not work for every setup. Here a list of -# available iFace names: -" - amixer scontrols - echo " " - read -rp "Use Headphone as iFace? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - read -rp "Type the iFace name you want to use:" AUDIOiFace - ;; - *) - AUDIOiFace="Headphone" - ;; - esac - # append variables to config file - echo "AUDIOiFace=\"$AUDIOiFace\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - echo "Your iFace is called '$AUDIOiFace'" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -config_spotify() { - ##################################################### - # Configure spotify - - clear - - echo "##################################################### -# -# OPTIONAL: INCLUDE SPOTIFY -# -# Note: if this is your first time installing a phoniebox -# it might be best to do a test install without Spotify -# to make sure all your hardware works. -# -# If you want to include Spotify, MUST have your -# credentials ready: -# -# * username -# * password -# * client_id -# * client_secret - -" - read -rp "Do you want to enable Spotify? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - SPOTinstall=NO - echo "You don't want spotify support." - ;; - *) - SPOTinstall=YES - clear - echo "##################################################### -# -# CREDENTIALS for Spotify -# -# Requires Spotify username, password, client_id and client_secret -# to get connection to Spotify. -# -# (Note: You need a device with browser to generate ID and SECRET) -# -# Please go to this website: -# https://www.mopidy.com/authenticate/ -# and follow the instructions. -# -# Your credential will appear on the site below the login button. -# Please note your client_id and client_secret! -# -" - read -rp "Type your Spotify username: " SPOTIuser - read -rp "Type your Spotify password: " SPOTIpass - read -rp "Type your client_id: " SPOTIclientid - read -rp "Type your client_secret: " SPOTIclientsecret - ;; - esac - # append variables to config file - { - echo "SPOTinstall=\"$SPOTinstall\""; - echo "SPOTIuser=\"$SPOTIuser\""; - echo "SPOTIpass=\"$SPOTIpass\""; - echo "SPOTIclientid=\"$SPOTIclientid\""; - echo "SPOTIclientsecret=\"$SPOTIclientsecret\"" - } >> "${HOME_DIR}/PhonieboxInstall.conf" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -config_mpd() { - ##################################################### - # Configure MPD - - clear - - echo "##################################################### -# -# CONFIGURE MPD -# -# MPD (Music Player Daemon) runs the audio output and must -# be configured. Do it now, if you are unsure. -# (Note: can be done manually later.) -" - read -rp "Do you want to configure MPD? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - MPDconfig=NO - echo "You want to configure MPD later." - ;; - *) - MPDconfig=YES - echo "MPD will be set up with default values." - ;; - esac - # append variables to config file - echo "MPDconfig=\"$MPDconfig\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -config_audio_folder() { - local jukebox_dir="$1" - - ##################################################### - # Folder path for audio files - # default: /home/pi/RPi-Jukebox-RFID/shared/audiofolders - - clear - - echo "##################################################### -# -# FOLDER CONTAINING AUDIO FILES -# -# The default location for folders containing audio files: -# ${jukebox_dir}/shared/audiofolders -# -# If unsure, keep it like this. If your files are somewhere -# else, you can specify the folder in the next step. -# IMPORTANT: the folder will not be created, only the path -# will be remembered. If you use a custom folder, you must -# create it. -" - - read -rp "Do you want to use the default location? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - echo "Please type the absolute path here (no trailing slash)." - echo "Default would be for example: ${jukebox_dir}/shared/audiofolders" - read -r DIRaudioFolders - ;; - *) - DIRaudioFolders="${jukebox_dir}/shared/audiofolders" - ;; - esac - # append variables to config file - echo "DIRaudioFolders=\"$DIRaudioFolders\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - echo "Your audio folders live in this dir:" - echo "${DIRaudioFolders}" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -check_variable() { - local variable=${1} - # check if variable exist and if it's empty - test -z "${!variable+x}" && echo "ERROR: \$${variable} is missing!" && fail=true && return - test "${!variable}" == "" && echo "ERROR: \$${variable} is empty!" && fail=true -} - -config_gpio() { - ##################################################### - # Configure GPIO - - clear - - echo "##################################################### -# -# ACTIVATE GPIO-Control -# -# Activation of the GPIO-Control-Service, which mangages Buttons -# or a Rotary Encoder for Volume and/or Track control. -# To configure the controls please consult the wiki: -# https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/Using-GPIO-hardware-buttons -# It's also possible to activate the service later (see wiki). -" - read -rp "Do you want to activate the GPIO-Control-Service? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - GPIOconfig=NO - echo "You don't want to activate GPIO-Controls now." - ;; - *) - GPIOconfig=YES - echo "GPIO-Control-Service will be activated and set to default values." - ;; - esac - # append variables to config file - echo "GPIOconfig=\"$GPIOconfig\"" >> "${HOME_DIR}/PhonieboxInstall.conf" - echo "" - read -rp "Hit ENTER to proceed to the next step." INPUT -} - -check_config_file() { - local install_conf="${HOME_DIR}/PhonieboxInstall.conf" - echo "Checking PhonieboxInstall.conf..." - # check that PhonieboxInstall.conf exists and is not empty - - # check if config file exists - if [[ -f "${install_conf}" ]]; then - # Source config file - source "${install_conf}" - cat "${install_conf}" - echo "" - else - echo "ERROR: ${install_conf} does not exist!" - exit 1 - fi - - fail=false - if [[ -z "${WIFIconfig+x}" ]]; then - echo "ERROR: \$WIFIconfig is missing or not set!" && fail=true - else - if [[ "$WIFIconfig" == "YES" ]]; then - check_variable "WIFIcountryCode" - check_variable "WIFIssid" - check_variable "WIFIpass" - check_variable "WIFIip" - check_variable "WIFIipRouter" - fi - fi - check_variable "EXISTINGuse" - check_variable "AUDIOiFace" - - if [[ -z "${SPOTinstall+x}" ]]; then - echo "ERROR: \$SPOTinstall is missing or not set!" && fail=true - else - if [ "$SPOTinstall" == "YES" ]; then - check_variable "SPOTIuser" - check_variable "SPOTIpass" - check_variable "SPOTIclientid" - check_variable "SPOTIclientsecret" - fi - fi - check_variable "MPDconfig" - check_variable "DIRaudioFolders" - check_variable "GPIOconfig" - - if [ "${fail}" == "true" ]; then - exit 1 - fi - - echo "" -} - -samba_config() { - local smb_conf="/etc/samba/smb.conf" - echo "Configuring Samba..." - # Samba configuration settings - # -rw-r--r-- 1 root root 9416 Apr 30 09:02 /etc/samba/smb.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/smb.conf.buster-default.sample ${smb_conf} - sudo chown root:root "${smb_conf}" - sudo chmod 644 "${smb_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${smb_conf}" - # Samba: create user 'pi' with password 'raspberry' - (echo "raspberry"; echo "raspberry") | sudo smbpasswd -s -a pi -} - -web_server_config() { - local lighthttpd_conf="/etc/lighttpd/lighttpd.conf" - local fastcgi_php_conf="/etc/lighttpd/conf-available/15-fastcgi-php.conf" - local php_ini="/etc/php/7.3/cgi/php.ini" - local sudoers="/etc/sudoers" - - echo "Configuring web server..." - # Web server configuration settings - # -rw-r--r-- 1 root root 1040 Apr 30 09:19 /etc/lighttpd/lighttpd.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/lighttpd.conf.buster-default.sample "${lighthttpd_conf}" - sudo chown root:root "${lighthttpd_conf}" - sudo chmod 644 "${lighthttpd_conf}" - - # Web server PHP7 fastcgi conf - # -rw-r--r-- 1 root root 398 Apr 30 09:35 /etc/lighttpd/conf-available/15-fastcgi-php.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/15-fastcgi-php.conf.buster-default.sample ${fastcgi_php_conf} - sudo chown root:root "${fastcgi_php_conf}" - sudo chmod 644 "${fastcgi_php_conf}" - - # settings for php.ini to support upload - # -rw-r--r-- 1 root root 70999 Jun 14 13:50 /etc/php/7.3/cgi/php.ini - sudo cp "${jukebox_dir}"/misc/sampleconfigs/php.ini.buster-default.sample ${php_ini} - sudo chown root:root "${php_ini}" - sudo chmod 644 "${php_ini}" - - # SUDO users (adding web server here) - # -r--r----- 1 root root 703 Nov 17 21:08 /etc/sudoers - sudo cp "${jukebox_dir}"/misc/sampleconfigs/sudoers.buster-default.sample ${sudoers} - sudo chown root:root "${sudoers}" - sudo chmod 440 "${sudoers}" -} - -install_main() { - local jukebox_dir="$1" - local apt_get="sudo apt-get -qq --yes" - local allow_downgrades="--allow-downgrades --allow-remove-essential --allow-change-held-packages" - - clear - - echo "##################################################### -# -# START INSTALLATION -# -# Good news: you completed the input. -# Let the install begin. -# -# Get yourself a cup of something. The install takes -# between 15 minutes to half an hour, depending on -# your Raspberry Pi and Internet connectivity. -# -# You will be prompted later to complete the installation. -" - - if [[ ${INTERACTIVE} == "true" ]]; then - read -rp "Do you want to start the installation? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - echo "Exiting the installation." - echo "Your configuration data was saved in this file:" - echo "${HOME_DIR}/PhonieboxInstall.conf" - echo - exit - ;; - esac - fi - - # Start logging here - log_open - - # Add conffile into logfile for better debugging - echo "################################################" - grep -v -e "SPOTI" -e "WIFIpass" "${HOME_DIR}/PhonieboxInstall.conf" - echo "################################################" - - ##################################################### - # INSTALLATION - - # Read install config as written so far - # (this might look stupid so far, but makes sense once - # the option to install from config file is introduced.) - # shellcheck source=scripts/installscripts/tests/ShellCheck/PhonieboxInstall.conf - . "${HOME_DIR}/PhonieboxInstall.conf" - - # power management of wifi: switch off to avoid disconnecting - sudo iwconfig wlan0 power off - - # create backup of /etc/resolv.conf - sudo cp /etc/resolv.conf /etc/resolv.conf.orig - - # Generate locales - sudo locale-gen "${LANG}" - - # Install required packages - ${apt_get} ${allow_downgrades} install apt-transport-https - wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add - - sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list - - ${apt_get} update - ${apt_get} upgrade - ${apt_get} install libspotify-dev - - # some packages are only available on raspberry pi's but not on test docker containers running on x86_64 machines - if [[ $(uname -m) =~ ^armv.+$ ]]; then - ${apt_get} ${allow_downgrades} install raspberrypi-kernel-headers - fi - - ${apt_get} ${allow_downgrades} install samba samba-common-bin gcc lighttpd php7.3-common php7.3-cgi php7.3 at mpd mpc mpg123 git ffmpeg resolvconf spi-tools netcat alsa-tools - - # restore backup of /etc/resolv.conf in case installation of resolvconf cleared it - sudo cp /etc/resolv.conf.orig /etc/resolv.conf - - # prepare python3 - ${apt_get} ${allow_downgrades} install python3 python3-dev python3-pip python3-mutagen python3-gpiozero python3-spidev - - # use python3.7 as default - sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.7 1 - - # Get github code - cd "${HOME_DIR}" || exit - git clone ${GIT_URL} --branch "${GIT_BRANCH}" - - # VERSION of installation - - # Get version number - VERSION_NO=`cat ${jukebox_dir}/settings/version-number` - - # add used git branch and commit hash to version file - USED_BRANCH="$(git --git-dir=${jukebox_dir}/.git rev-parse --abbrev-ref HEAD)" - - # add git commit hash to version file - COMMIT_NO="$(git --git-dir=${jukebox_dir}/.git describe --always)" - - echo "${VERSION_NO} - ${COMMIT_NO} - ${USED_BRANCH}" > ${jukebox_dir}/settings/version - chmod 777 ${jukebox_dir}/settings/version - - # Install required spotify packages - if [ "${SPOTinstall}" == "YES" ]; then - echo "Installing dependencies for Spotify support..." - # keep major verson 3 of mopidy - echo -e "Package: mopidy\nPin: version 3.*\nPin-Priority: 1001" | sudo tee /etc/apt/preferences.d/mopidy - - wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add - - sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/buster.list - ${apt_get} update - ${apt_get} upgrade - ${apt_get} ${allow_downgrades} install mopidy mopidy-mpd mopidy-local mopidy-spotify - ${apt_get} ${allow_downgrades} install libspotify12 python3-cffi python3-ply python3-pycparser python3-spotify - - # Install necessary Python packages - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements-spotify.txt - fi - - # Install more required packages - echo "Installing additional Python packages..." - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements.txt - - samba_config - - web_server_config - - # copy shell script for player - cp "${jukebox_dir}"/settings/rfid_trigger_play.conf.sample "${jukebox_dir}"/settings/rfid_trigger_play.conf - - # creating files containing editable values for configuration - echo "$AUDIOiFace" > "${jukebox_dir}"/settings/Audio_iFace_Name - echo "$DIRaudioFolders" > "${jukebox_dir}"/settings/Audio_Folders_Path - echo "3" > "${jukebox_dir}"/settings/Audio_Volume_Change_Step - echo "100" > "${jukebox_dir}"/settings/Max_Volume_Limit - echo "0" > "${jukebox_dir}"/settings/Idle_Time_Before_Shutdown - echo "RESTART" > "${jukebox_dir}"/settings/Second_Swipe - echo "${jukebox_dir}/playlists" > "${jukebox_dir}"/settings/Playlists_Folders_Path - echo "ON" > "${jukebox_dir}"/settings/ShowCover - - # sample file for debugging with all options set to FALSE - sudo cp "${jukebox_dir}"/settings/debugLogging.conf.sample "${jukebox_dir}"/settings/debugLogging.conf - sudo chmod 777 "${jukebox_dir}"/settings/debugLogging.conf - - # The new way of making the bash daemon is using the helperscripts - # creating the shortcuts and script from a CSV file. - # see scripts/helperscripts/AssignIDs4Shortcuts.php - - # create config file for web app from sample - sudo cp "${jukebox_dir}"/htdocs/config.php.sample "${jukebox_dir}"/htdocs/config.php - - # Starting web server and php7 - sudo lighttpd-enable-mod fastcgi - sudo lighttpd-enable-mod fastcgi-php - sudo service lighttpd force-reload - - # make sure bash scripts have the right settings - sudo chown pi:www-data "${jukebox_dir}"/scripts/*.sh - sudo chmod +x "${jukebox_dir}"/scripts/*.sh - sudo chown pi:www-data "${jukebox_dir}"/scripts/*.py - sudo chmod +x "${jukebox_dir}"/scripts/*.py - - # services to launch after boot using systemd - # -rw-r--r-- 1 root root 304 Apr 30 10:07 phoniebox-rfid-reader.service - # 1. delete old services (this is legacy, might throw errors but is necessary. Valid for versions < 1.1.8-beta) - local systemd_dir="/etc/systemd/system" - echo "### Deleting older versions of service daemons. This might throw errors, ignore them" - sudo systemctl disable idle-watchdog - sudo systemctl disable rfid-reader - sudo systemctl disable phoniebox-startup-sound - sudo systemctl disable gpio-buttons - sudo systemctl disable phoniebox-rotary-encoder - sudo systemctl disable phoniebox-gpio-buttons.service - sudo rm "${systemd_dir}"/rfid-reader.service - sudo rm "${systemd_dir}"/startup-sound.service - sudo rm "${systemd_dir}"/gpio-buttons.service - sudo rm "${systemd_dir}"/idle-watchdog.service - sudo rm "${systemd_dir}"/phoniebox-rotary-encoder.service - sudo rm "${systemd_dir}"/phoniebox-gpio-buttons.service - echo "### Done with erasing old daemons. Stop ignoring errors!" - # 2. install new ones - this is version > 1.1.8-beta - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-rfid-reader.service.stretch-default.sample "${systemd_dir}"/phoniebox-rfid-reader.service - #startup sound now part of phoniebox-startup-scripts - #sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-startup-sound.service.stretch-default.sample "${systemd_dir}"/phoniebox-startup-sound.service - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-startup-scripts.service.stretch-default.sample "${systemd_dir}"/phoniebox-startup-scripts.service - sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-idle-watchdog.service.sample "${systemd_dir}"/phoniebox-idle-watchdog.service - [[ "${GPIOconfig}" == "YES" ]] && sudo cp "${jukebox_dir}"/misc/sampleconfigs/phoniebox-gpio-control.service.sample "${systemd_dir}"/phoniebox-gpio-control.service - sudo chown root:root "${systemd_dir}"/phoniebox-*.service - sudo chmod 644 "${systemd_dir}"/phoniebox-*.service - # enable the services needed - sudo systemctl enable phoniebox-idle-watchdog - sudo systemctl enable phoniebox-rfid-reader - #startup sound is part of phoniebox-startup-scripts now - #sudo systemctl enable phoniebox-startup-sound - sudo systemctl enable phoniebox-startup-scripts - # copy mp3s for startup and shutdown sound to the right folder - cp "${jukebox_dir}"/misc/sampleconfigs/startupsound.mp3.sample "${jukebox_dir}"/shared/startupsound.mp3 - cp "${jukebox_dir}"/misc/sampleconfigs/shutdownsound.mp3.sample "${jukebox_dir}"/shared/shutdownsound.mp3 - - # Spotify config - if [ "${SPOTinstall}" == "YES" ]; then - local etc_mopidy_conf="/etc/mopidy/mopidy.conf" - local mopidy_conf="${HOME_DIR}/.config/mopidy/mopidy.conf" - echo "Configuring Spotify support..." - sudo systemctl disable mpd - sudo systemctl enable mopidy - # Install Config Files - sudo cp "${jukebox_dir}"/misc/sampleconfigs/locale.gen.sample /etc/locale.gen - sudo cp "${jukebox_dir}"/misc/sampleconfigs/locale.sample /etc/default/locale - sudo locale-gen - mkdir -p "${HOME_DIR}"/.config/mopidy - sudo cp "${jukebox_dir}"/misc/sampleconfigs/mopidy-etc.sample "${etc_mopidy_conf}" - cp "${jukebox_dir}"/misc/sampleconfigs/mopidy.sample "${mopidy_conf}" - # Change vars to match install config - sudo sed -i 's/%spotify_username%/'"$SPOTIuser"'/' "${etc_mopidy_conf}" - sudo sed -i 's/%spotify_password%/'"$SPOTIpass"'/' "${etc_mopidy_conf}" - sudo sed -i 's/%spotify_client_id%/'"$SPOTIclientid"'/' "${etc_mopidy_conf}" - sudo sed -i 's/%spotify_client_secret%/'"$SPOTIclientsecret"'/' "${etc_mopidy_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${etc_mopidy_conf}" - sed -i 's/%spotify_username%/'"$SPOTIuser"'/' "${mopidy_conf}" - sed -i 's/%spotify_password%/'"$SPOTIpass"'/' "${mopidy_conf}" - sed -i 's/%spotify_client_id%/'"$SPOTIclientid"'/' "${mopidy_conf}" - sed -i 's/%spotify_client_secret%/'"$SPOTIclientsecret"'/' "${mopidy_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${mopidy_conf}" - fi - - # GPIO-Control - if [[ "${GPIOconfig}" == "YES" ]]; then - sudo python3 -m pip install --upgrade --force-reinstall -q -r "${jukebox_dir}"/requirements-GPIO.txt - sudo systemctl enable phoniebox-gpio-control.service - if [[ ! -f "${jukebox_dir}"/settings/gpio_settings.ini ]]; then - cp "${jukebox_dir}"/misc/sampleconfigs/gpio_settings.ini.sample "${jukebox_dir}"/settings/gpio_settings.ini - fi - fi - - if [ "${MPDconfig}" == "YES" ]; then - local mpd_conf="/etc/mpd.conf" - - echo "Configuring MPD..." - # MPD configuration - # -rw-r----- 1 mpd audio 14043 Jul 17 20:16 /etc/mpd.conf - sudo cp "${jukebox_dir}"/misc/sampleconfigs/mpd.conf.buster-default.sample ${mpd_conf} - # Change vars to match install config - sudo sed -i 's/%AUDIOiFace%/'"$AUDIOiFace"'/' "${mpd_conf}" - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' "${mpd_conf}" - sudo chown mpd:audio "${mpd_conf}" - sudo chmod 640 "${mpd_conf}" - fi - - # set which version has been installed - if [ "${SPOTinstall}" == "YES" ]; then - echo "plusSpotify" > "${jukebox_dir}"/settings/edition - else - echo "classic" > "${jukebox_dir}"/settings/edition - fi - - # update mpc / mpd DB - mpc update - - # / INSTALLATION - ##################################################### -} - -wifi_settings() { - local sample_configs_dir="$1" - local dhcpcd_conf="$2" - local wpa_supplicant_conf="$3" - - ############################### - # WiFi settings (SSID password) - # - # https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md - # - # $WIFIssid - # $WIFIpass - # $WIFIip - # $WIFIipRouter - if [ "${WIFIconfig}" == "YES" ]; then - # DHCP configuration settings - echo "Setting ${dhcpcd_conf}..." - #-rw-rw-r-- 1 root netdev 0 Apr 17 11:25 /etc/dhcpcd.conf - sudo cp "${sample_configs_dir}"/dhcpcd.conf.buster-default-noHotspot.sample "${dhcpcd_conf}" - # Change IP for router and Phoniebox - sudo sed -i 's/%WIFIip%/'"$WIFIip"'/' "${dhcpcd_conf}" - sudo sed -i 's/%WIFIipRouter%/'"$WIFIipRouter"'/' "${dhcpcd_conf}" - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' "${dhcpcd_conf}" - # Change user:group and access mod - sudo chown root:netdev "${dhcpcd_conf}" - sudo chmod 664 "${dhcpcd_conf}" - - # WiFi SSID & Password - echo "Setting ${wpa_supplicant_conf}..." - # -rw-rw-r-- 1 root netdev 137 Jul 16 08:53 /etc/wpa_supplicant/wpa_supplicant.conf - sudo cp "${sample_configs_dir}"/wpa_supplicant.conf.buster-default.sample "${wpa_supplicant_conf}" - sudo sed -i 's/%WIFIssid%/'"$WIFIssid"'/' "${wpa_supplicant_conf}" - sudo sed -i 's/%WIFIpass%/'"$WIFIpass"'/' "${wpa_supplicant_conf}" - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' "${wpa_supplicant_conf}" - sudo chown root:netdev "${wpa_supplicant_conf}" - sudo chmod 664 "${wpa_supplicant_conf}" - fi - - # start DHCP - echo "Starting dhcpcd service..." - sudo service dhcpcd start - sudo systemctl enable dhcpcd - -# / WiFi settings (SSID password) -############################### -} - -existing_assets() { - local jukebox_dir="$1" - local backup_dir="$2" - - ##################################################### - # EXISTING ASSETS TO USE FROM EXISTING INSTALL - - if [ "${EXISTINGuse}" == "YES" ]; then - # RFID config for system control - if [ "${EXISTINGuseRfidConf}" == "YES" ]; then - # read old values and write them into new file (copied above already) - # do not overwrite but use 'sed' in case there are new vars in new version installed - - # Read the existing RFID config file line by line and use - # only lines which are separated (IFS) by '='. - while IFS='=' read -r key val ; do - # $var should be stripped of possible leading or trailing " - val=${val%\"} - val=${val#\"} - key=${key} - # Additional error check: key should not start with a hash and not be empty. - if [ ! "${key:0:1}" == '#' ] && [ -n "$key" ]; then - # Replace the matching value in the newly created conf file - sed -i 's/%'"$key"'%/'"$val"'/' "${jukebox_dir}"/settings/rfid_trigger_play.conf - fi - done <"${backup_dir}"/settings/rfid_trigger_play.conf - fi - - # RFID shortcuts for audio folders - if [ "${EXISTINGuseRfidLinks}" == "YES" ]; then - # copy from backup to new install - cp -R "${backup_dir}"/shared/shortcuts/* "${jukebox_dir}"/shared/shortcuts/ - fi - - # Audio folders: use existing - if [ "${EXISTINGuseAudio}" == "YES" ]; then - # copy from backup to new install - cp -R "${backup_dir}"/shared/audiofolders/* "$DIRaudioFolders/" - fi - - # GPIO: use existing file - if [ "${EXISTINGuseGpio}" == "YES" ]; then - # copy from backup to new install - cp "${backup_dir}"/settings/gpio_settings.ini "${jukebox_dir}"/settings/gpio_settings.ini - fi - - # Button USB Encoder: use existing file - if [ "${EXISTINGuseButtonUSBEncoder}" == "YES" ]; then - # copy from backup to new install - cp "${backup_dir}"/components/controls/buttons_usb_encoder/deviceName.txt "${jukebox_dir}"/components/controls/buttons_usb_encoder/deviceName.txt - cp "${backup_dir}"/components/controls/buttons_usb_encoder/buttonMap.json "${jukebox_dir}"/components/controls/buttons_usb_encoder/buttonMap.json - # make buttons_usb_encoder.py ready to be use from phoniebox-buttons-usb-encoder service - sudo chmod +x "${jukebox_dir}"/components/controls/buttons_usb_encoder/buttons_usb_encoder.py - # make sure service is still enabled by registering again - sudo cp -v "${jukebox_dir}"/components/controls/buttons_usb_encoder/phoniebox-buttons-usb-encoder.service.sample /etc/systemd/system/phoniebox-buttons-usb-encoder.service - sudo systemctl start phoniebox-buttons-usb-encoder.service - sudo systemctl enable phoniebox-buttons-usb-encoder.service - fi - - # Sound effects: use existing startup / shutdown sounds - if [ "${EXISTINGuseSounds}" == "YES" ]; then - # copy from backup to new install - cp "${backup_dir}"/shared/startupsound.mp3 "${jukebox_dir}"/shared/startupsound.mp3 - cp "${backup_dir}"/shared/shutdownsound.mp3 "${jukebox_dir}"/shared/shutdownsound.mp3 - fi - - fi - - # / EXISTING ASSETS TO USE FROM EXISTING INSTALL - ################################################ -} - - -folder_access() { - local jukebox_dir="$1" - local user_group="$2" - local mod="$3" - - ##################################################### - # Folders and Access Settings - - echo "Setting owner and permissions for directories..." - - # create playlists folder - mkdir -p "${jukebox_dir}"/playlists - sudo chown -R "${user_group}" "${jukebox_dir}"/playlists - sudo chmod -R "${mod}" "${jukebox_dir}"/playlists - - # make sure the shared folder is accessible by the web server - sudo chown -R "${user_group}" "${jukebox_dir}"/shared - sudo chmod -R "${mod}" "${jukebox_dir}"/shared - - # make sure the htdocs folder can be changed by the web server - sudo chown -R "${user_group}" "${jukebox_dir}"/htdocs - sudo chmod -R "${mod}" "${jukebox_dir}"/htdocs - - sudo chown -R "${user_group}" "${jukebox_dir}"/settings - sudo chmod -R "${mod}" "${jukebox_dir}"/settings - - # logs dir accessible by pi and www-data - sudo chown "${user_group}" "${jukebox_dir}"/logs - sudo chmod "${mod}" "${jukebox_dir}"/logs - - # audio folders might be somewhere else, so treat them separately - sudo chown "${user_group}" "${DIRaudioFolders}" - sudo chmod "${mod}" "${DIRaudioFolders}" - - # make sure bash scripts have the right settings - sudo chown "${user_group}" "${jukebox_dir}"/scripts/*.sh - sudo chmod +x "${jukebox_dir}"/scripts/*.sh - sudo chown "${user_group}" "${jukebox_dir}"/scripts/*.py - sudo chmod +x "${jukebox_dir}"/scripts/*.py - - # set audio volume to 100% - # see: https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/54 - sudo amixer cset numid=1 100% - - # delete the global.conf file, in case somebody manually copied stuff back and forth - # this will be created the first time the Phoniebox is put to use by web app or RFID - GLOBAL_CONF="${jukebox_dir}"/settings/global.conf - if [ -f "${GLOBAL_CONF}" ]; then - echo "global.conf needs to be deleted." - rm "${GLOBAL_CONF}" - fi - - # / Access settings - ##################################################### -} - -finish_installation() { - local jukebox_dir="$1" - echo " -# -# INSTALLATION FINISHED -# -##################################################### -" - - ##################################################### - # Register external device(s) - - echo "If you are using an RFID reader, connect it to your RPi." - echo "(In case your RFID reader required soldering, consult the manual.)" - # Use -e to display response of user in the logfile - read -e -r -p "Have you connected your RFID reader? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - ;; - *) - echo 'Please select the RFID reader you want to use' - options=("USB-Reader (e.g. Neuftech)" "RC522" "PN532" "Manual configuration" "Multiple RFID reader") - select opt in "${options[@]}"; do - case $opt in - "USB-Reader (e.g. Neuftech)") - cd "${jukebox_dir}"/scripts/ || exit - python3 RegisterDevice.py - sudo chown pi:www-data "${jukebox_dir}"/scripts/deviceName.txt - sudo chmod 644 "${jukebox_dir}"/scripts/deviceName.txt - break - ;; - "RC522") - bash "${jukebox_dir}"/components/rfid-reader/RC522/setup_rc522.sh - break - ;; - "PN532") - bash "${jukebox_dir}"/components/rfid-reader/PN532/setup_pn532.sh - break - ;; - "Manual configuration") - echo "Please configure your reader manually." - break - ;; - "Multiple RFID reader") - cd "${jukebox_dir}"/scripts/ || exit - sudo python3 RegisterDevice.py.Multi - break - ;; - *) - echo "This is not a number" - ;; - esac - done - esac - - echo - echo "DONE. Let the sounds begin." - echo "Find more information and documentation on the github account:" - echo "https://github.com/MiczFlor/RPi-Jukebox-RFID/wiki/" - - echo "Reboot is needed to activate all settings" - # Use -e to display response of user in the logfile - read -e -r -p "Would you like to reboot now? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - # Close logging - log_close - ;; - *) - # Close logging - log_close - sudo shutdown -r now - ;; - esac -} - -######## -# Main # -######## -main() { - # Skip interactive Samba WINS config dialog - echo "samba-common samba-common/dhcp boolean false" | sudo debconf-set-selections - - if [[ ${INTERACTIVE} == "true" ]]; then - welcome - #reset_install_config_file - config_wifi - check_existing "${JUKEBOX_HOME_DIR}" "${JUKEBOX_BACKUP_DIR}" "${HOME_DIR}" - config_audio_interface - config_spotify - config_mpd - config_audio_folder "${JUKEBOX_HOME_DIR}" - config_gpio - else - echo "Non-interactive installation!" - check_config_file - fi - install_main "${JUKEBOX_HOME_DIR}" - wifi_settings "${JUKEBOX_HOME_DIR}/misc/sampleconfigs" "/etc/dhcpcd.conf" "/etc/wpa_supplicant/wpa_supplicant.conf" - existing_assets "${JUKEBOX_HOME_DIR}" "${JUKEBOX_BACKUP_DIR}" - folder_access "${JUKEBOX_HOME_DIR}" "pi:www-data" 775 - - # Copy PhonieboxInstall.conf configuration file to settings folder - sudo cp "${HOME_DIR}/PhonieboxInstall.conf" "${JUKEBOX_HOME_DIR}/settings/" - sudo chown pi:www-data "${JUKEBOX_HOME_DIR}/settings/PhonieboxInstall.conf" - sudo chmod 775 "${JUKEBOX_HOME_DIR}/settings/PhonieboxInstall.conf" - - if [[ ${INTERACTIVE} == "true" ]]; then - finish_installation "${JUKEBOX_HOME_DIR}" - else - echo "Skipping USB device setup..." - echo "For manual registration of a USB card reader type:" - echo "python3 /home/pi/RPi-Jukebox-RFID/scripts/RegisterDevice.py" - echo " " - echo "Reboot is required to activate all settings!" - fi -} - -start=$(date +%s) - -main - -end=$(date +%s) -runtime=$((end-start)) -((h=${runtime}/3600)) -((m=(${runtime}%3600)/60)) -((s=${runtime}%60)) -echo "Done (in ${h}h ${m}m ${s}s)." - -##################################################### -# notes for things to do - -# CLEANUP -## remove dir BACKUP (possibly not, because we do this at the beginning after user confirms for latest config) -##################################################### diff --git a/scripts/installscripts/stretch-install-default-HotspotAddOn.sh b/scripts/installscripts/stretch-install-default-HotspotAddOn.sh deleted file mode 100644 index a7f9aa276..000000000 --- a/scripts/installscripts/stretch-install-default-HotspotAddOn.sh +++ /dev/null @@ -1,124 +0,0 @@ -#!/bin/bash -# DO NOT USE UNTIL THIS LINE HAS DISAPPEARED -# -# This script turns the Phoniebox into a Hotspot -# IF there is no other WiFi network to connect to. -# Needs to run on top of a finished install. And might -# not work if you are not using a Pi3 or ZERO with Wifi. -# See for more information: -# http://www.raspberryconnect.com/network/item/331-raspberry-pi-auto-wifi-hotspot-switch-no-internet-routing -# -# Belongs to: https://github.com/MiczFlor/RPi-Jukebox-RFID - -##################################################### -# Ask if access point - -clear - -echo "##################################################### -# -# CONFIGURE ACCESS POINT / HOTSPOT -# -# If you take your Phoniebox on the road and it is not -# connected to a WiFi network, it can automatically turn -# into an access point and show up as SSID 'phoniebox'. -# This will work for RPi3 out of the box. It might not -# work for other models and WiFi cards. -# (Note: can be done manually later, if you are unsure.) -" -read -r -p "Do you want to configure as Access Point? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - ACCESSconfig=NO - echo "You don't want to configure as an Access Point." - echo "Hit ENTER to proceed to the next step." - read -r - ;; - *) - ACCESSconfig=YES - ;; -esac -# append variables to config file -echo "ACCESSconfig=\"$ACCESSconfig\"" >> "${PATHDATA}/PhonieboxInstall.conf" - - -######################## -# Access Point / Hotspot -# http://www.raspberryconnect.com/network/item/331-raspberry-pi-auto-wifi-hotspot-switch-no-internet-routing -if [ $ACCESSconfig == "IGNOREFORNOWYES" ] -then - -# -# NOT IMPLEMENTED YET -# - # Work in progress, so keep in mind: BACKUP conf files for ACCESS POINT - # cp /etc/hostapd/hostapd.conf hostapd.conf.stretch.sample - # cp /etc/default/hostapd hostapd.stretch.sample - # cp /etc/dnsmasq.conf dnsmasq.conf.stretch.sample - # cp /etc/network/interfaces interfaces.stretch.sample - # WIFIcountryCode - # https://www.cisco.com/en/US/products/ps6305/products_configuration_guide_chapter09186a00804ddd8a.html - - # Remove dns-root-data - sudo apt-get purge dns-root-data - # Install packages - sudo apt-get install hostapd dnsmasq iw - # enter Y when prompted - - # The installers will have set up the programme so they run when the pi is started. - # For this setup they only need to be started if the home router is not found. - # So automatic startup needs to be disabled. This is done with the following commands: - sudo systemctl disable hostapd - sudo systemctl disable dnsmasq - - # -rw-r--r-- 1 root root 345 Aug 13 17:55 /etc/hostapd/hostapd.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/hostapd.conf.stretch-default2-Hotspot.sample /etc/hostapd/hostapd.conf - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' /etc/hostapd/hostapd.conf - sudo chmod 644 /etc/hostapd/hostapd.conf - sudo chown root:root /etc/hostapd/hostapd.conf - - # -rw-r--r-- 1 root root 794 Aug 13 18:40 /etc/default/hostapd - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/hostapd.stretch-default2-Hotspot.sample /etc/default/hostapd - sudo chmod 644 /etc/default/hostapd - sudo chown root:root /etc/default/hostapd - - # -rw-r--r-- 1 root root 82 Jul 17 15:13 /etc/network/interfaces - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/interfaces.stretch-default2-Hotspot.sample /etc/network/interfaces - sudo chmod 644 /etc/network/interfaces - sudo chown root:root /etc/network/interfaces - - # DHCP configuration settings - #-rw-rw-r-- 1 root netdev 0 Apr 17 11:25 /etc/dhcpcd.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/dhcpcd.conf.stretch-default2-Hotspot.sample /etc/dhcpcd.conf - # Change IP for router and Phoniebox - sudo sed -i 's/%WIFIip%/'"$WIFIip"'/' /etc/dhcpcd.conf - sudo sed -i 's/%WIFIipRouter%/'"$WIFIipRouter"'/' /etc/dhcpcd.conf - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' /etc/dhcpcd.conf - # Change user:group and access mod - sudo chown root:netdev /etc/dhcpcd.conf - sudo chmod 664 /etc/dhcpcd.conf - - # /usr/bin/autohotspot - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/autohotspot.stretch-default2-Hotspot.sample /usr/bin/autohotspot - sudo chown root:root /usr/bin/autohotspot - sudo chmod 644 /usr/bin/autohotspot - sudo chmod +x /usr/bin/autohotspot - - # /etc/systemd/system/autohotspot.service - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/autohotspot.service.stretch-default2-Hotspot.sample /etc/systemd/system/autohotspot.service - sudo chown root:root /etc/systemd/system/autohotspot.service - sudo chmod 644 /etc/systemd/system/autohotspot.service - sudo systemctl enable autohotspot.service - - echo " - ######################## - # Hotspot (Access Point) - NOTE: - The network 'phoniebox' appears only when away from your usual WiFi. - You can connect from any device with the password 'PlayItLoud'. - In your browser, open the IP '10.0.0.10' to access the web app. - " -fi - -# / Access Point -################ \ No newline at end of file diff --git a/scripts/installscripts/stretch-install-default.sh b/scripts/installscripts/stretch-install-default.sh deleted file mode 100755 index 49843d7cf..000000000 --- a/scripts/installscripts/stretch-install-default.sh +++ /dev/null @@ -1,894 +0,0 @@ -#!/bin/bash -# -# see https://github.com/MiczFlor/RPi-Jukebox-RFID for details -# Especially the docs folder for documentation - -# The absolute path to the folder which contains this script -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -GIT_BRANCH=${GIT_BRANCH:-master} - -clear -echo "##################################################### -# ___ __ ______ _ __________ ____ __ _ _ # -# / _ \/ // / __ \/ |/ / _/ __/( _ \ / \( \/ ) # -# / ___/ _ / /_/ / // // _/ ) _ (( O )) ( # -# /_/ /_//_/\____/_/|_/___/____/ (____/ \__/(_/\_) # -# # -##################################################### - -Welcome to the installation script. - -This script will install Phoniebox on your Raspberry Pi. -To do so, you must be online. The install script can -automatically configure: - -* WiFi settings (SSID, password and static IP) - -All these are optional and can also be done later -manually. - -If you are ready, hit ENTER" -read -r INPUT - -##################################################### -# CONFIG FILE -# This file will contain all the data given in the -# following dialogue -# At a later stage, the install should also be done -# from such a config file with no user input. - -# Remove existing config file -rm PhonieboxInstall.conf -# Create empty config file -touch PhonieboxInstall.conf -echo "# Phoniebox config" > "${PATHDATA}/PhonieboxInstall.conf" - -##################################################### -# Ask if wifi config - -clear - -echo "##################################################### -# -# CONFIGURE WIFI -# -# Requires SSID, WiFi password and the static IP you want -# to assign to your Phoniebox. -# (Note: can be done manually later, if you are unsure.) -" -read -r -p "Do you want to configure your WiFi? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - WIFIconfig=NO - echo "You want to configure WiFi later." - echo "Hit ENTER to proceed to the next step." - read -r INPUT - # append variables to config file - echo "WIFIconfig=$WIFIconfig" >> "${PATHDATA}/PhonieboxInstall.conf" - # make a fallback for WiFi Country Code, because we need that even without WiFi config - echo "WIFIcountryCode=DE" >> "${PATHDATA}/PhonieboxInstall.conf" - ;; - *) - WIFIconfig=YES - #Ask for ssid - echo "* Type SSID name" - read -r INPUT - WIFIssid="$INPUT" - #Ask for wifi country code - echo "* WiFi Country Code (e.g. DE, GB, CZ or US)" - read -r INPUT - WIFIcountryCode="$INPUT" - #Ask for password - echo "* Type password" - read -r INPUT - WIFIpass="$INPUT" - #Ask for IP - echo "* Static IP (e.g. 192.168.1.199)" - read -r INPUT - WIFIip="$INPUT" - #Ask for Router IP - echo "* Router IP (e.g. 192.168.1.1)" - read -r INPUT - WIFIipRouter="$INPUT" - echo "Your WiFi config:" - echo "SSID : $WIFIssid" - echo "WiFi Country Code : $WIFIcountryCode" - echo "Password : $WIFIpass" - echo "Static IP : $WIFIip" - echo "Router IP : $WIFIipRouter" - read -r -p "Are these values correct? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - echo "The values are incorrect." - echo "Hit ENTER to exit and start over." - read -r INPUT; exit - ;; - *) - # append variables to config file - echo "WIFIconfig=\"$WIFIconfig\"" >> "${PATHDATA}/PhonieboxInstall.conf" - echo "WIFIcountryCode=\"$WIFIcountryCode\"" >> "${PATHDATA}/PhonieboxInstall.conf" - echo "WIFIssid=\"$WIFIssid\"" >> "${PATHDATA}/PhonieboxInstall.conf" - echo "WIFIpass=\"$WIFIpass\"" >> "${PATHDATA}/PhonieboxInstall.conf" - echo "WIFIip=\"$WIFIip\"" >> "${PATHDATA}/PhonieboxInstall.conf" - echo "WIFIipRouter=\"$WIFIipRouter\"" >> "${PATHDATA}/PhonieboxInstall.conf" - ;; - esac - ;; -esac - -##################################################### -# Check for existing Phoniebox -# -# In case there is no existing install, -# set the var now for later use: -EXISTINGuse=NO - -# The install will be in the home dir of user pi -# Move to home directory now to check -cd || exit -if [ -d /home/pi/RPi-Jukebox-RFID ]; then - # Houston, we found something! - clear -echo "##################################################### -# -# . . . * alert * alert * alert * alert * . . . -# -# WARNING: an existing Phoniebox installation was found. -# -" - # check if we find the version number - if [ -f /home/pi/RPi-Jukebox-RFID/settings/version ]; then - echo "The version of your installation is: $(cat RPi-Jukebox-RFID/settings/version)" - fi - echo "IMPORTANT: you can use the existing content and configuration files for your new install." - echo "Whatever you chose to keep will be moved to the new install." - echo "Everything else will remain in a folder called 'BACKUP'. - " - # Delete or use existing installation? - read -r -p "Re-use config, audio and RFID codes for the new install? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuse=NO - echo "Phoniebox will be a fresh install. The existing version will be dropped." - echo "Hit ENTER to proceed to the next step." - sudo rm -rf RPi-Jukebox-RFID - read -r INPUT - ;; - *) - EXISTINGuse=YES - # CREATE BACKUP - # delete existing BACKUP dir if exists - if [ -d BACKUP ]; then - sudo rm -r BACKUP - fi - # move install to BACKUP dir - mv RPi-Jukebox-RFID BACKUP - # delete .git dir - if [ -d BACKUP/.git ]; then - sudo rm -r BACKUP/.git - fi - # delete placeholder files so moving the folder content back later will not create git pull conflicts - rm BACKUP/shared/audiofolders/placeholder - rm BACKUP/shared/shortcuts/placeholder - - # ask for things to use - echo "Ok. You want to use stuff from the existing installation." - echo "What would you want to keep? Answer now." - read -r -p "RFID config for system control (e.g. 'volume up' etc.)? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseRfidConf=NO - ;; - *) - EXISTINGuseRfidConf=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseRfidConf=$EXISTINGuseRfidConf" >> "${PATHDATA}/PhonieboxInstall.conf" - - read -r -p "RFID shortcuts to play audio folders? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseRfidLinks=NO - ;; - *) - EXISTINGuseRfidLinks=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseRfidLinks=$EXISTINGuseRfidLinks" >> "${PATHDATA}/PhonieboxInstall.conf" - - read -r -p "Audio folders: use existing? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseAudio=NO - ;; - *) - EXISTINGuseAudio=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseAudio=$EXISTINGuseAudio" >> "${PATHDATA}/PhonieboxInstall.conf" - - read -r -p "GPIO: use existing file? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseGpio=NO - ;; - *) - EXISTINGuseGpio=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseGpio=$EXISTINGuseGpio" >> "${PATHDATA}/PhonieboxInstall.conf" - - read -r -p "Sound effects: use existing startup / shutdown sounds? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseSounds=NO - ;; - *) - EXISTINGuseSounds=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseSounds=$EXISTINGuseSounds" >> "${PATHDATA}/PhonieboxInstall.conf" - - read -r -p "Button USB Encoder: use existing device and button mapping? [Y/n] " response - case "$response" in - [nN][oO]|[nN]) - EXISTINGuseButtonUSBEncoder=NO - ;; - *) - EXISTINGuseButtonUSBEncoder=YES - ;; - esac - # append variables to config file - echo "EXISTINGuseButtonUSBEncoder=$EXISTINGuseButtonUSBEncoder" >> "${PATHDATA}/PhonieboxInstall.conf" - - echo "Thanks. Got it." - echo "The existing install can be found in the BACKUP directory." - echo "Hit ENTER to proceed to the next step." - read -r INPUT - ;; - esac -fi -# append variables to config file -echo "EXISTINGuse=$EXISTINGuse" >> "${PATHDATA}/PhonieboxInstall.conf" - -##################################################### -# Audio iFace - -clear - -echo "##################################################### -# -# CONFIGURE AUDIO INTERFACE (iFace) -# -# By default for the RPi the audio interface would be 'PCM'. -# But this does not work for every setup, alternatives are -# 'Master' or 'Speaker'. Other external sound cards might -# use different interface names. -# To list all available iFace names, type 'amixer scontrols' -# in the terminal. -" -read -r -p "Use PCM as iFace? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - echo "Type the iFace name you want to use:" - read -r INPUT - AUDIOiFace="$INPUT" - ;; - *) - AUDIOiFace="PCM" - ;; -esac -# append variables to config file -echo "AUDIOiFace=\"$AUDIOiFace\"" >> "${PATHDATA}/PhonieboxInstall.conf" -echo "Your iFace is called'$AUDIOiFace'" -echo "Hit ENTER to proceed to the next step." -read -r INPUT - -##################################################### -# Configure spotify - -clear - -echo "##################################################### -# -# OPTIONAL: INCLUDE SPOTIFY SUPPORT -# -# Spotify uses Mopidy for audio output and must -# be configured. Do it now, or never. -# (Note: To add this later, you must re-install phoniebox) -" -read -r -p "Do you want to install Mopidy? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - SPOTinstall=NO - echo "You don't want spotify support." - echo "Hit ENTER to proceed to the next step." - read -r INPUT - ;; - *) - SPOTinstall=YES - clear - echo "This was a great decision! Mopidy will be set up." - echo "##################################################### -# -# CONFIGURE MOPIDY -# -# Requires spotify username, password, client_id and client_secret -# to get connection to Spotify. -# -# (Note: You need a device with browser to generate ID and SECRET) -# -# Please go to this website: -# https://www.mopidy.com/authenticate/ -# and follow the instructions. -# -# Your credential will appear on the site below the login button. -# Please note your client_id and client_secret! -# -" - echo "" - echo "Type your Spotify username:" - read -r INPUT - SPOTIuser="$INPUT" - echo "" - echo "Type your Spotify password:" - read -r INPUT - SPOTIpass="$INPUT" - echo "" - echo "Type your client_id:" - read -r INPUT - SPOTIclientid="$INPUT" - echo "" - echo "Type your client_secret:" - read -r INPUT - SPOTIclientsecret="$INPUT" - echo "" - echo "Hit ENTER to proceed to the next step." - read -r INPUT - ;; -esac -# append variables to config file -{ - echo "SPOTinstall=\"$SPOTinstall\""; - echo "SPOTIuser=\"$SPOTIuser\""; - echo "SPOTIpass=\"$SPOTIpass\""; - echo "SPOTIclientid=\"$SPOTIclientid\""; - echo "SPOTIclientsecret=\"$SPOTIclientsecret\"" -} >> "${PATHDATA}/PhonieboxInstall.conf" - -if [ $SPOTinstall == "NO" ]; then -##################################################### -# Configure MPD - -clear - -echo "##################################################### -# -# CONFIGURE MPD -# -# MPD (Music Player Daemon) runs the audio output and must -# be configured. Do it now, if you are unsure. -# (Note: can be done manually later.) -" -read -r -p "Do you want to configure MPD? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - MPDconfig=NO - echo "You want to configure MPD later." - echo "Hit ENTER to proceed to the next step." - read -r INPUT - ;; - *) - MPDconfig=YES - echo "MPD will be set up with default values." - echo "Hit ENTER to proceed to the next step." - read -r INPUT - ;; -esac -# append variables to config file -echo "MPDconfig=\"$MPDconfig\"" >> "${PATHDATA}/PhonieboxInstall.conf" -fi - -##################################################### -# Folder path for audio files -# default: /home/pi/RPi-Jukebox-RFID/shared/audiofolders - -clear - -echo "##################################################### -# -# FOLDER CONTAINING AUDIO FILES -# -# The default location for folders containing audio files: -# /home/pi/RPi-Jukebox-RFID/shared/audiofolders -# -# If unsure, keep it like this. If your files are somewhere -# else, you can specify the folder in the next step. -# IMPORTANT: the folder will not be created, only the path -# will be remembered. If you use a custom folder, you must -# create it. -" - -read -r -p "Do you want to use the default location? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - echo "Please type the absolute path here (no trailing slash)." - echo "Default would be for example:" - echo "/home/pi/RPi-Jukebox-RFID/shared/audiofolders" - read -r INPUT - DIRaudioFolders="$INPUT" - ;; - *) - DIRaudioFolders="/home/pi/RPi-Jukebox-RFID/shared/audiofolders" - ;; -esac -# append variables to config file -echo "DIRaudioFolders=\"$DIRaudioFolders\"" >> "${PATHDATA}/PhonieboxInstall.conf" -echo "Your audio folders live in this dir:" -echo $DIRaudioFolders -echo "Hit ENTER to proceed to the next step." -read -r INPUT - -clear - -echo "##################################################### -# -# START INSTALLATION -# -# Good news: you completed the input. -# Let the install begin. -# -# Get yourself a cup of something. The install takes -# between 15 minutes to half an hour, depending on -# your Raspberry Pi and Internet connectivity. -# -# You will be prompted later to complete the installation. -" - -read -r -p "Do you want to start the installation? [Y/n] " response -case "$response" in - [nN][oO]|[nN]) - echo "Exiting the installation." - echo "Your configuration data was saved in this file:" - echo "${PATHDATA}/PhonieboxInstall.conf" - echo - exit - ;; -esac - -##################################################### -# INSTALLATION - -# Read install config as written so far -# (this might look stupid so far, but makes sense once -# the option to install from config file is introduced.) -# shellcheck source=scripts/installscripts/tests/ShellCheck/PhonieboxInstall.conf -. "${PATHDATA}/PhonieboxInstall.conf" - -# power management of wifi: switch off to avoid disconnecting -sudo iwconfig wlan0 power off - -# Install required packages -sudo apt-get update -sudo apt-get --yes --force-yes install apt-transport-https samba samba-common-bin gcc linux-headers-4.9 lighttpd php7.0-common php7.0-cgi php7.0 at mpd mpc mpg123 git ffmpeg - -# prepare for python2 and python3 -sudo apt-get --yes --force-yes install python-dev python-pip python-mutagen python-gpiozero python-spidev -sudo apt-get --yes --force-yes install python3-dev python3-pip python3-mutagen python3-gpiozero python3-spidev - -# use python3.5 as default -sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.5 1 -# Install required spotify packages -if [ $SPOTinstall == "YES" ] -then - wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add - - sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/stretch.list - sudo apt-get update - sudo apt-get --yes --force-yes install mopidy - sudo apt-get --yes --force-yes install libspotify12 python-cffi python-ply python-pycparser python-spotify - sudo apt-get --yes --force-yes install libspotify12 python3-cffi python3-ply python3-pycparser - sudo python3 -m pip install spotify - sudo rm -rf /usr/lib/python2.7/dist-packages/mopidy_spotify* - sudo rm -rf /usr/lib/python2.7/dist-packages/Mopidy_Spotify-* - cd || exit - sudo rm -rf mopidy-spotify - git clone -b fix/web_api_playlists --single-branch https://github.com/princemaxwell/mopidy-spotify.git - cd mopidy-spotify || exit - sudo python setup.py install - cd || exit - # should be removed, if Mopidy-Iris can be installed normally - # pylast >= 3.0.0 removed the python2 support - sudo pip install pylast==2.4.0 - sudo pip install Mopidy-Iris -fi - -# Get github code -cd /home/pi/ || exit -git clone https://github.com/MiczFlor/RPi-Jukebox-RFID.git --branch "${GIT_BRANCH}" - -# check, which branch was cloned -git status - -# the following three lines are needed as long as this is not the master branch: -cd /home/pi/RPi-Jukebox-RFID || exit -git fetch - -# Install more required packages -sudo pip install -r requirements.txt -sudo pip3 install -r /home/pi/RPi-Jukebox-RFID/components/rfid-reader/PN532/requirements.txt - -# actually, for the time being most of the requirements are run here (again). -# the requirements.txt version seems to throw errors. Help if you can to fix this: - -sudo pip install "evdev == 0.7.0" -sudo pip install --upgrade youtube_dl -sudo pip install spidev -sudo pip install git+git://github.com/lthiery/SPI-Py.git#egg=spi-py -sudo pip install pyserial -sudo pip install RPi.GPIO -sudo pip install pi-rc522 - -sudo python3 -m pip install "evdev == 0.7.0" - -# Switch of WiFi power management -sudo iwconfig wlan0 power off - -# Samba configuration settings -# -rw-r--r-- 1 root root 9416 Apr 30 09:02 /etc/samba/smb.conf -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/smb.conf.stretch-default2.sample /etc/samba/smb.conf -sudo chown root:root /etc/samba/smb.conf -sudo chmod 644 /etc/samba/smb.conf -# for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash -sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' /etc/samba/smb.conf -# Samba: create user 'pi' with password 'raspberry' -(echo "raspberry"; echo "raspberry") | sudo smbpasswd -s -a pi - -# Web server configuration settings -# -rw-r--r-- 1 root root 1040 Apr 30 09:19 /etc/lighttpd/lighttpd.conf -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/lighttpd.conf.stretch-default.sample /etc/lighttpd/lighttpd.conf -sudo chown root:root /etc/lighttpd/lighttpd.conf -sudo chmod 644 /etc/lighttpd/lighttpd.conf - -# Web server PHP7 fastcgi conf -# -rw-r--r-- 1 root root 398 Apr 30 09:35 /etc/lighttpd/conf-available/15-fastcgi-php.conf -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/15-fastcgi-php.conf.stretch-default.sample /etc/lighttpd/conf-available/15-fastcgi-php.conf -sudo chown root:root /etc/lighttpd/conf-available/15-fastcgi-php.conf -sudo chmod 644 /etc/lighttpd/conf-available/15-fastcgi-php.conf -# settings for php.ini to support upload -# -rw-r--r-- 1 root root 70999 Jun 14 13:50 /etc/php/7.0/fpm/php.ini -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/php.ini.stretch-default.sample /etc/php/7.0/fpm/php.ini -sudo chown root:root /etc/php/7.0/fpm/php.ini -sudo chmod 644 /etc/php/7.0/fpm/php.ini - -# SUDO users (adding web server here) -# -r--r----- 1 root root 703 Nov 17 21:08 /etc/sudoers -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/sudoers.stretch-default.sample /etc/sudoers -sudo chown root:root /etc/sudoers -sudo chmod 440 /etc/sudoers - -# copy shell script for player -cp /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf.sample /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf - -# creating files containing editable values for configuration -# DISCONTINUED: now done by MPD? echo "PCM" > /home/pi/RPi-Jukebox-RFID/settings/Audio_iFace_Name -echo "$AUDIOiFace" > /home/pi/RPi-Jukebox-RFID/settings/Audio_iFace_Name -echo "$DIRaudioFolders" > /home/pi/RPi-Jukebox-RFID/settings/Audio_Folders_Path -echo "3" > /home/pi/RPi-Jukebox-RFID/settings/Audio_Volume_Change_Step -echo "100" > /home/pi/RPi-Jukebox-RFID/settings/Max_Volume_Limit -echo "0" > /home/pi/RPi-Jukebox-RFID/settings/Idle_Time_Before_Shutdown -echo "RESTART" > /home/pi/RPi-Jukebox-RFID/settings/Second_Swipe -echo "/home/pi/RPi-Jukebox-RFID/playlists" > /home/pi/RPi-Jukebox-RFID/settings/Playlists_Folders_Path -echo "ON" > /home/pi/RPi-Jukebox-RFID/settings/ShowCover - -# The new way of making the bash daemon is using the helperscripts -# creating the shortcuts and script from a CSV file. -# see scripts/helperscripts/AssignIDs4Shortcuts.php - -# create config file for web app from sample -sudo cp /home/pi/RPi-Jukebox-RFID/htdocs/config.php.sample /home/pi/RPi-Jukebox-RFID/htdocs/config.php - -# Starting web server and php7 -sudo lighttpd-enable-mod fastcgi -sudo lighttpd-enable-mod fastcgi-php -sudo service lighttpd force-reload -sudo service php7.0-fpm restart - -# create copy of GPIO script -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/gpio-buttons.py.sample /home/pi/RPi-Jukebox-RFID/scripts/gpio-buttons.py -sudo chmod +x /home/pi/RPi-Jukebox-RFID/scripts/gpio-buttons.py - -# make sure bash scripts have the right settings -sudo chown pi:www-data /home/pi/RPi-Jukebox-RFID/scripts/*.sh -sudo chmod +x /home/pi/RPi-Jukebox-RFID/scripts/*.sh -sudo chown pi:www-data /home/pi/RPi-Jukebox-RFID/scripts/*.py -sudo chmod +x /home/pi/RPi-Jukebox-RFID/scripts/*.py - -# services to launch after boot using systemd -# -rw-r--r-- 1 root root 304 Apr 30 10:07 phoniebox-rfid-reader.service -# 1. delete old services (this is legacy, might throw errors but is necessary. Valid for versions < 1.1.8-beta) -echo "### Deleting older versions of service daemons. This might throw errors, ignore them" -sudo systemctl disable idle-watchdog -sudo systemctl disable rfid-reader -sudo systemctl disable startup-sound -sudo systemctl disable gpio-buttons -sudo rm /etc/systemd/system/rfid-reader.service -sudo rm /etc/systemd/system/startup-sound.service -sudo rm /etc/systemd/system/gpio-buttons.service -sudo rm /etc/systemd/system/idle-watchdog.service -echo "### Done with erasing old daemons. Stop ignoring errors!" -# 2. install new ones - this is version > 1.1.8-beta -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-rfid-reader.service.stretch-default.sample /etc/systemd/system/phoniebox-rfid-reader.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-startup-sound.service.stretch-default.sample /etc/systemd/system/phoniebox-startup-sound.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-gpio-buttons.service.stretch-default.sample /etc/systemd/system/phoniebox-gpio-buttons.service -sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/phoniebox-idle-watchdog.service.sample /etc/systemd/system/phoniebox-idle-watchdog.service -sudo chown root:root /etc/systemd/system/phoniebox-rfid-reader.service -sudo chown root:root /etc/systemd/system/phoniebox-startup-sound.service -sudo chown root:root /etc/systemd/system/phoniebox-gpio-buttons.service -sudo chown root:root /etc/systemd/system/phoniebox-idle-watchdog.service -sudo chmod 644 /etc/systemd/system/phoniebox-rfid-reader.service -sudo chmod 644 /etc/systemd/system/phoniebox-startup-sound.service -sudo chmod 644 /etc/systemd/system/phoniebox-gpio-buttons.service -sudo chmod 644 /etc/systemd/system/phoniebox-idle-watchdog.service -# enable the services needed -sudo systemctl enable phoniebox-idle-watchdog -sudo systemctl enable phoniebox-rfid-reader -sudo systemctl enable phoniebox-startup-sound -sudo systemctl enable phoniebox-gpio-buttons - -# copy mp3s for startup and shutdown sound to the right folder -cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/startupsound.mp3.sample /home/pi/RPi-Jukebox-RFID/shared/startupsound.mp3 -cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/shutdownsound.mp3.sample /home/pi/RPi-Jukebox-RFID/shared/shutdownsound.mp3 - -if [ $SPOTinstall == "NO" ] -then - # MPD configuration - # -rw-r----- 1 mpd audio 14043 Jul 17 20:16 /etc/mpd.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/mpd.conf.sample /etc/mpd.conf - # Change vars to match install config - sudo sed -i 's/%AUDIOiFace%/'"$AUDIOiFace"'/' /etc/mpd.conf - # for $DIRaudioFolders using | as alternate regex delimiter because of the folder path slash - sudo sed -i 's|%DIRaudioFolders%|'"$DIRaudioFolders"'|' /etc/mpd.conf - echo "classic" > /home/pi/RPi-Jukebox-RFID/settings/edition - sudo chown mpd:audio /etc/mpd.conf - sudo chmod 640 /etc/mpd.conf - # update mpc / mpd DB - mpc update -fi - -if [ $SPOTinstall == "YES" ] -then - sudo systemctl disable mpd - sudo systemctl enable mopidy - # Install Config Files - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/locale.gen.sample /etc/locale.gen - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/locale.sample /etc/default/locale - sudo locale-gen - sudo mkdir /home/pi/.config - sudo mkdir /home/pi/.config/mopidy - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/mopidy-etc.sample /etc/mopidy/mopidy.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/mopidy.sample ~/.config/mopidy/mopidy.conf - echo "plusSpotify" > /home/pi/RPi-Jukebox-RFID/settings/edition - # Change vars to match install config - sudo sed -i 's/%spotify_username%/'"$SPOTIuser"'/' /etc/mopidy/mopidy.conf - sudo sed -i 's/%spotify_password%/'"$SPOTIpass"'/' /etc/mopidy/mopidy.conf - sudo sed -i 's/%spotify_client_id%/'"$SPOTIclientid"'/' /etc/mopidy/mopidy.conf - sudo sed -i 's/%spotify_client_secret%/'"$SPOTIclientsecret"'/' /etc/mopidy/mopidy.conf - sudo sed -i 's/%spotify_username%/'"$SPOTIuser"'/' ~/.config/mopidy/mopidy.conf - sudo sed -i 's/%spotify_password%/'"$SPOTIpass"'/' ~/.config/mopidy/mopidy.conf - sudo sed -i 's/%spotify_client_id%/'"$SPOTIclientid"'/' ~/.config/mopidy/mopidy.conf - sudo sed -i 's/%spotify_client_secret%/'"$SPOTIclientsecret"'/' ~/.config/mopidy/mopidy.conf -fi - -############################### -# WiFi settings (SSID password) -# -# https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md -# -# $WIFIssid -# $WIFIpass -# $WIFIip -# $WIFIipRouter -if [ $WIFIconfig == "YES" ] -then - # DHCP configuration settings - #-rw-rw-r-- 1 root netdev 0 Apr 17 11:25 /etc/dhcpcd.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/dhcpcd.conf.stretch-default2-noHotspot.sample /etc/dhcpcd.conf - # Change IP for router and Phoniebox - sudo sed -i 's/%WIFIip%/'"$WIFIip"'/' /etc/dhcpcd.conf - sudo sed -i 's/%WIFIipRouter%/'"$WIFIipRouter"'/' /etc/dhcpcd.conf - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' /etc/dhcpcd.conf - # Change user:group and access mod - sudo chown root:netdev /etc/dhcpcd.conf - sudo chmod 664 /etc/dhcpcd.conf - - # WiFi SSID & Password - # -rw-rw-r-- 1 root netdev 137 Jul 16 08:53 /etc/wpa_supplicant/wpa_supplicant.conf - sudo cp /home/pi/RPi-Jukebox-RFID/misc/sampleconfigs/wpa_supplicant.conf.stretch.sample /etc/wpa_supplicant/wpa_supplicant.conf - sudo sed -i 's/%WIFIssid%/'"$WIFIssid"'/' /etc/wpa_supplicant/wpa_supplicant.conf - sudo sed -i 's/%WIFIpass%/'"$WIFIpass"'/' /etc/wpa_supplicant/wpa_supplicant.conf - sudo sed -i 's/%WIFIcountryCode%/'"$WIFIcountryCode"'/' /etc/wpa_supplicant/wpa_supplicant.conf - sudo chown root:netdev /etc/wpa_supplicant/wpa_supplicant.conf - sudo chmod 664 /etc/wpa_supplicant/wpa_supplicant.conf -fi - -# start DHCP -sudo service dhcpcd start -sudo systemctl enable dhcpcd - -# / WiFi settings (SSID password) -############################### - -# / INSTALLATION -##################################################### - -##################################################### -# EXISTING ASSETS TO USE FROM EXISTING INSTALL - -if [ $EXISTINGuse == "YES" ] -then - - # RFID config for system control - if [ $EXISTINGuseRfidConf == "YES" ] - then - # read old values and write them into new file (copied above already) - # do not overwrite but use 'sed' in case there are new vars in new version installed - - # Read the existing RFID config file line by line and use - # only lines which are separated (IFS) by '='. - while IFS='=' read -r key val ; do - # $var should be stripped of possible leading or trailing " - val=${val%\"} - val=${val#\"} - key=${key} - # Additional error check: key should not start with a hash and not be empty. - if [ ! "${key:0:1}" == '#' ] && [ -n "$key" ] - then - # Replace the matching value in the newly created conf file - sed -i 's/%'"$key"'%/'"$val"'/' /home/pi/RPi-Jukebox-RFID/settings/rfid_trigger_play.conf - fi - done /dev/null | grep 'installed') ]]; then - echo " ${package} is installed" - else - echo " ERROR: ${package} is not installed" - ((failed_tests++)) - fi - ((tests++)) - done -} - -verify_pip_packages() { - local modules="evdev spi-py youtube_dl pyserial RPi.GPIO" - local modules_spotify="Mopidy-Iris" - local modules_pn532="py532lib" - local modules_rc522="pi-rc522" - local deviceName="${JUKEBOX_HOME_DIR}"/scripts/deviceName.txt - - printf "\nTESTING installed pip modules...\n\n" - - # also check for spotify pip modules if it has been installed - if [[ "${SPOTinstall}" == "YES" ]]; then - modules="${modules} ${modules_spotify}" - fi - - if [[ -f "${deviceName}" ]]; then - # RC522 reader is used - if grep -Fxq "${deviceName}" MFRC522 - then - modules="${modules} ${modules_rc522}" - fi - - # PN532 reader is used - if grep -Fxq "${deviceName}" PN532 - then - modules="${modules} ${modules_pn532}" - fi - fi - - for module in ${modules} - do - if [[ $(pip3 show "${module}") ]]; then - echo " ${module} is installed" - else - echo " ERROR: pip module ${module} is not installed" - ((failed_tests++)) - fi - ((tests++)) - done -} - -verify_samba_config() { - printf "\nTESTING samba config...\n\n" - check_chmod_chown 644 root root "/etc/samba" "smb.conf" - - check_file_contains_string "path=${DIRaudioFolders}" "/etc/samba/smb.conf" -} - -verify_webserver_config() { - printf "\nTESTING webserver config...\n\n" - check_chmod_chown 644 root root "/etc/lighttpd" "lighttpd.conf" - check_chmod_chown 644 root root "/etc/lighttpd/conf-available" "15-fastcgi-php.conf" - check_chmod_chown 644 root root "/etc/php/7.3/cgi" "php.ini" - check_chmod_chown 440 root root "/etc" "sudoers" - - # Bonus TODO: check that fastcgi and fastcgi-php mods are enabled -} - -verify_systemd_services() { - printf "\nTESTING systemd services...\n\n" - # check that services exist - check_chmod_chown 644 root root "/etc/systemd/system" "phoniebox-rfid-reader.service phoniebox-startup-scripts.service phoniebox-gpio-control.service phoniebox-idle-watchdog.service" - - # check that phoniebox services are enabled - check_service_enablement phoniebox-idle-watchdog enabled - check_service_enablement phoniebox-rfid-reader enabled - check_service_enablement phoniebox-startup-scripts enabled - check_service_enablement phoniebox-gpio-control enabled -} - -verify_spotify_config() { - local etc_mopidy_conf="/etc/mopidy/mopidy.conf" - local mopidy_conf="${HOME_DIR}/.config/mopidy/mopidy.conf" - - printf "\nTESTING spotify config...\n\n" - - check_file_contains_string "username = ${SPOTIuser}" "${etc_mopidy_conf}" - check_file_contains_string "password = ${SPOTIpass}" "${etc_mopidy_conf}" - check_file_contains_string "client_id = ${SPOTIclientid}" "${etc_mopidy_conf}" - check_file_contains_string "client_secret = ${SPOTIclientsecret}" "${etc_mopidy_conf}" - check_file_contains_string "media_dir = ${DIRaudioFolders}" "${etc_mopidy_conf}" - - check_file_contains_string "username = ${SPOTIuser}" "${mopidy_conf}" - check_file_contains_string "password = ${SPOTIpass}" "${mopidy_conf}" - check_file_contains_string "client_id = ${SPOTIclientid}" "${mopidy_conf}" - check_file_contains_string "client_secret = ${SPOTIclientsecret}" "${mopidy_conf}" - check_file_contains_string "media_dir = ${DIRaudioFolders}" "${mopidy_conf}" - - # check that mopidy service is enabled - check_service_enablement mopidy enabled - # check that mpd service is disabled - check_service_enablement mpd disabled -} - -verify_mpd_config() { - local mpd_conf="/etc/mpd.conf" - - printf "\nTESTING mpd config...\n\n" - - check_file_contains_string "^[[:blank:]]\+mixer_control[[:blank:]]\+\"${AUDIOiFace}\"" "${mpd_conf}" - check_file_contains_string "^music_directory[[:blank:]]\+\"${DIRaudioFolders}\"" "${mpd_conf}" - - check_chmod_chown 640 mpd audio "/etc" "mpd.conf" - - # check that mpd service is enabled, when Spotify support is not installed - if [[ "${SPOTinstall}" == "NO" ]]; then - check_service_enablement mpd enabled - fi -} - -verify_folder_access() { - local jukebox_dir="${HOME_DIR}/RPi-Jukebox-RFID" - printf "\nTESTING folder access...\n\n" - - # check owner and permissions - check_chmod_chown 775 pi www-data "${jukebox_dir}" "playlists shared htdocs settings" - # ${DIRaudioFolders} => "testing" "audiofolders" - check_chmod_chown 775 pi www-data "${DIRaudioFolders}/.." "audiofolders" - - #find .sh and .py scripts that are NOT executable - local count=$(find . -maxdepth 1 -type f \( -name "*.sh" -o -name "*.py" \) ! -executable | wc -l) - if [[ "${count}" -gt 0 ]]; then - echo " ERROR: found ${count} '*.sh' and/or '*.py' files that are NOT executable:" - find . -maxdepth 1 -type f \( -name "*.sh" -o -name "*.py" \) ! -executable - ((failed_tests++)) - fi - ((tests++)) -} - -main() { - printf "\nTesting installation:\n" - verify_conf_file - if [[ "$WIFIconfig" == "YES" ]]; then - verify_wifi_settings - fi - verify_apt_packages - verify_pip_packages - verify_samba_config - verify_webserver_config - verify_systemd_services - if [[ "${SPOTinstall}" == "YES" ]]; then - verify_spotify_config - fi - verify_mpd_config - verify_folder_access -} - -start=$(date +%s) -main -end=$(date +%s) - -runtime=$((end-start)) -((h=${runtime}/3600)) -((m=($runtime%3600)/60)) -((s=$runtime%60)) - -if [[ "${failed_tests}" -gt 0 ]]; then - echo "${failed_tests} Test(s) failed (of ${tests} tests) (in ${h}h ${m}m ${s}s)." - exit 1 -else - echo "${tests} tests done in ${h}h ${m}m ${s}s." -fi - diff --git a/scripts/playlist_recursive_by_folder.php b/scripts/playlist_recursive_by_folder.php deleted file mode 100755 index 8d62de3ad..000000000 --- a/scripts/playlist_recursive_by_folder.php +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/php - $value) { - // drop directories - if(is_dir($folder."/".$value)){ - unset($folder_files[$key]); - } - // drop config files - if($folder."/".$value == $folder."/folder.conf"){ - unset($folder_files[$key]); - } - // drop cover files - if($folder."/".$value == $folder."/cover.jpg"){ - unset($folder_files[$key]); - } - // drop title files - if($folder."/".$value == $folder."/title.txt"){ - unset($folder_files[$key]); - } - } - // some debugging info - if($debug == "true") { - print "\$folder_files cleaned:"; - print_r($folder_files); - } - - /* - * relative path from the $Audio_Folders_Path_Playlist folder - * which is also set in the mpd.conf - */ - if ($edition == "plusSpotify") { - // M3U will contain local:track: path for mopidy - foreach ($folder_files as $key => $value) { - $folder_files[$key] = "local:track:".str_replace("%2F", "/", rawurlencode(str_replace($Audio_Folders_Path."/", "", $folder."/".$value))); - } - } elseif ($edition == "classic") { - // M3U will contain normal relative path - foreach ($folder_files as $key => $value) { - $folder_files[$key] = substr($Audio_Folders_Path."/".$folder."/".$value, strlen($Audio_Folders_Path) + 1, strlen($folder."/".$value)); - } - } - /* - * order the remaining files - if any... - * NOTE: podcast content is NOT ordered - because they are an ordered playlist already - */ - usort($folder_files, 'strnatcasecmp'); - } - /* - * push files to playlist - */ - $files_playlist = array_merge($files_playlist, $folder_files); - //} -} - -$return = ""; -foreach($files_playlist as $file_playlist) { - if($file_playlist != "") { - $return .= $file_playlist."\n"; - } -} -print $return; -//print trim($return); - -?> diff --git a/scripts/playout_controls.sh b/scripts/playout_controls.sh deleted file mode 100755 index 483f1410f..000000000 --- a/scripts/playout_controls.sh +++ /dev/null @@ -1,1035 +0,0 @@ -#!/bin/bash - -# This shell script contains all the functionality to control -# playout and change volume and the like. -# This script is called from the web app and the bash script. -# The purpose is to have all playout logic in one place, this -# makes further development and potential replacement of -# the playout player easier. - -# Set the date and time of now -NOW=`date +%Y-%m-%d.%H:%M:%S` - -mtime=`date +%s` - - -# USAGE EXAMPLES: -# -# shutdown RPi: -# ./playout_controls.sh -c=shutdown -# -# set volume to 80% -# ./playout_controls.sh -c=setvolume -v=80 -# -# VALID COMMANDS: -# shutdown -# shutdownsilent -# shutdownafter -# shutdownvolumereduction -# reboot -# scan -# mute -# setvolume -# setmaxvolume -# setstartupvolume -# getstartupvolume -# setvolumetostartup -# volumeup -# volumedown -# getchapters -# getvolume -# getmaxvolume -# setvolstep -# getvolstep -# playerstop -# playerstopafter -# playernext -# playerprev -# playernextchapter -# playerprevchapter -# playerpause -# playerpauseforce -# playerplay -# playerremove -# playermoveup -# playermovedown -# playerreplay -# playerrepeat -# playershuffle -# playlistclear -# playlistaddplay -# playlistadd -# playlistappend -# playlistreset -# playsinglefile -# getidletime -# setidletime -# disablewifi -# enablewifi -# togglewifi -# recordstart -# recordstop -# recordplaylatest -# readwifiipoverspeaker - -# The absolute path to the folder which contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -############################################################# -# $DEBUG TRUE|FALSE -# Read debug logging configuration file -. ${PATHDATA}/../settings/debugLogging.conf - -if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "########### SCRIPT playout_controls.sh ($NOW) ##" >> ${PATHDATA}/../logs/debug.log; fi - -########################################################### -# Read global configuration file (and create if not exists) -# create the global configuration file from single files - if it does not exist -if [ ! -f ${PATHDATA}/../settings/global.conf ]; then - . ${PATHDATA}/inc.writeGlobalConfig.sh -fi -. ${PATHDATA}/../settings/global.conf -########################################################### - -################################# -# path to file storing the current volume level -# this file does not need to exist -# it will be created or deleted by this script -VOLFILE=${PATHDATA}/../settings/Audio_Volume_Level - -############################################################# - -# Get args from command line (see Usage above) -# Read the args passed on by the command line -# see following file for details: -. ${PATHDATA}/inc.readArgsFromCommandLine.sh - -if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "VAR COMMAND: ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi -if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "VAR VALUE: ${VALUE}" >> ${PATHDATA}/../logs/debug.log; fi - -# Regex that declares commands for which the following code can be shortcut -# and we can immediately jump to the switch-case statement. Increases execution -# speed of these commands. -shortcutCommands="^(setvolume|volumedown|volumeup|mute)$" - -# Run the code from this block only, if the current command is not in "shortcutCommands" -if [[ ! "$COMMAND" =~ $shortcutCommands ]] -then - - function dbg { - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then - echo "$1" >> ${PATHDATA}/../logs/debug.log; - fi - } - - function sec_to_ms() { - SECONDSPART="$(cut -d '.' -f 1 <<< "$1")" - MILLISECONDSPART="$(cut -d '.' -f 2 <<< "$1")" - MILLISECONDSPART_NORMALIZED="$(echo "$MILLISECONDSPART" | cut -c1-3 | sed 's/^0*//')" - - if [[ "" == "$SECONDSPART" ]]; then - SECONDSPART="0" - fi - - if [[ "" == "$MILLISECONDSPART_NORMALIZED" ]]; then - MILLISECONDSPART_NORMALIZED="0" - fi - echo "$((${SECONDSPART} * 1000 + ${MILLISECONDSPART_NORMALIZED}))" - } - - AUDIO_FOLDERS_PATH=$(cat "${PATHDATA}/../settings/Audio_Folders_Path") - - CURRENT_SONG_INFO=$(echo -e "currentsong\nclose" | nc -w 1 localhost 6600) - CURRENT_SONG_FILE=$(echo "$CURRENT_SONG_INFO" | grep -o -P '(?<=file: ).*') - CURRENT_SONG_FILE_ABS="${AUDIO_FOLDERS_PATH}/${CURRENT_SONG_FILE}" - dbg "current file: $CURRENT_SONG_FILE_ABS" - - CURRENT_SONG_DIR="$(dirname -- "$CURRENT_SONG_FILE_ABS")" - CURRENT_SONG_BASENAME="$(basename -- "${CURRENT_SONG_FILE_ABS}")" - CURRENT_SONG_FILE_EXT="${CURRENT_SONG_BASENAME##*.}" - CURRENT_SONG_ELAPSED=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=elapsed: ).*') - CURRENT_SONG_DURATION=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=duration: ).*') - - CHAPTERS_FILE="${CURRENT_SONG_DIR}/${CURRENT_SONG_BASENAME%.*}.chapters.json" - dbg "chapters file: $CHAPTERS_FILE" - - if [ "$(grep -wo "$CURRENT_SONG_FILE_EXT" <<< "$CHAPTEREXTENSIONS")" == "$CURRENT_SONG_FILE_EXT" ]; then - CHAPTER_SUPPORT_FOR_EXTENSION="1" - else - CHAPTER_SUPPORT_FOR_EXTENSION="0" - fi - dbg "chapters for extension enabled: $CHAPTER_SUPPORT_FOR_EXTENSION" - - - if [ "$(printf "${CURRENT_SONG_DURATION}\n${CHAPTERMINDURATION}\n" | sort -g | head -1)" == "${CHAPTERMINDURATION}" ]; then - CHAPTER_SUPPORT_FOR_DURATION="1" - else - CHAPTER_SUPPORT_FOR_DURATION="0" - fi - dbg "chapters for duration enabled: $CHAPTER_SUPPORT_FOR_DURATION" - - if [ "${CHAPTER_SUPPORT_FOR_EXTENSION}${CHAPTER_SUPPORT_FOR_DURATION}" == "11" ]; then - if ! [ -f "${CHAPTERS_FILE}" ]; then - CHAPTERS_COUNT="0" - dbg "chaptes file does not exist - export triggered" - ffprobe -i "${CURRENT_SONG_FILE_ABS}" -print_format json -show_chapters -loglevel error > "${CHAPTERS_FILE}" & - else - CHAPTERS_COUNT="$(grep '"id":' "${CHAPTERS_FILE}" | wc -l )" - dbg "chapters file does exist, chapter count: $CHAPTERS_COUNT" - fi - - CHAPTER_START_TIMES="$( ( echo -e $CURRENT_SONG_ELAPSED & grep 'start_time' "$CHAPTERS_FILE" | cut -d '"' -f 4 | sed 's/000$//') | sort -V)" - ELAPSED_MATCH_CHAPTER_COUNT=$(grep "$CURRENT_SONG_ELAPSED" <<< "$CHAPTER_START_TIMES" | wc -l) - - # elapsed and chapter start exactly match -> skip one line - if [ "$ELAPSED_MATCH_CHAPTER_COUNT" == "2" ]; then - PREV_CHAPTER_START=$(grep "$CURRENT_SONG_ELAPSED" -B 1 <<< "$CHAPTER_START_TIMES" | head -n1) - CURRENT_CHAPTER_START="$CURRENT_SONG_ELAPSED" - else - PREV_CHAPTER_START=$(grep "$CURRENT_SONG_ELAPSED" -B 2 <<< "$CHAPTER_START_TIMES" | head -n1) - CURRENT_CHAPTER_START=$(grep "$CURRENT_SONG_ELAPSED" -B 1 <<< "$CHAPTER_START_TIMES" | head -n1) - fi - - NEXT_CHAPTER_START=$(grep "$CURRENT_SONG_ELAPSED" -A 1 <<< "$CHAPTER_START_TIMES" | tail -n1) - fi - - # SHUFFLE_STATUS=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=random: ).*') -fi # END COMMANDS SHORTCUT - -case $COMMAND in - shutdown) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - while : - do - apt=1 - sudo lsof /var/lib/apt/lists/lock > /dev/null - apt=$(($apt * $?)) - sudo lsof /var/lib/dpkg/lock > /dev/null - apt=$(($apt * $?)) - sudo lsof /var/cache/apt/archives/lock > /dev/null - apt=$(($apt * $?)) - if [ $apt -eq 0 ]; then - sleep 5 - else - break - fi - done - ${PATHDATA}/resume_play.sh -c=savepos && mpc clear - #remove shuffle mode if active - SHUFFLE_STATUS=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=random: ).*') - if [ "$SHUFFLE_STATUS" == 1 ] ; then mpc random off; fi - sleep 1 - /usr/bin/mpg123 ${PATHDATA}/../shared/shutdownsound.mp3 - sleep 3 - ${POWEROFFCMD} - ;; - shutdownsilent) - # doesn't play a shutdown sound - while : - do - apt=1 - sudo lsof /var/lib/apt/lists/lock > /dev/null - apt=$(($apt * $?)) - sudo lsof /var/lib/dpkg/lock > /dev/null - apt=$(($apt * $?)) - sudo lsof /var/cache/apt/archives/lock > /dev/null - apt=$(($apt * $?)) - if [ $apt -eq 0 ]; then - sleep 5 - else - break - fi - done - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - ${PATHDATA}/resume_play.sh -c=savepos && mpc clear - #remove shuffle mode if active - SHUFFLE_STATUS=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=random: ).*') - if [ "$SHUFFLE_STATUS" == 1 ] ; then mpc random off; fi - ${POWEROFFCMD} - ;; - shutdownafter) - # remove shutdown times if existent - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - for i in `sudo atq -q t | awk '{print $1}'`;do sudo atrm $i;done - # -c=shutdownafter -v=0 is to remove the shutdown timer - if [ ${VALUE} -gt 0 ]; - then - # shutdown pi after ${VALUE} minutes - echo "${PATHDATA}/playout_controls.sh -c=shutdownsilent" | at -q t now + ${VALUE} minute - fi - ;; - shutdownvolumereduction) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - # remove existing volume and shutdown commands - for i in `sudo atq -q r | awk '{print $1}'`;do sudo atrm $i;done - for i in `sudo atq -q q | awk '{print $1}'`;do sudo atrm $i;done - # get current volume in percent - VOLPERCENT=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=volume: ).*') - # divide current volume by 10 to get a step size for reducing the volume - VOLSTEP=`expr $((VOLPERCENT / 10))`; - # divide VALUE by 10, volume will be reduced every TIMESTEP minutes (e.g. for a value of "30" it will be every "3" minutes) - TIMESTEP=`expr $((VALUE / 10))`; - # loop 10 times to reduce the volume by VOLSTEP every TIMESTEP minutes - for i in $(seq 1 10); do - VOLPERCENT=`expr ${VOLPERCENT} - ${VOLSTEP}`; echo "${PATHDATA}/playout_controls.sh -c=setvolume -v="$VOLPERCENT | at -q r now + `expr $(((i * TIMESTEP)-1))` minute; - done - # schedule shutdown after VALUE minutes - if [ ${VALUE} -gt 0 ]; - then - # schedule shutdown after VALUE minutes - echo "${PATHDATA}/playout_controls.sh -c=shutdownsilent" | at -q q now + ${VALUE} minute - fi - ;; - reboot) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - ${PATHDATA}/resume_play.sh -c=savepos && mpc clear - #remove shuffle mode if active - SHUFFLE_STATUS=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=random: ).*') - if [ "$SHUFFLE_STATUS" == 1 ] ; then mpc random off; fi - sudo reboot - ;; - scan) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - ${PATHDATA}/resume_play.sh -c=savepos && mpc clear - #remove shuffle mode if active - SHUFFLE_STATUS=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=random: ).*') - if [ "$SHUFFLE_STATUS" == 1 ] ; then mpc random off; fi - sudo systemctl stop mopidy - sudo mopidyctl local scan - sudo systemctl start mopidy - ;; - mute) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND} | VOLUMEMANAGER:${VOLUMEMANAGER}" >> ${PATHDATA}/../logs/debug.log; fi - if [ ! -f $VOLFILE ]; then - # $VOLFILE does NOT exist == audio on - # read volume in percent and write to $VOLFILE - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sget \'$AUDIOIFACENAME\' | grep -Po -m 1 '(?<=\[)[^]]*(?=%])' > $VOLFILE - else - # manage volume with mpd - echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=volume: ).*' > $VOLFILE - fi - # set volume to 0% - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' 0% - else - # manage volume with mpd - echo -e setvol 0\\nclose | nc -w 1 localhost 6600 - fi - else - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - else - # manage volume with mpd - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - fi - # delete $VOLFILE - rm -f $VOLFILE - fi - ;; - setvolume) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND} | VOLUMEMANAGER:${VOLUMEMANAGER}" >> ${PATHDATA}/../logs/debug.log; fi - #increase volume only if VOLPERCENT is below the max volume limit and above min volume limit - if [ ${VALUE} -le $AUDIOVOLMAXLIMIT ] && [ ${VALUE} -ge $AUDIOVOLMINLIMIT ]; - then - # set volume level in percent - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' $VALUE% - else - # manage volume with mpd - echo -e setvol $VALUE\\nclose | nc -w 1 localhost 6600 - fi - else - if [ ${VALUE} -gt $AUDIOVOLMAXLIMIT ]; - then - # if we are over the max volume limit, set the volume to maxvol - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' $AUDIOVOLMAXLIMIT% - else - # manage volume with mpd - echo -e setvol $AUDIOVOLMAXLIMIT\\nclose | nc -w 1 localhost 6600 - fi - fi - if [ ${VALUE} -lt $AUDIOVOLMINLIMIT ]; - then - # if we are unter the min volume limit, set the volume to minvol - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' $AUDIOVOLMINLIMIT% - else - # manage volume with mpd - echo -e setvol $AUDIOVOLMINLIMIT\\nclose | nc -w 1 localhost 6600 - fi - fi - fi - ;; - volumeup) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - #check for volume change during idle - if [ $VOLCHANGEIDLE == "FALSE" ] || [ $VOLCHANGEIDLE == "OnlyDown" ]; - then - PLAYSTATE=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=state: ).*') - if [ "$PLAYSTATE" != "play" ] - then - #Volume change is not allowed - leave program - exit 1 - fi - fi - if [ ! -f $VOLFILE ]; then - if [ -z ${VALUE} ]; then - VALUE=1 - fi - # $VOLFILE does NOT exist == audio on - # read volume in percent - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - VOLPERCENT=`amixer sget \'$AUDIOIFACENAME\' | grep -Po -m 1 '(?<=\[)[^]]*(?=%])'` - else - # manage volume with mpd - VOLPERCENT=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=volume: ).*') - fi - # increase by $AUDIOVOLCHANGESTEP - VOLPERCENT=`expr ${VOLPERCENT} + \( ${AUDIOVOLCHANGESTEP} \* ${VALUE} \)` - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " VOLPERCENT:${VOLPERCENT} | VOLUMEMANAGER:${VOLUMEMANAGER}" >> ${PATHDATA}/../logs/debug.log; fi - #increase volume only if VOLPERCENT is below the max volume limit - if [ $VOLPERCENT -le $AUDIOVOLMAXLIMIT ]; - then - # set volume level in percent - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' ${VOLPERCENT}% - else - # manage volume with mpd - echo -e setvol +$VOLPERCENT\\nclose | nc -w 1 localhost 6600 - fi - else - # if we are over the max volume limit, set the volume to maxvol - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' ${AUDIOVOLMAXLIMIT}% - else - # manage volume with mpd - echo -e setvol $AUDIOVOLMAXLIMIT\\nclose | nc -w 1 localhost 6600 - fi - fi - else - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - else - # manage volume with mpd - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - fi - # delete $VOLFILE - rm -f $VOLFILE - fi - ;; - volumedown) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - #check for volume change during idle - if [ $VOLCHANGEIDLE == "FALSE" ] || [ $VOLCHANGEIDLE == "OnlyUp" ]; - then - PLAYSTATE=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=state: ).*') - if [ "$PLAYSTATE" != "play" ] - then - #Volume change is not allowed - leave program - exit 1 - fi - fi - if [ ! -f $VOLFILE ]; then - if [ -z ${VALUE} ]; then - VALUE=1 - fi - # $VOLFILE does NOT exist == audio on - # read volume in percent - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - VOLPERCENT=`amixer sget \'$AUDIOIFACENAME\' | grep -Po -m 1 '(?<=\[)[^]]*(?=%])'` - else - # manage volume with mpd - VOLPERCENT=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=volume: ).*') - fi - # decrease by $AUDIOVOLCHANGESTEP - VOLPERCENT=`expr ${VOLPERCENT} - \( ${AUDIOVOLCHANGESTEP} \* ${VALUE} \)` - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " VOLPERCENT:${VOLPERCENT} | VOLUMEMANAGER:${VOLUMEMANAGER}" >> ${PATHDATA}/../logs/debug.log; fi - #decrease volume only if VOLPERCENT is above the min volume limit - if [ $VOLPERCENT -ge $AUDIOVOLMINLIMIT ]; - then - # set volume level in percent - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' ${VOLPERCENT}% - else - # manage volume with mpd - echo -e setvol +$VOLPERCENT\\nclose | nc -w 1 localhost 6600 - fi - else - # if we are below the min volume limit, set the volume to minvol - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' ${AUDIOVOLMINLIMIT}% - else - # manage volume with mpd - echo -e setvol $AUDIOVOLMINLIMIT\\nclose | nc -w 1 localhost 6600 - fi - fi - else - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - else - # manage volume with mpd - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - fi - # delete $VOLFILE - rm -f $VOLFILE - fi - ;; - getchapters) - if [ -f "${CHAPTERS_FILE}" ]; then cat "${CHAPTERS_FILE}"; fi - ;; - getvolume) - # read volume in percent - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "# ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - VOLPERCENT=`amixer sget \'$AUDIOIFACENAME\' | grep -Po -m 1 '(?<=\[)[^]]*(?=%])'` - else - # manage volume with mpd - VOLPERCENT=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=volume: ).*') - fi - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " VOLPERCENT:${VOLPERCENT} | VOLUMEMANAGER:${VOLUMEMANAGER}" >> ${PATHDATA}/../logs/debug.log; fi - echo $VOLPERCENT - ;; - setmaxvolume) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - # read volume in percent - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - VOLPERCENT=`amixer sget \'$AUDIOIFACENAME\' | grep -Po -m 1 '(?<=\[)[^]]*(?=%])'` - else - # manage volume with mpd - VOLPERCENT=$(echo -e status\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=volume: ).*') - fi - # if volume of the box is greater than wanted maxvolume, set volume to maxvolume - if [ $VOLPERCENT -gt ${VALUE} ]; - then - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer sset \'$AUDIOIFACENAME\' ${VALUE}% - else - # manage volume with mpd - echo -e setvol ${VALUE} | nc -w 1 localhost 6600 - fi - fi - # if startupvolume is greater than wanted maxvolume, set startupvolume to maxvolume - if [ ${AUDIOVOLSTARTUP} -gt ${VALUE} ]; - then - # write new value to file - echo "$VALUE" > ${PATHDATA}/../settings/Startup_Volume - fi - # write new value to file - echo "$VALUE" > ${PATHDATA}/../settings/Max_Volume_Limit - # create global config file because individual setting got changed - . ${PATHDATA}/inc.writeGlobalConfig.sh - ;; - getmaxvolume) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - echo $AUDIOVOLMAXLIMIT - ;; - setvolstep) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - # write new value to file - echo "$VALUE" > ${PATHDATA}/../settings/Audio_Volume_Change_Step - # create global config file because individual setting got changed - . ${PATHDATA}/inc.writeGlobalConfig.sh - ;; - getvolstep) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - echo $AUDIOVOLCHANGESTEP - ;; - setstartupvolume) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - # if value is greater than wanted maxvolume, set value to maxvolume - if [ ${VALUE} -gt $AUDIOVOLMAXLIMIT ]; - then - VALUE=$AUDIOVOLMAXLIMIT; - fi - # write new value to file - echo "$VALUE" > ${PATHDATA}/../settings/Startup_Volume - # create global config file because individual setting got changed - . ${PATHDATA}/inc.writeGlobalConfig.sh - ;; - getstartupvolume) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - echo ${AUDIOVOLSTARTUP} - ;; - setvolumetostartup) - echo "setvolumetostartup $(expr `date +%s` - $mtime) s" - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - # check if startup-volume is disabled - if [ "${AUDIOVOLSTARTUP}" == 0 ]; then - exit 1 - else - # set volume level in percent - if [ "${VOLUMEMANAGER}" == "amixer" ]; then - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - amixer -q sset \'$AUDIOIFACENAME\' ${AUDIOVOLSTARTUP}% - echo "after amixer setvolumetostartup $(expr `date +%s` - $mtime) s" - else - # manage volume with mpd - echo -e setvol ${AUDIOVOLSTARTUP}\\nclose | nc -w 1 localhost 6600 - fi - - fi - echo "after setvolumetostartup $(expr `date +%s` - $mtime) s" - ;; - playerstop) - # stop the player - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - ${PATHDATA}/resume_play.sh -c=savepos && mpc stop - #if [ -e $AUDIOFOLDERSPATH/playing.txt ] - #then - # sudo rm $AUDIOFOLDERSPATH/playing.txt - #fi - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "remove playing.txt" >> ${PATHDATA}/../logs/debug.log; fi - ;; - playerstopafter) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - # remove playerstop timer if existent - for i in `sudo atq -q s | awk '{print $1}'`;do sudo atrm $i;done - # stop player after ${VALUE} minutes - if [ ${VALUE} -gt 0 ]; - then - echo "${PATHDATA}/resume_play.sh -c=savepos && mpc stop" | at -q s now + ${VALUE} minute - fi - ;; - playernext) - # play next track in playlist (==folder) - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - # amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - # delete $VOLFILE - rm -f $VOLFILE - fi - - mpc next - ;; - playerprev) - # play previous track in playlist (==folder) - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - # amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - # delete $VOLFILE - rm -f $VOLFILE - fi - - mpc prev - ;; - playerprevchapter) - CURRENT_SONG_ELAPSED_MS=$(sec_to_ms "$CURRENT_SONG_ELAPSED") - CURRENT_CHAPTER_START_MS=$(sec_to_ms "$CURRENT_CHAPTER_START") - CHAPTER_DIFF_ELAPSED_CURRENT_MS=$(($CURRENT_SONG_ELAPSED_MS-$CURRENT_CHAPTER_START_MS)) - - # if elapsed - current > 5.000 => seek current chapter - # if elapsed - current <= 5.000 => seek prev chapter - # if prev === 0.000 && elapsed < 5.000 => prev track? (don't do that) - if [ "$CHAPTER_DIFF_ELAPSED_CURRENT_MS" -gt 5000 ]; then - dbg "chapter is already running for longer, seek to current chapter: $SEEK_POS" - echo -e "seekcur $CURRENT_CHAPTER_START\nclose" | nc -w 1 localhost 6600 - else - dbg "chapter just started, seek to prev chapter $PREV_CHAPTER_START" - echo -e "seekcur $PREV_CHAPTER_START\nclose" | nc -w 1 localhost 6600 - fi - ;; - playernextchapter) - # if next === elapsed => next track - if ! [ "$NEXT_CHAPTER_START" == "$CURRENT_SONG_ELAPSED" ]; then - dbg "next chapter $NEXT_CHAPTER_START" - echo -e "seekcur $NEXT_CHAPTER_START\nclose" | nc -w 1 localhost 6600 - else - dbg "next chapter not available, last chapter already playing" - fi - ;; - playerrewind) - # play the first track in playlist (==folder) - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - # amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - # delete $VOLFILE - rm -f $VOLFILE - fi - - mpc play 1 - ;; - playerpause) - # toggle current track - # mpc knows "pause", which pauses only, and "toggle" which pauses and unpauses, whatever is needed - # Why on earth has this been called pause instead of toggle? :-) - - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - # amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - # delete $VOLFILE - rm -f $VOLFILE - fi - mpc toggle - ;; - playerpauseforce) - # pause current track with optional delay - if [ -n ${VALUE} ]; - then - /bin/sleep $VALUE - fi - mpc pause - ;; - playerplay) - # play / resume current track - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "Attempting to play: $VALUE" >> ${PATHDATA}/../logs/debug.log; fi - # May be called with e.g. -v=1 to start a track in the middle of the playlist. - # Note: the numbering of the tracks starts with 0, so -v=1 starts the second track - # of the playlist - # Another note: "mpc play 1" starts the first track (!) - - # Change some settings according to current folder IF the folder.conf exists - . ${PATHDATA}/inc.settingsFolderSpecific.sh - - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - # amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - # delete $VOLFILE - rm -f $VOLFILE - fi - - # No checking for resume if the audio is paused, just unpause it - PLAYSTATE=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=state: ).*') - if [ "$PLAYSTATE" == "pause" ] - then - echo -e "play $VALUE\nclose" | nc -w 1 localhost 6600 - else - #${PATHDATA}/resume_play.sh -c=resume -v=$VALUE - mpc play $VALUE - fi - ;; - playerremove) - # remove selected song position - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "Attempting to remove: $VALUE" >> ${PATHDATA}/../logs/debug.log; fi - - # Change some settings according to current folder IF the folder.conf exists - . ${PATHDATA}/inc.settingsFolderSpecific.sh - - mpc del $VALUE - ;; - playermoveup) - # remove selected song position - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "Attempting to move: $VALUE" >> ${PATHDATA}/../logs/debug.log; fi - - # Change some settings according to current folder IF the folder.conf exists - . ${PATHDATA}/inc.settingsFolderSpecific.sh - - mpc move $(($VALUE)) $(($VALUE-1)) - ;; - playermovedown) - # remove selected song position - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "Attempting to move: $VALUE" >> ${PATHDATA}/../logs/debug.log; fi - - # Change some settings according to current folder IF the folder.conf exists - . ${PATHDATA}/inc.settingsFolderSpecific.sh - - mpc move $(($VALUE)) $(($VALUE+1)) - ;; - playerseek) - # jumps back and forward in track. - # Usage: ./playout_controls.sh -c=playerseek -v=+15 to jump 15 seconds ahead - # ./playout_controls.sh -c=playerseek -v=-10 to jump 10 seconds back - # Note: Not using "mpc seek" here as it fails if one tries to jump ahead of the beginning of the track - # (e.g. "mpc seek -15" executed at an elapsed time of 10 seconds let the player hang). - # mpd seekcur can handle this. - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - # amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - # delete $VOLFILE - rm -f $VOLFILE - fi - - # if value does not start with + or - (relative seek), perform an absolute seek - if [[ $VALUE =~ ^[0-9] ]]; then - # seek absolute position - echo -e "seekcur $VALUE\nclose" | nc -w 1 localhost 6600 - else - # Seek negative value doesn't work in mpd anymore. - # solution taken from: https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/1031 - # if there are issues, please comment in that thread - CUR_POS=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=elapsed: ).*' | awk '{print int($1)}') - NEW_POS=$(($CUR_POS + $VALUE)) - echo -e "seekcur $NEW_POS\nclose" | nc -w 1 localhost 6600 - fi - ;; - playerreplay) - # start the playing track from beginning - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - # amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - # delete $VOLFILE - rm -f $VOLFILE - fi - mpc seek 0 - ;; - playerrepeat) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND} value:${VALUE}" >> ${PATHDATA}/../logs/debug.log; fi - # repeats a single track or a playlist. - # Remark: If "single" is "on" but "repeat" is "off", the playout stops after the current song. - # This command may be called with ./playout_controls.sh -c=playerrepeat -v=single, playlist or off - - case ${VALUE} in - single) - mpc repeat on - mpc single on - ;; - playlist) - mpc repeat on - mpc single off - ;; - *) - mpc repeat off - mpc single off - ;; - esac - ;; - playershuffle) - # toogles shuffle mode on/off (not only the current playlist but for the whole mpd) - # this is why a check if "random on" has to be done for shutdown and reboot - # This command may be called with ./playout_controls.sh -c=playershuffle - mpc shuffle - ;; - playlistclear) - # clear playlist - ${PATHDATA}/resume_play.sh -c=savepos - mpc clear - ;; - playlistaddplay) - # add to playlist (and play) - # this command clears the playlist, loads a new playlist and plays it. It also handles the resume play feature. - # FOLDER = rel path from audiofolders - # VALUE = name of playlist - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " playlistaddplay playlist name VALUE: $VALUE" >> ${PATHDATA}/../logs/debug.log; fi - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " playlistaddplay FOLDER: $FOLDER" >> ${PATHDATA}/../logs/debug.log; fi - - # NEW VERSION: - # Read the current config file (include will execute == read) - . "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" - - # load playlist - mpc clear - mpc load "${VALUE//\//SLASH}" - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "mpc load "${VALUE//\//SLASH} >> ${PATHDATA}/../logs/debug.log; fi - - # Change some settings according to current folder IF the folder.conf exists - #. ${PATHDATA}/inc.settingsFolderSpecific.sh - - # check if we switch to single file playout - ${PATHDATA}/single_play.sh -c=single_check -d="${FOLDER}" - - # check if we shuffle the playlist - ${PATHDATA}/shuffle_play.sh -c=shuffle_check -d="${FOLDER}" - - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # volume handling alternative with amixer not mpd (2020-06-12 related to ticket #973) - # amixer sset \'$AUDIOIFACENAME\' `<$VOLFILE`% - # delete $VOLFILE - rm -f $VOLFILE - fi - - # Now load and play - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "mpc load "${VALUE//\//SLASH}" && ${PATHDATA}/resume_play.sh -c=resume -d="${FOLDER}"" >> ${PATHDATA}/../logs/debug.log; fi - ${PATHDATA}/resume_play.sh -c=resume -d="${FOLDER}" - - # write latest folder played to settings file - sudo echo ${FOLDER} > ${PATHDATA}/../settings/Latest_Folder_Played - sudo chown pi:www-data ${PATHDATA}/../settings/Latest_Folder_Played - sudo chmod 777 ${PATHDATA}/../settings/Latest_Folder_Played - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " echo ${FOLDER} > ${PATHDATA}/../settings/Latest_Folder_Played" >> ${PATHDATA}/../logs/debug.log; fi - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " VAR Latest_Folder_Played: ${FOLDER}" >> ${PATHDATA}/../logs/debug.log; fi - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " # end playout_controls.sh playlistaddplay" >> ${PATHDATA}/../logs/debug.log; fi - - # OLD VERSION (pre 20190302 - delete once the new version really seems to work): - # call shuffle_check HERE to enable/disable folder-based shuffling - # (mpc shuffle is different to random, because when you shuffle before playing, - # you start your playlist with a different track EVERYTIME. With random you EVER - # has the first song and random from track 2. - #mpc load "${VALUE//\//SLASH}" && ${PATHDATA}/shuffle_play.sh -c=shuffle_check && ${PATHDATA}/single_play.sh -c=single_check && ${PATHDATA}/resume_play.sh -c=resume - #mpc load "${VALUE//\//SLASH}" && ${PATHDATA}/single_play.sh -c=single_check && ${PATHDATA}/resume_play.sh -c=resume - - ;; - playlistadd) - # add to playlist, no autoplay - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND} value:${VALUE}" >> ${PATHDATA}/../logs/debug.log; fi - # save playlist playing - mpc load "${VALUE}" - ;; - playlistappend) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND} value:${VALUE}" >> ${PATHDATA}/../logs/debug.log; fi - mpc add "${VALUE}" - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # delete $VOLFILE - rm -f $VOLFILE - fi - mpc play - ;; - playlistreset) - if [ -e $PATHDATA/../shared/audiofolders/$FOLDERPATH/lastplayed.dat ] - then - echo "" > $PATHDATA/../shared/audiofolders/$FOLDERPATH/lastplayed.dat - fi - mpc play 1 - ;; - playsinglefile) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND} value:${VALUE}" >> ${PATHDATA}/../logs/debug.log; fi - mpc clear - mpc add "${VALUE}" - mpc repeat off - mpc single on - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # delete $VOLFILE - rm -f $VOLFILE - fi - mpc play - ;; - setidletime) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND} value:${VALUE}" >> ${PATHDATA}/../logs/debug.log; fi - # write new value to file - echo "$VALUE" > ${PATHDATA}/../settings/Idle_Time_Before_Shutdown - # create global config file because individual setting got changed - . ${PATHDATA}/inc.writeGlobalConfig.sh - # restart service to apply the new value - sudo systemctl restart phoniebox-idle-watchdog.service & - ;; - getidletime) - echo $IDLETIMESHUTDOWN - ;; - enablewifi) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - rfkill unblock wifi - ;; - disablewifi) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - # see https://forum-raspberrypi.de/forum/thread/25696-bluetooth-und-wlan-deaktivieren/#pid226072 seems to disable wifi, - # as good as it gets - rfkill block wifi - ;; - togglewifi) - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " ${COMMAND}" >> ${PATHDATA}/../logs/debug.log; fi - # function to allow toggle the wifi state - # Build special for franzformator - rfkill list wifi | grep -i "Soft blocked: no" > /dev/null 2>&1 - WIFI_SOFTBLOCK_RESULT=$? - wpa_cli -i wlan0 status | grep 'ip_address' > /dev/null 2>&1 - WIFI_IP_RESULT=$? - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " WIFI_IP_RESULT='${WIFI_IP_RESULT}' WIFI_SOFTBLOCK_RESULT='${WIFI_SOFTBLOCK_RESULT}'" >> ${PATHDATA}/../logs/debug.log; fi - if [ $WIFI_SOFTBLOCK_RESULT -eq 0 ] && [ $WIFI_IP_RESULT -eq 0 ] - then - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " Wifi will now be deactivated" >> ${PATHDATA}/../logs/debug.log; fi - echo "Wifi will now be deactivated" - rfkill block wifi - else - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo " Wifi will now be activated" >> ${PATHDATA}/../logs/debug.log; fi - echo "Wifi will now be activated" - rfkill unblock wifi - fi - ;; - recordstart) - #mkdir $AUDIOFOLDERSPATH/Recordings - #kill the potential current playback - sudo pkill aplay - #start recorder if not already started - if ! pgrep -x "arecord" > /dev/null - then - echo "start recorder" - arecord -D plughw:1 --duration=${VALUE} -f cd -vv $AUDIOFOLDERSPATH/Recordings/$(date +"%Y-%m-%d_%H-%M-%S").wav & - else - echo "device is already recording" - fi - ;; - recordstop) - #kill arecord instances - sudo pkill arecord - ;; - recordplaylatest) - #kill arecord and aplay instances - sudo pkill arecord - sudo pkill aplay - # Unmute if muted - if [ -f $VOLFILE ]; then - # $VOLFILE DOES exist == audio off - # read volume level from $VOLFILE and set as percent - echo -e setvol `<$VOLFILE`\\nclose | nc -w 1 localhost 6600 - # delete $VOLFILE - rm -f $VOLFILE - fi - aplay `ls $AUDIOFOLDERSPATH/Recordings/*.wav -1t|head -1` - ;; - readwifiipoverspeaker) - # will read out the IP address over the Pi's speaker. - # Why? Imagine to go to a new wifi, hook up and not know where to point your browser - cd /home/pi/RPi-Jukebox-RFID/misc/ - # delete older mp3 (in case process was interrupted) - sudo rm WifiIp.mp3 - /usr/bin/php /home/pi/RPi-Jukebox-RFID/scripts/helperscripts/cli_ReadWifiIp.php - ;; - *) - echo Unknown COMMAND $COMMAND VALUE $VALUE - if [ "${DEBUG_playout_controls_sh}" == "TRUE" ]; then echo "Unknown COMMAND ${COMMAND} VALUE ${VALUE}" >> ${PATHDATA}/../logs/debug.log; fi - ;; -esac diff --git a/scripts/python-phoniebox/ConfigParserExtended.py b/scripts/python-phoniebox/ConfigParserExtended.py deleted file mode 100644 index 3227210e5..000000000 --- a/scripts/python-phoniebox/ConfigParserExtended.py +++ /dev/null @@ -1,31 +0,0 @@ -# from configparser import RawConfigParser -import configparser - - -class ConfigParserExtended(configparser.ConfigParser): - - def as_dict(self, section="all"): - if section == "all": - d = self.__dict__['_sections'] - else: - d = self.__dict__['_sections'][section] - return d - - def as_json(self, section="all"): - import json - if section == "all": - d = self.__dict__['_sections'] - else: - d = self.__dict__['_sections'][section] - return json.dumps(d, separators=(',', ':'), indent=4, sort_keys=True, - ensure_ascii=False).encode('utf8') - - def print_ini(self, section="all"): - if section == "all": - sections = self.sections() - else: - sections = [section] - for section_name in sections: - print("[{}]".format(section_name)) - for key, value in self.items(section_name): - print('{} = {}'.format(key, value)) diff --git a/scripts/python-phoniebox/LICENSE b/scripts/python-phoniebox/LICENSE deleted file mode 100644 index e27d99892..000000000 --- a/scripts/python-phoniebox/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 laclaro - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/scripts/python-phoniebox/Phoniebox.py b/scripts/python-phoniebox/Phoniebox.py deleted file mode 100755 index b4f2e2b1a..000000000 --- a/scripts/python-phoniebox/Phoniebox.py +++ /dev/null @@ -1,412 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -__name__ = "Phoniebox" - -import configparser # needed only for the exception types ?! -from ConfigParserExtended import ConfigParserExtended -import codecs -import subprocess # needed for aplay call -import os, sys -from time import sleep -from mpd import MPDClient - -# get absolute path of this script -dir_path = os.path.dirname(os.path.realpath(__file__)) -defaultconfigFilePath = os.path.join(dir_path, './phoniebox.conf') - - -# TODO: externalize helper functions for the package. How? -def is_int(s): - """ return True if string is an int """ - try: - int(s) - return True - except ValueError: - return False - - -def str2bool(s): - """ convert string to a python boolean """ - return s.lower() in ("yes", "true", "t", "1") - - -def str2num(s): - """ convert string to an int or a float """ - try: - return int(s) - except ValueError: - return float(s) - - -def find_modified_files(path, since): - modified_files = [] - for root, dirs, files in os.walk(path): - for basename in files: - filename = os.path.join(path, basename) - status = os.stat(filename) - if status.st_mtime > since: - modified_files.append(filename) - return modified_files - - -def file_modified(filename, since): - if os.stat(filename).st_mtime > since: - return True - else: - return False - - -class Phoniebox(object): - - def __init__(self, configFilePath=defaultconfigFilePath): - print("Using configuration file {}".format(configFilePath)) - self.read_config(configFilePath) - # read cardAssignments from given card assignments file - card_assignments_file = self.get_setting("phoniebox", "card_assignments_file") - self.cardAssignments = self.read_cardAssignments() - if self.get_setting("phoniebox", "translate_legacy_cardassignments", "bool") is True: - self.log("Translating legacy cardAssignment config from folder.conf files.", 3) - legacy_cardAssignments = self.translate_legacy_cardAssignments() - self.update_cardAssignments(legacy_cardAssignments) - - def log(self, msg, level=3): - """ level based logging to stdout """ - log_level_map = {0: None, 1: "error", 2: "warning", 3: "info", 4: "extended", 5: "debug"} - log_level = int(self.get_setting("phoniebox", "log_level")) - if log_level >= level and log_level != -1: - print("{}: {}".format(log_level_map[level].upper(), msg)) - - def mpd_init_connection(self): - """ connect to mpd """ - host = self.get_setting("mpd", "host") - if host == -1: - host = "localhost" - port = self.get_setting("mpd", "port") - if port == -1: - port = 6600 - timeout = self.get_setting("mpd", "timeout") - if timeout == -1: - timeout = 3 - - self.client = MPDClient() - self.client.host = host - self.client.port = port - self.client.timeout = timeout - - # ret = self.mpd_connect_timeout() - if self.mpd_connect_timeout() != 0: - sys.exit() - else: - self.log("connected to MPD with settings host = {}, port = {}, timeout = {}".format(host, port, timeout), 3) - - def mpd_connect_timeout(self): - """ establishes the connection to MPD when disconnected """ - success = False - runtime = 0 - try: - self.client.disconnect() - except: - pass - while success is not True and runtime <= self.client.timeout: - try: - self.client.connect(self.client.host, self.client.port) - success = True - self.log("Connected to MPD at {} on port {}.".format(self.client.host, self.client.port), 5) - return 0 - except: - self.log("Could not connect to MPD, retrying.", 5) - sleep(0.2) - runtime += 0.2 - if runtime >= self.client.timeout: - self.log("Could not connect to MPD for {}s, giving up.".format(self.client.timeout), 2) - return 1 - - def do_second_swipe(self): - """ react to the second swipe of the same card according to settings""" - second_swipe_map = {'default': self.do_restart_playlist, - 'restart': self.do_restart_playlist, - 'restart_track': self.do_restart_track, - 'stop': self.do_stop, - 'pause': self.do_toggle, - 'noaudioplay': self.do_pass, - 'skipnext': self.do_next, - } - setting_key = "second_swipe" - map_key = self.config.get("phoniebox", setting_key) - try: - second_swipe_map[map_key]() - except KeyError as e: - self.log("Unknown setting \"{} = {}\", using \"{} = default\".".format(setting_key, map_key, setting_key), 5) - second_swipe_map['default']() - - def do_restart_playlist(self): - """ restart the same playlist from the beginning """ - # TODO: Any reason not to just start the first item in the current playlist? - self.mpd_connect_timeout() - self.set_mpd_playmode(self.lastplayedID) - self.play_mpd(self.get_cardsetting(self.lastplayedID, "uri")) - - def do_restart_track(self): - """ restart currently playing track """ - self.mpd_connect_timeout() - mpd_status = self.client.status() - self.set_mpd_playmode(self.lastplayedID) - # restart current track - self.client.play(mpd_status['song']) - - def do_start_playlist(self, cardid): - """ restart the same playlist, eventually resume """ - if self.get_cardsetting(self.lastplayedID, "resume"): - self.resume(self.lastplayedID, "save") - self.mpd_connect_timeout() - self.set_mpd_playmode(cardid) - self.play_mpd(self.get_cardsetting(cardid, "uri")) - if self.get_cardsetting(cardid, "resume"): - self.resume(cardid, "resume") - self.lastplayedID = cardid - - def do_toggle(self): - """ toggle play/pause """ - self.mpd_connect_timeout() - status = self.client.status() - if status['state'] == "play": - self.client.pause() - else: - self.client.play() - - def do_pass(self): - """ do nothing (on second swipe with noaudioplay) """ - pass - - def do_next(self): - """ skip to next track or restart playlist if stopped (on second swipe with noaudioplay) """ - self.mpd_connect_timeout() - status = self.client.status() - # start playlist if in stop state or there is only one song in the playlist (virtually loop) - if (status["state"] == "stop") or (status["playlistlength"] == "1"): - self.do_restart_playlist() - else: - self.client.next() - - def do_stop(self): - """ do nothing (on second swipe with noaudioplay) """ - self.mpd_connect_timeout() - self.client.stop() - - def play_alsa(self, audiofile): - """ pause mpd and play file on alsa player """ - self.mpd_connect_timeout() - self.client.pause() - # TODO: use the standard audio device or set them via phoniebox.conf - subprocess.call(["aplay -q -Dsysdefault:CARD=sndrpijustboomd " + audiofile], shell=True) - subprocess.call(["aplay -q -Dsysdefault " + audiofile], shell=True) - - def play_mpd(self, uri): - """ play uri in mpd """ - self.mpd_connect_timeout() - self.client.clear() - self.client.add(uri) - self.client.play() - self.log("phoniebox: playing {}".format(uri.encode('utf-8')), 3) - - # TODO: is there a better way to check for "value not present" than to return -1? - def get_setting(self, section, key, opt_type="string"): - """ get a setting from configFile file or cardAssignmentsFile - if not present, return -1 - """ - try: - num = str2num(section) - parser = self.cardAssignments - except ValueError: - parser = self.config - - try: - opt = parser.get(section, key) - except configparser.NoOptionError: - print("No option {} in section {}".format(key, section)) - return -1 - except configparser.NoSectionError: - print("No section {}".format(section)) - return -1 - if "bool" in opt_type.lower(): - return str2bool(opt) - else: - try: - return str2num(opt) - except ValueError: - return opt - - def get_cardsetting(self, cardid, key, opt_type="string"): - """ catches Errors """ - return self.get_setting(cardid, key, opt_type) - - def mpd_init_settings(self): - """ set initial mpd state: - max_volume - initial_volume """ - mpd_status = self.client.status() - max_volume = self.get_setting("phoniebox", "max_volume") - init_volume = self.get_setting("phoniebox", "init_volume") - if max_volume == -1: - max_volume = 100 # the absolute max_volume is 100% - if init_volume == -1: - init_volume = 0 # to be able to compare - if max_volume < init_volume: - self.log("init_volume cannot exceed max_volume.", 2) - init_volume = max_volume # do not exceed max_volume - if mpd_status["volume"] > max_volume: - self.client.setvol(init_volume) - - def set_mpd_playmode(self, cardid): - """ set playmode in mpd according to card settings """ - playmode_defaults_map = {"repeat": 0, "random": 0, "single": 0, "consume": 0} - set_playmode_map = {"repeat": self.client.repeat, - "random": self.client.random, - "single": self.client.single, - "consume": self.client.consume} - for key in set_playmode_map.keys(): - # option is set if config file contains "option = 1" or just "option" without value. - playmode_setting = self.get_cardsetting(cardid, key) - if playmode_setting == -1 or playmode_setting == 1: - playmode_setting = 1 - else: - playmode_setting = playmode_defaults_map[key] - # set value - set_playmode_map[key](playmode_setting) - self.log("setting mpd {} = {}".format(key, playmode_setting), 5) - - def resume(self, cardid, action="resume"): - """ seek to saved position if resume is activated """ - self.mpd_connect_timeout() - mpd_status = self.client.status() - print(mpd_status) - if action in ["resume", "restore"]: - opt_resume = self.get_cardsetting(cardid, "resume") - if opt_resume == -1 or opt_resume == 1: - resume_elapsed = self.get_cardsetting(cardid, "resume_elapsed") - resume_song = self.get_cardsetting(cardid, "resume_song") - if resume_song == -1: - resume_song = 0 - if resume_elapsed != -1 and resume_elapsed != 0: - self.log("{}: resume song {} at time {}s".format(cardid, - self.get_cardsetting(cardid, "resume_song"), - self.get_cardsetting(cardid, "resume_elapsed")), 5) - self.client.seek(resume_song, resume_elapsed) - elif action in ["save", "store"]: - try: - self.log("{}: save state, song {} at time {}s".format(cardid, - mpd_status["song"], mpd_status["elapsed"]), 5) - self.cardAssignments.set(cardid, "resume_elapsed", - mpd_status["elapsed"]) - self.cardAssignments.set(cardid, "resume_song", - mpd_status["song"]) - except KeyError as e: - print("KeyError: {}".format(e)) - except ValueError as e: - print("ValueError: {}".format(e)) - - def read_cardAssignments(self): - card_assignments_file = self.config.get("phoniebox", "card_assignments_file") - parser = ConfigParserExtended(allow_no_value=True) - dataset = parser.read(card_assignments_file) - if len(dataset) != 1: - raise ValueError("Config file {} not found!".format(card_assignments_file)) - return parser - - def update_cardAssignments(self, static_cardAssignments): - """card_assignments_file = self.config.get("phoniebox","card_assignments_file") - parser = ConfigParserExtended(allow_no_value=True) - dataset = parser.read(card_assignments_file) - if len(dataset) != 1: - raise ValueError("Config file {} not found!".format(card_assignments_file)) - # if cardAssignments is still empty, store new cardAssignments directly - # otherwise compare new values with old values and update only certain values - if hasattr(self, 'cardAssignments'): - self.debug("cardAssignments already set, updating data in memory with new data from file {}".format(card_assignments_file)) - static_cardAssignments = parser""" - self.log("Updating changes in cardAssignments from disk.", 3) - keep_cardsettings = ["resume_song", "resume_elapsed"] - common_sections = list(set(static_cardAssignments.sections()).intersection(self.cardAssignments.sections())) - for section in common_sections: - for option in keep_cardsettings: - if self.cardAssignments.has_option(section, option): - value = self.cardAssignments.get(section, option) - static_cardAssignments.set(section, option, value) - self.log("Updating cardid {} with \"{} = {}\".".format(section, option, value), 5) - # finally assign new values - self.cardAssignments = static_cardAssignments - - def read_config(self, configFilePath=defaultconfigFilePath): - """ read config variables from file """ - configParser = ConfigParserExtended(allow_no_value=True, interpolation=configparser.BasicInterpolation()) - dataset = configParser.read(configFilePath) - if len(dataset) != 1: - raise ValueError("Config file {} not found!".format(configFilePath)) - self.config = configParser - - def translate_legacy_cardAssignments(self, last_translate_legacy_cardAssignments=0): - """ reads the card settings data from the old scheme an translates them """ - shortcuts_path = self.get_setting("phoniebox", "shortcuts_path") - audiofolders_path = self.get_setting("phoniebox", "audiofolders_path") - if shortcuts_path != -1: - configParser = ConfigParserExtended() - shortcut_files = [f for f in os.listdir(shortcuts_path) if os.path.isfile(os.path.join(shortcuts_path, f)) and is_int(f)] - - # filename is the cardid - for filename in shortcut_files: - with open(os.path.join(shortcuts_path, filename)) as f: - uri = f.readline().strip().decode('utf-8') - - # add default settings - if filename not in configParser.sections(): - self.log("Adding section {} to cardAssignments".format(filename), 5) - configParser.add_section(filename) - configParser[filename] = self.config["default_cardsettings"] - configParser.set(filename, "cardid", filename) - configParser.set(filename, "uri", uri) - # translate and add folder.conf settings if they contradict default_cardsettings - cardsettings_map = {"CURRENTFILENAME": None, - "ELAPSED": "resume_elapsed", - "PLAYSTATUS": None, - "RESUME": "resume", - "SHUFFLE": "random", - "LOOP": "repeat"} - folderconf = os.path.join(audiofolders_path, uri, "folder.conf") - if os.path.isfile(folderconf) and file_modified(folderconf, last_translate_legacy_cardAssignments): - with open(folderconf) as f: - lines = f.readlines() - cardsettings_old = dict([l.strip().replace('"', '').split("=") for l in lines]) - for key in cardsettings_old.keys(): - if cardsettings_map[key] is not None: - # ignore 0 and OFF values, drop settings that have None in cardsettings_map - if key != "ELAPSED": - if cardsettings_old[key] != "0" and cardsettings_old[key] != "OFF": - configParser.set(filename, cardsettings_map[key], "1") - else: - configParser.set(filename, cardsettings_map[key], "0") - else: - try: - elapsed_val = float(cardsettings_old[key]) - except ValueError: - elaped_val = 0 - configParser.set(filename, cardsettings_map[key], str(elapsed_val)) - return configParser - - def write_new_cardAssignments(self): - """ updates the cardsettings with according to playstate """ - card_assignments_file = self.config.get("phoniebox", "card_assignments_file") - self.log("Write new card assignments to file {}.".format(card_assignments_file), 3) - with codecs.open(card_assignments_file, 'w', 'utf-8') as f: - self.cardAssignments.write(f) - - def print_to_file(self, filename, string): - """ simple function to write a string to a file """ - with codecs.open(filename, 'w', 'utf-8') as f: - f.write(string) - - -if __name__ == "__main__": - print("This module is not to be run! Use \"from Phoniebox import Phoniebox\" instead!") -else: - print("Phoniebox imported. Use \"box = Phoniebox(configFile)\" to get it working.") diff --git a/scripts/python-phoniebox/PhonieboxConfigChanger.py b/scripts/python-phoniebox/PhonieboxConfigChanger.py deleted file mode 100755 index 4c3c9bd46..000000000 --- a/scripts/python-phoniebox/PhonieboxConfigChanger.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# import json -import os, sys, signal -# from mpd import MPDClient -import configparser -# from RawConfigParserExtended import RawConfigParserExtended -from Phoniebox import Phoniebox - -# get absolute path of this script -dir_path = os.path.dirname(os.path.realpath(__file__)) -defaultconfigFilePath = os.path.join(dir_path, './phoniebox.conf') - - -def is_int(s): - """ return True if string is an int """ - try: - int(s) - return True - except ValueError: - return False - - -def str2bool(s): - """ convert string to a python boolean """ - return s.lower() in ("yes", "true", "t", "1") - - -def str2num(s): - """ convert string to an int or a float """ - try: - return int(s) - except ValueError: - return float(s) - - -class PhonieboxConfigChanger(Phoniebox): - - def __init__(self, configFilePath=defaultconfigFilePath): - Phoniebox.__init__(self, configFilePath) - - def assigncard(self, cardid, uri): - section = cardid - # set uri and cardid for card (section = cardid) - if not section in self.cardAssignments.sections(): - self.cardAssignments.add_section(section) - self.cardAssignments.set(section, "cardid", cardid) - self.cardAssignments.set(section, "uri", uri) - # write updated assignments to file - with open(self.config['card_assignments_file'], 'w') as cardAssignmentsFile: - self.cardAssignments.write(cardAssignmentsFile) - - def removecard(self, cardid): - section = cardid - if section in self.cardAssignments.sections(): - self.cardAssignments.remove_section(section) - # write updated assignments to file - with open(self.config['card_assignments_file'], 'w') as f: - self.cardAssignments.write(f) - - def set(self, section, key, value): - try: - num = int(section) - parser = self.cardAssignments - config_file = self.config.get("phoniebox", "card_assignments_file") - except ValueError: - parser = self.config - # update value - try: - parser.set(section, key, value) - self.debug("Set {} = {} in section {}".format(key, value, section)) - except configparser.NoSectionError as e: - raise e - - def get(self, section, t="ini"): - try: - num = int(section) - parser = self.cardAssignments - except ValueError: - parser = self.config - - if t == "json": - print(parser.as_json(section)) - elif t == "dict": - print(parser.as_dict(section)) - else: - print(parser.print_ini(section)) - - def print_usage(self): - print("Usage: {} set ".format(sys.argv[0])) - - -def main(self): - - cmdlist = ["assigncard", "removecard", "set", "get"] - - if len(sys.argv) < 1: - sys.exit() - else: - if sys.argv[1] in cmdlist: - configFilePath = defaultconfigFilePath - cmd = sys.argv[1] - shift = 0 - else: - configFilePath = sys.argv[1] - cmd = sys.argv[2] - shift = 1 - - ConfigChanger = PhonieboxConfigChanger(configFilePath) - try: - if cmd == "assigncard": - cardid = sys.argv[2+shift] - uri = sys.argv[3+shift] - ConfigChanger.assigncard(cardid, uri) - elif cmd == "removecard": - cardid = sys.argv[2+shift] - ConfigChanger.removecard(cardid) - elif cmd == "set": - section = sys.argv[2+shift] - key = sys.argv[3+shift] - value = sys.argv[4+shift] - ConfigChanger.set(section, key, value) - elif cmd == "get": - section = sys.argv[2+shift] - try: - t = sys.argv[3+shift] - except: - t = "ini" - ConfigChanger.get(section, t) - else: - # will never be reached - print("supported commands are {} and {}".format(", ".join(cmdlist[:-1]), cmdlist[-1])) - except: - self.print_usage() - - -if __name__ == "__main__": - main() diff --git a/scripts/python-phoniebox/README.md b/scripts/python-phoniebox/README.md deleted file mode 100644 index 35d1242d2..000000000 --- a/scripts/python-phoniebox/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# python-phoniebox -python daemon to be used with the RPi-Jukebox-RFID by MiczFlor - -https://github.com/MiczFlor/RPi-Jukebox-RFID - - Make sure to edit the defaultconfigFilePath in the file Phoniebox.py to match the path of the phoniebox.conf file. diff --git a/scripts/python-phoniebox/RawConfigParserExtended.py b/scripts/python-phoniebox/RawConfigParserExtended.py deleted file mode 100755 index 49cd28ff9..000000000 --- a/scripts/python-phoniebox/RawConfigParserExtended.py +++ /dev/null @@ -1,31 +0,0 @@ -# from configparser import RawConfigParser -import configparser - - -class RawConfigParserExtended(configparser.RawConfigParser): - - def as_dict(self, section="all"): - if section == "all": - d = self.__dict__['_sections'] - else: - d = self.__dict__['_sections'][section] - return d - - def as_json(self, section="all"): - import json - if section == "all": - d = self.__dict__['_sections'] - else: - d = self.__dict__['_sections'][section] - return json.dumps(d, separators=(',', ':'), indent=4, sort_keys=True, - ensure_ascii=False).encode('utf8') - - def print_ini(self, section="all"): - if section == "all": - sections = self.sections() - else: - sections = [section] - for section_name in sections: - print("[{}]".format(section_name)) - for key, value in self.items(section_name): - print('{} = {}'.format(key, value)) diff --git a/scripts/python-phoniebox/Reader.py b/scripts/python-phoniebox/Reader.py deleted file mode 100755 index 927912f8f..000000000 --- a/scripts/python-phoniebox/Reader.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python3 -# This alternative Reader.py script was meant to cover not only USB readers but more. -# It can be used to replace Reader.py if you have readers such as -# MFRC522 or RDM6300. -# Please use the github issue threads to share bugs and improvements -# or create pull requests. - -import os.path -import sys -import serial -import string -import RPi.GPIO as GPIO - -from evdev import InputDevice, categorize, ecodes, list_devices -import pirc522 - - -def get_devices(): - devices = [InputDevice(fn) for fn in list_devices()] - devices.append(NonUsbDevice('MFRC522')) - devices.append(NonUsbDevice('RDM6300')) - return devices - - -class NonUsbDevice(object): - name = None - - def __init__(self, name): - self.name = name - - -class UsbReader(object): - def __init__(self, device): - self.keys = "X^1234567890XXXXqwertzuiopXXXXasdfghjklXXXXXyxcvbnmXXXXXXXXXXXXXXXXXXXXXXX" - self.dev = device - - def readCard(self): - from select import select - stri = '' - key = '' - while key != 'KEY_ENTER': - select([self.dev], [], []) - for event in self.dev.read(): - if event.type == 1 and event.value == 1: - stri += self.keys[event.code] - key = ecodes.KEY[event.code] - return stri[:-1] - - -class Mfrc522Reader(object): - def __init__(self): - self.device = pirc522.RFID() - - def readCard(self): - # Scan for cards - self.device.wait_for_tag() - (error, tag_type) = self.device.request() - - if not error: - print("Card detected.") - # Perform anti-collision detection to find card uid - (error, uid) = self.device.anticoll() - if not error: - return ''.join((str(x) for x in uid)) - - print("No Device ID found.") - return None - - @staticmethod - def cleanup(): - GPIO.cleanup() - - -class Rdm6300Reader: - def __init__(self): - device = '/dev/ttyS0' - baudrate = 9600 - ser_timeout = 0.1 - self.last_card_id = '' - try: - self.rfid_serial = serial.Serial(device, baudrate, timeout=ser_timeout) - except serial.SerialException as e: - print(e) - exit(1) - - def readCard(self): - byte_card_id = b'' - - try: - while True: - try: - read_byte = self.rfid_serial.read() - - if read_byte == b'\x02': # start byte - while read_byte != b'\x03': # end bye - read_byte = self.rfid_serial.read() - byte_card_id += read_byte - - card_id = byte_card_id.decode('utf-8') - byte_card_id = '' - card_id = ''.join(x for x in card_id if x in string.printable) - - # Only return UUIDs with correct length - if len(card_id) == 12 and card_id != self.last_card_id: - self.last_card_id = card_id - self.rfid_serial.reset_input_buffer() - return self.last_card_id - - else: # wrong UUID length or already send that UUID last time - self.rfid_serial.reset_input_buffer() - - except ValueError as ve: - print(ve) - - except serial.SerialException as se: - print(se) - - def cleanup(self): - self.rfid_serial.close() - - -class Reader(object): - def __init__(self): - path = os.path.dirname(os.path.realpath(__file__)) - if not os.path.isfile(path + '/deviceName.txt'): - sys.exit('Please run RegisterDevice.py first') - else: - with open(path + '/deviceName.txt', 'r') as f: - device_name = f.read() - - if device_name == 'MFRC522': - self.reader = Mfrc522Reader() - elif device_name == 'RDM6300': - self.reader = Rdm6300Reader() - else: - try: - device = [device for device in get_devices() if device.name == device_name][0] - self.reader = UsbReader(device) - except IndexError: - sys.exit('Could not find the device %s.\n Make sure it is connected' % device_name) diff --git a/scripts/python-phoniebox/__init__.py b/scripts/python-phoniebox/__init__.py deleted file mode 100755 index e69de29bb..000000000 diff --git a/scripts/python-phoniebox/deviceName.txt b/scripts/python-phoniebox/deviceName.txt deleted file mode 100755 index a404db7da..000000000 --- a/scripts/python-phoniebox/deviceName.txt +++ /dev/null @@ -1 +0,0 @@ -MFRC522 \ No newline at end of file diff --git a/scripts/python-phoniebox/helpers_unused_atm/__init__.py b/scripts/python-phoniebox/helpers_unused_atm/__init__.py deleted file mode 100755 index e69de29bb..000000000 diff --git a/scripts/python-phoniebox/helpers_unused_atm/helpers.py b/scripts/python-phoniebox/helpers_unused_atm/helpers.py deleted file mode 100755 index 68aef4b68..000000000 --- a/scripts/python-phoniebox/helpers_unused_atm/helpers.py +++ /dev/null @@ -1,23 +0,0 @@ -__name__ = "helpers" - - -def is_int(s): - """ return True if string is an int """ - try: - int(s) - return True - except ValueError: - return False - - -def str2bool(s): - """ convert string to a python boolean """ - return s.lower() in ("yes", "true", "t", "1") - - -def str2num(s): - """ convert string to an int or a float """ - try: - return int(s) - except ValueError: - return float(s) diff --git a/scripts/python-phoniebox/phoniebox.conf b/scripts/python-phoniebox/phoniebox.conf deleted file mode 100755 index d52c9fdbf..000000000 --- a/scripts/python-phoniebox/phoniebox.conf +++ /dev/null @@ -1,62 +0,0 @@ -[phoniebox] -# log level -# 0: no output -# 1: error -# 2: warning -# 3: info (default) -# 4: not used -# 5: debug -log_level = 3 - -# time in seconds to pause detection after swipe (default: 0.5) -debounce_time = 0.5 - -# setup directories -base_path = /home/pi/RPi-Jukebox-RFID/ -audiofolders_path = %(base_path)s/shared/audiofolders -card_assignments_file = %(base_path)s/settings/Card_Assignments.txt -# card detection sound will be played on swipe by aplay (default: none) -card_detection_sound = %(base_path)s/shared/card_detection_sound.wav -# PhonieboxDaemon startup sound will be played by aplay (default: none) -startup_sound = %(base_path)s/shared/startupsound.wav - -# file to log detected card IDs. Required for web interface -Latest_RFID_file = %(base_path)s/shared/latestID.txt - -# use the old-style folder.conf files as card-assignments -# which enables sticking to the legacy-web interface -# resume-settings are not imported, but kept up-to-date by PhonieboxDaemon -translate_legacy_cardassignments = 1 -# the legacy shortcut files are only used to find the legacy cardassignments -shortcuts_path = %(base_path)s/shared/shortcuts/ - -# store card assignments and resume data regularly on disk (default: 30) -store_card_assignments = 30 - -# action for second swipe of the same RFID card. Possible values: -# restart (default), restart_track, stop, pause, skipnext or next, noaudioplay -# note that the combination of "second_swipe = restart" for an RFID card -# with random in the cardsettings behaves similar to "skipnext" with random enabled. -second_swipe = skipnext -# seconds to wait until second swipe is possible (default: 0) -second_swipe_delay = 0 - -# volume settings -init_volume = 65 -max_volume = 80 -# only used by rotary_volume.py -volume_step = 2 - -[mpd] -# mpd connection settings (default: localhost:6600) -host = localhost -port = 6600 -timeout = 5 - -[default_cardsettings] -# default settings for newly registered or translated RFID cards -repeat = 0 -resume = 1 -random = 1 -single = 0 -consume = 0 diff --git a/scripts/resume_play.sh b/scripts/resume_play.sh deleted file mode 100755 index 5482bb3db..000000000 --- a/scripts/resume_play.sh +++ /dev/null @@ -1,180 +0,0 @@ -#!/bin/bash - -# This script saves or restores the last position (song and time) in a playlist (=folder) -# Saving and restoring will only be made if a "lastplayed.dat" file is found in the folder where the -# audio is stored. -# Usage: -# Save the position: ./resume_play.sh -c=savepos -# Restore position and play or play from playlist position: ./resume_play-sh -c=resume -v=playlist_pos -# Enable resume for folder: ./resume_play-sh -c=enableresume -v=foldername_in_audiofolders -# Disable resume for folder: ./resume_play-sh -c=disableresume -v=foldername_in_audiofolders -# -# Call this script with "savepos" everytime -# - before you clear the playlist (mpc clear) -# - before you stop the player -# - before you shutdown the Pi (maybe not necessary as mpc stores the position between reboots, but it feels saver) - -# Set the date and time of now -NOW=`date +%Y-%m-%d.%H:%M:%S` - -# The absolute path to the folder whjch contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -############################################################# -# $DEBUG TRUE|FALSE -# Read debug logging configuration file -. $PATHDATA/../settings/debugLogging.conf - -# Read the args passed on by the command line -# see following file for details: -. $PATHDATA/inc.readArgsFromCommandLine.sh - -########################################################### -# Read global configuration file (and create is not exists) -# create the global configuration file from single files - if it does not exist -if [ ! -f $PATHDATA/../settings/global.conf ]; then - . inc.writeGlobalConfig.sh -fi -. $PATHDATA/../settings/global.conf -########################################################### - -if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo "#START##### SCRIPT resume_play.sh ($NOW) ##" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo "VAR AUDIOFOLDERSPATH: $AUDIOFOLDERSPATH" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo "VAR COMMAND: $COMMAND" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo "VAR VALUE: $VALUE" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo "VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi - - -# Some error checking: if folder.conf does not exist, create default -if [ ! -e "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" ] -then - # now we create a default folder.conf file by calling this script - # with the command param createDefaultFolderConf - # (see script for details) - # the $FOLDER would not need to be passed on, because it is already set in this script - # see inc.writeFolderConfig.sh for details - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " - calling inc.writeFolderConfig.sh -c=createDefaultFolderConf -d=\$FOLDER" >> $PATHDATA/../logs/debug.log; fi - . $PATHDATA/inc.writeFolderConfig.sh -c=createDefaultFolderConf -d="$FOLDER" - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " - back from inc.writeFolderConfig.sh" >> $PATHDATA/../logs/debug.log; fi -fi - -if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " content of $AUDIOFOLDERSPATH/$FOLDER/folder.conf" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then cat "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " Now doing what COMMAND wants: $COMMAND" >> $PATHDATA/../logs/debug.log; fi - -case "$COMMAND" in - -savepos) - # Get folder name of currently played audio - FOLDER=$(cat $PATHDATA/../settings/Latest_Folder_Played) - # Read the current config file (include will execute == read) - . "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo "VAR FOLDER from settings/Latest_Folder_Played: $FOLDER" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " savepos FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi - # Check if "folder.conf" exists - if [ $RESUME == "ON" ] || [ $SINGLE == "ON" ]; - then - # Get the elapsed time of the currently played audio file from mpd - ELAPSED=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=elapsed: ).*') - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " savepos ELAPSED: $ELAPSED" >> $PATHDATA/../logs/debug.log; fi - # mpd reports an elapsed time only if the audio is playing or is paused. Check if we got an elapsed time - if [ ! -z $ELAPSED ]; # Why does -n not work here? - then - #Get the filename of the currently played audio - CURRENTFILENAME=$(echo -e "currentsong\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=file: ).*') - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " savepos CURRENTFILENAME: $CURRENTFILENAME" >> $PATHDATA/../logs/debug.log; fi - # "Stopped" for signaling -c=resume that there was a stopping event - # (this is done to get a proper resume on the first track if the playlist has ended before) - - # set the vars we need to change - CURRENTFILENAME=$CURRENTFILENAME - ELAPSED=$ELAPSED - PLAYSTATUS="Stopped" - # now calling a script which will only replace these new vars in folder.conf - # (see script for details) - . $PATHDATA/inc.writeFolderConfig.sh - fi - fi - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then cat "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" >> $PATHDATA/../logs/debug.log; fi - ;; -resume) - # Read the current config file (include will execute == read) - # read vars from folder.conf - . "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " savepos FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " entering: resume with value $RESUME" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " entering: single with value $SINGLE" >> $PATHDATA/../logs/debug.log; fi - # Check if RESUME is switched on - if [ $RESUME == "ON" ] || [ $SINGLE == "ON" ]; - then - # will generate variables: - #CURRENTFILENAME - #ELAPSED - #PLAYSTATUS - - # Check if we got a "savepos" command after the last "resume". Otherwise we assume that the playlist was played until the end. - # In this case, start the playlist from beginning - if [ $PLAYSTATUS == "Stopped" ] - then - # Get the playlist position of the file from mpd - # Alternative approach: "mpc searchplay xx && mpc seek yy" - PLAYLISTPOS=$(echo -e playlistfind filename \"$CURRENTFILENAME\"\\nclose | nc -w 1 localhost 6600 | grep -o -P '(?<=Pos: ).*') - - # If the file is found, it is played from ELAPSED, otherwise start playlist from beginning. If we got a playlist position - # play from that position, not the saved one. - if [ ! -z $PLAYLISTPOS ] && [ -z $VALUE ] ; - then - # doesnt work correctly - # echo -e seek $PLAYLISTPOS $ELAPSED \\nclose | nc -w 1 localhost 6600 - # workaround, see https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/878#issuecomment-672283454 - echo -e "play $PLAYLISTPOS" | nc -w 1 localhost 6600 - echo -e seekcur $ELAPSED \\nclose | nc -w 1 localhost 6600 - else - echo -e "play $VALUE" | nc -w 1 localhost 6600 - fi - # If the playlist ends without any stop/shutdown/new swipe (you've listened to all of the tracks), - # there's no savepos event and we would resume at the last position anywhere in the playlist. - # To catch these, we signal it to the next "resume" call via writing it to folder.conf that - # we still assume that the audio is playing. - # be anything here, as we won't use the information if "Playing" is found by "resume". - - # set the vars we need to change - PLAYSTATUS="Playing" - # now calling a script which will only replace these new vars in folder.conf - # (see script for details) - . $PATHDATA/inc.writeFolderConfig.sh - - else - # We assume that the playlist ran to the end the last time and start from the beginning. - # Or: playlist is playing and we've got a play from playlist position command. - echo -e "play $VALUE" | nc -w 1 localhost 6600 - fi - else - # if no last played data exists (resume play disabled), we play the playlist from the beginning or the given playlist position - echo -e "play $VALUE" | nc -w 1 localhost 6600 - fi - ;; -enableresume) - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " entering: enableresume" >> $PATHDATA/../logs/debug.log; fi - # set the vars we need to change - RESUME="ON" - # now calling a script which will only replace these new vars in folder.conf - # (see script for details) - . $PATHDATA/inc.writeFolderConfig.sh - ;; -disableresume) - if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo " entering: disableresume" >> $PATHDATA/../logs/debug.log; fi - # set the vars we need to change - RESUME="OFF" - # now calling a script which will only replace these new vars in folder.conf - - # (see script for details) - . $PATHDATA/inc.writeFolderConfig.sh - ;; -*) - echo "Command unknown", $COMMAND - ;; -esac - -if [ "${DEBUG_resume_play_sh}" == "TRUE" ]; then echo "#END####### SCRIPT resume_play.sh ($NOW) ##" >> $PATHDATA/../logs/debug.log; fi diff --git a/scripts/rfid_trigger_play.sh b/scripts/rfid_trigger_play.sh deleted file mode 100755 index e96902eb7..000000000 --- a/scripts/rfid_trigger_play.sh +++ /dev/null @@ -1,499 +0,0 @@ -#!/bin/bash - -# Reads the card ID or the folder name with audio files -# from the command line (see Usage). -# Then attempts to get the folder name from the card ID -# or play audio folder content directly -# -# Usage for card ID -# ./rfid_trigger_play.sh -i=1234567890 -# or -# ./rfid_trigger_play.sh --cardid=1234567890 -# -# For folder names: -# ./rfid_trigger_play.sh -d='foldername' -# or -# ./rfid_trigger_play.sh --dir='foldername' -# -# or for recursive play of sudfolders -# ./rfid_trigger_play.sh -d='foldername' -v=recursive - -# ADD / EDIT RFID CARDS TO CONTROL THE PHONIEBOX -# All controls are assigned to RFID cards in this -# file: -# settings/rfid_trigger_play.conf -# Please consult this file for more information. -# Do NOT edit anything in this file. - -# Set the date and time of now -NOW=`date +%Y-%m-%d.%H:%M:%S` - -# The absolute path to the folder whjch contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -############################################################# -# $DEBUG TRUE|FALSE -# Read debug logging configuration file -. $PATHDATA/../settings/debugLogging.conf - -if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "########### SCRIPT rfid_trigger_play.sh ($NOW) ##" >> $PATHDATA/../logs/debug.log; fi - -# create the configuration file from sample - if it does not exist -if [ ! -f $PATHDATA/../settings/rfid_trigger_play.conf ]; then - cp $PATHDATA/../settings/rfid_trigger_play.conf.sample $PATHDATA/../settings/rfid_trigger_play.conf - # change the read/write so that later this might also be editable through the web app - sudo chown -R pi:www-data $PATHDATA/../settings/rfid_trigger_play.conf - sudo chmod -R 775 $PATHDATA/../settings/rfid_trigger_play.conf -fi - -########################################################### -# Read global configuration file (and create is not exists) -# create the global configuration file from single files - if it does not exist -if [ ! -f $PATHDATA/../settings/global.conf ]; then - . inc.writeGlobalConfig.sh -fi -. $PATHDATA/../settings/global.conf -########################################################### - -# Read configuration file -. $PATHDATA/../settings/rfid_trigger_play.conf - -# Get args from command line (see Usage above) -# see following file for details: -. $PATHDATA/inc.readArgsFromCommandLine.sh - -################################################################## -# Check if we got the card ID or the audio folder from the prompt. -# Sloppy error check, because we assume the best. -if [ "$CARDID" ]; then - # we got the card ID - # If you want to see the CARDID printed, uncomment the following line - # echo CARDID = $CARDID - - # Add info into the log, making it easer to monitor cards - echo "Card ID '$CARDID' was used at '$NOW'." > $PATHDATA/../shared/latestID.txt - echo "$CARDID" > $PATHDATA/../settings/Latest_RFID - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Card ID '$CARDID' was used" >> $PATHDATA/../logs/debug.log; fi - - # If the input is of 'special' use, don't treat it like a trigger to play audio. - # Special uses are for example volume changes, skipping, muting sound. - - case $CARDID in - $CMDSHUFFLE) - # toggles shuffle mode (random on/off) - $PATHDATA/playout_controls.sh -c=playershuffle - ;; - $CMDMAXVOL30) - # limit volume to 30% - $PATHDATA/playout_controls.sh -c=setmaxvolume -v=30 - ;; - $CMDMAXVOL50) - # limit volume to 50% - $PATHDATA/playout_controls.sh -c=setmaxvolume -v=50 - ;; - $CMDMAXVOL75) - # limit volume to 75% - $PATHDATA/playout_controls.sh -c=setmaxvolume -v=75 - ;; - $CMDMAXVOL80) - # limit volume to 80% - $PATHDATA/playout_controls.sh -c=setmaxvolume -v=80 - ;; - $CMDMAXVOL85) - # limit volume to 85% - $PATHDATA/playout_controls.sh -c=setmaxvolume -v=85 - ;; - $CMDMAXVOL90) - # limit volume to 90% - $PATHDATA/playout_controls.sh -c=setmaxvolume -v=90 - ;; - $CMDMAXVOL95) - # limit volume to 95% - $PATHDATA/playout_controls.sh -c=setmaxvolume -v=95 - ;; - $CMDMAXVOL100) - # limit volume to 100% - $PATHDATA/playout_controls.sh -c=setmaxvolume -v=100 - ;; - $CMDMUTE) - # amixer sset 'PCM' 0% - $PATHDATA/playout_controls.sh -c=mute - ;; - $CMDVOL30) - # amixer sset 'PCM' 30% - $PATHDATA/playout_controls.sh -c=setvolume -v=30 - ;; - $CMDVOL50) - # amixer sset 'PCM' 50% - $PATHDATA/playout_controls.sh -c=setvolume -v=50 - ;; - $CMDVOL75) - # amixer sset 'PCM' 75% - $PATHDATA/playout_controls.sh -c=setvolume -v=75 - ;; - $CMDVOL80) - # amixer sset 'PCM' 80% - $PATHDATA/playout_controls.sh -c=setvolume -v=80 - ;; - $CMDVOL85) - # amixer sset 'PCM' 85% - $PATHDATA/playout_controls.sh -c=setvolume -v=85 - ;; - $CMDVOL90) - # amixer sset 'PCM' 90% - $PATHDATA/playout_controls.sh -c=setvolume -v=90 - ;; - $CMDVOL95) - # amixer sset 'PCM' 95% - $PATHDATA/playout_controls.sh -c=setvolume -v=95 - ;; - $CMDVOL100) - # amixer sset 'PCM' 100% - $PATHDATA/playout_controls.sh -c=setvolume -v=100 - ;; - $CMDVOLUP) - # increase volume by x% set in Audio_Volume_Change_Step - $PATHDATA/playout_controls.sh -c=volumeup - ;; - $CMDVOLDOWN) - # decrease volume by x% set in Audio_Volume_Change_Step - $PATHDATA/playout_controls.sh -c=volumedown - ;; - $CMDSTOP) - # kill all running audio players - $PATHDATA/playout_controls.sh -c=playerstop - ;; - $CMDSHUTDOWN) - # shutdown the RPi nicely - # sudo halt - $PATHDATA/playout_controls.sh -c=shutdown - ;; - $CMDREBOOT) - # shutdown the RPi nicely - # sudo reboot - $PATHDATA/playout_controls.sh -c=reboot - ;; - $CMDNEXT) - # play next track in playlist - $PATHDATA/playout_controls.sh -c=playernext - ;; - $CMDPREV) - # play previous track in playlist - # echo "prev" | nc.openbsd -w 1 localhost 4212 - sudo $PATHDATA/playout_controls.sh -c=playerprev - #/usr/bin/sudo /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh -c=playerprev - ;; - $CMDREWIND) - # play the first track in playlist - sudo $PATHDATA/playout_controls.sh -c=playerrewind - ;; - $CMDSEEKFORW) - # jump 15 seconds ahead - $PATHDATA/playout_controls.sh -c=playerseek -v=+15 - ;; - $CMDSEEKBACK) - # jump 15 seconds back - $PATHDATA/playout_controls.sh -c=playerseek -v=-15 - ;; - $CMDPAUSE) - # pause current track - # echo "pause" | nc.openbsd -w 1 localhost 4212 - $PATHDATA/playout_controls.sh -c=playerpause - ;; - $CMDPLAY) - # play / resume current track - # echo "play" | nc.openbsd -w 1 localhost 4212 - $PATHDATA/playout_controls.sh -c=playerplay - ;; - $STOPAFTER5) - # stop player after -v minutes - $PATHDATA/playout_controls.sh -c=playerstopafter -v=5 - ;; - $STOPAFTER15) - # stop player after -v minutes - $PATHDATA/playout_controls.sh -c=playerstopafter -v=15 - ;; - $STOPAFTER30) - # stop player after -v minutes - $PATHDATA/playout_controls.sh -c=playerstopafter -v=30 - ;; - $STOPAFTER60) - # stop player after -v minutes - $PATHDATA/playout_controls.sh -c=playerstopafter -v=60 - ;; - $SHUTDOWNAFTER5) - # shutdown after -v minutes - $PATHDATA/playout_controls.sh -c=shutdownafter -v=5 - ;; - $SHUTDOWNAFTER15) - # shutdown after -v minutes - $PATHDATA/playout_controls.sh -c=shutdownafter -v=15 - ;; - $SHUTDOWNAFTER30) - # shutdown after -v minutes - $PATHDATA/playout_controls.sh -c=shutdownafter -v=30 - ;; - $SHUTDOWNAFTER60) - # shutdown after -v minutes - $PATHDATA/playout_controls.sh -c=shutdownafter -v=60 - ;; - $SHUTDOWNVOLUMEREDUCTION10) - # reduce volume until shutdown in -v minutes - $PATHDATA/playout_controls.sh -c=shutdownvolumereduction -v=10 - ;; - $SHUTDOWNVOLUMEREDUCTION15) - # reduce volume until shutdown in -v minutes - $PATHDATA/playout_controls.sh -c=shutdownvolumereduction -v=15 - ;; - $SHUTDOWNVOLUMEREDUCTION30) - # reduce volume until shutdown in -v minutes - $PATHDATA/playout_controls.sh -c=shutdownvolumereduction -v=30 - ;; - $SHUTDOWNVOLUMEREDUCTION60) - # reduce volume until shutdown in -v minutes - $PATHDATA/playout_controls.sh -c=shutdownvolumereduction -v=60 - ;; - $ENABLEWIFI) - $PATHDATA/playout_controls.sh -c=enablewifi - ;; - $DISABLEWIFI) - $PATHDATA/playout_controls.sh -c=disablewifi - ;; - $TOGGLEWIFI) - $PATHDATA/playout_controls.sh -c=togglewifi - ;; - $CMDPLAYCUSTOMPLS) - $PATHDATA/playout_controls.sh -c=playlistaddplay -v="PhonieCustomPLS" -d="PhonieCustomPLS" - ;; - $RECORDSTART600) - #start recorder for -v seconds - $PATHDATA/playout_controls.sh -c=recordstart -v=600 - ;; - $RECORDSTART60) - #start recorder for -v seconds - $PATHDATA/playout_controls.sh -c=recordstart -v=60 - ;; - $RECORDSTART10) - #start recorder for -v seconds - $PATHDATA/playout_controls.sh -c=recordstart -v=10 - ;; - $RECORDSTOP) - $PATHDATA/playout_controls.sh -c=recordstop - ;; - $RECORDPLAYBACKLATEST) - $PATHDATA/playout_controls.sh -c=recordplaylatest - ;; - $CMDREADWIFIIP) - $PATHDATA/playout_controls.sh -c=readwifiipoverspeaker - ;; - *) - - # We checked if the card was a special command, seems it wasn't. - # Now we expect it to be a trigger for one or more audio file(s). - # Let's look at the ID, write a bit of log information and then try to play audio. - - # Look for human readable shortcut in folder 'shortcuts' - # check if CARDID has a text file by the same name - which would contain the human readable folder name - if [ -f $PATHDATA/../shared/shortcuts/$CARDID ] - then - # Read human readable shortcut from file - FOLDER=`cat $PATHDATA/../shared/shortcuts/$CARDID` - # Add info into the log, making it easer to monitor cards - echo "This ID has been used before." >> $PATHDATA/../shared/latestID.txt - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "This ID has been used before." >> $PATHDATA/../logs/debug.log; fi - else - # Human readable shortcut does not exists, so create one with the content $CARDID - # this file can later be edited manually over the samba network - echo "$CARDID" > $PATHDATA/../shared/shortcuts/$CARDID - FOLDER=$CARDID - # Add info into the log, making it easer to monitor cards - echo "This ID was used for the first time." >> $PATHDATA/../shared/latestID.txt - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "This ID was used for the first time." >> $PATHDATA/../logs/debug.log; fi - fi - # Add info into the log, making it easer to monitor cards - echo "The shortcut points to audiofolder '$FOLDER'." >> $PATHDATA/../shared/latestID.txt - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "The shortcut points to audiofolder '$FOLDER'." >> $PATHDATA/../logs/debug.log; fi - ;; - esac -fi - -############################################################## -# We should now have a folder name with the audio files. -# Either from prompt of from the card ID processing above -# Sloppy error check, because we assume the best. - -if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "# Attempting to play: $AUDIOFOLDERSPATH/$FOLDER" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "# Type of play \$VALUE: $VALUE" >> $PATHDATA/../logs/debug.log; fi - -# check if -# - $FOLDER is not empty (! -z "$FOLDER") -# - AND (-a) -# - $FOLDER is set (! -z ${FOLDER+x}) -# - AND (-a) -# - and points to existing directory (-d "${AUDIOFOLDERSPATH}/${FOLDER}") -if [ ! -z "$FOLDER" -a ! -z ${FOLDER+x} -a -d "${AUDIOFOLDERSPATH}/${FOLDER}" ]; then - - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "\$FOLDER set, not empty and dir exists: ${AUDIOFOLDERSPATH}/${FOLDER}" >> $PATHDATA/../logs/debug.log; fi - - # if we play a folder the first time, add some sensible information to the folder.conf - if [ ! -f "${AUDIOFOLDERSPATH}/${FOLDER}/folder.conf" ]; then - # now we create a default folder.conf file by calling this script - # with the command param createDefaultFolderConf - # (see script for details) - # the $FOLDER would not need to be passed on, because it is already set in this script - # see inc.writeFolderConfig.sh for details - . $PATHDATA/inc.writeFolderConfig.sh -c=createDefaultFolderConf -d="${FOLDER}" - fi - - # get the name of the last folder played. As mpd doesn't store the name of the last - # playlist, we have to keep track of it via the Latest_Folder_Played file - LASTFOLDER=$(cat $PATHDATA/../settings/Latest_Folder_Played) - LASTPLAYLIST=$(cat $PATHDATA/../settings/Latest_Playlist_Played) - # this might need to go? resume not working... echo ${FOLDER} > $PATHDATA/../settings/Latest_Folder_Played - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$LASTFOLDER: $LASTFOLDER" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$LASTPLAYLIST: $LASTPLAYLIST" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Checking 'recursive' list? VAR \$VALUE: $VALUE" >> $PATHDATA/../logs/debug.log; fi - - if [ "$VALUE" == "recursive" ]; then - # set path to playlist - # replace subfolder slashes with " % " - PLAYLISTPATH="${PLAYLISTSFOLDERPATH}/${FOLDER//\//\ %\ }-%RCRSV%.m3u" - PLAYLISTNAME="${FOLDER//\//\ %\ }-%RCRSV%" - $PATHDATA/playlist_recursive_by_folder.php --folder "${FOLDER}" --list 'recursive' > "${PLAYLISTPATH}" - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "recursive? YES" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "$PATHDATA/playlist_recursive_by_folder.php --folder \"${FOLDER}\" --list 'recursive' > \"${PLAYLISTPATH}\"" >> $PATHDATA/../logs/debug.log; fi - else - # set path to playlist - # replace subfolder slashes with " % " - PLAYLISTPATH="${PLAYLISTSFOLDERPATH}/${FOLDER//\//\ %\ }.m3u" - PLAYLISTNAME="${FOLDER//\//\ %\ }" - $PATHDATA/playlist_recursive_by_folder.php --folder "${FOLDER}" > "${PLAYLISTPATH}" - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "recursive? NO" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "$PATHDATA/playlist_recursive_by_folder.php --folder \"${FOLDER}\" > \"${PLAYLISTPATH}\"" >> $PATHDATA/../logs/debug.log; fi - fi - - # Second Swipe value - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$SECONDSWIPE: ${SECONDSWIPE}" >> $PATHDATA/../logs/debug.log; fi - # Playlist name - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$PLAYLISTNAME: ${PLAYLISTNAME}" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Var \$LASTPLAYLIST: ${LASTPLAYLIST}" >> $PATHDATA/../logs/debug.log; fi - - # Setting a VAR to start "play playlist from start" - # This will be changed in the following checks "if this is the second swipe" - PLAYPLAYLIST=yes - - # Check if the second swipe happened - # - The same playlist is cued up ("$LASTPLAYLIST" == "$PLAYLISTNAME") - if [ "$LASTPLAYLIST" == "$PLAYLISTNAME" ] - then - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Second Swipe DID happen: \$LASTPLAYLIST == \$PLAYLISTNAME" >> $PATHDATA/../logs/debug.log; fi - - # check if - # - $SECONDSWIPE is set to toggle pause/play ("$SECONDSWIPE" == "PAUSE") - # - AND (-a) - # - check the length of the playlist, if =0 then it was cleared before, a state, which should only - # be possible after a reboot ($PLLENGTH -gt 0) - PLLENGTH=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=playlistlength: ).*') - if [ $PLLENGTH -eq 0 ] - then - # after a reboot we want to play the playlist once no matter what the setting is - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Take second wipe as first after fresh boot" >> $PATHDATA/../logs/debug.log; fi - elif [ "$SECONDSWIPE" == "PAUSE" -a $PLLENGTH -gt 0 ] - then - # The following involves NOT playing the playlist, so we set: - PLAYPLAYLIST=no - - STATE=$(echo -e "status\nclose" | nc -w 1 localhost 6600 | grep -o -P '(?<=state: ).*') - if [ $STATE == "play" ] - then - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " MPD playing, pausing the player" >> $PATHDATA/../logs/debug.log; fi - sudo $PATHDATA/playout_controls.sh -c=playerpause &>/dev/null - else - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "MPD not playing, start playing" >> $PATHDATA/../logs/debug.log; fi - sudo $PATHDATA/playout_controls.sh -c=playerplay &>/dev/null - fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: toggle pause/play" >> $PATHDATA/../logs/debug.log; fi - elif [ "$SECONDSWIPE" == "PLAY" -a $PLLENGTH -gt 0 ] - then - # The following involves NOT playing the playlist, so we set: - PLAYPLAYLIST=no - sudo $PATHDATA/playout_controls.sh -c=playerplay &>/dev/null - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: Resume playback" >> $PATHDATA/../logs/debug.log; fi - elif [ "$SECONDSWIPE" == "NOAUDIOPLAY" ] - then - # The following involves NOT playing the playlist, so we set: - PLAYPLAYLIST=no - # following needs testing (see https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/914) - # Special case for NOAUDIOPLAY because once the playlist has finished, - # it needs to be noted by the system that the second swipe is like a *first* swipe. - currentSong=`mpc current` - if [[ -z "$currentSong" ]]; then - #end of playlist (EOPL) reached. Ignore last played playlist - PLAYPLAYLIST=yes - fi - - # "$SECONDSWIPE" == "NOAUDIOPLAY" - # "$LASTPLAYLIST" == "$PLAYLISTNAME" => same playlist triggered again - # => do nothing - # echo "do nothing" > /dev/null 2>&1 - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: do nothing" >> $PATHDATA/../logs/debug.log; fi - elif [ "$SECONDSWIPE" == "SKIPNEXT" ] - then - # We will not play the playlist but skip to the next track: - PLAYPLAYLIST=skipnext - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Completed: skip next track" >> $PATHDATA/../logs/debug.log; fi - fi - fi - # now we check if we are still on for playing what we got passed on: - if [ "$PLAYPLAYLIST" == "yes" ] - then - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "We must play the playlist no matter what: \$PLAYPLAYLIST == yes" >> $PATHDATA/../logs/debug.log; fi - - # Above we already checked if the folder exists -d "$AUDIOFOLDERSPATH/$FOLDER" - # - # the process is as such - because of the recursive play option: - # - each folder can be played. - # - a single folder will create a playlist with the same name as the folder - # - because folders can live inside other folders, the relative path might contain - # slashes (e.g. audiobooks/Moby Dick/) - # - because slashes can not be in the playlist name, slashes are replaced with " % " - # - the "recursive" option means that the content of the folder AND all subfolders - # is being played - # - in this case, the playlist is related to the same folder name, which means we need - # to make a different name for "recursive" playout - # - a recursive playlist has the suffix " %RCRSV%" - keeping it cryptic to avoid clashes - # with a possible "real" name for a folder - # - with this new logic, there are no more SPECIALFORMAT playlists. Live streams and podcasts - # are now all unfolded into the playlist - # - creating the playlist is now done in the php script with parameters: - # $PATHDATA/playlist_recursive_by_folder.php --folder "${FOLDER}" --list 'recursive' - - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR PLAYLISTPATH: $PLAYLISTPATH" >> $PATHDATA/../logs/debug.log; fi - - # save position of current playing list "stop" - $PATHDATA/playout_controls.sh -c=playerstop - # play playlist - # the variable passed on to play is the playlist name -v (NOT the folder name) - # because (see above) a folder can be played recursively (including subfolders) or flat (only containing files) - # load new playlist and play - $PATHDATA/playout_controls.sh -c=playlistaddplay -v="${PLAYLISTNAME}" -d="${FOLDER}" - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Command: $PATHDATA/playout_controls.sh -c=playlistaddplay -v=\"${PLAYLISTNAME}\" -d=\"${FOLDER}\"" >> $PATHDATA/../logs/debug.log; fi - # save latest playlist not to file - sudo echo ${PLAYLISTNAME} > $PATHDATA/../settings/Latest_Playlist_Played - sudo chown pi:www-data $PATHDATA/../settings/Latest_Playlist_Played - sudo chmod 777 $PATHDATA/../settings/Latest_Playlist_Played - fi - if [ "$PLAYPLAYLIST" == "skipnext" ] - then - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Skip to the next track in the playlist: \$PLAYPLAYLIST == skipnext" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " VAR PLAYLISTPATH: $PLAYLISTPATH" >> $PATHDATA/../logs/debug.log; fi - - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo " Command: $PATHDATA/playout_controls.sh -c=playernext" >> $PATHDATA/../logs/debug.log; fi - $PATHDATA/playout_controls.sh -c=playernext - fi -else - if [ "${DEBUG_rfid_trigger_play_sh}" == "TRUE" ]; then echo "Path not found $AUDIOFOLDERSPATH/$FOLDER" >> $PATHDATA/../logs/debug.log; fi -fi diff --git a/scripts/shuffle_play.sh b/scripts/shuffle_play.sh deleted file mode 100755 index c0b80d067..000000000 --- a/scripts/shuffle_play.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/bash - -# This script saves or restores the SHUFFLE status in a playlist (=folder) and enables/disables shuffle mode according to the folder.conf of the current folder/playlist -# Usage: -# Enable shuffle for folder: ./shuffle_play-sh -c=enableshuffle -v=foldername_in_audiofolders -# Disable resume for folder: ./shuffle_play-sh -c=disableshuffle -v=foldername_in_audiofolders -# -# TODO: When to call this script? -# Call this script with "playlistaddplay" (playout_controls.sh) everytime - -# Set the date and time of now -NOW=`date +%Y-%m-%d.%H:%M:%S` - -# The absolute path to the folder whjch contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -############################################################# -# $DEBUG TRUE|FALSE -# Read debug logging configuration file -. $PATHDATA/../settings/debugLogging.conf - -# Read the args passed on by the command line -# see following file for details: -. $PATHDATA/inc.readArgsFromCommandLine.sh - -# path to audio folders -AUDIOFOLDERSPATH=`cat $PATHDATA/../settings/Audio_Folders_Path` - -if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo "## SCRIPT shuffle_play.sh ($NOW) ##" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo "VAR AUDIOFOLDERSPATH: $AUDIOFOLDERSPATH" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo "VAR COMMAND: $COMMAND" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo "VAR VALUE: $VALUE" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo "VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi - -# Get folder name of currently played audio by extracting the playlist name -# ONLY if none was passed on. The "pass on" is needed to save position -# when starting a new playlist while an old is playing. In this case -# mpc lsplaylists will get confused because it has more than one. -# check if $FOLDER is empty / unset -if [ -z "$FOLDER" ] -then - # this is old: FOLDER=$(mpc lsplaylists) - # actually, this should be the latest folder: - FOLDER=$(cat $PATHDATA/../settings/Latest_Folder_Played) -fi - -# Some error checking: if folder.conf does not exist, create default -if [ ! -e "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" ] -then - # now we create a default folder.conf file by calling this script - # with the command param createDefaultFolderConf - # (see script for details) - # the $FOLDER would not need to be passed on, because it is already set in this script - # see inc.writeFolderConfig.sh for details - if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo " - calling inc.writeFolderConfig.sh -c=createDefaultFolderConf -d=\$FOLDER" >> $PATHDATA/../logs/debug.log; fi - . $PATHDATA/inc.writeFolderConfig.sh -c=createDefaultFolderConf -d="$FOLDER" - if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo " - back from inc.writeFolderConfig.sh" >> $PATHDATA/../logs/debug.log; fi -fi -# Read the current config file (include will execute == read) -. "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" -if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo "# found content in folder.conf:" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then cat "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" >> $PATHDATA/../logs/debug.log; fi - -if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo " Now doing what COMMAND wants: $COMMAND" >> $PATHDATA/../logs/debug.log; fi - -case "$COMMAND" in - -shuffle_check) - #Check if SHUFFLE is switched on. As this is called for each playlist change, it will overwrite temporary shuffle mode - if [ $SHUFFLE == "ON" ]; - then - if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo " entering: shuffle_check with value $SHUFFLE" >> $PATHDATA/../logs/debug.log; fi - mpc shuffle - else - if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo " entering: shuffle_check with value $SHUFFLE" >> $PATHDATA/../logs/debug.log; fi - mpc random off - fi - ;; -enableshuffle) - if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo " entering: enableshuffle" >> $PATHDATA/../logs/debug.log; fi - # set the vars we need to change - SHUFFLE="ON" - # now calling a script which will only replace these new vars in folder.conf - # (see script for details) - . $PATHDATA/inc.writeFolderConfig.sh - ;; -disableshuffle) - if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo " entering: disableshuffle" >> $PATHDATA/../logs/debug.log; fi - # set the vars we need to change - SHUFFLE="OFF" - # now calling a script which will only replace these new vars in folder.conf - # (see script for details) - . $PATHDATA/inc.writeFolderConfig.sh - ;; - - -*) - echo "Command unknown" - ;; -esac - -if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then echo "# new content in folder.conf:" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_shuffle_play_sh}" == "TRUE" ]; then cat "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" >> $PATHDATA/../logs/debug.log; fi diff --git a/scripts/single_play.sh b/scripts/single_play.sh deleted file mode 100755 index be5cfbd67..000000000 --- a/scripts/single_play.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/bash - -# This script saves or restores the SINGLE status in a playlist (=folder) and enables/disables -# single mode according to the folder.conf of the current folder/playlist -# Usage: -# Enable single mode for folder: ./single_play-sh -c=enablesingle -v=foldername_in_audiofolders -# Disable single mode for folder: ./single_play-sh -c=disablesingle -v=foldername_in_audiofolders -# -# TODO: When to call this script? -# Call this script with "playlistaddplay" (playout_controls.sh) everytime - -# Set the date and time of now -NOW=`date +%Y-%m-%d.%H:%M:%S` - -# The absolute path to the folder whjch contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -############################################################# -# $DEBUG TRUE|FALSE -# Read debug logging configuration file -. $PATHDATA/../settings/debugLogging.conf - -# Get args from command line (see Usage above) -# see following file for details: -. $PATHDATA/inc.readArgsFromCommandLine.sh - -# path to audio folders -AUDIOFOLDERSPATH=`cat $PATHDATA/../settings/Audio_Folders_Path` - -if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo "## SCRIPT single_play.sh ($NOW) ##" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo "VAR AUDIOFOLDERSPATH: $AUDIOFOLDERSPATH" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo "VAR COMMAND: $COMMAND" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo "VAR VALUE: $VALUE" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo "VAR FOLDER: $FOLDER" >> $PATHDATA/../logs/debug.log; fi - -# Get folder name of currently played audio by extracting the playlist name -# ONLY if none was passed on. The "pass on" is needed to save position -# when starting a new playlist while an old is playing. In this case -# mpc lsplaylists will get confused because it has more than one. -# check if $FOLDER is empty / unset -if [ -z "$FOLDER" ] -then - # actually, this should be the latest folder: - FOLDER=$(cat $PATHDATA/../settings/Latest_Folder_Played) -fi - -# Some error checking: if folder.conf does not exist, create default -if [ ! -e "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" ] -then - # now we create a default folder.conf file by calling this script - # with the command param createDefaultFolderConf - # (see script for details) - # the $FOLDER would not need to be passed on, because it is already set in this script - # see inc.writeFolderConfig.sh for details - if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo " - calling inc.writeFolderConfig.sh -c=createDefaultFolderConf -d=\$FOLDER" >> $PATHDATA/../logs/debug.log; fi - . $PATHDATA/inc.writeFolderConfig.sh -c=createDefaultFolderConf -d="$FOLDER" - if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo " - back from inc.writeFolderConfig.sh" >> $PATHDATA/../logs/debug.log; fi -fi -# Read the current config file (include will execute == read) -. "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" -if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo " content of $AUDIOFOLDERSPATH/$FOLDER/folder.conf" >> $PATHDATA/../logs/debug.log; fi -if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then cat "$AUDIOFOLDERSPATH/$FOLDER/folder.conf" >> $PATHDATA/../logs/debug.log; fi - -if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo " Now doing what COMMAND wants: $COMMAND" >> $PATHDATA/../logs/debug.log; fi - -case "$COMMAND" in - -single_check) - #Check if SINGLE is switched on. As this is called for each playlist change, it will overwrite temporary shuffle mode - if [ $SINGLE == "ON" ] - then - if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo " entering: single_check with value $SINGLE" >> $PATHDATA/../logs/debug.log; fi - mpc single on - else - if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo " entering: single_check with value $SINGLE" >> $PATHDATA/../logs/debug.log; fi - mpc single off - fi - ;; -singleenable) - if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo " entering: singleenable" >> $PATHDATA/../logs/debug.log; fi - # set the vars we need to change - SINGLE="ON" - # now calling a script which will only replace these new vars in folder.conf - # (see script for details) - . $PATHDATA/inc.writeFolderConfig.sh - ;; -singledisable) - if [ "${DEBUG_single_play_sh}" == "TRUE" ]; then echo " entering: singledisable" >> $PATHDATA/../logs/debug.log; fi - # set the vars we need to change - SINGLE="OFF" - # now calling a script which will only replace these new vars in folder.conf - # (see script for details) - . $PATHDATA/inc.writeFolderConfig.sh - ;; - - -*) - echo "Command unknown" - ;; -esac diff --git a/scripts/startup-scripts.sh b/scripts/startup-scripts.sh deleted file mode 100755 index 6de44f52b..000000000 --- a/scripts/startup-scripts.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash - -start_time=`date +%s` - -# The absolute path to the folder whjch contains all the scripts. -# Unless you are working with symlinks, leave the following line untouched. -PATHDATA="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -########################################################### -# Read global configuration file (and create is not exists) -# create the global configuration file from single files - if it does not exist -if [ ! -f $PATHDATA/../settings/global.conf ]; then - . /home/pi/RPi-Jukebox-RFID/scripts/inc.writeGlobalConfig.sh -fi -. $PATHDATA/../settings/global.conf -########################################################### -echo "Phoniebox is starting...$(expr `date +%s` - $start_time) s" - -#cat $PATHDATA/../settings/version-number - -#cat $PATHDATA/../settings/global.conf - -#echo "${AUDIOVOLSTARTUP} is the mpd startup volume $(expr `date +%s` - $start_time) s" - -#################################### -# make playists, files and folders -# and shortcuts -# readable and writable to all -#sudo chmod -R 777 ${AUDIOFOLDERSPATH} -#sudo chmod -R 777 ${PLAYLISTSFOLDERPATH} -#sudo chmod -R 777 $PATHDATA/../shared/shortcuts - - -#echo "before mpd status $(expr `date +%s` - $start_time) s" - -######################################### -# wait until mopidy/MPD server is running -STATUS=0 -while [ "$STATUS" != "ACTIVE" ]; do STATUS=$(echo -e status\\nclose | nc -w 0 localhost 6600 | grep 'OK MPD'| sed 's/^.*$/ACTIVE/'); done - - -#echo "before playout $(expr `date +%s` - $start_time) s" - -#################################### -# check if and set volume on startup -#/home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh -c=setvolumetostartup - - -#echo "after vol $(expr `date +%s` - $start_time) s" - -#################### -# play startup sound -#mpgvolume=$((32768*${AUDIOVOLSTARTUP}/100)) -#echo "${mpgvolume} is the mpg123 startup volume" -#/usr/bin/mpg123 -f -${mpgvolume} /home/pi/RPi-Jukebox-RFID/shared/startupsound.mp3 - -####################### -# re-scan music library -#mpc rescan - -####################### -# read out wifi config? -#if [ "${READWLANIPYN}" == "ON" ]; then -# /home/pi/RPi-Jukebox-RFID/scripts/playout_controls.sh -c=readwifiipoverspeaker -#fi diff --git a/scripts/startup_sound.sh b/scripts/startup_sound.sh deleted file mode 100755 index 3ca5da787..000000000 --- a/scripts/startup_sound.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -#sleep 1.5 - -#################### -# play startup sound -mpgvolume=$((32768*50/100)) -echo "${mpgvolume} is the mpg123 startup volume" -/usr/bin/mpg123 -f -${mpgvolume} /home/pi/RPi-Jukebox-RFID/shared/startupsound.mp3 - -####################### diff --git a/scripts/test/mockedGPIO.py b/scripts/test/mockedGPIO.py deleted file mode 100644 index e4ff6a153..000000000 --- a/scripts/test/mockedGPIO.py +++ /dev/null @@ -1,17 +0,0 @@ -from mock import MagicMock, patch - -MockRPi = MagicMock() -modules = { - "RPi": MockRPi, - "RPi.GPIO": MockRPi.GPIO, -} - -MockRPi.GPIO.RISING = 31 -MockRPi.GPIO.FALLING = 32 -MockRPi.GPIO.BOTH = 33 -MockRPi.GPIO.HIGH = 1 -MockRPi.GPIO.LOW = 0 -patcher = patch.dict("sys.modules", modules) -patcher.start() -import RPi.GPIO -GPIO = RPi.GPIO diff --git a/scripts/test/test_TwoButtonControl.py b/scripts/test/test_TwoButtonControl.py deleted file mode 100644 index d59125cc6..000000000 --- a/scripts/test/test_TwoButtonControl.py +++ /dev/null @@ -1,157 +0,0 @@ -import mock -import pytest -from mock import MagicMock -from test.mockedGPIO import GPIO - - -import TwoButtonControl - - -@pytest.fixture -def btn1Mock(): - return mock.MagicMock() - - -@pytest.fixture -def btn2Mock(): - return mock.MagicMock() - - -@pytest.fixture -def functionCall1Mock(): - return mock.MagicMock() - - -@pytest.fixture -def functionCall2Mock(): - return mock.MagicMock() - - -@pytest.fixture -def functionCallBothPressedMock(): - return mock.MagicMock() - - -def test_functionCallTwoButtonsOnlyBtn1Pressed(btn1Mock, - btn2Mock, - functionCall1Mock, - functionCall2Mock, - functionCallBothPressedMock): - btn1Mock.is_pressed = True - btn2Mock.is_pressed = False - func = TwoButtonControl.functionCallTwoButtons(btn1Mock, - btn2Mock, - functionCall1Mock, - functionCall2Mock, - functionCallBothPressed=functionCallBothPressedMock) - func() - functionCall1Mock.assert_called_once_with() - functionCall2Mock.assert_not_called() - functionCallBothPressedMock.assert_not_called() - - -def test_functionCallTwoButtonsBothBtnsPressedFunctionCallBothPressedExists(btn1Mock, - btn2Mock, - functionCall1Mock, - functionCall2Mock, - functionCallBothPressedMock): - btn1Mock.is_pressed = True - btn2Mock.is_pressed = True - func = TwoButtonControl.functionCallTwoButtons(btn1Mock, btn2Mock, functionCall1Mock, functionCall2Mock, - functionCallBothPressed=functionCallBothPressedMock) - func() - functionCall1Mock.assert_not_called() - functionCall2Mock.assert_not_called() - functionCallBothPressedMock.assert_called_once_with() - - -def test_functionCallTwoButtonsBothBtnsPressedFunctionCallBothPressedIsNone(btn1Mock, - btn2Mock, - functionCall1Mock, - functionCall2Mock): - btn1Mock.is_pressed = True - btn2Mock.is_pressed = True - func = TwoButtonControl.functionCallTwoButtons(btn1Mock, btn2Mock, functionCall1Mock, functionCall2Mock, - functionCallBothPressed=None) - func() - functionCall1Mock.assert_not_called() - functionCall2Mock.assert_not_called() - - -mockedFunction1 = MagicMock() -mockedFunction2 = MagicMock() -mockedFunction3 = MagicMock() - - -@pytest.fixture -def two_button_control(): - mockedFunction1.reset_mock() - mockedFunction2.reset_mock() - mockedFunction3.reset_mock() - return TwoButtonControl.TwoButtonControl(bcmPin1=1, - bcmPin2=2, - functionCallBtn1=mockedFunction1, - functionCallBtn2=mockedFunction2, - functionCallTwoBtns=mockedFunction3, - pull_up=True, - hold_repeat=False, - hold_time=0.3, - name='TwoButtonControl') - - -class TestTwoButtonControl: - def test_init(self): - TwoButtonControl.TwoButtonControl(bcmPin1=1, - bcmPin2=2, - functionCallBtn1=mockedFunction1, - functionCallBtn2=mockedFunction2, - functionCallTwoBtns=mockedFunction3, - pull_up=True, - hold_repeat=False, - hold_time=0.3, - name='TwoButtonControl') - - def test_btn1_pressed(self, two_button_control): - pinA = two_button_control.bcmPin1 - pinB = two_button_control.bcmPin2 - - def func(pin): - values = {pinA: False, pinB: True} - if pin in values: - return values[pin] - else: - print('Cannot find pin {} in values: {}'.format(pin, values)) - return None - TwoButtonControl.GPIO.input.side_effect = func - two_button_control.action() - mockedFunction1.assert_called_once() - mockedFunction2.assert_not_called() - mockedFunction3.assert_not_called() - two_button_control.action() - assert mockedFunction1.call_count == 2 - - def test_btn2_pressed(self, two_button_control): - pinA = two_button_control.bcmPin1 - pinB = two_button_control.bcmPin2 - TwoButtonControl.GPIO.input.side_effect = lambda pin: {pinA: True, pinB: False}[pin] - two_button_control.action() - mockedFunction1.assert_not_called() - mockedFunction2.assert_called_once() - mockedFunction3.assert_not_called() - two_button_control.action() - assert mockedFunction2.call_count == 2 - - def test_btn1_and_btn2_pressed(self, two_button_control): - pinA = two_button_control.bcmPin1 - pinB = two_button_control.bcmPin2 - TwoButtonControl.GPIO.input.side_effect = lambda pin: {pinA: False, pinB: False}[pin] - two_button_control.action() - mockedFunction1.assert_not_called() - mockedFunction2.assert_not_called() - mockedFunction3.assert_called_once() - two_button_control.action() - assert mockedFunction3.call_count == 2 - - def test_repr(self, two_button_control): - expected = "
tPa(b%B=LqAPdvm!SOoo{JcbO1W1$akPI#+m>z4c4UXLi`koOgzdte z< KgU1}LEj+5;CG-(?wp1Q ztGO!-PtAy$NFvfK{3UcV#D#W+w?w{?GpKgVC~l8HO9R0(aHX;eyGqoSyTfYQzqNa{ z4Yad0{nU1%Cf*d)A^(9hffTWXd&yK%ZK94yQMgw4edu$jdbl`T63L04pt>?zu8hAc zZU*{*5ojjzkMae&8%xFK;7jq5IDoIhzM}>-OIaO>hjkFIAmxc)LaHT>7S8YpzmNmD z)3V0ZScD~+0K+q}Y*%(0OR{4*54VJ`CfJ2L;vwm8V5edmcmVnfUWJTPHb&j(0xS>H z;xPUa>xmsh-zo1S>txURORk}E#Q*VESsk;3Y7xyMTShL0Cxn-UUEy<)CuBPHnm)pw z;9rVLMO!&am!KnXn&__XpmAtwXbsw}n#=0xa>Sc4o6-+mRV S5E-9kSP- zh4(>Qz-5ZXz*^~`_+F4%N I(E>_+xCwk{jb>e*Db0Xt0AzL;$xSN3iBAb(9* zC(e?_0h1I FDpkPelO4U=3nWGRpVpaty}D;Opc)PLS)z zedr2hQ{*;e0eb+8#r^y})=PJ!e#+Lm6Sjpvg*>5Q;p9kb@>+B$J)hmje-pD6v!D~m zC3G|1Om#wiQqxd7R2!q6ubHWiQ!U5OqN@-EB+qLLd)Z&;4$;y`Lga1uVK_f*itLT7 zCyS%2>9K4V-YBk-P5|2!8)UnjfR`h&%E8LcN*D4wf*~H5hgC=!yc|}*vmplD4=w`N zf*Zij;Bm!EAWxFS#^O?;m~YN6;1;n%nbGtU>M-S^Zqa7e!0#0|C<@@wm`CN+Dhwrt z6$Y#RlI8&M3wjq?2n-cwvxStOd>=U!X-EDWt)!=Ous9r;4UU2nlnc;)*dJI0I#>BC z+*}b7&a!){myw)Mxj)gzc#e3gdrN#*gNw oUHBtv-@pRRH zsytPqYBugt-i2a-9{f(aJ-Hz?HBjXH>Rsc_^u6#;3z1|CRumob++?}>kv`K5*u)q( zE
F)aer{OzvM5qgO!FaXN zP}`hiWvtJvk1UMoPs0T57otRY9b6|~VE?45lb6HJ(92NUaL33e@;%jzRSA@I0W5>Z zDtn;^(c$PR<#faYRVo%qXZepzbE=VCNjC}i2&*E)$xLb-Q;Xjq^@Qr8`Gi4xLOux$GrR8O Cyold8UzaOHP-H-B?I@_r6(kACA?Dpo2x zsiy008%>tc*0 iJ_)O C|8@V-z{C(ANurN(1EgXQ zQy#)D5DnBi&9CxVQ$no8RwEeLUfe4qkmDmrC@m26?eZn~R|WDzXp~~wiB~{DX;6LD zrWhZa4_G(Y7Ta1_%S=o3lhs8i0U1OS(?8 >%cvNqUM+$Z I5#8k(9w`75WM7h4xf>VF N#2Ugj1)(nlC7v#Oc6(lV?d`oO)^VH zblrNb@lRtXV?V=golf%!7m!bisX~3GJy{uy@mG3AxDUGSxn8;NcoznI;hz-E8GsP9 z1^r2!)>P?681%+s!z;Pxn55o}uTxHi#sFi5+w2JX@8~GfEuUoFqb1Z=Ccrfm=K$xy zbMP4D74&y(9`+a=DEE3f;AP1y%wt9BD)}_rN$zu(1;>U`A{(PC7(c%km $;zVWuMnR+mm4dXx(f1Z9rt_ha~qk-3f`N43g78#*3WHjZ1 zVlSM8*25nWcT}WY5vLI`*d(MY7#6Q^2W9+qTljf!dmuZoJn$;$30Fp!vh&0};Bn=8 zIhJY}j>=On&8#Wba`QRkdfhYC8k7S&iw77h83?rV4t0%jEVtja3yyTR$#*<>nY6Lj z#o }@Oev#A@=C-JIY$Cikp3SxTs)#sBO|a$ zs<6hXYhoxeyf;9G$vU$}Ps~&<1pA5|*cH+2aPNS|x6pIaeb&9n)6-WRFhy=r>$u;g z4Cs!s3cso@(@xT78k7c`{(su~>K*t?5CgW+6qE!BgaBTo_ahrh{F zeuL$l5;Vq{dz;UjQjGaJyLvkQC(=goAK#x&j|>WQ_bS{MWM=-h6L%+iL;hLe6_l4- z4g_HnenP!QciDiNj+!QzMj5y2VXc=Kh#rQDWel( Am706p`!ecFIP|XUGe98gyRquXICr!)39hG)|wQZc&}-(G0+ug>6y~ zus#w+7ZRJ)>Dp>Co;yjmSF6#K6Bg_>{EK3m@SYhN?Hj%r*z3#iPW3GC4Dq7=S;0Ax z5^4>XD;0sgm2+iQeufs;m*~CvCi>6Xu= %pL|HxH2-yWbawv<-^ zJ)zyo8~8@GsCDaqk#V;H#w @!j^x4MN}t9v({;~D%lQ-YUhq3Y zhoe_mM(hNQN3&G}v<3Rz# 7U)w~R==r3>gmOmFs 0QxKI22tiL&KC3LDwU)cHuK(D*=%f2?n^ubO{f;AW^l zIfy>MF=B6UIWh|aRLPos+6B5@I$W2p$yOVP3uqRy79^#`LKkj2lR&qkglJ9bCsiqT zs}H%60wJ9NV!@UW0QZ73;BC-0aEPK(8Yw>GTX4^qee^wQ6t$G9Lyu&1T#~R*Lc#0s z2sDhhR@c&Q)OFT()9=*P)7Dd;!>=m`LXRYo>rMX``6pPz-$S0u_~LHwnd%+luLx?$ zBlKVVHedtX1Y00ac(l+TGxRmKHqJ8ybuTnJRY2y>Iw?$I3b&b_9xaPF!`s7U;ct z(T?;wwv6vAV<4NLcF2C^ALtMC5c*lU3i%hhE_-PcLCwX>Hpq=GB72fg$^7Vc`Yk(M z=mYeJx+^pA>#CsUl SSsi97OgZHQ#c6W1+@U-wf z415X?rJ8U(rAg3lsE=SZqxCvt)R<&iX>4QYtNW?;;AfTHA&>No4>Q}S2jtAi&G6 }vkBcp4Z2{sTRO2P4~%{>XXw95euY1Jsoc2#t9w*N%P5++~dHH&)M| zkxz&Zig>t}atLN6{!mSjxutt*wfePusvT06L*>9@;WGP#iX-zvaPWyg)}Q7t^7jr7 z4m-&=w4ck8hJaI%R@g1#A9W2apsTLCu05woSN}=~=oUl`EdwlKK8LW|>8n&*>Nn~e zb(((9#BuxhRPm?;DH1_HI1CyO>7ilZG(|f=6b}fkc$RfBS cfnUUy{4BPTzD_x#=b~&hpX$N<$}JJB zz$0+AjJ^Fu996f{cGI2L_0_e|E>mX{{m>lvGLS87WU`}JcwAt#5A&|_-10o~&hdW? z{u{B-Pq=;3EGQM7L3Gy4)!~Nk2FN%=u9~N7t?KT0Go}0wF6k3roh_z}(Kqtch&|jR zl1uK2j->msbNFTABsrRvLL1=@$XaA3k`G6rt6+P@J*kCQ%s=Le*fDG)b|IU|)t4 w*5k +l(99pp7Q8Aun+e1DdvHS~V!Z;GYP z(ia#9+l_xCw33bhj}(W%bf_Z~2kikrDhhzB(ju{yVCECJAuKPWCKF`DU^4F#u1bd$ zccE`Ge{mOYqWVp3R|nNo)csYD@e49?KM9;Fb>>?z{iE-~SAsPH4g7vz8-IsDNzf8` z5-not3x@z6ibvft^OK^Tq|@ki`pLR9ZEv-L7>%xnPb)r&wfXnVTdHNW7I`i5Ix fDq>c0n`IQD zId}s$qFwO1s_W`Ynj~$p2GT53O~buP6t)BVg&u4cl^b~;{OaH2 tXJ7r}3r4qtF64hibwuL6F{zV-mM&Ps1q4G4>M_`w@o&O>;{nO||>LwMSR?E{o z>)3Z(E8(!nN@)r;cmsqX1M~sx2JTiI1rABe#A(73{ubAcOXT`;72G{OB=nJ3;41hh z+*VnP=Hjho W@`+ZPc_4Ed?U-D48`nu_EcH_? zli86g=q%h${8aT-H&(Avbtg7q6O@%unxci+iJMF3k=tdiW=jAFpn;nKA^0g=Jz7Nv zxEeB}xCNPpc?eOq{TSU@-B8_JEu=B19%8Y|KF|u_wa|-8W_nUVQcqrre2@G=Zi %X z#^Oz&DYOT H45SPN@OnW*YTfPSkG9jiK zH=F-1)Rraya}+JX=O7A+;61P=IA5^^*e4y4c|w|>!dK_(@QY;@loAr8X@FO;0K$;@ zGV**G8-Q=ZN8zurf6?ERo8Tp21K^b~OqMbdtu1$i-$Fw|vqQxHadZ{XRpmf5$+It2 z+}+*X9g4fVJH_2u+}(>qDNvwDad-E!Nb$w0U!Em<;q>foVcYz?%*-9Tlb2Eqe8Jbg zW=67gM$BPFl^xnS=Op);fXRW;fgQjP3UXI-=GCst9obv)kKNgvq$l}ad8>M}ct?3F z`nvh==@ZRLwkFPzHtdiTE%#O;fTBbxCOf4VT8CWXP0`7IXQVau>f3c{+%vr9XgpO0 znnrRXZ<+0Q<2>W4;Lh(};hO98Xd&uFsTN(pADSif^WHtFdh-3G%1PyuZYCupuTQ<` zt*5880!3OzlvpjT%NZ~sut(6bppikF0&541aMf^JQwmFSiEeK<=jqRV)4kE2W}bl_ z;qiG}`oHP>%*l3BVUaoPj&u={->S@1xLidpED;t>hM*ds-ENFt#4vM)nPkRV_v{>E zJt@deNJVj~^Rxzz-Hy$Utd45hCnZd7&*~8;e`&_*cYMWAAq+{4L4EKaR1d16D%#Dw zXxAaJEQeA}OXHk@IDzA9k^7*ltMi%`r#zPS(^X=<{mATWl+uU$6~FMc@$3FydU~^u zb=l4&+LFGs0(-==NyVfDHi})N@g!AvcmObezZGUxvj$rU)=~RB7osoy%KFO>lr);= zxPXc{b1ru5)B3BIB~c`IQ^DS@~%x?lM<2=n6e~gRceUWM1AYD)lS%SzWh^_ zofmMTj{`CU-VPv$5}Z!Ac26G7GLn1tG4qq&&)>y&(YxOJ%e&oo3VwdC*~QKvu97ge zMp`MCQpPGxmB+FnePC;75faTC*`}F ~EN9O!!Q zdf{pU=Ep7VhjK(JM>lcs-t|zQ!!s(SRr2Meb4jg}!+}oaeMj_RR!32lg(zFK_s(dy zGw?}ZaL~!XX8~i~yPeau?8+vVnH;evm LhJl9gEr$(i=_YCrW#y+o_+-^s ^$Nqp^a4LODiaHOuLlz#JB`*&jJ57f2x0}J_6m{XzRCKKr|$^C}T??`xmGh z=VDW76nP+i@r>ve#ao-K1=bC#t}Sy(lt35s9jhwOQnsrzwJeUVj@pikK&E|4Ub!V} zL#pxoRz9PR|B`os=V)q+)LyASQWHI$e1#EpO}FDjB{oZ5uJ(02b$)bBa<6q)aSw2n z1P|w~a!)!zw}FN8z-(lwdRb%@$9 t|K%2#wNCZ;S&P2*Mk4UM~2e~|{cR+8#*>~_6#?+Ex1uqEKFdz;JU zOsl2H`@rY<6FJp0uKV} F6&uR|V=xlp7j}X65S6L}NmA@)i)sEU~ZM^1JbEqD9vh;-dMJO+b z811;f33_1*Jxx8sk!N#n7r$bBNBmQSbcQ9?SL3z(&H&dU*A`b(*DB{fj)K}6<$=Ul zQ8JeQYt1$X8XNQ+dXhh*J`bGTjAk~gg58RDht+4N=V?CHhBaeuwuh#nqsV2EN&Ex& zxMD}x=j~v=nRfxluQeURR!9-@YNfgQQVrIqwn2?oUdi($lhz{Pd;{W%()vx`Zt!JC z;OmX&koTuATn{sw*(1aT8YS&ex}ZZF=bY`j;#%SIJAID*TCiGQ?#qUf_58lo!c>hc z`aCeN#`}NyPwTNps#(L{!&4y3`Yg9}LSpD`oRW%4{o$7ek#?d!PV*lt)!dISpSjWs zx0myO(HFbPs>@rIyXqyamt((UsUyHq6c*n>p35ea&b*A3-Kgka?yckL3{LmwlwPo< zGv1m04aRq?r--9< SM)coo|rI(yVT1UO;TFtWJjqb?FbNZ%vt9ZM6 p7Eos^tK>eChxQ@IxMX)RU+c5|<9x@wO}urzTfJRTGmO{&F$dW_;43;y zrO-hv>?r8G=TuxToQ<6w9l5n_iY^sry~$Q?S&PkH##CJg^XR+3yPg&LS=E|l-{)yb zO|Z;d(kdxVdM2%u0;E>RL5Gq)qB9?2M_7T@DfFwqn1iiKc2z!6+$XizZb`@m)lAwI zEsZ0@5utrj&nX?{?d%%4%CA}v42M1jm4Mcs_|zw P#hv3 zXc9Xu)sn}_LlNKoBVA?h=~wbo=sYi(+K zdRZx`RFTu8qKX-AZdzjy!M^f;@ip>EzO>+=w)T(IpBba9$~>6-hBdWOj;JrR&5kV2 z!r*u`2ivZ)`b2IiouPTjc3#bvEtlECh|>>)!&bn!Zp<-9Sp)4syr-x^B)WlWtQxD! zGP3Km75amv5#eVLdw4ruoR{JK!RzfNvXCF-35{hNrJk~+j8l#%k?>@XWg(@ogJ6$c z;q{?ky%A@Z_RsX?@@4Z4_vHdxa=2lb2kdF0CCv-oKnr!gHqDXQ+0j|mdDfALuK8%? zn^c)CBd>WoJITCnB dm=w5Zj)>1z88?DLhk(~!Fsc;G?v^K z@43cXp_@C->SirL8oC#(w6)?Ikyu@6xI9^Dq5e?IYbCVjz|fq)z$R=Zxy@6oim0TQ z@rU}Fc;9*c_0;w{eHHvi^)b-ViDCuaB+WpUz1*?gS aiL8WBhr*1ukojwI139#VBwj*0L_rJ0N}@`J*&My2S{~gLt&3*up*b zG`osj*6wdVvM2Bwq6{fPE3y(&uzXc+q%6Q!btO`MDP3oCX;!j>XR)KqR*2CW`y+k* ze4~ADkh@0f4tTZZJQMkbT5&~Xt$IS6 v5 z*XX_V$@&X@lu_9%VwHe>)Dh*0o1Vd^FNB|8!0NE4v^_n8d(<|FY`Cv&2A{~6@prt9 zNDzC-Xjoo|bQ!Gf+mODhoRjOylcd?KBbX!ycwPIudB9kw$M|#jZ~AWgvimRlPoOv7 z9sci-7)mosN5IIbsbxd<^3HJ)e1Y*=4>cWfS0@`q-t*yhE-T2aY#apJY=Zts?+;#a z8LOc^gf9f=WHxQYp0kotQ>mo%hIL|x=ns;KG!YB=Cws7+&DQMV_5wQ(|H5C2cf_PF zDUJL?-l?Qj!_*4uOQp2ZP|hx0r40}lX0w-@`Hb)WZ@wzN7x2`jd|!Mi{xIX6x!azJ zoz{{hWuE$6djJmWapwkSMrT8Cxz2#gHIzk>L>^|pG?yEj^)LPf{;B?0e^VW!EM^I- zpS_bm6)EHkIKcI#UD8GApwvnF#Okrt^c8MVn<$d_Ox}o>;!XJ)u8IvJ45xpOE@!1B zbe`oJa(Vd&bmcg^1HE1<+VFJtFEh@t!N~gTKMw|Kb3G6oywcWU+X*g8cD6+NC~MH} zmD(pQQQNC!)#|7f6|b}%anN0`cuU&w>gFb+1egt_jAceH^M!fR+F`HabHP>4LL+H5 z)`1O0Mjyl?X&HJLcjE06WyD8*fbZZJ5Z{d!LhL2o!Sj2-#!H6OSzaJdLdJ4jqEaYh z^uAcY8vt288u8$aE%G<_xA!0Qchu_}W6eiaH||IEy@GU9rfO#GGcwnej((2cT5c_q z`bh34y`+uE$-i;>4 %{68Uz+YFUbBi z?f|SMmh)8mAG?`d%N_$>+F)K-5Te5#;t@5El?}P2(p@Q`90NKDc-*-po7iJlvA!B- zQAN+{Kkqy2vwU0q%kYHS4Lp4%L7R(9r^Fd#%3X4e&`q)O0~RqILs6v w*^9!poH=~6mrGJ8og(*ER-$RajD z^0|2--h-dz^>8EKIub?|whwl{7B+QHT7oQV9=k|yldIrjuCW(b>&)v$A@I-FA%6)l z_9Hs~$2tSa4<=W!)7o+iC69Ve&7kGceyO9>6Uqbmm^71BroTlLpKZ^y_L&-FA8yP9 zXSJD0tZUXD@OVauIz*#eX+~Jl1lEt0VR3XI{YH9{H)4bc7BBfZev@0gHSR#{3cs+Q zwqf6J{x?zYSAa^RVSnjZL7I{H_#Hda+F(W*zx6)A>&!syulh;joM~F^`8`pOo@Qy_ z&BD}l+7j(ND)42sIqFJfBv|I>;Vr)4Df^+uwGF(xXZkBWi?P*cWtOwb+4Xs6a17hi zV(b>Hflr(y)tA1o?vT8W8w &B13kz-K<~4+g()kr83~tpQ-n&7zVtT0Q{Q{shgd6?8Zq zJG7swSGgt+l)Q92vG{ts0V+t~)PfOO5;*!mpJ=qh)WaluH@_|7$TL(%8^GS*L-uQ> zg3=b2O6$-$ ;o$=b(7jjnWZQe%39OWWCm(# z^Xw(4sR>kk3jnjrV7{cd=`~ZVVBQEe{{nT3^2l{9WtkeUCaP!Drs`Vdl)M96&a#LQ z&+zT`PV1pr$-HYEG-3>H3^Se9B_Ku*UPdG%zAQzz)BmW8IoKPzhqk2#*@#;nzv1@E zsUloV!>yO!pdm*wvv-7+U>ljvDoCBBHc~$6CgOv|^dz}0Zu6V=IaH_;jGD+GC+g!6 zQ Y3V1o1^vBgxWzJ3f5(IWH94NPVw2kVm$`$Y!z~} zrp6+}XKXRMTeWQT@q|p`$V!?6T&0ujD%--^u`je2y#vW_6ro}VZ^ertBI(Ib^Rl?H zatb0sg38n%Z(B_sEDw}RAg^{yWmpj!L|*WX_5et}EATq69`FC@udF}O52LQ>vWFuh zZ%;2H+HR;+R{d%?5OlRxPFt+*P?pGTC57#ThtciZ)-BUAh8n?!j!1Np5egJNWgV~& zB2!z63AZfRV+zZJe#kR6n+38d^doM}j1@J-7rvh_=W8MN++scMH@yKQO`((7S9r4a zQgg{69bjo#ce)Vwqn_ZW?5CDxHZac`gN!;jm%T >t{i zhMuH%$xRW<_u0FxGiEY)ojPRx zMXzSuHP)C5tw=kb7b4*_l0BC0AS
+fdv+9=PbKX1yT#3t=0R{` z>lnQ--PzvEfQnbV{hZ$vQK)?6W&2qY%ZIA?7o1T>HXppwKIFCN1DA7=Z{+* gRG~J-3drO5V1rKDF88SJLS5PsN6z5 z&XQ}&gQan72)cv~M0Y;UK7?IHVvlpoHRf2egBfmqHlJ8Uz$u@LPp-_;NeR+U)JRIo z?SS3;=v%Ng-}Alp6Ke(LN~_y1?Z*5E|0P<`&8YW=$)n{_K>7)Cg2cd)C`EqqK;GEy zW(|W^8VE${Y=!X|grd^G96vC7T*+0&(O9v-` r>^8xIhuitxpfBfV8?`z3NeMRkfw#)G(a9`-rwAs?VNmDgs zWq?N;!IoMjd}ovQCp7ro_V?z5>dCFVeauv{MD5~^3n~^`C(ZXz9vl-8>X^+EtzW)H zDVY+#{`&H>+piS~HE~ndAS)joq{z->_w7JWU}Qik*G2UgtBYHdruq%k&SFxFdsTg@ z)s8d 5{XP&yrClfnj?&eL(9A9;7C0(UHan%S~7P2<9dFamIdI5*E zHLQ)@-5-=1nV98w;?Ft1_9rMQ-F!}T LGepM`$O315;DJj9$x zWHr#864X3&c$%td=7-D(?BFaVZ{rKVv+yN7Ovs;bDB&V*$|`0w71QK~&Juw+LKI9x zk (6d`n8b`6&HTYAmL4U;O;}v+i$_^egq0 zUPC0v|2aPfJ`Ne1W>K19q4$HXx$Z0bNF;9Ii%hAR^e#apyuuAs+4OhzG3L~My7C9* z4A~rVD!5_bMrRu(j+C@we2FQ}qz(y<6OQ4|iI(0P#z4N9tpoe&oqKaYxqwLAfiPOh z%m#6<(E$@9>AkPLQ~i&OU-n))TH%f#?&!dDL1P1Nxqmu}D5uFiGs*io`CEeZtMjis zzq2HE1eZ^<%d$*bBlqZ_VIeKhksK2g?7pLhvfg$hJ;sxoJThre(z)c3p8EO>`wOkD zHgbTpv6%WNUDnz)Y?HbsUYc3i{2I^NIHFUB5Ra+)omzSN#F@9{OGB?0n*O1o{J> zxIa4sv<1>5(cWsVck|8n9`?riUg+n+oD$M*ZJujDK Oua%l9 zDPKZ+%&5&wJeHE+J7?XZ3)R)G*MY@CvWCtNSrgRCom*SR0{L$Jq33mS?xYimDM^!4 zy}kfz9mx!4V`9M6-~}NCLc)V~x<6}sB`WG0hG%bbc;d1IJ7GbRp3>IW(Of3h;ij&I znD^@C{_5)E4AMg6t7N+U#vr=i_sSRLA7XfMN7zM4M!)Hl`((h;fCKLF&LV0M+W~e@ zHIJ5jG-1&1fxllRtV! tIv*@pUlYG=aOSdrlyqJAeUOV!-w+0jr+#2xQMI0^V zoaCkX+}AR7TGFwEYzglZ5|i?ILiIlO%Re_~IzI>CK9%6`pfLd}oEEsPK0Cc}!#gpx zUCPju{i#2^srq(1k{(xTIUNBpft7+52flIVb#725($aPg{g9_v%KoHsNgtB7q%`-Q z(^uH7=^1&3w$d5pig!6&RUJ{v8Fo>4Q1>KydVdyFKhl^-?X%>8v{!YY$9&wq+#QA> z^SNAtcC_c|q23CxkD-bGCaz5m^W678w=&aON{}-!zzW 50DJty?OG( Eir!F4JI}gX1fC1b9oWx(A2q z2w1pLV7T4)eDggu8uLUtP?_ks<7yIcJ|IItZ&!@gUEWLHTW$4v-sF@8$<>pkl&7iT zz70kopF)qwJ+dq0eqIR z+}GWcH#H&UW9nmXw4TAfMmo#eF#DYa43fxzdTyWNv(k^9 l4wBW5&?kD0l-9}HlB}dADf>L<{nM>c`1Ge*glkj4>cDB3Mk !_^s5P4dIKq-XIJ@Z?P8DR)!*c#rxg znydLvI#NEUmUE<_UKi|`sZNw#Y`th}&qfvbhHmPgjEUB2PU#fsoU%YW?I`4YfDYw; zbkkhqt@T_l>dWD|mC_qCPoq3{e2 oAEq&254WbVuGqTk^VQg#Wnr zh-aH;nYWGqo^jqzCPm}`t*`UDYZj&!-(W^Lt@4$w D^gFIrgYZ!qc@VqDYU}sMrkJ* zY_~Kf_)2; +7pKtsqg7WmDE^J)Lb`eO)V^-?i1sDYi|_x31_5e8SVjGsx4|o6A4eC~Z5) zd6rIzR}HO= Ctam}`gp~FvrBf3;gZ<&=173-Z!@W{ KqnLnn;HPRk@@cJ<->fjHV)roa z`<{8WrZ!LYqz>>N_75{7_ Z)@b>0FOoCtbIlX~5_pQf9EY9va{LhkUhsTYR_tn+(%h zE9#@0d>QtU0Q=BU%g!q=r}udw>#F|Vx5k^n+tC~D%cBp*B=RDnN+p$Nxc4fpV;iQT zp3Aq`2GW}kM>j7)kJfYH-5GDJ_dGl8AoWnt?$+u#9%vEjLp;xOk-;8il=jc^&i8cj zBtu3W^dII8evZzOU#MFgTj4>%oTkRq)lwn} h%?H$%o&AyI%H)n)5sFLhq*^z -u*yAD=`HuywMjd{nb)*VSjr2>B4ZMB;b>`?*PQrY`fB z*}%5=dvcZylus+O)a&4`byjXk*XTS^&ep&~x`Te-C+`$rtbeI--Kr{1Q77u@ &&pcsY5$|a{q;y^FsdWYiw!5-O>PHoE#KL@| ze~&MtuPQ3wz4U5eMBNeDSU&l-@>S6ieuP@<$eG+C73=d5TmzggHkY2L8P@^@kx zEsW}VALXX9Q~4q9lO*OQw#|VI|N6P_9(rg^^!H%V=My98VQD28K`B~Eu)reG>q#el zBYVKb`)tJMne?Kl`Q|a-TfcZ7^jvZ&3)P{h5m(akt1IP&tSL#dubZFsss1CriM}MC z>0e}wx7P79;1~9gahDjXORAa$CsmoPAsTe_6xe9FtYxUlp5>Lvby@@aYyn>7H06>! zLwZg>iD&i;(`D@PpZ1OL-SOS LH zK>fCU+o*22cqnnRPf};4lX^*AuHH~a%ct2fvWc&?UKrE#NdExzymss9%*WOvexF3K zTJm5egIY;_sC<>TNx|UP-b2T~gLTeaZ`$T_D;-}hO3{-nhn!Q1Ma86v(m=k?2z3ev z?g-hfulC#Eyd3p^)mNG;?Mot=dQr)Eu8!6wpo@K1sV5I(lgM2D%o=H~F{+?8S<{?l z<>Cq8htI+UNeVQ-n|e}NB!9=MzfsT1ZtlfCYx@WK3*go&&H8C4g5R)7N|8S+wbk5e zxY8Ru#NqV0=)sGFh3GSbt*zD?`x$0^V!^H~B*)3wlsGx3oPeK-6ff-z)=DE>f8dYt zm(`0I2h4DLf|x@`NFhoC)q}3j9yL;_4gTL2as++-mF8xnm{HG2F;EAx$BM4B0PfCs zgMQmCwWL}U6SUvx5AoHOtPw_aeZ7CW-|(CIATy6Gi4SBW?h*@Dwm|dBD{XO0(M8%2 z{kUtkVJ){dqLco^PAB@3+t_Dr`Kg> QpOzqx!34`^WyZ4?L}fG--1I1Wu&7DXL7Ks83Q(kuwiB#-x7-Td z^4<9SX!9y++8vE} e#!{o2+0u%! z8;c||oxPV5 aMK(-2Ev=E9QV!-N+eHU- cn2FlLYSAxZJ)dPC#guhfYra((9gap~I9Wu)Syri!)JVF 9*&!5 zg3<3Cj{74QTA}D=@1le8 9JU~uhamw;h*##nJ22? ;`QtG=aLrL1T?`4qkk{h}4LE<21)%rJI=#)0ualQ*<0TYXTye-6HbY38(7@Z#h( zoglrHy~-Z-wYo|Dpj^k~QY@87f1ZjyPg*n9_}A!yPU%qGA(02Yj47-ZI=XwM>e380 zn3g3k`8sgPcbcWm5OcVh+bRnlT!I)vFR?^0Mw%*vl&s1ac?#G*f%G2wqgU*l_P^Fg zs~K(`yUWj@8b1@&_{nT0E5K&bMP!61$GP d>`9;irJhMd6j};by1Dm|rO(+K^tfD2rtG*(T; u&V)R(`T zPjM5@aceU^Jv|uGhuK4E9gwlKk|Z}nXS+7;6S^+8^F!#CL|R8I#ohr9%K+S=&KjgXg+{GdgA5#Qa2htBxJbYlAz~4Z5^bsiO8)v!I944;-*4S{hov z(LQLUxBkWbqBC$SM|H3>I+7Ns?N4J{@wT-uG(F7(9ErDIT4}+f>TPZU+asf0hpz_< zu{Un7STEOrh7MFxfZ~~?c)EoQ7VY>9+iRV-;&6-KfAF6>#WYff-l6Hi47fn^(GK9& zH3!FIAa2I$2MJxqdCs>Vz$?ViJW?lg(7wRa#VhrdCUOukv^crL7uqYW|IF>?Iq*3A zmd_3mm2g{9PIiJ3={N2nct(HW7J@T8(mrqDEX^3xZC$Vq*>8AuXvjujXearcd|#dq zRzwCVkR_9U!A!`-w}Ck`5!{*1JgayuBJu2ZaHgqr8+t{>NKx?T17Vw^A$w}Jz$sC? zCBGp$(ig0Z+*om`!w_M8Rf3c+(lVBT9u%E;4SR%@jILe?yhvBO5qL3p10LN?RdnZG z)6R4sI#54(I ><5Oj)6O)+hgrg zc2#@6otEF@Tf|6Gj$VO|RzT-<5q(Pj6QB8O`v)SHZIID)^mt>z9SXv2TF+=csXF}J zD#R|~%0v0Lbek;!Qz8VqSHV7E&9nAHo@eYO(5Hrk(N**l{e^CAF*=E?7l-&&+XE&P z2mi5}^~gG6U*a}qH7CI*^pTU~Tnba>$@is4>@03Rnk|;`S9WK+gk8tpVi)Cap(QOz zJh%yyXv?)2xEF$_3}*6WNES@5RDc5;{tY(aVj*PGx&85T~ QKwWB`;1res{!g#AakTNfQ8T)OfQWAGS`6&TB5r&5;uC~ z5vk%ZsYqvF-45UwwEz$2E_dPQ6xh>GFwy?p{&Y~B2Nx}tO_khoOSvf+CIh7%U?)VA zv*I}~jDFP!dz^h4w)ur`z $jY!}%?pOI`4zsG-4S2Y? zL 1xTEU>Y-x_%OHRe~RydnP=aJRoCNF?}Y_^Z#Cui_X zcvEC^bboWx+OYRWct_?I5r@z1h)#c3c&~xhTWgcOkVlGFB$ySJ(#w|-wH8w1<$CfE zsUs^yQ^Y;~#14Vgce5s TOf!K~dXg4`q$0#a?m+yIWSvESI @ znro$CqHhtf;SBi~Ec#PYTQFBnfGzq MZwt32h`mQhEqnnlD)*v25!z+ychHY zDM$y=a7gL}-qN{V{L701Z8M-t`os#cSE1vdUt}T~fL|}!Wa* e;^a*ryI2cCtq4_t# zd7f$Kw^Omt?sgK`Gqc1H(uNiQyDv;y3KmpL@D1v+RrCf4B;CauK8<(f-T4NbXMZqL zx{xcxBxz_e-i2Bea(uxv@j-T+H44_$5q`F@ot@_pRnSWgXMLms@*eq(d{gc(U%;v# z=`(Tz*39jm;0yk?(tTIc_^bOp(&GaGm*-TvEO?U>#wh~{$WpF7n;f<*&q!2Al1L;A$)pnkE z4EEO)Te71tKXDm+? 1Q)YN0?Ch6WpMS1kd@*quft>PFgp#T-_pKr4+E1p9|@!$a1h%|$E8oOriqB! z>%ivsgW**Q_dZp}1dp3n;VZb#C*WPS&B+Q9Lk^H|ut8P|MGQvlFv8AfyTD4AXJ_TF z`6UqpcGU{jM*1vOl IJ+e7Vob_;uh9SRJeiTJ80{f)beTv9!$gH!+vqZ(`@{qpzcGm0a8 zHXjWZ#lO6Q*a;qDH?oREldX7 +Ozq8^kTo!MIK*ev2z)4;{v`fXn<+dh<6D-ooM`*HWY#_ R3Lzs6nL8TmN)*j+fGOknp6V6RzG zsSda>?+_0@qs3wKPegV2hmpJ V>gQu2YpF%eE z40l-XgFkkWf5{HogBh5#*^7vMjHF7#STyDroTQ?d$9?unoaJD9JEno=;kk|g^9~V} zmW14$$ZMKmf}kmEu0QNF1-Mv}FXbU(zi2@W#7 Z!82f&=W)+u4>F(ZA`3|uc!PCdCa=QzL?gaxZx6F$?85vmIKn+iB{0~}utw5u z>ArMI8X^4zj*O?fz*lpCd-59iISl%I1=hTmSA^tC6Y#*v2Xcq3CAGlX87@>rPosEy z@b$KU0XbG^WIL&hnTS$s2Kdpdz?d}XG$2`X5-kdeSe$2b-Wu9+0}@&b-r7K*=v(rc zT*H2IlOv)4Jbh^}6?a49FF@y)fP?o 5qSkBVJw%oj--$5!_rCW8X*AGKO=$TXZMs=>ysyth&ll z7paNllGY%%YEQQ#YOD^vU^VFU3&f3?AlFB{I`~eZ(E8 HT&tqP9h0C ovg|ryjs3u#sltY|TY`aEfw#qpr9wk*A#$2dP9b`F zjCYHNLz0(7Z}^eZd=YeR7DwHW_r=q62d}doJxqNxGs}+p%q7~Lnq)5a5h*%|wBWIQ z!%yag&2NT=W+b&qYgk%IypR2;=!_?i;zQwIi}UiZy9;0dUKG6`qZN4aN$fm(#cr~t ztSF-J^r&UL0Q>S9xYjw~lLMduv-nG#)=qfPM!?Z!u%w}QcY7) HSzxU+hPW+*y0a?idS(;#emi(GD;8WNAKb^YqM6Y93;P! zR;1_g8#i#C468;UZaU200GB)AOkdz#@wtGo!C?JGi6OA2PtePiV5sgzTwMta;QS;K zS?XcL>Rpka&jdR>13N;?W7 P z26*H-@LhY6O~%k%Y%u)CTHtbVb|0%gB^}6f#2OjITj 9;Et*hnW*PpPvMf z$KVV%!Dn9L3$gAXL__CzsF*0cVl?!AD1D5nj5?UoEP>ggJ+v`$w%$0ib)uojjtMgv zT>k1fzul0#Ez&|aW#Hi+=zAvQUu$4X9gzhr0N1~$*d%fxt|)?v2g7 cHlAf^|C*`ZkUvVyAcU
IBiKklabiTA32l&Qe;I$-U*)V5;(%Ska^WaEav{p$*u<(M&mR)z}|X6171S! z_v2?Gkk?J4kD&VnS#Bn?JIF6{(@Q`KH}aO*u)hYPKJ>XibbO^a1WS*C?T-;Hfv{g; z@5?aLH4Zj^j=S*euS93Ws$tMj8FNY $DxQIg!ZK*gI!rIT YY+{_
`ylZ(jJa?>*KM;Vc^ogveJ5l(2! zSy* 6=*_RGM>x>ii|@v8jPC#P*~D=c)0S&QWTyAIrvV*I7^|!yGbtiC7o8o zEJ#=63Ic5LdeHj;B )02iGYVAP?iNXn%5+Sgnj5yD5U|q5(4ypeGU0FfKkh+N1 z&SO5RsQ89SgiX-7L-5Es5j#8))qo^^QlE}PHDMi{1*Fe{YW(!SQA`x%G8}795G!yF zpG6vY>L#QWp1mNkVFeQ~ar+HEa}FZWF+k^gxM_U`JV;M+pOl5B-$2IX#RNwzok~jp zM<&DHKE;U-5{ ;#XR6VWfllV7Gm ztR&*^LM#D3uNJbP&g26kqU_=|B)=KIbCLUbNvs+pe!%K0k~)xjULwR}tUgw>5fyPx z 7ntvp)YyJ59rQj==uuC>Y{iD-%%6@+6FjM0W9w) zK>r%zH!!9za?{+1Fq*^Wzwzcc&$fuFJJ4IWd8#9u2=07q7Qjx!mOdheRmqOO(L*AC zh3NJRB8ZHz)uzDwzW8bjsTV`W5Daw6jPJUOjflW&kS)m0n?v6B=?|KUDS~KJ60^dJ zIs!r0;~YZ}5ybHih%bv^l`X&>Hz@&`*9O`L!fWjo1Mt)~aQi+^G!aqDAY>}J;Va&t z;ucPK(6jU;{yhqL&}ZOXJ)rMJu^Q+-7}zicmboAL{}dMRR@?zbEygnxgKj>8h3-bi zcO7e%6Z4=SVW{?`r6aJzH_-fFz^9$S&=49+dcoIS! T%prprB8r&X;Hf#gxtnN?(vTQ z0!9?a`g5_vyYS54F$Wrl{T_e}N5kWF0)mf5 5%?j@$}B+)bPWjF3OR2EG80wK zCUhfxK}}S%yomEx(}pw&I#v;0VlBLKNyycK>Tr5se+`^sU!3nq;C>&`9@bC;NKgxC zI250LAGX#35&CC%y7qYDC3F!TL!06(AHX(C!#iw)N3JD`AR;V`9rb`l9)*l_$UXz2 zdJbuvf$!@FznTO4bppRD!j|^{8LA_qe1!U0HN^7+X+P*@0X+W&pju-@%^#3!@4;`b z!atjFdPni+v-o$!Un$jxlyJ8&^!Ed#o*lZoR(yhvuES|oqf=m&w_x>`=vq|dbED!p z7l`p4`ZM~kUn+tVC {0r zM^$bQ5ULtYfHl-7DX`|gSSdhI=%EXEUJWNO9olpZd%cV&KZNh+!{P_yYzN`f*W&;D zhd8x0^5@H#yvzb!uS_ezjx1yXo8TSF5k}tQw-00OeZc$+;sNyiGxX>czKax#phKl# zo9__Wo`ux^1vb~i8KF0hxJf~uU@e~fE$s6VvYIi_skdYSa@Itg;duC*KeEq=uk4Un zDeSinqR85?g|g7#68O8?i0CI`-|_H9!;zbsq$;Gd91}2G=zL@!1(D0I2Leg(I`g3~ zHDH4!5ox!?GcLxCuL67GaB?>gm#z}yppzAmDQ1CwR1)1_!*@~V>x0P2L-Hb~8wx}o zg>F$9%+y^+Mi53q$U9)(7Ob@Z{$@F(uo*eX7O@5vH4xcuAw(ich|gc*$vr$9uyj4n zrYiRIom9bU`!F4RhhBrv8;p1)4q9Io_tqZ+rgz5Emd9SJ;uJc;(#OGXOoQwP0qyHz zmjxjGB7Y;R)i~+2@LPv~cvVm}UP|}E@>kG4*ym5=z-{1jZvZuV;_OP{`76R|dI0}d zz*eK-MWTUqD{$I9@JSVc24!I({oqe;qB;@=Pxy$qVC@|!?xjNvS`@Osf!b#)k^?h^ z*YUgS@buv0i|tq`26`U@xv# wAJ4syPDDQQ6TYK0Q1Ur6eks _iM!2r G;<41wKsGi10sfd zc Plp+w*{zjBM1y)-eIet9!Jsc80@fYc4(I%+zo @PfpC@jMY|y1h@)Jl`6R}Mr#5kd-30;6)_9K-L zFH49+{qP0?=M(^s5rV(@4is4f#4HM3zk;lI8lvx6kkm7t5hr>P`Z=AvK$P5r&Vg=5 zpqm>G|LH v7 (E$dWUgJ-7#rQQCkYfKG(rM$3R0fBd*(ylP--Y zJRVPb9J;>`+I|RM`(RUZp`DFTz2Mm6WyDL-IM iF0YA Yzc#p`U2@hpx**c zJz_Be1lWKWs1?}*T&j*|UyHqNhezrKTuQ-C$H2$Qs7S{mYS;unyAE2q2|B+HxH|#a zay_7Xpzt8teb2w6&QKWsU@LUE6zu2*359kJLFZ)_5U(vQjLhpCbgUtwt)GZyPD3IG zaQ1& _ GP=mVU?6X@wN>^K~_Tm) _84r&Sx=+sY~=qG5?b9mqrh;%1oPkCWScYt;4fghXrDd bP{d;!QR0GNUs(6HuyXmNgMO$728LbK5#@WENBM&IMvmtp_4flO}5$&U!p5)|Lb zu-2cjr4zvFKJcara;Qs)=A)3$J?Apywp@HfcXA2xncVOje^>@9k >GT8|o*#iF=iIa>$4!;|?KMAYWhAo94Mzc5rLYIRtUJDJ)fc$?wGI;~HcNIn) zmJbz?M4aYU#Pm&ocmdeucjRy1fN|*73IpGNfDb CE(qk?4vk*{7c|{ z6ePa?uby7Q`Ch|L{+#Lx=u{8*y0X|`9{f`d8ao=F_X5#PJ;ckq&~N^XI*vh7VgJv` zNod1dG6;EM9a0_nYiU@2KHNkTh)?;3PuYbGq6s39ROtH& owaih_N8-o8^o@9rN{%Aiz z^)mr`eh6gUjNfjD7|e}s??Y5x&p}EbxD%1uNT7I ^8lF-L5my067OTZ;)p{! z&^Fj>G4vfjq8qUc9;6=X6hWw}{Qj%$Z{VZu{XN;O(8R%iqxt;6ya1eRMntwvvCD1v z35xUTf!{xfuG=f}4spawSXL}{zMd>b4Qmv <5IuV#g~Py<_E &znJp1JG=`)ypg(s9xz`l<`Esb@Q0V&?oZ}sw)gNo0 z0L^Rwq)!7+mk8`k0Me(2g!%&+o+5*8h~JEaP9_rtr|6^%ncNFt(@s<&!V!Uop~F!E z>t@CoFhnNrfY1AoYxhDllNlL)JP`Q~wDSv)q!hI2Pn9DRGGkwL6!_w=*uzsqQ89>c7C_2v zfTH;j;iZMA&kx&gi@)0lyGTTRwIPsw32-k4r*Iix=OOt+u-YwTGj_TNmC7mb&v*w3 z_8JNdJO^LW1Go_cM#8(lH6wwFT`Oc`XYt7eA=~MHSG$F-@O3=zF6ht%JZ)RxU_;cu zn&PVq)*A@D8i@Zk!r4-E&9?%VOCl4$`}Yo!f1vyS7j+(RJ67)le_t~*d(R|$?=6|x zdqjkktyI4v8Yn3mQnIs>itNbVE1AibnY~wd{lDLH*XQ5!dG(IxIrnw0eXez;6RVGl zs|ct4hSa~ns>krh%ER@~bLwn@JY_+aeuw^V#WW%65=)$F8MJv1Z>K4E%MX_)!zLvL z)@)GxS k;8ULunT*aMkMliy{T>)cLG3QAQVtF`CZCPyWJTb80qnfXJBP7{F6hAY zc;++EP b^e=dR1m0H_XmX#^@HWl{OIUFSe4mov_C