#Listing 1. Fragmenty kodu źródłowy Raspberry PiRate Radio try: #próba importu biblioteki Pythona 3.x import configparser except: #import biblioteki Pythona 2.x, jeśli operacja nie powiodła się dla Pythona 3.x import ConfigParser as configparser finally: #import pozostałych bibliotek import re import re import random import sys import os import threading import time import subprocess #zmienne globalne, do przechowywania ustawień fm_process = None on_off = ["off", "on"] config_location = "/pirateradio/pirateradio.conf" frequency = 87.9 shuffle = False repeat_all = False merge_audio_in = False play_stereo = True music_dir = "/pirateradio" music_pipe_r,music_pipe_w = os.pipe() microphone_pipe_r,microphone_pipe_w = os.pipe() #główne polecenia programu def main(): daemonize() setup() files = build_file_list() if repeat_all == True: while(True): play_songs(files) else: play_songs(files) return 0 #tworzenie listy plików w oparciu o przeszukiwanie katalogu z muzyką def build_file_list(): file_list = [] for root, folders, files in os.walk(music_dir): folders.sort() files.sort() for filename in files: if re.search(".(aac|mp3|wav|flac|m4a|ogg|pls|m3u)$", filename) != None: file_list.append(os.path.join(root, filename)) return file_list #główna funkcja odtwarzająca pliki def play_songs(file_list): print("Playing songs to frequency ", str(frequency)) print("Shuffle is " + on_off[shuffle]) print("Repeat All is " + on_off[repeat_all]) # print("Stereo playback is " + on_off[play_stereo]) #w przypadku odtwarzania losowego, lista plików jest wstępnie mieszana if shuffle == True: random.shuffle(file_list) with open(os.devnull, "w") as dev_null: for filename in file_list: print("Playing ",filename) #w przypadku gdy plik jest tak naprawdę listą utworów, jest on przetwarzany przed odtwarzaniem if re.search(".pls$", filename) != None: streamurl = parse_pls(filename, 1) if streamurl != None: print("streaming radio from " + streamurl) subprocess.call(["ffmpeg","-i",streamurl,"-f","s16le","-acodec","pcm_s16le","-ac", "2" if play_stereo else "1" ,"-ar","44100","-"],stdout=music_pipe_w, stderr=dev_null) elif re.search(".m3u$", filename) != None: streamurl = parse_m3u(filename, 1) if streamurl != None: print("streaming radio from " + streamurl) subprocess.call(["ffmpeg","-i",streamurl,"-f","s16le","-acodec","pcm_s16le","-ac", "2" if play_stereo else "1" ,"-ar","44100","-"],stdout=music_pipe_w, stderr=dev_null) else: #niezależnie od formatu pliku jest on dekodowany programem ffmpeg, a przekonwertowany strumień jest przekazywany dalej poprzez music_pipe_w subprocess.call(["ffmpeg","-i",filename,"-f","s16le","-acodec","pcm_s16le","-ac", "2" if play_stereo else "1" ,"-ar","44100","-"],stdout=music_pipe_w, stderr=dev_null) #wczytywanie ustawień z użyciem wygodnej biblioteki config. def read_config(): global frequency global shuffle global repeat_all global play_stereo global music_dir try: config = configparser.ConfigParser() config.read(config_location) except: print("Error reading from config file.") else: play_stereo = config.get("pirateradio", 'stereo_playback', fallback=True) frequency = config.get("pirateradio",'frequency') shuffle = config.getboolean("pirateradio",'shuffle',fallback=False) repeat_all = config.getboolean("pirateradio",'repeat_all', fallback=False) music_dir = config.get("pirateradio", 'music_dir', fallback="/pirateradio") #funkcja dzieląca pozycje pliku w formacie pls na pojedyncze pliki dźwiękowe (pominięta) def parse_pls(src, titleindex): #funkcja dzieląca pozycje pliku w formacie m3u na pojedyncze pliki dźwiękowe (pominięta) def parse_m3u(src, titleindex): #funkcja tworząca drugi proces i zamykająca pierwotny. Dzięki temu cały program działa jako demon, uwalniając konsolę użytkownika, który go wywołał def daemonize(): fpid=os.fork() if fpid!=0: #pierwotny proces ma ustalone fpid i w ten sposób można go rozpoznać i zamknąć sys.exit(0) #funkcja wywołująca wczytanie konfiguracji a następnie włączenie procesu PiFM w tle def setup(): global frequency read_config() run_pifm() #uruchamianie biblioteki PiFM jako podrzędnego procesu, w którym strumień music_pipe_r jest traktowany jako wejście def run_pifm(use_audio_in=False): global fm_process with open(os.devnull, "w") as dev_null: fm_process = subprocess.Popen(["/root/pifm","-",str(frequency),"44100", "stereo" if play_stereo else "mono"], stdin=music_pipe_r, stdout=dev_null) main()