picture.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. # -*- coding: utf-8 -*-
  2. # Copyright (c) 2014-2016 Tomek Wójcik <tomek@bthlabs.pl>
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to deal
  6. # in the Software without restriction, including without limitation the rights
  7. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. # THE SOFTWARE.
  21. #
  22. """
  23. pie_time.cards.picture
  24. ======================
  25. This module containse the PictureCard class.
  26. """
  27. import cStringIO
  28. import os
  29. import urlparse
  30. import pygame
  31. import requests
  32. from pie_time.card import AbstractCard
  33. class PictureCard(AbstractCard):
  34. """
  35. The picture card.
  36. This cards displays a picture from list of pre-defined pictures. If more
  37. than one picture is defined, it's changed each time the card transitions
  38. to current card.
  39. **Settings dictionary keys**:
  40. * **urls** (*list*) - **required** list of picture URLs. Currently, only
  41. ``file://``, ``http://`` and ``https://`` URL schemes are supported.
  42. """
  43. def initialize(self):
  44. self._pictures = []
  45. self._current_picture_idx = None
  46. self._should_redraw = True
  47. for url in self._settings['urls']:
  48. self._pictures.append(self._load_picture(url))
  49. def _load_picture(self, url):
  50. self._app.logger.debug(
  51. 'PictureCard: Attempting to load picture: %s' % url
  52. )
  53. parsed_url = urlparse.urlparse(url)
  54. surface = None
  55. try:
  56. format = None
  57. if parsed_url.scheme == 'file':
  58. surface = pygame.image.load(parsed_url.path)
  59. _, ext = os.path.splitext(parsed_url.path)
  60. format = ext.lower()
  61. elif parsed_url.scheme.startswith('http'):
  62. rsp = requests.get(url)
  63. assert rsp.status_code == 200
  64. format = rsp.headers['Content-Type'].replace('image/', '')
  65. surface = pygame.image.load(
  66. cStringIO.StringIO(rsp.content), 'picture.%s' % format
  67. )
  68. if surface and format:
  69. if format.lower().endswith('png'):
  70. surface = surface.convert_alpha(self._app.screen)
  71. else:
  72. surface = surface.convert(self._app.screen)
  73. except Exception as exc:
  74. self._app.logger.error(
  75. 'PictureCard: Could not load picture: %s' % url, exc_info=True
  76. )
  77. return surface
  78. def show(self):
  79. if len(self._pictures) == 0:
  80. self._current_picture_idx = None
  81. elif len(self._pictures) == 1:
  82. self._current_picture_idx = 0
  83. else:
  84. if self._current_picture_idx is None:
  85. self._current_picture_idx = 0
  86. else:
  87. new_picture_idx = self._current_picture_idx + 1
  88. if new_picture_idx >= len(self._pictures):
  89. new_picture_idx = 0
  90. self._app.logger.debug(
  91. 'PictureCard: Picture transition %d -> %d' % (
  92. self._current_picture_idx, new_picture_idx
  93. )
  94. )
  95. self._current_picture_idx = new_picture_idx
  96. self._should_redraw = True
  97. def tick(self):
  98. if self._should_redraw:
  99. self.surface.fill(self.background_color)
  100. if self._current_picture_idx is not None:
  101. picture = self._pictures[self._current_picture_idx]
  102. picture_size = picture.get_size()
  103. picture_rect = picture.get_rect()
  104. if picture_size != self._app.screen_size:
  105. picture_rect = (
  106. (self.width - picture_size[0]) / 2.0,
  107. (self.height - picture_size[1]) / 2.0,
  108. picture_size[0], picture_size[1]
  109. )
  110. self.surface.blit(picture, picture_rect)
  111. self._should_redraw = False