interface.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. # GPL 3 or later
  2. import os
  3. import json
  4. import time
  5. import random
  6. import threading
  7. import subprocess
  8. from datetime import datetime
  9. from datetime import timedelta
  10. from ui import *
  11. now = {"now_playing":None,
  12. "mpv": None}
  13. # There will be 2 threads. One showing the current progress. The other playing the actual
  14. # songs themselves.
  15. def get_list():
  16. with open('stuff.json') as json_file:
  17. stuff = json.load(json_file)
  18. new_date_format = "%Y/%m/%d"
  19. today = datetime.strftime(datetime.today(), new_date_format)
  20. playlist = []
  21. users_songs = {}
  22. for n, username in enumerate(stuff.get("users", {})):
  23. if username in stuff.get("present", {}).get(today, []):
  24. user = stuff.get("users", {}).get(username, {})
  25. users_songs[username] = user.get("now", []).copy()
  26. while users_songs:
  27. try:
  28. for user in users_songs:
  29. if not users_songs[user]:
  30. try:
  31. del users_songs[user]
  32. except:
  33. pass
  34. else:
  35. videoId = users_songs[user].pop(0)
  36. playlist.append({"username":user,
  37. "videoId":videoId,
  38. "data":stuff.get("songs", {}).get(videoId, {})})
  39. except:
  40. pass
  41. return playlist
  42. def player():
  43. index = 0
  44. while True:
  45. index = index + 1
  46. try:
  47. time.sleep(5)
  48. if datetime.now().hour >= 16 and datetime.now().minute >= 50:
  49. os.system("shutdown --poweroff")
  50. # Instead of turning it off we wait till the morning
  51. # which is 14 hours
  52. #time.sleep(60*60*14)
  53. break
  54. with open('stuff.json') as json_file:
  55. stuff = json.load(json_file)
  56. # Checking if it's time to play songs.
  57. tobreak = False
  58. for br in stuff.get("breaks", []):
  59. if br.get("start", {}).get("hour", 0) <= datetime.now().hour\
  60. and br.get("start", {}).get("minute", 0) <= datetime.now().minute\
  61. and br.get("end", {}).get("hour", 0) >= datetime.now().hour\
  62. and br.get("end", {}).get("minute", 0) >= datetime.now().minute:
  63. tobreak = True
  64. if tobreak:
  65. continue
  66. # Pipewire eats a lot of RAM. So to avoid it, before
  67. # each song we restart it.
  68. if index % 5 == 0:
  69. os.system("systemctl --user restart pipewire.service")
  70. time.sleep(10)
  71. playlist = get_list()
  72. # Checks!
  73. users = []
  74. for i in playlist:
  75. if i["username"] not in users:
  76. users.append(i["username"])
  77. # If only the music operator sent songs. We wait for more people to send
  78. # songs.
  79. # if len(users) == 1 and stuff.get("matrix", {}).get("username") in users:
  80. # continue
  81. # If there not a single song by the operator. Add one random from his
  82. # history.
  83. # for user in stuff.get("users", {}):
  84. # if not stuff.get("users", {}).get(user, {}).get("now", [])\
  85. # and len(stuff.get("users", {}).get(user, {}).get("history", [])) > 4:
  86. # try:
  87. # rs = random.choice(stuff["users"][user]["history"])
  88. # stuff["users"][user]["now"].append(rs)
  89. # with open('stuff.json', 'w') as fp:
  90. # json.dump(stuff, fp, indent=4)
  91. # except:
  92. # pass
  93. for i in playlist:
  94. filename = i["data"].get("file")
  95. username = i["username"]
  96. videoId = i["videoId"]
  97. if filename:# and (time.time() - stuff.get("songs", {}).get(videoId, {}).get("last_played", 0)) > 60*60*2:
  98. # Writing the time at which the song started playing
  99. with open('stuff.json') as json_file:
  100. stuff = json.load(json_file)
  101. stuff["last_played"] = int(time.time())
  102. stuff["now_playing"] = videoId
  103. stuff["now_username"] = username
  104. with open('stuff.json', 'w') as fp:
  105. json.dump(stuff, fp, indent=4)
  106. # Playing the song
  107. now["now_playing"] = videoId
  108. now["mpv"] = subprocess.Popen(["mpv", filename, "--no-video", "--audio-channels=mono", "--af=lavfi=dynaudnorm", "--no-terminal"])
  109. now["mpv"].wait()
  110. # Removing the song from the 'now' playlist
  111. with open('stuff.json') as json_file:
  112. stuff = json.load(json_file)
  113. try:
  114. stuff["songs"][videoId]["last_played"] = int(time.time())
  115. while videoId in stuff["users"][username]["now"]:
  116. stuff["users"][username]["now"].remove(videoId)
  117. user = stuff["users"][username].copy()
  118. del stuff["users"][username]
  119. stuff["users"][username] = user
  120. except:
  121. pass
  122. with open('stuff.json', 'w') as fp:
  123. json.dump(stuff, fp, indent=4)
  124. # In case
  125. if stuff and "songs" in stuff and "users" in stuff:
  126. with open('stuff_backup.json', 'w') as fp:
  127. json.dump(stuff, fp, indent=4)
  128. break
  129. # elif not (time.time() - stuff.get("songs", {}).get(videoId, {}).get("last_played", 0)) > 60*60*2:
  130. # with open('stuff.json') as json_file:
  131. # stuff = json.load(json_file)
  132. # try:
  133. # while videoId in stuff["users"][username]["now"]:
  134. # stuff["users"][username]["now"].remove(videoId)
  135. # except:
  136. # pass
  137. # with open('stuff.json', 'w') as fp:
  138. # json.dump(stuff, fp, indent=4)
  139. except:
  140. pass
  141. t2 = threading.Thread(target=player)
  142. t2.setDaemon(True)
  143. t2.start()
  144. while True:
  145. try:
  146. time.sleep(1)
  147. with open('stuff.json') as json_file:
  148. stuff = json.load(json_file)
  149. new_date_format = "%Y/%m/%d"
  150. today = datetime.strftime(datetime.today(), new_date_format)
  151. for d in range(400):
  152. yesterday = datetime.strftime(datetime.today()-timedelta(days=d+1), new_date_format)
  153. if yesterday in stuff.get("volume", {}):
  154. break
  155. # Making volume 20%
  156. try:
  157. v = stuff["volume"][yesterday]["average"]
  158. except:
  159. v = 20
  160. try:
  161. v = stuff["volume"][today]["average"]
  162. except:
  163. pass
  164. y = 0
  165. try:
  166. y = stuff["volume"][yesterday]["average"]
  167. except:
  168. pass
  169. os.system("amixer -D pulse sset Master "+str(max(0,min(v, 100))*0.3)+"%")
  170. os.system("clear")
  171. users_volumes = {}
  172. try:
  173. users_volumes = stuff["volume"][today]["users"]
  174. except:
  175. pass
  176. w, h = tsize()
  177. w = w - 4
  178. h = h - 5
  179. playlist = get_list()
  180. print()
  181. for n, i in enumerate(playlist):
  182. if n > h-len(stuff.get("present", {}).get(today, []))-5:
  183. break
  184. if now["now_playing"] == i["videoId"]:
  185. playing = clr["bdbu"]+" > "
  186. elif i["data"].get("file"):
  187. playing = " "
  188. else:
  189. playing = clr["bdyl"]+"..."+clr["norm"]+" "
  190. print(" "+playing+clr["bold"]+wdth(i["data"].get("title"), w-40)+clr["norm"]+" "+\
  191. clr["tdbl"]+"t"+clr["tbyl"]+wdth(timestring(i["data"].get("duration")), 10)+clr["norm"]+" "+\
  192. wdth(user_emoji(i["username"],stuff), 19, False))
  193. # Percent of the song ( Progress bar in the bottom
  194. duration = stuff.get("songs", {}).get(now["now_playing"], {}).get("duration", 1)
  195. started = stuff.get("last_played", 0)
  196. percent = max(0, min(1, (time.time()-started) / duration))
  197. print()
  198. print(" "+wdth(timestring(duration)+" / "+timestring(int(time.time()-started)), int(w/5))+clr["bbbu"]+(" "*int((w-int(w/5))*percent))+clr["norm"])
  199. print()
  200. # VOLUME
  201. us = []
  202. for u in stuff.get("present", {}).get(today, []):
  203. try:
  204. print( " ", wdth(user_emoji(u, stuff), int(w/3), False), clr["tdbl"]+"t"+clr["norm"], clr["tbyl"], str(round(users_volumes[u], 2))+"%" , clr["norm"])
  205. us.append(u)
  206. except:
  207. print( " ", wdth(user_emoji(u, stuff), int(w/3), False), clr["tdbl"]+"t"+clr["norm"], clr["tbrd"], "Not Voted!" , clr["norm"])
  208. print()
  209. not_voted = 0
  210. for u in stuff.get("present", {}).get(today, []):
  211. if u not in us:
  212. not_voted = not_voted+1
  213. if not_voted:
  214. center(" + ( "+ str(not_voted)+ " * " + str(round(y,2))+"% ) not voted! ", "tbrd")
  215. print()
  216. if stuff.get("skip"):
  217. try:
  218. now["mpv"].kill()
  219. stuff["skip"] = False
  220. videoId = stuff["now_playing"]
  221. username = stuff["now_username"]
  222. stuff["songs"][videoId]["last_played"] = int(time.time())
  223. while videoId in stuff["users"][username]["now"]:
  224. stuff["users"][username]["now"].remove(videoId)
  225. user = stuff["users"][username].copy()
  226. del stuff["users"][username]
  227. stuff["users"][username] = user
  228. except:
  229. pass
  230. with open('stuff.json', 'w') as fp:
  231. json.dump(stuff, fp, indent=4)
  232. print(" "+wdth("Volume: "+str(round(v, 2))+"%", int(w/5))+clr["bbbu"]+(" "*int((w-int(w/5))*(v/100)))+clr["norm"])
  233. except Exception as e:
  234. pass