DarrenHill

Volumio PirateAudio Radio

Jan 5th, 2022 (edited)
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 28.45 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. import time
  4. from PIL import ImageFont, Image, ImageDraw, ImageStat, ImageFilter
  5. from PIL import ImageFilter  # v0.0.4
  6. import os
  7. import os.path
  8. import ST7789 #v0.0.6
  9. from socketIO_client import SocketIO
  10. import requests
  11. from io import BytesIO
  12. from numpy import mean
  13. import sys
  14. import signal
  15. import RPi.GPIO as GPIO
  16. import math
  17. import json
  18. from signal import *
  19. from time import strftime, gmtime  # v.0.0.4
  20. import time  # v.0.0.4
  21.  
  22.  
  23. # get the path of the script
  24. script_path = os.path.dirname(os.path.abspath(__file__))
  25. # set script path as current directory
  26. os.chdir(script_path)
  27.  
  28. # Create ST7789 LCD display class.
  29. disp = ST7789.ST7789(
  30.     height=240, #v0.0.6
  31.     width=240, #v0.0.6
  32.     rotation=90,  # Needed to display the right way up on Pirate Audio
  33.     port=0,       # SPI port
  34.     cs=1,         # SPI port Chip-select channel
  35.     dc=9,         # BCM pin used for data/command
  36.     backlight=13,
  37.     spi_speed_hz=80 * 1000 * 1000,
  38.     offset_left=0, #v0.0.6
  39.     offset_top=0 #v0.0.6
  40. )
  41.  
  42.  
  43. # read json file (plugin values)
  44. with open('/data/configuration/miscellanea/pirateaudio/config.json', 'r') as myfile:
  45.     data = myfile.read()
  46. obj = json.loads(data)  # parse file
  47.  
  48. # read json file (volumio language)
  49. with open('/data/configuration/miscellanea/appearance/config.json', 'r') as mylangfile:
  50.     data_lang = mylangfile.read()
  51. obj_lang = json.loads(data_lang)  # parse file
  52. langcode = obj_lang['language_code']['value']
  53. langpath = '/data/plugins/miscellanea/pirateaudio/i18n/strings_' + langcode + '.json'
  54. if os.path.exists(langpath) is False:  # change to en as default language
  55.     langpath = '/data/plugins/miscellanea/pirateaudio/i18n/strings_en.json'
  56.  
  57. # read json file (language file for translation)
  58. with open(langpath, 'r') as mytransfile:
  59.     data_trans = mytransfile.read()
  60. obj_trans = json.loads(data_trans)  # parse file
  61.  
  62. WIDTH = 240
  63. HEIGHT = 240
  64. font_s = ImageFont.truetype(script_path + '/fonts/Roboto-Medium.ttf', 20)
  65. font_m = ImageFont.truetype(script_path + '/fonts/Roboto-Medium.ttf', 24)
  66. font_l = ImageFont.truetype(script_path + '/fonts/Roboto-Medium.ttf', 30)
  67. font_fas = ImageFont.truetype(script_path + '/fonts/FontAwesome5-Free-Solid.otf', 28)
  68. bg_default = Image.open('images/default.jpg').resize((240, 240))
  69.  
  70. albumart, artist, album, title, img_check = '', '', '', '', ''
  71. mode = 'player'
  72. title_queue, len_queue = [], 0  # v.0.0.4
  73. position = ''  # v.0.0.4
  74. nav_array_name, nav_array_uri, nav_array_type, nav_array_service = [], [], [], []
  75. marker, listmax, liststart, listresult = 0, int(obj['listmax']['value']), 0, 0
  76.  
  77.  
  78. BUTTONS = [5, 6, 16, obj['gpio_ybutton']['value']]
  79. # LABELS = ['A', 'B', 'X', 'Y']
  80. GPIO.setmode(GPIO.BCM)  # Set up RPi.GPIO with the "BCM" numbering scheme
  81.  
  82.  
  83. # exit function (even is service is stopped)
  84. def clean(*args):
  85.     disp.set_backlight(False)
  86.     GPIO.cleanup(BUTTONS)  # v0.0.4
  87.     sys.exit(0)
  88.  
  89. for sig in (SIGABRT, SIGILL, SIGINT, SIGSEGV, SIGTERM):
  90.     signal(sig, clean)
  91. # exit function (even is service is stopped)
  92.  
  93.  
  94. def on_connect():
  95.     # print('connect')
  96.     # start_time = time.time()  # debug, time of code execution
  97.     socketIO.on('pushState', on_push_state)
  98.     socketIO.emit('getState', '', on_push_state)
  99.     socketIO.on('pushBrowseSources', on_push_browsesources)
  100.     socketIO.on('pushBrowseLibrary', on_push_browselibrary)
  101.     socketIO.on('pushQueue', on_push_queue)
  102.     socketIO.emit('getQueue', on_push_queue)
  103.     # print("on_connect--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  104.  
  105.  
  106. def on_disconnect():
  107.     display_stuff('bg_default', obj_trans['DISPLAY']['LOSTCONNECTION'], 0, 0, 'info')
  108.  
  109.  
  110. def navigation_handler():
  111.     # start_time = time.time()  # debug, time of code execution
  112.     global mode, nav_array_name, nav_array_uri, nav_array_type, marker, liststart, listresult
  113.     if mode == 'player':
  114.         mode = 'menu'
  115.         # Original menu set-up with prev/next, seek and timer plus shutdown adn reboot
  116.         # emit_action = ['setSleep', {'enabled': 'true', 'time': strftime("%H:%M", gmtime(obj['sleeptimer']['value']*60))}]
  117.         # nav_array_name = [obj_trans['DISPLAY']['MUSICSELECTION'], obj_trans['DISPLAY']['SEEK'], obj_trans['DISPLAY']['PREVNEXT'], 'Sleeptimer ' + str(obj['sleeptimer']['value']) + 'M', obj_trans['DISPLAY']['SHUTDOWN'], obj_trans['DISPLAY']['REBOOT']]
  118.         # nav_array_uri = ['', 'seek', 'prevnext', emit_action, 'shutdown', 'reboot']
  119.         # nav_array_type = ['', 'seek', 'prevnext', 'emit', 'emit', 'emit']
  120.         # listresult = 6
  121.         nav_array_name = ["Stations", "Radio", "Sources", "Shutdown"]
  122.         nav_array_uri = ['radio/myWebRadio', 'radio', '', 'shutdown']
  123.         nav_array_type = ['mywebradio', 'radio', '', 'emit']
  124.         listresult = 4
  125.         display_stuff('bg_default', nav_array_name, marker, liststart)
  126.     else:
  127.         print('else navigation_handler() eingetreten')
  128.     # print("navigation_handler--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  129.  
  130.  
  131. def on_push_browsesources(*args):
  132.     # start_time = time.time()  # debug, time of code execution
  133.     global listresult  # v.0.0.4 removed some globals, as thex not needed here
  134.     if mode == 'navigation':  # v.0.0.4 added, to make sure this getting not displayed on_connect
  135.         listresult = len(args[0])
  136.         i = 0
  137.         append_n = nav_array_name.append  # to avoid dots in for loop
  138.         append_u = nav_array_uri.append
  139.         for i in range(listresult):
  140.             append_n(args[0][i]['name'])
  141.             append_u(args[0][i]['uri'])
  142.         display_stuff('bg_default', nav_array_name, marker, 0)
  143.     # print("on_push_browsesources--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  144.  
  145.  
  146. def on_push_browselibrary(*args):
  147.     # start_time = time.time()  # debug, time of code execution
  148.     global listresult  # v.0.0.4 removed some globals, as thex not needed here
  149.     reset_variable('navigation')
  150.     listresult = len(args[0]['navigation']['lists'][0]['items'])  # v.0.0.4 code cleaning
  151.     i = 0
  152.     if listresult > 0:  # we have item entries
  153.         append_s = nav_array_service.append  # to avoid dots in for loop
  154.         append_t = nav_array_type.append
  155.         append_n = nav_array_name.append
  156.         append_u = nav_array_uri.append
  157.         for i in range(listresult):
  158.             if 'service' in args[0]['navigation']['lists'][0]['items'][i]:  # v.0.0.4
  159.                 append_s(args[0]['navigation']['lists'][0]['items'][i]['service'])  # v.0.0.4
  160.             if 'title' in args[0]['navigation']['lists'][0]['items'][i]:  # v.0.0.4
  161.                 append_n(args[0]['navigation']['lists'][0]['items'][i]['title'])
  162.             append_t(args[0]['navigation']['lists'][0]['items'][i]['type'])
  163.             if 'uri' in args[0]['navigation']['lists'][0]['items'][i]:  # v.0.0.4 spotify check
  164.                 append_u(args[0]['navigation']['lists'][0]['items'][i]['uri'])  # v.0.04
  165.         display_stuff('bg_default', nav_array_name, marker, liststart)
  166.     elif listresult == 0:  # we have no item entries
  167.         display_stuff('bg_default', obj_trans['DISPLAY']['EMPTY'], marker, liststart)
  168.     # print("on_push_browselibrary--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  169.  
  170.  
  171. def reset_variable(varmode):
  172.     # start_time = time.time()  # debug, time of code execution
  173.     global mode, nav_array_service, nav_array_name, nav_array_uri, nav_array_type, marker, liststart, img_check, albumart
  174.     mode = varmode
  175.     del nav_array_name[:]  # v.0.0.4 del is cleaner than = []
  176.     del nav_array_uri[:]
  177.     del nav_array_type[:]
  178.     del nav_array_service[:]
  179.     marker, liststart = 0, 0
  180.     img_check, albumart = '', ''  # reset albumart so display gets refreshed
  181.     # print("reset_variable--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  182.  
  183.  
  184. def sendtodisplay(img):
  185.     # start_time = time.time()  # debug, time of code execution
  186.     disp.display(img)
  187.     # time.sleep(0.1)  # ohne sleep 82% CPU, sleep: 0.5 = 40%, 0.25 = 53%, 0.1 = 70%
  188.     # print("sendtodisplay--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  189.  
  190.  
  191. def display_stuff(picture, text, marked, start, icons='nav'):  # v.0.0.4 test for better performance
  192.     # start_time = time.time()  # debug, time of code execution
  193.     global img3, listmax  # v.0.0.4
  194.     i = 0
  195.     if picture == 'bg_default':
  196.         img3 = bg_default.copy()
  197.     else:
  198.         img3 = Image.open(picture).convert('RGBA')  # v.0.0.4
  199.     draw3 = ImageDraw.Draw(img3, 'RGBA')
  200.  
  201.     if isinstance(text, list):  # check if text is array
  202.         result = len(text)  # count items of list/array
  203.         totaltextheight = 0
  204.         # Loop for finding out the sum of textheight for positioning, only text to display
  205.         listbis = start + listmax
  206.         if listbis > result:
  207.             listbis = result
  208.         for i in range(start, listbis):  # v.0.0.4 range max werteliste
  209.             len1, hei1 = draw3.textsize(text[0+i], font=font_m)
  210.             totaltextheight += hei1
  211.         i = 0
  212.         y = (HEIGHT // 2) - (totaltextheight // 2)
  213.  
  214.         # Loop for creating text to display
  215.         for i in range(start, listbis):  # v.0.0.4
  216.             len1, hei1 = draw3.textsize(text[0+i], font=font_m)
  217.             x2 = (WIDTH - len1)//2
  218.             if x2 < 0:  # v.0.0.4 dont center text if to long
  219.                 x2 = 0
  220.             if i == marked:
  221.                 draw3.rectangle((x2, y + 2, x2 + len1, y + hei1), (255, 255, 255))
  222.                 draw3.text((x2, y), text[0+i], font=font_m, fill=(0, 0, 0))
  223.             else:
  224.                 draw3.text((x2 + 3, y + 3), text[0+i], font=font_m, fill=(15, 15, 15))  # shadow v.0.0.4
  225.                 draw3.text((x2, y), text[0+i], font=font_m, fill=(255, 255, 255))
  226.             y += hei1
  227.     else:
  228.         result = 1  # needed for right pageindex
  229.         len1, hei1 = draw3.textsize(text, font=font_m)
  230.         x2 = (WIDTH - len1)//2
  231.         y2 = (HEIGHT - hei1)//2
  232.         draw3.rectangle((x2, y2, x2 + len1, y2 + hei1), (255, 255, 255))
  233.         draw3.text((x2, y2), text, font=font_m, fill=(0, 0, 0))
  234.  
  235.     # draw symbols
  236.     if icons == 'nav':  # v.0.0.4
  237.         draw3.text((0, 50), u"\uf14a", font=font_fas, fill=(255, 255, 255))  # Fontawesome symbols ok
  238.         draw3.text((210, 50), u"\uf151", font=font_fas, fill=(255, 255, 255))  # Fontawesome symbols up
  239.         draw3.text((0, 170), u"\uf0e2", font=font_fas, fill=(255, 255, 255))  # Fontawesome symbols back
  240.         draw3.text((210, 170), u"\uf150", font=font_fas, fill=(255, 255, 255))  # Fontawesome symbols down
  241.     elif icons == 'info':
  242.         draw3.text((10, 10), u"\uf05a", font=font_fas, fill=(255, 255, 255))  # Fontawesome symbols info
  243.     elif icons == 'seek':
  244.         draw3.text((210, 50), u"\uf04e", font=font_fas, fill=(255, 255, 255))  # Fontawesome symbols forward
  245.         draw3.text((0, 170), u"\uf0e2", font=font_fas, fill=(255, 255, 255))  # Fontawesome symbols back
  246.         draw3.text((210, 170), u"\uf04a", font=font_fas, fill=(255, 255, 255))  # Fontawesome symbols backward
  247.  
  248.     page = int(math.ceil((float(marked) + 1)/float(listmax)))
  249.     pages = int(math.ceil(float(result)/float(listmax)))
  250.     if pages != 1:  # only show index if more than one site
  251.         pagestring = str(page) + '/' + str(pages)
  252.         len1, hei1 = draw3.textsize(pagestring, font=font_m)
  253.         x2 = (WIDTH - len1)//2
  254.         draw3.text((x2, HEIGHT - hei1), pagestring, font=font_m, fill=(255, 255, 255))
  255.     sendtodisplay(img3)
  256.     # print("displaystuff--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  257.  
  258.  
  259. # position in code is important, so display_stuff works v.0.0.4
  260. display_stuff('bg_default', obj_trans['DISPLAY']['WAIT'], 0, 0, 'info')
  261. socketIO = SocketIO('localhost', 3000)
  262.  
  263.  
  264. def seeking(direction):
  265.     # start_time = time.time()  # debug, time of code execution
  266.     global seek, duration
  267.     step = 60000  # 60 seconds
  268.     if direction == '+':
  269.         if int(float((seek + step)/1000)) < duration:
  270.             seek += step
  271.             socketIO.emit('seek', int(float(seek/1000)))
  272.             display_stuff('bg_default', [obj_trans['DISPLAY']['SEEK'], strftime("%M:%S", gmtime(int(float(seek/1000)))) + ' / ' + strftime("%M:%S", gmtime(duration))], 0, 0, 'seek')
  273.     else:
  274.         if int(float((seek - step)/1000)) > 0:
  275.             seek -= step
  276.             socketIO.emit('seek', int(float(seek/1000)))
  277.             display_stuff('bg_default', [obj_trans['DISPLAY']['SEEK'], strftime("%M:%S", gmtime(int(float(seek/1000)))) + ' / ' + strftime("%M:%S", gmtime(duration))], 0, 0, 'seek')
  278.     # print("seeking--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  279.  
  280.  
  281. def prevnext(direction):
  282.     # start_time = time.time()  # debug, time of code execution
  283.     global position
  284.     if direction == 'prev':
  285.         position -= 1
  286.     else:
  287.         position += 1
  288.     if position > len_queue - 1:  # set position to first entry to loop through playlist infinite
  289.         position = 0
  290.     elif position < 0:  # set position to last entry to loop through playlist infinite
  291.         position = len_queue - 1
  292.     display_stuff('bg_default', [str(position + 1) + '/' + str(len_queue), obj_trans['DISPLAY']['PREVNEXT'], title_queue[position]], 1, 0, 'seek')
  293.     socketIO.emit('stop')
  294.     socketIO.emit('play', {"value": position})
  295.     # print("prevnext--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  296.  
  297.  
  298. def on_push_queue(*args):
  299.     global title_queue, len_queue
  300.     # reset variables first
  301.     del title_queue[:]
  302.     len_queue = 0
  303.     if len(args[0]) != 0:
  304.         len_queue = len(args[0])
  305.         append_t = title_queue.append  # to avoid dots in for loop
  306.         for i in range(len_queue):
  307.             append_t(args[0][i]['name'])
  308.  
  309.  
  310. def on_push_state(*args):
  311.     # start_time = time.time()  # debug, time of code execution
  312.     global img, img2, dark, txt_col, str_col, bar_bgcol, bar_col, status, service, volume, albumart, img_check, mode, seek, duration, position
  313.  
  314.     def f_textsize(text, fontsize):
  315.         w1, y1 = draw.textsize(text, fontsize)
  316.         return w1
  317.  
  318.     def f_drawtext(x, y, text, fontstring, fillstring):
  319.         draw.text((x, y), text, font=fontstring, fill=fillstring)
  320.  
  321.     def f_x1(textwidth):
  322.         if textwidth <= WIDTH:
  323.             x1 = (WIDTH - textwidth)//2
  324.         else:
  325.             x1 = 0
  326.         return x1
  327.  
  328.     def f_content(field, fontsize, top, shadowoffset=1):
  329.         if field in args[0]:
  330.             if args[0][field] is not None:
  331.                 w1 = f_textsize(args[0][field], fontsize)
  332.                 x1 = f_x1(w1)
  333.                 f_drawtext(x1 + shadowoffset, top + shadowoffset, args[0][field], fontsize, str_col)  # shadow
  334.                 f_drawtext(x1, top, args[0][field], fontsize, txt_col)
  335.                 # return args[0][field]
  336.  
  337.     volume = int(args[0]['volume'])
  338.     position = args[0]['position']  # v.0.0.4
  339.     if mode == 'player':
  340.         #status = args[0]['status'].encode('ascii', 'ignore')
  341.         status = args[0]['status'] # v0.0.6
  342.         #service = args[0]['service'].encode('ascii', 'ignore')
  343.         service = args[0]['service'] # v0.0.6
  344.  
  345.         # if args[0]['albumart'].encode('ascii', 'ignore') != albumart:  # Load albumcover or radio cover (and only if changes)
  346.         if args[0]['albumart'].encode('ascii', 'ignore').decode('utf-8') != albumart:  #v0.0.6 # Load albumcover or radio cover (and only if changes)
  347.             # albumart = args[0]['albumart'].encode('ascii', 'ignore')
  348.             albumart = args[0]['albumart'].encode('ascii', 'ignore').decode('utf-8')  #v0.0.6
  349.             print('Albumart', albumart) #v0.0.6
  350.  
  351.             albumart2 = albumart
  352.             if len(albumart2) == 0:  # to catch a empty field on start
  353.                 albumart2 = 'http://localhost:3000/albumart'
  354.             if 'http' not in albumart2:
  355.                 albumart2 = 'http://localhost:3000'+args[0]['albumart']
  356.  
  357.             response = requests.get(albumart2)
  358.             # img = Image.open(BytesIO(response.content)) # v.0.04 gab bei spotify probleme
  359.             img = Image.open(BytesIO(response.content)).convert('RGBA')  # v.0.04 gab bei spotify probleme
  360.             img = img.resize((WIDTH, HEIGHT))
  361.             img = img.filter(ImageFilter.BLUR)  # Blur
  362.             draw = ImageDraw.Draw(img, 'RGBA')
  363.             # draw = ImageDraw.Draw(img)  # v.0.04 gab bei spotify probleme
  364.             img2 = img.copy()
  365.  
  366.             # Light / Dark Symbols and bars, depending on background
  367.             im_stat = ImageStat.Stat(img)
  368.             im_mean = im_stat.mean
  369.             mn = mean(im_mean)
  370.  
  371.             txt_col = (255, 255, 255)
  372.             str_col = (15, 15, 15)  # v0.0.4 needed for shadow
  373.             bar_bgcol = (200, 200, 200)
  374.             bar_col = (255, 255, 255)
  375.             dark = False
  376.             if mn > 175:
  377.                 txt_col = (55, 55, 55)
  378.                 str_col = (200, 200, 200)  # v0.0.4 needed for shadow
  379.                 dark = True
  380.                 bar_bgcol = (255, 255, 255)
  381.                 bar_col = (100, 100, 100)
  382.             if mn < 80:
  383.                 txt_col = (200, 200, 200)
  384.         else:  # if albumart didnt change, copy the last unpasted version
  385.             img = img2.copy()
  386.             draw = ImageDraw.Draw(img, 'RGBA')
  387.  
  388.         # paste button symbol overlay in light/dark mode
  389.         if status == 'play':
  390.             # draw.text((4, 53), u"\uf04C", font=font_fas, fill=txt_col)  # Fontawesome symbol pause
  391.             f_drawtext(4, 53, u"\uf04C", font_fas, txt_col)
  392.         else:
  393.             # draw.text((4, 53), u"\uf04b", font=font_fas, fill=txt_col)  # Fontawesome symbol play
  394.             f_drawtext(4, 53, u"\uf04b", font_fas, txt_col)
  395.         # draw.text((210, 53), u"\uf0c9", font=font_fas, fill=txt_col)  # Fontawesome symbol menu
  396.         f_drawtext(210, 53, u"\uf0c9", font_fas, txt_col)
  397.         # draw.text((210, 174), u"\uf028", font=font_fas, fill=txt_col)  # Fontawesome symbol speaker
  398.         f_drawtext(210, 174, u"\uf028", font_fas, txt_col)
  399.  
  400.         f_content('artist', font_m, 7, 2)  # 'artist', font_m
  401.         f_content('album', font_m, 35, 2)
  402.         f_content('title', font_l, 105, 2)  # falscher top wert
  403.  
  404.         # volume bar
  405.         vol_x = int((float(args[0]['volume'])/100)*(WIDTH - 33))
  406.         draw.rectangle((5, 184, WIDTH-34, 184 + 8), bar_bgcol)  # background
  407.         draw.rectangle((5, 184, vol_x, 184 + 8), bar_col)
  408.  
  409.         # time bar
  410.         if 'duration' in args[0]:
  411.             duration = args[0]['duration']  # seconds
  412.             if duration != 0:
  413.                 # if 'seek' in args[0]:
  414.                 if 'seek' in args[0] and args[0]['seek'] is not None:  # v0.0.4 sometime seek = null or None
  415.                     seek = args[0]['seek']  # time elapsed seconds
  416.                     # if seek != 0:  # v0.0.4 seek=0 is ok to show
  417.                     el_time = int(float(args[0]['seek'])/1000)
  418.                     du_time = int(float(args[0]['duration']))
  419.                     dur_x = int((float(el_time)/float(du_time))*(WIDTH-10))
  420.                     draw.rectangle((5, 230, WIDTH-5, 230 + 8), bar_bgcol)  # background
  421.                     draw.rectangle((5, 230, dur_x, 230 + 8), bar_col)
  422.  
  423.                     # v0.0.4 show remaining time of track
  424.                     remaining = '-' + strftime("%M:%S", gmtime(duration - int(float(seek)/1000)))
  425.                     # w4, y4 = draw.textsize(remaining, font_m)
  426.                     w4 = f_textsize(remaining, font_m)
  427.                     # draw.text((WIDTH - w4 - 2 + 2, 206 - 2 + 2), remaining, font=font_m, fill=str_col)  # shadow, fill by mean
  428.                     f_drawtext(WIDTH - w4 - 2 + 2, 206 - 2 + 2, remaining, font_m, str_col)  # shadow, fill by mean)
  429.                     # draw.text((WIDTH - w4 - 2, 206 - 2), remaining, font=font_m, fill=txt_col)  # fill by mean
  430.                     f_drawtext(WIDTH - w4 - 2, 206 - 2, remaining, font_m, txt_col)  # fill by mean)
  431.  
  432.         # display only if img changed
  433.         if img_check != img:
  434.             img_check = img
  435.             sendtodisplay(img)
  436.     # print("on_push_state--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  437.  
  438.  
  439. img = Image.new('RGBA', (240, 240), color=(0, 0, 0, 25))
  440. draw = ImageDraw.Draw(img, 'RGBA')
  441. socketIO.once('connect', on_connect)
  442. socketIO.on('disconnect', on_disconnect)
  443.  
  444.  
  445. def handle_button(pin):
  446.     # start_time = time.time()  # debug, time of code execution
  447.     global mode, marker, liststart  # v.0.0.4
  448.     browselibrary = False
  449.  
  450.     if pin == 5:  # Button A, only needs single press function
  451.         print("Button 5 service:", service)
  452.         if mode == 'player':
  453.             if (status == 'play') and (service == 'webradio'):
  454.                 socketIO.emit('stop')
  455.             elif (status == 'play'):
  456.                 socketIO.emit('pause')
  457.             else:
  458.                 socketIO.emit('play')
  459.         elif mode == 'navigation':
  460.             if len(nav_array_uri) != 0:
  461.                 if len(nav_array_type) == 0:
  462.                     browselibrary = True
  463.                 else:
  464.                     if nav_array_type[marker] == 'song' or nav_array_type[marker] == 'webradio' or nav_array_type[marker] == 'mywebradio':  # v.0.0.4 fix for mywebradio
  465.                         socketIO.emit('replaceAndPlay', {"service": nav_array_service[marker], "type": nav_array_type[marker], "title": nav_array_name[marker], "uri": nav_array_uri[marker]})
  466.                         reset_variable('player')
  467.                     elif nav_array_type[marker] == 'playlist' and nav_array_service[marker] == 'mpd':  # v.0.0.4 modified because of spotifiy
  468.                         socketIO.emit('playPlaylist', {'name': nav_array_name[marker]})
  469.                         reset_variable('player')
  470.                     elif nav_array_type[marker] == 'playlist' and nav_array_service[marker] == 'spop':  # v.0.0.4 condition added because of spotifiy
  471.                         socketIO.emit('stop')  # v.0.0.4 fix otherwise change from any playing source to spotify dont work
  472.                         time.sleep(2)  # v.0.0.4 fix otherwise change from any playing source to spotify dont work
  473.                         socketIO.emit('replaceAndPlay', {"service": nav_array_service[marker], "type": nav_array_type[marker], "title": nav_array_name[marker], "uri": nav_array_uri[marker]})
  474.                         reset_variable('player')
  475.                     elif 'folder' in nav_array_type[marker]:
  476.                         if nav_array_service[marker] == 'podcast':
  477.                             display_stuff('bg_default', obj_trans['DISPLAY']['WAIT'], marker, liststart)  # note, please wait
  478.                         browselibrary = True
  479.                     elif 'radio-' in nav_array_type[marker]:  # the minus (-) is important, otherwise i cant decide between 'radiofolder' and 'webradiostream'
  480.                         browselibrary = True
  481.                     elif 'streaming-' in nav_array_type[marker]:
  482.                         browselibrary = True
  483.                     else:
  484.                         display_stuff('bg_default', obj_trans['DISPLAY']['NOTSUPPORTED'], marker, liststart)
  485.  
  486.                 if browselibrary is True:
  487.                     # replace "mnt/" in uri through "music-library/", otherwise calling them dont work (at least in favourites)
  488.                     uri = nav_array_uri[marker]
  489.                     uri = uri.replace('mnt/', 'music-library/')
  490.                     socketIO.emit('browseLibrary', {'uri': uri})
  491.                     browselibrary = False
  492.             else:
  493.                 reset_variable('player')
  494.                 socketIO.emit('getState', '', on_push_state)
  495.         elif mode == 'menu':
  496.             # socketIO.emit('getQueue', on_push_queue)  # refresh variables of queue
  497.             if nav_array_type[marker] == 'emit':
  498.                 if 'setSleep' in nav_array_uri[marker][0]:
  499.                     socketIO.emit(nav_array_uri[marker][0], nav_array_uri[marker][1])
  500.                     display_stuff('bg_default', obj_trans['DISPLAY']['SETSLEEPTIMER'], 0, 0, 'info')
  501.                     disp.set_backlight(False)
  502.                 else:
  503.                     socketIO.emit(nav_array_uri[marker])
  504.                     display_stuff('bg_default', ['executing:', nav_array_uri[marker]], 0, 0, 'info')
  505.             elif nav_array_type[marker] == 'seek':  # v.0.0.4
  506.                 mode = 'seek'
  507.                 display_stuff('bg_default', obj_trans['DISPLAY']['SEEK'], 0, 0, 'seek')
  508.             elif nav_array_type[marker] == 'prevnext':  # v.0.0.4
  509.                 socketIO.emit('getQueue', on_push_queue)  # refresh variables of queue
  510.                 mode = 'prevnext'
  511.                 display_stuff('bg_default', [str(position + 1) + '/' + str(len_queue), obj_trans['DISPLAY']['PREVNEXT'], title_queue[position]], 1, 0, 'seek')
  512.             elif nav_array_type[marker] == 'radio':  # DH radio
  513. #                reset_variable('navigation')
  514.                 socketIO.emit('browseLibrary', {'uri': nav_array_uri[marker]})
  515.             elif nav_array_type[marker] == 'mywebradio':  # DH my web radio
  516. #                reset_variable('navigation')
  517.                 socketIO.emit('browseLibrary', {'uri': nav_array_uri[marker]})
  518.             else:  # browsesource
  519.                 reset_variable('navigation')
  520.                 socketIO.emit('getBrowseSources', '', on_push_browsesources)
  521.         else:
  522.             reset_variable('player')
  523.             socketIO.emit('getState', '', on_push_state)
  524.  
  525.     if pin == 6:  # Button B, needs a pressed function in player mode
  526.         if mode == 'player':
  527.             while not GPIO.input(6) and volume > 0:  # limit/exit at volume 0 so amixer dont go crazy
  528.                 socketIO.emit('volume', '-')
  529.                 time.sleep(0.5)
  530.         elif mode == 'navigation' or mode == 'menu' or mode == 'seek' or mode == 'prevnext':
  531.             reset_variable('player')
  532.             socketIO.emit('getState', '', on_push_state)
  533.  
  534.     if pin == 16:  # Button X, needs a pressed function in navigation and menu mode
  535.         if mode == 'player':
  536.             navigation_handler()
  537.             disp.set_backlight(True)  # v.0.0.4
  538.         elif mode == 'navigation' or mode == 'menu':
  539.             while not GPIO.input(16):
  540.                 marker -= 1  # count minus 1
  541.                 if marker < 0:  # blaettere nach oben durch
  542.                     marker = listresult - 1
  543.                     if listresult > listmax - 1:  # dann aendere auch noch den liststart
  544.                         liststart = int(liststart + (math.floor(listresult/listmax)*listmax))
  545.                 liststart = int(math.floor(marker/listmax)*listmax)  # definiert das blaettern zur naechsten Seite
  546.                 display_stuff('bg_default', nav_array_name, marker, liststart)
  547.         elif mode == 'seek':  # v.0.0.4
  548.             seeking('+')
  549.         elif mode == 'prevnext':  # v.0.0.4
  550.             prevnext('next')
  551.  
  552.     if pin == BUTTONS[3]:  # Button Y, needs a pressed function in  all modes
  553.         if mode == 'seek':
  554.             seeking('-')
  555.         elif mode == 'prevnext':
  556.             prevnext('prev')
  557.         else:
  558.             while not GPIO.input(BUTTONS[3]):
  559.                 if mode == 'player' and volume < 100:  # limit/exit at volume 100 so amixer dont go crazy:
  560.                     socketIO.emit('volume', '+')
  561.                     time.sleep(0.5)
  562.                 elif mode == 'navigation' or mode == 'menu':
  563.                     marker += 1  # count plus 1
  564.                     liststart = int(math.floor(marker/listmax)*listmax)  # definiert das blaettern zur naechsten Seite
  565.                     if marker > listresult - 1:  # blaettere nach unten durch
  566.                         marker = 0
  567.                         liststart = 0
  568.                     display_stuff('bg_default', nav_array_name, marker, liststart)
  569.     # print("handle_button--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  570.  
  571.  
  572. def setup_channel(channel):
  573.     # start_time = time.time()  # debug, time of code execution
  574.     try:
  575.         #print('register %d') % channel
  576.         print('register %d' % channel) #v0.0.6
  577.         GPIO.setup(channel, GPIO.IN, GPIO.PUD_UP)
  578.         GPIO.add_event_detect(channel, GPIO.FALLING, handle_button, bouncetime=400)
  579.         print('success')
  580.     except (ValueError, RuntimeError) as e:
  581.         print('ERROR:', e)
  582.     # print("setup_channel--- %s seconds ---" % (time.time() - start_time))  # debug, time of code execution
  583.  
  584.  
  585. for x in BUTTONS:
  586.     setup_channel(x)
  587.  
  588.  
  589. def main():
  590.     socketIO.wait()
  591.     time.sleep(0.5)
  592.  
  593.  
  594. try:
  595.     main()
  596. except KeyboardInterrupt:
  597.     clean()
  598.     pass
  599.  
Add Comment
Please, Sign In to add comment