main_screen.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. import hashlib
  2. import json
  3. import logging
  4. import os
  5. import time
  6. import urllib
  7. import urllib2
  8. from threading import Thread
  9. import pygame
  10. from .screen_objects import (Progressbar, ScreenObjectsManager,
  11. TextItem,
  12. TouchAndTextItem)
  13. from .input_manager import InputManager
  14. logger = logging.getLogger(__name__)
  15. class MainScreen():
  16. def __init__(self, size, manager, cache, core, fonts):
  17. self.core = core
  18. self.size = size
  19. self.base_size = self.size[1] / 8
  20. self.fonts = fonts
  21. self.manager = manager
  22. self.track = None
  23. self.cache = cache
  24. self.image = None
  25. self.artists = None
  26. self.track_duration = "00:00"
  27. self.touch_text_manager = ScreenObjectsManager()
  28. current_track = self.core.playback.current_track.get()
  29. if current_track is None:
  30. self.track_playback_ended(None, None)
  31. else:
  32. self.track_started(current_track)
  33. def update(self, screen, update_all):
  34. if self.track is not None:
  35. self.touch_text_manager.get_touch_object(
  36. "time_progress").set_value(
  37. self.core.playback.time_position.get() / 1000)
  38. self.touch_text_manager.get_touch_object(
  39. "time_progress").set_text(
  40. time.strftime('%M:%S', time.gmtime(
  41. self.core.playback.time_position.get() / 1000)) + "/" + self.track_duration)
  42. screen.blit(self.image, (
  43. self.base_size / 2, self.base_size + self.base_size / 2))
  44. self.touch_text_manager.render(screen)
  45. return screen
  46. def track_started(self, track):
  47. self.image = None
  48. x = self.base_size * 5
  49. width = self.size[0] - self.base_size / 2 - x
  50. self.track_duration = time.strftime('%M:%S', time.gmtime(
  51. track.length / 1000))
  52. # Load all artists
  53. self.artists = []
  54. for artist in track.artists:
  55. self.artists.append(artist)
  56. # Track name
  57. label = TextItem(self.fonts['base'],
  58. MainScreen.get_track_name(track),
  59. (x, self.base_size * 2),
  60. (width, self.size[1]))
  61. self.touch_text_manager.set_object("track_name", label)
  62. # Album name
  63. label = TextItem(self.fonts['base'],
  64. MainScreen.get_track_album_name(track),
  65. (x, self.base_size * 3),
  66. (width, self.size[1]))
  67. self.touch_text_manager.set_object("album_name", label)
  68. # Artist
  69. label = TextItem(self.fonts['base'], self.get_artist_string(),
  70. (x, self.base_size * 4),
  71. (width, self.size[1]))
  72. self.touch_text_manager.set_object("artist_name", label)
  73. # Previous track button
  74. button = TouchAndTextItem(self.fonts['icon'], u"\ue61c",
  75. (0, self.base_size * 6), None)
  76. self.touch_text_manager.set_touch_object("previous", button)
  77. size_1 = button.get_right_pos()
  78. size_2 = self.fonts['icon'].size(u"\ue61d")[0]
  79. button = TouchAndTextItem(self.fonts['icon'], u"\ue61d",
  80. (self.size[0] - size_2,
  81. self.base_size * 6),
  82. None)
  83. self.touch_text_manager.set_touch_object("next", button)
  84. # Progress
  85. progress = Progressbar(self.fonts['base'],
  86. time.strftime('%M:%S', time.gmtime(
  87. 0)) + "/" + time.strftime('%M:%S',
  88. time.gmtime(
  89. 0)),
  90. (size_1, self.base_size * 6),
  91. (
  92. self.size[0] - size_1 - size_2,
  93. self.base_size),
  94. track.length / 1000, False)
  95. self.touch_text_manager.set_touch_object("time_progress",
  96. progress)
  97. self.track = track
  98. if not self.is_image_in_cache():
  99. thread = Thread(target=self.download_image(0))
  100. thread.start()
  101. else:
  102. self.load_image()
  103. def get_artist_string(self):
  104. artists_string = ''
  105. for artist in self.artists:
  106. artists_string += artist.name + ', '
  107. if len(artists_string) > 2:
  108. artists_string = artists_string[:-2]
  109. elif len(artists_string) == 0:
  110. artists_string = "Unknow Artist"
  111. return artists_string
  112. def get_image_file_name(self):
  113. name = MainScreen.get_track_album_name(
  114. self.track) + '-' + self.get_artist_string()
  115. md5name = hashlib.md5(name.encode('utf-8')).hexdigest()
  116. return md5name
  117. def get_cover_folder(self):
  118. if not os.path.isdir(self.cache + "/covers"):
  119. os.makedirs(self.cache + "/covers")
  120. return self.cache + "/covers/"
  121. def is_image_in_cache(self):
  122. self.get_cover_folder()
  123. return os.path.isfile(
  124. self.get_cover_folder() + self.get_image_file_name())
  125. def download_image(self, artist_index):
  126. if artist_index < len(self.artists):
  127. try:
  128. safe_artist = urllib.quote_plus(
  129. self.artists[artist_index].name)
  130. safe_album = urllib.quote_plus(
  131. MainScreen.get_track_album_name(self.track))
  132. url = "http://ws.audioscrobbler.com/2.0/?"
  133. params = "method=album.getinfo&" + \
  134. "api_key=59a04c6a73fb99d6e8996e01db306829&" \
  135. + "artist=" \
  136. + safe_artist + "&album=" + safe_album + \
  137. "&format=json"
  138. response = urllib2.urlopen(url + params)
  139. data = json.load(response)
  140. image = data['album']['image'][-1]['#text']
  141. urllib.urlretrieve(image,
  142. self.get_cover_folder() +
  143. self.get_image_file_name())
  144. self.load_image()
  145. except:
  146. self.download_image(artist_index + 1)
  147. else:
  148. logger.info("Cover could not be downloaded")
  149. # There is no cover so it will use all the screen size for the text
  150. width = self.size[0] - self.base_size
  151. current = TextItem(self.fonts['base'],
  152. MainScreen.get_track_name(self.track),
  153. (self.base_size / 2,
  154. self.base_size * 2),
  155. (width, -1))
  156. self.touch_text_manager.set_object("track_name", current)
  157. current = TextItem(self.fonts['base'],
  158. MainScreen.get_track_album_name(
  159. self.track),
  160. (self.base_size / 2,
  161. self.base_size * 3),
  162. (width, -1))
  163. self.touch_text_manager.set_object("album_name", current)
  164. current = TextItem(self.fonts['base'],
  165. self.get_artist_string(),
  166. (self.base_size / 2,
  167. self.base_size * 4),
  168. (width, -1))
  169. self.touch_text_manager.set_object("artist_name", current)
  170. def track_playback_ended(self, tl_track, time_position):
  171. if self.image is not None:
  172. self.dirty_area.append(pygame.Rect(self.base_size / 2,
  173. self.base_size + self.base_size / 2,
  174. self.image.get_rect().width,
  175. self.image.get_rect().height))
  176. self.image = None
  177. self.track_duration = "00:00"
  178. # There is no cover so it will use all the screen size for the text
  179. width = self.size[0] - self.base_size
  180. current = TextItem(self.fonts['base'], "Stopped",
  181. (self.base_size / 2, self.base_size * 2),
  182. (width, -1))
  183. self.touch_text_manager.set_object("track_name", current)
  184. current = TextItem(self.fonts['base'], "",
  185. (self.base_size / 2, self.base_size * 3),
  186. (width, -1))
  187. self.touch_text_manager.set_object("album_name", current)
  188. current = TextItem(self.fonts['base'], "",
  189. (self.base_size / 2, self.base_size * 4),
  190. (width, -1))
  191. self.touch_text_manager.set_object("artist_name", current)
  192. def load_image(self):
  193. size = self.base_size * 4
  194. self.image = pygame.transform.scale(
  195. pygame.image.load(
  196. self.get_cover_folder() +
  197. self.get_image_file_name()).convert(),
  198. (size, size))
  199. self.image_now_loaded = True
  200. def touch_event(self, event):
  201. if event.type == InputManager.click:
  202. objects = self.touch_text_manager.get_touch_objects_in_pos(
  203. event.current_pos)
  204. if objects is not None:
  205. for key in objects:
  206. if key == "time_progress":
  207. value = self.touch_text_manager.get_touch_object(
  208. key).get_pos_value(
  209. event.current_pos) * 1000
  210. self.core.playback.seek(value)
  211. elif key == "previous":
  212. self.core.playback.previous()
  213. elif key == "next":
  214. self.core.playback.next()
  215. elif event.type == InputManager.swipe:
  216. if event.direction == InputManager.left:
  217. self.core.playback.next()
  218. elif event.direction == InputManager.right:
  219. self.core.playback.previous()
  220. elif event.direction == InputManager.up:
  221. volume = self.core.playback.volume.get() + 10
  222. if volume > 100:
  223. volume = 100
  224. self.manager.backend.tell(
  225. {'action': 'volume', 'value': volume})
  226. self.manager.volume_changed(volume)
  227. elif event.direction == InputManager.down:
  228. volume = self.core.playback.volume.get() - 10
  229. if volume < 0:
  230. volume = 0
  231. self.manager.backend.tell(
  232. {'action': 'volume', 'value': volume})
  233. self.manager.volume_changed(volume)
  234. @staticmethod
  235. def get_track_name(track):
  236. if track.name is None:
  237. return track.uri
  238. else:
  239. return track.name
  240. @staticmethod
  241. def get_track_album_name(track):
  242. if track.album is not None and track.album.name is not None and len(
  243. track.album.name) > 0:
  244. return track.album.name
  245. else:
  246. return "Unknow Album"