main_screen.py 11 KB

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