Advertisement
DarrenHill

DisplayHat Pirate Audio

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