Merge lp:~mblayman/entertainer/videolibz into lp:entertainer
- videolibz
- Merge into trunk
Proposed by
Matt Layman
Status: | Merged |
---|---|
Approved by: | Matt Layman |
Approved revision: | 478 |
Merged at revision: | not available |
Proposed branch: | lp:~mblayman/entertainer/videolibz |
Merge into: | lp:entertainer |
Diff against target: |
1557 lines (+290/-836) 12 files modified
entertainerlib/client/media_player.py (+4/-11) entertainerlib/client/medialibrary/videos.py (+216/-704) entertainerlib/gui/screens/factory.py (+1/-0) entertainerlib/gui/screens/movie.py (+12/-13) entertainerlib/gui/screens/tv_episodes.py (+13/-19) entertainerlib/gui/screens/tv_series.py (+9/-8) entertainerlib/gui/tabs/movies_tab.py (+6/-6) entertainerlib/gui/tabs/series_tab.py (+3/-4) entertainerlib/gui/tabs/video_clips_tab.py (+2/-2) entertainerlib/tests/mock.py (+21/-66) entertainerlib/tests/test_mediaplayer.py (+1/-2) entertainerlib/tests/test_screenfactory.py (+2/-1) |
To merge this branch: | bzr merge lp:~mblayman/entertainer/videolibz |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matt Layman | Approve | ||
Review via email: mp+22770@code.launchpad.net |
Commit message
Video classes are now more Pythonic and do not talk directly to the database anymore.
Description of the change
I did the same clean up to the video library as I did early to the music library. Now all the video classes are just plain Python objects. Any method that talks to the database has been pushed into some factory methods in the VideoLibrary. This leaves only the VideoLibrary to work with when we move away from directly using the database directly (first to Storm, then to Twisted probably).
To post a comment you must log in.
Revision history for this message
Matt Layman (mblayman) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'entertainerlib/client/media_player.py' |
2 | --- entertainerlib/client/media_player.py 2009-12-21 22:21:55 +0000 |
3 | +++ entertainerlib/client/media_player.py 2010-04-03 23:02:16 +0000 |
4 | @@ -15,17 +15,10 @@ |
5 | from entertainerlib.logger import Logger |
6 | |
7 | class MediaPlayer(gobject.GObject, object): |
8 | - ''' |
9 | - MediaPlayer class for Entertainer |
10 | - |
11 | - MediaPlayer uses Gstreamer backend and is able to play all video and audio |
12 | - files that gstreamer supports. Entertainer has only one MediaPlayer object |
13 | - at runtime. |
14 | - |
15 | - MediaPlayer can play objects that implement Playable interface. These |
16 | - classes are Track, Movie, TVEpisode, Movie, VideoClip and CompactDiscTrack. |
17 | - (and Channel in the future) |
18 | - ''' |
19 | + '''MediaPlayer uses Gstreamer to play all video and audio files. Entertainer |
20 | + has only one MediaPlayer object at runtime. MediaPlayer can play objects |
21 | + that implement Playable interface.''' |
22 | + |
23 | __gsignals__ = { |
24 | 'play' : ( gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, () ), |
25 | 'pause' : ( gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, () ), |
26 | |
27 | === modified file 'entertainerlib/client/medialibrary/videos.py' |
28 | --- entertainerlib/client/medialibrary/videos.py 2010-04-03 14:33:37 +0000 |
29 | +++ entertainerlib/client/medialibrary/videos.py 2010-04-03 23:02:16 +0000 |
30 | @@ -2,15 +2,14 @@ |
31 | '''Video Library - Interface for Entertainer video library cache''' |
32 | |
33 | import os |
34 | + |
35 | from pysqlite2 import dbapi2 as sqlite |
36 | |
37 | from entertainerlib.client.medialibrary.playable import Playable |
38 | from entertainerlib.configuration import Configuration |
39 | -from entertainerlib.logger import Logger |
40 | - |
41 | - |
42 | -class VideoLibrary: |
43 | - """Interface for Entertainer's video cache.""" |
44 | + |
45 | +class VideoLibrary(object): |
46 | + '''Interface for Entertainer's video cache.''' |
47 | |
48 | def __init__(self): |
49 | self.config = Configuration() |
50 | @@ -18,778 +17,291 @@ |
51 | if not os.path.exists(self.config.VIDEO_DB): |
52 | raise Exception("Video database doesn't exist!") |
53 | |
54 | + self.connection = sqlite.connect(self.config.VIDEO_DB) |
55 | + self.cursor = self.connection.cursor() |
56 | + |
57 | + def __del__(self): |
58 | + '''Close the db connection when this object is deleted.''' |
59 | + self.connection.close() |
60 | + |
61 | def get_movies(self): |
62 | - """ |
63 | - Get all movies |
64 | - @return: List of Movie objects |
65 | - """ |
66 | - connection = sqlite.connect(self.config.VIDEO_DB) |
67 | - cursor = connection.cursor() |
68 | - cursor.execute("""SELECT videofile.filename |
69 | + '''Get all the movies.''' |
70 | + self.cursor.execute("""SELECT videofile.filename |
71 | FROM videofile, metadata |
72 | WHERE type='MOVIE' |
73 | AND videofile.filename=metadata.filename |
74 | ORDER BY title""") |
75 | movies = [] |
76 | - for row in cursor: |
77 | - movies.append(Movie(row[0])) |
78 | - connection.close() |
79 | + for row in self.cursor.fetchall(): |
80 | + movies.append(self._create_movie(row[0])) |
81 | return movies |
82 | |
83 | + def _create_movie(self, filename): |
84 | + '''Factory method to create a movie.''' |
85 | + self.cursor.execute( |
86 | + """SELECT metadata.filename, hash, length, resolution, |
87 | + title, runtime, genres, rating, year, |
88 | + plot_outline, plot, actor_1, actor_2, |
89 | + actor_3, actor_4, actor_5, writer_1, |
90 | + writer_2, director_1, director_2 |
91 | + FROM videofile, metadata |
92 | + WHERE metadata.filename=:fn |
93 | + AND videofile.filename=metadata.filename |
94 | + ORDER BY title""", { "fn" : filename }) |
95 | + result = self.cursor.fetchall() |
96 | + db_movie = result[0] |
97 | + |
98 | + movie = Movie() |
99 | + movie.filename = db_movie[0] |
100 | + movie.art_hash = db_movie[1] |
101 | + movie.title = db_movie[4] |
102 | + movie.runtime = db_movie[5] |
103 | + movie.genres = db_movie[6].split(',') |
104 | + movie.plot = db_movie[10] |
105 | + movie.rating = db_movie[7] |
106 | + movie.short_plot = db_movie[9] |
107 | + movie.year = db_movie[8] |
108 | + |
109 | + for i in range(11, 16): |
110 | + if len(db_movie[i]) > 0: |
111 | + movie.actors.append(db_movie[i]) |
112 | + |
113 | + for i in [16, 17]: |
114 | + if len(db_movie[i]) > 0: |
115 | + movie.writers.append(db_movie[i]) |
116 | + |
117 | + for i in [18, 19]: |
118 | + if len(db_movie[i]) > 0: |
119 | + movie.directors.append(db_movie[i]) |
120 | + |
121 | + return movie |
122 | + |
123 | def get_tv_series(self): |
124 | - """ |
125 | - Get all TV-series. |
126 | - @return: List of TV-series titles (strings) |
127 | - """ |
128 | - connection = sqlite.connect(self.config.VIDEO_DB) |
129 | - cursor = connection.cursor() |
130 | - cursor.execute("""SELECT DISTINCT series_title |
131 | + '''Get all the TV series.''' |
132 | + self.cursor.execute("""SELECT DISTINCT series_title |
133 | FROM metadata |
134 | WHERE type='TV-SERIES' |
135 | ORDER BY title""") |
136 | series = [] |
137 | - for row in cursor: |
138 | - series.append(TVSeries(row[0])) |
139 | - connection.close() |
140 | + for row in self.cursor.fetchall(): |
141 | + series.append(self._create_tv_series(row[0])) |
142 | return series |
143 | |
144 | + def _create_tv_series(self, title): |
145 | + '''Factory method to create a TV series.''' |
146 | + tv_series = TVSeries(title) |
147 | + |
148 | + self.cursor.execute( |
149 | + "SELECT DISTINCT season FROM metadata WHERE series_title=:title", |
150 | + { "title" : title }) |
151 | + for row in self.cursor.fetchall(): |
152 | + tv_series.seasons.append(row[0]) |
153 | + |
154 | + self.cursor.execute( |
155 | + "SELECT COUNT(filename) FROM metadata WHERE series_title=:title", |
156 | + { "title" : title }) |
157 | + result = self.cursor.fetchall() |
158 | + tv_series.number_of_episodes = result[0][0] |
159 | + |
160 | + return tv_series |
161 | + |
162 | def get_video_clips(self): |
163 | - """ |
164 | - Get List of videos that or not movies or tv-series episodes. |
165 | - @return: List of VideoClip objects |
166 | - """ |
167 | - connection = sqlite.connect(self.config.VIDEO_DB) |
168 | - cursor = connection.cursor() |
169 | - cursor.execute("""SELECT filename |
170 | + '''Get all the video clips.''' |
171 | + self.cursor.execute("""SELECT filename |
172 | FROM metadata |
173 | WHERE type='CLIP' |
174 | ORDER BY title""") |
175 | clips = [] |
176 | - for row in cursor: |
177 | - clips.append(VideoClip(row[0])) |
178 | - connection.close() |
179 | + for row in self.cursor.fetchall(): |
180 | + clips.append(self._create_video_clip(row[0])) |
181 | return clips |
182 | |
183 | + def _create_video_clip(self, filename): |
184 | + '''Factory method to create a video clip.''' |
185 | + self.cursor.execute( |
186 | + """SELECT videofile.filename, hash, title |
187 | + FROM videofile, metadata |
188 | + WHERE videofile.filename=:fn |
189 | + AND videofile.filename=metadata.filename |
190 | + ORDER BY title""", { "fn" : filename }) |
191 | + result = self.cursor.fetchall() |
192 | + |
193 | + video_item = VideoItem() |
194 | + video_item.filename = result[0][0] |
195 | + video_item.art_hash = result[0][1] |
196 | + video_item.title = result[0][2] |
197 | + return video_item |
198 | + |
199 | def get_number_of_movies(self): |
200 | - """ |
201 | - Get number of movies in the video library |
202 | - @return: Integer |
203 | - """ |
204 | - connection = sqlite.connect(self.config.VIDEO_DB) |
205 | - cursor = connection.cursor() |
206 | - cursor.execute("""SELECT COUNT(filename) |
207 | - FROM metadata |
208 | - WHERE type='MOVIE'""") |
209 | - result = cursor.fetchall() |
210 | - connection.close() |
211 | + '''Get the number of movies.''' |
212 | + self.cursor.execute( |
213 | + """SELECT COUNT(filename) FROM metadata WHERE type='MOVIE'""") |
214 | + result = self.cursor.fetchall() |
215 | return result[0][0] |
216 | |
217 | def get_number_of_tv_series(self): |
218 | - """ |
219 | - Get number of TV-series in the video library |
220 | - @return: Integer |
221 | - """ |
222 | - connection = sqlite.connect(self.config.VIDEO_DB) |
223 | - cursor = connection.cursor() |
224 | - cursor.execute("""SELECT DISTINCT COUNT(series_title) |
225 | + '''Get the number of TV series.''' |
226 | + self.cursor.execute("""SELECT DISTINCT COUNT(series_title) |
227 | FROM metadata |
228 | WHERE type='TV-SERIES'""") |
229 | - result = cursor.fetchall() |
230 | - connection.close() |
231 | + result = self.cursor.fetchall() |
232 | return result[0][0] |
233 | |
234 | def get_number_of_video_clips(self): |
235 | - """ |
236 | - Get number of misc. VideoClips in the video library |
237 | - @return: Integer |
238 | - """ |
239 | - connection = sqlite.connect(self.config.VIDEO_DB) |
240 | - cursor = connection.cursor() |
241 | - cursor.execute("""SELECT COUNT(filename) |
242 | + '''Get the number of video clips.''' |
243 | + self.cursor.execute( |
244 | + """SELECT COUNT(filename) FROM metadata WHERE type='CLIP'""") |
245 | + result = self.cursor.fetchall() |
246 | + return result[0][0] |
247 | + |
248 | + def get_episodes_from_season(self, series_title, season_number): |
249 | + '''Get TV episodes from the series' season.''' |
250 | + self.cursor.execute("""SELECT filename |
251 | FROM metadata |
252 | - WHERE type='CLIP'""") |
253 | - result = cursor.fetchall() |
254 | - connection.close() |
255 | - return result[0][0] |
256 | + WHERE series_title=:title |
257 | + AND season=:season |
258 | + ORDER BY episode""", |
259 | + { "title" : series_title, "season" : season_number }) |
260 | + episodes = [] |
261 | + for row in self.cursor.fetchall(): |
262 | + episodes.append(self._create_tv_episode(row[0])) |
263 | + return episodes |
264 | + |
265 | + def _create_tv_episode(self, filename): |
266 | + '''Factory method to create a TV episode.''' |
267 | + self.cursor.execute( |
268 | + """SELECT videofile.filename, hash, title, plot, episode |
269 | + FROM videofile, metadata |
270 | + WHERE videofile.filename=:fn |
271 | + AND videofile.filename=metadata.filename |
272 | + ORDER BY title""", { "fn" : filename }) |
273 | + result = self.cursor.fetchall() |
274 | + db_episode = result[0] |
275 | + |
276 | + tv_episode = TVEpisode() |
277 | + tv_episode.filename = db_episode[0] |
278 | + tv_episode.art_hash = db_episode[1] |
279 | + tv_episode.title = db_episode[2] |
280 | + tv_episode.plot = db_episode[3] |
281 | + tv_episode.number = db_episode[4] |
282 | + |
283 | + return tv_episode |
284 | |
285 | |
286 | class VideoItem(Playable): |
287 | - """ |
288 | - Objects from this class represents video items |
289 | - """ |
290 | + '''Representation of a playable video item.''' |
291 | |
292 | def __init__(self): |
293 | - """Initialize the VideoItem object""" |
294 | + # XXX: laymansterms - VideoItem should really have a few mandatory |
295 | + # parameters. title, filename, maybe more. |
296 | Playable.__init__(self) |
297 | self.config = Configuration() |
298 | |
299 | - #Setting default values |
300 | - self.logger = Logger().getLogger( |
301 | - 'client.medialibrary.videos.VideoItem') |
302 | - self.__title = "" |
303 | - self.__filename = "" |
304 | - self.__length = 0 |
305 | - self.__resolution = "" |
306 | - self.__art_hash = "" |
307 | - |
308 | - def get_cover_art_url(self): |
309 | - """ |
310 | - Get absolute filename of the cover art image file. |
311 | - @return: String |
312 | - """ |
313 | - return os.path.join(self.config.MOVIE_ART_DIR, |
314 | - self.get_title() + ".jpg") |
315 | - |
316 | - def get_filename(self): |
317 | - """ |
318 | - Get filename (abs path) of the VideoItem |
319 | - @return: String |
320 | - """ |
321 | - return self.__filename |
322 | - |
323 | - def set_filename(self, filename): |
324 | - """ |
325 | - Sets the filename of the VideoItem |
326 | - @param filename String |
327 | - """ |
328 | - self.__filename = filename |
329 | - |
330 | - def get_title(self): |
331 | - """ |
332 | - Get title of the VideoItem |
333 | - @return: String |
334 | - """ |
335 | - if (self.__title == "") or (self.__title == None): |
336 | - return self.get_filename() |
337 | - else: |
338 | - return self.__title |
339 | - |
340 | - def set_title(self, title): |
341 | - """ |
342 | - Sets the title of the VideoItem |
343 | - @param title String |
344 | - """ |
345 | - self.__title = title |
346 | - |
347 | - def get_length(self): |
348 | - """ |
349 | - Get length of the VideoItem |
350 | - @return: Integer |
351 | - """ |
352 | - return self.__length |
353 | - |
354 | - def set_length(self, length): |
355 | - """ |
356 | - Sets the length of the VideoItem |
357 | - @param length Integer |
358 | - """ |
359 | - self.__length = length |
360 | - |
361 | - def get_resolution(self): |
362 | - """ |
363 | - Get resolution of the VideoItem |
364 | - @return: String |
365 | - """ |
366 | - return self.__resolution |
367 | - |
368 | - def set_resolution(self, res): |
369 | - """ |
370 | - Sets the resolution of the VideoItem |
371 | - @param res String |
372 | - """ |
373 | - self.__resolution = res |
374 | - |
375 | - def get_thumbnail_url(self): |
376 | - """ |
377 | - Get absolute path of the thumbnail image file. |
378 | - @return: String |
379 | - """ |
380 | - if self.get_art_hash() is not None: |
381 | - thumb = os.path.join(self.config.VIDEO_THUMB_DIR, |
382 | - self.get_art_hash() + ".jpg") |
383 | - if os.path.exists(thumb): |
384 | - return thumb |
385 | - else: |
386 | - self.logger.error("Thumbnail does not exist for " + \ |
387 | - self.get_filename() + ", using default art instead") |
388 | - return os.path.join(self.config.theme_path, |
389 | - "images/default_movie_art.png") |
390 | - else: |
391 | - self.logger.error("Thumbnail does not exist for " + \ |
392 | - self.get_filename() + ", using default art instead") |
393 | - return os.path.join(self.config.theme_path, |
394 | - "images/default_movie_art.png") |
395 | + self._title = "" |
396 | + self.filename = "" |
397 | + self.art_hash = "" |
398 | + |
399 | + def _get_title(self): |
400 | + '''Get the title.''' |
401 | + if (self._title == "") or (self._title == None): |
402 | + return self.filename |
403 | + else: |
404 | + return self._title |
405 | + |
406 | + def _set_title(self, title): |
407 | + '''Set the title.''' |
408 | + self._title = title |
409 | + |
410 | + title = property(_get_title, _set_title) |
411 | |
412 | def has_thumbnail(self): |
413 | - """ |
414 | - Is there a thumbnail for this VideoItem |
415 | - @return Boolean |
416 | - """ |
417 | + '''Test if there is a thumbnail.''' |
418 | thumb_path = os.path.join(self.config.VIDEO_THUMB_DIR, |
419 | - self.get_art_hash() + ".jpg") |
420 | + self.art_hash + ".jpg") |
421 | return os.path.exists(thumb_path) |
422 | |
423 | - def get_art_hash(self): |
424 | - """ |
425 | - Gets the art hash |
426 | - @return String |
427 | - """ |
428 | - return self.__art_hash |
429 | - |
430 | - def set_art_hash(self, arthash): |
431 | - """ |
432 | - Sets the art hash |
433 | - @param arthash String |
434 | - """ |
435 | - self.__art_hash = arthash |
436 | - |
437 | - def has_cover_art(self): |
438 | - """ |
439 | - Is there cover art file for this VideoItem |
440 | - @return: Boolean |
441 | - """ |
442 | - art_path = os.path.join(self.config.MOVIE_ART_DIR, |
443 | - self.get_title() + ".jpg") |
444 | - return os.path.exists(art_path) |
445 | + @property |
446 | + def thumbnail_url(self): |
447 | + '''Get the path to the thumbnail or a default.''' |
448 | + thumb = os.path.join(self.config.VIDEO_THUMB_DIR, |
449 | + self.art_hash + ".jpg") |
450 | + if os.path.exists(thumb): |
451 | + return thumb |
452 | + else: |
453 | + return os.path.join(self.config.theme_path, |
454 | + "images/default_movie_art.png") |
455 | |
456 | # Implement playable interface |
457 | + def get_title(self): |
458 | + '''Get the title.''' |
459 | + return self.title |
460 | + |
461 | def get_type(self): |
462 | - """ |
463 | - Track is an video stream. |
464 | - @return: Integer |
465 | - """ |
466 | + '''Get the type.''' |
467 | return Playable.VIDEO_STREAM |
468 | |
469 | def get_uri(self): |
470 | - """ |
471 | - Get URI of the video file |
472 | - @return: String |
473 | - """ |
474 | - return "file://" + self.get_filename() |
475 | + '''Get the URI.''' |
476 | + return "file://" + self.filename |
477 | |
478 | |
479 | class VideoFilm(VideoItem): |
480 | - '''Objects from this class represents video films''' |
481 | + '''Generic representation of a film.''' |
482 | + |
483 | def __init__(self): |
484 | VideoItem.__init__(self) |
485 | - #initialise values |
486 | - self.__plot_outline = "" |
487 | - self.__plot = "" |
488 | - self.__actors = [] |
489 | - self.__writers = [] |
490 | - self.__directors = [] |
491 | - self.__runtime = "" |
492 | - self.__genres = [] |
493 | - self.__rating = 0.0 |
494 | - self.__year = 2000 |
495 | - |
496 | - def get_short_plot(self): |
497 | - """ |
498 | - Get plot outline text. |
499 | - @return: String |
500 | - """ |
501 | - return self.__plot_outline |
502 | - |
503 | - def set_short_plot(self, plot): |
504 | - """ |
505 | - Set plot outline |
506 | - @param plot String |
507 | - """ |
508 | - self.__plot_outline = plot |
509 | - |
510 | - def get_plot(self): |
511 | - """ |
512 | - Get long plot text. |
513 | - @return: String |
514 | - """ |
515 | - return self.__plot |
516 | - |
517 | - def set_plot(self, plot): |
518 | - """ |
519 | - Sets the long plot |
520 | - @param plot String |
521 | - """ |
522 | - self.__plot = plot |
523 | - |
524 | - def get_actors(self): |
525 | - """ |
526 | - Get list of actors |
527 | - @return: List of strings |
528 | - """ |
529 | - return self.__actors |
530 | - |
531 | - def set_actors(self, actors): |
532 | - """ |
533 | - Sets list of actors |
534 | - @param actors List of Strings |
535 | - """ |
536 | - self.__actors = actors |
537 | - |
538 | - def get_writers(self): |
539 | - """ |
540 | - Get list of writers |
541 | - @return: List of strings |
542 | - """ |
543 | - return self.__writers |
544 | - |
545 | - def set_writers(self, writers): |
546 | - """ |
547 | - Sets list of writers |
548 | - @param writers List of Strings |
549 | - """ |
550 | - self.__writers = writers |
551 | - |
552 | - def get_directors(self): |
553 | - """ |
554 | - Get list of directors |
555 | - @return: List of strings |
556 | - """ |
557 | - return self.__directors |
558 | - |
559 | - def set_directors(self, directors): |
560 | - """ |
561 | - Sets list of directors |
562 | - @param directors List of Strings |
563 | - """ |
564 | - self.__directors = directors |
565 | - |
566 | - def get_runtime(self): |
567 | - """ |
568 | - Get runtime of the VideoFilm |
569 | - @return: String |
570 | - """ |
571 | - return self.__runtime |
572 | - |
573 | - def set_runtime(self, run): |
574 | - """ |
575 | - Set runtime of the VideoFilm |
576 | - @param run String |
577 | - """ |
578 | - self.__runtime = run |
579 | - |
580 | - def get_genres(self): |
581 | - """ |
582 | - Get list of genre strings |
583 | - @return: List of strings |
584 | - """ |
585 | - return self.__genres |
586 | - |
587 | - def set_genres(self, genres): |
588 | - """ |
589 | - Sets list of genres |
590 | - @param genres List of Strings |
591 | - """ |
592 | - self.__genres = genres |
593 | - |
594 | - def get_rating(self): |
595 | - """ |
596 | - Get rating of the VideoFilm (1-5) |
597 | - @return: Integer |
598 | - """ |
599 | - return int(self.__rating) |
600 | - |
601 | - def set_rating(self, rating): |
602 | - """ |
603 | - Sets rating of the VideoFilm (1-5) |
604 | - @param rating Integer |
605 | - """ |
606 | - self.__rating = int(rating) |
607 | - |
608 | - def get_year(self): |
609 | - """ |
610 | - Get release year of the VideoFilm. |
611 | - @return: String |
612 | - """ |
613 | - return int(self.__year) |
614 | - |
615 | - def set_year(self, year): |
616 | - """ |
617 | - Sets the year of the VideoFilm |
618 | - @param year String |
619 | - """ |
620 | - try: |
621 | - self.__year = int(year) |
622 | - except ValueError: |
623 | - self.__year = 0 |
624 | - print "Year for Video should be an integer, not: ", year |
625 | - |
626 | - |
627 | -class VideoClip(VideoItem): |
628 | - """ |
629 | - Objects from this class represents video files. |
630 | - """ |
631 | - |
632 | - def __init__(self, filename): |
633 | - """ |
634 | - Initialize Clip information |
635 | - @param filename: Absolute path of the video clip file |
636 | - """ |
637 | - VideoItem.__init__(self) |
638 | - connection = sqlite.connect(self.config.VIDEO_DB) |
639 | - cursor = connection.cursor() |
640 | - cursor.execute( |
641 | - """SELECT videofile.filename, hash, length, resolution, title |
642 | - FROM videofile, metadata |
643 | - WHERE videofile.filename=:fn |
644 | - AND videofile.filename=metadata.filename |
645 | - ORDER BY title""", { "fn" : filename }) |
646 | - result = cursor.fetchall() |
647 | - self.set_filename(result[0][0]) # Filename of the clip |
648 | - self.set_art_hash(result[0][1]) # Cover art hash |
649 | - self.set_length(result[0][2]) # Lenght of the movie |
650 | - self.set_resolution(result[0][3]) # Video resolution |
651 | - self.set_title(result[0][4]) # Clip title |
652 | - connection.close() |
653 | + self.actors = [] |
654 | + self.directors = [] |
655 | + self.genres = [] |
656 | + self.plot = '' |
657 | + self.runtime = '' |
658 | + self.short_plot = '' |
659 | + self.writers = [] |
660 | + self.rating = 0 |
661 | + self.year = 2000 |
662 | |
663 | |
664 | class Movie(VideoFilm): |
665 | - """ |
666 | - Objects from this class represents movie. |
667 | - """ |
668 | - |
669 | - |
670 | - def __init__(self, filename): |
671 | - """ |
672 | - Initialize Movie information |
673 | - @param filename: Absolute path of the Movie file |
674 | - """ |
675 | - VideoFilm.__init__(self) |
676 | - connection = sqlite.connect(self.config.VIDEO_DB) |
677 | - cursor = connection.cursor() |
678 | - cursor.execute("""SELECT metadata.filename, hash, length, resolution, |
679 | - title, runtime, genres, rating, year, |
680 | - plot_outline, plot, actor_1, actor_2, |
681 | - actor_3, actor_4, actor_5, writer_1, |
682 | - writer_2, director_1, director_2 |
683 | - FROM videofile, metadata |
684 | - WHERE metadata.filename=:fn |
685 | - AND videofile.filename=metadata.filename |
686 | - ORDER BY title""", { "fn" : filename }) |
687 | - result = cursor.fetchall() |
688 | - self.set_filename(result[0][0]) |
689 | - self.set_art_hash(result[0][1]) |
690 | - self.set_length(result[0][2]) |
691 | - self.set_resolution(result[0][3]) |
692 | - self.set_title(result[0][4]) |
693 | - self.set_runtime(result[0][5]) |
694 | - self.set_genres(result[0][6].split(',')) |
695 | - self.set_rating(result[0][7]) |
696 | - self.set_year(result[0][8]) |
697 | - self.set_short_plot(result[0][9]) |
698 | - self.set_plot(result[0][10]) |
699 | - self.set_actors([]) |
700 | - self.set_art_hash([]) |
701 | - self.set_directors([]) |
702 | - |
703 | - # Actors |
704 | - if len(result[0][11]) > 0: |
705 | - self.get_actors().append(result[0][11]) |
706 | - if len(result[0][12]) > 0: |
707 | - self.get_actors().append(result[0][12]) |
708 | - if len(result[0][13]) > 0: |
709 | - self.get_actors().append(result[0][13]) |
710 | - if len(result[0][14]) > 0: |
711 | - self.get_actors().append(result[0][14]) |
712 | - if len(result[0][15]) > 0: |
713 | - self.get_actors().append(result[0][15]) |
714 | - |
715 | - # Writers |
716 | - if len(result[0][16]) > 0: |
717 | - self.get_writers().append(result[0][16]) |
718 | - if len(result[0][17]) > 0: |
719 | - self.get_writers().append(result[0][17]) |
720 | - |
721 | - # Directors |
722 | - if len(result[0][18]) > 0: |
723 | - self.get_directors().append(result[0][18]) |
724 | - if len(result[0][19]) > 0: |
725 | - self.get_directors().append(result[0][19]) |
726 | - |
727 | - connection.close() |
728 | + '''Representation of a movie.''' |
729 | + |
730 | + def has_cover_art(self): |
731 | + '''Test if there is cover art in the cache.''' |
732 | + art_path = os.path.join(self.config.MOVIE_ART_DIR, self.title + ".jpg") |
733 | + return os.path.exists(art_path) |
734 | + |
735 | + @property |
736 | + def cover_art_url(self): |
737 | + '''Get the URL to the cover art.''' |
738 | + return os.path.join(self.config.MOVIE_ART_DIR, self.title + ".jpg") |
739 | |
740 | |
741 | class TVSeries(object): |
742 | - """ |
743 | - TV Series |
744 | - |
745 | - TV Series contains TVEpisodes organized by seasons. |
746 | - """ |
747 | + '''TV Series contains TVEpisodes organized by seasons.''' |
748 | |
749 | def __init__(self, title): |
750 | - """ |
751 | - Initialize TV-Series |
752 | - @param title: Series title |
753 | - """ |
754 | self.config = Configuration() |
755 | |
756 | - connection = sqlite.connect(self.config.VIDEO_DB) |
757 | - cursor = connection.cursor() |
758 | - cursor.execute("""SELECT DISTINCT series_title |
759 | - FROM metadata |
760 | - WHERE series_title=:title""", { "title" : title }) |
761 | - result = cursor.fetchall() |
762 | - self.__title = None |
763 | - if len(result) == 0: |
764 | - raise Exception("No such TV-series as " + title) |
765 | - else: |
766 | - self.__title = title |
767 | - connection.close() |
768 | - |
769 | - def get_title(self): |
770 | - """ |
771 | - Get title of the series |
772 | - @return: String |
773 | - """ |
774 | - return self.__title |
775 | - |
776 | - def set_title(self, title): |
777 | - """ |
778 | - Sets title of the series |
779 | - @param title String |
780 | - """ |
781 | - self.__title = title |
782 | + self.number_of_episodes = 0 |
783 | + # Season list of numbers. For example [1,2,3,5] in case that user |
784 | + # doesn't have episodes from season 4. |
785 | + self.seasons = [] |
786 | + self.title = title |
787 | |
788 | def has_cover_art(self): |
789 | - """ |
790 | - Is there cover art file for this TV-serie |
791 | - @return: String |
792 | - """ |
793 | - art_path = os.path.join(self.config.MOVIE_ART_DIR, |
794 | - self.get_title() + ".jpg") |
795 | + '''Test if there is cover art in the cache.''' |
796 | + art_path = os.path.join(self.config.MOVIE_ART_DIR, self.title + ".jpg") |
797 | return os.path.exists(art_path) |
798 | |
799 | - def get_cover_art_url(self): |
800 | - """ |
801 | - Get absolute filename of the cover art image file. |
802 | - @return: String |
803 | - """ |
804 | - return os.path.join(self.config.MOVIE_ART_DIR, |
805 | - self.get_title() + ".jpg") |
806 | - |
807 | - def get_seasons(self): |
808 | - """ |
809 | - Return list of numbers. For example [1,2,3,5] in case that user |
810 | - doesn't have episodes from season 4. |
811 | - @return: List of Integers |
812 | - """ |
813 | - seasons = [] |
814 | - connection = sqlite.connect(self.config.VIDEO_DB) |
815 | - cursor = connection.cursor() |
816 | - cursor.execute("""SELECT DISTINCT season |
817 | - FROM metadata |
818 | - WHERE series_title=:title""", |
819 | - { "title" : self.get_title() }) |
820 | - for row in cursor: |
821 | - seasons.append(row[0]) |
822 | - connection.close() |
823 | - return seasons |
824 | - |
825 | - def get_number_of_episodes(self): |
826 | - """ |
827 | - Get number of episodes available on this series |
828 | - @return: Integer |
829 | - """ |
830 | - connection = sqlite.connect(self.config.VIDEO_DB) |
831 | - cursor = connection.cursor() |
832 | - cursor.execute("""SELECT COUNT(filename) |
833 | - FROM metadata |
834 | - WHERE series_title=:title""", |
835 | - { "title" : self.get_title() }) |
836 | - result = cursor.fetchall() |
837 | - connection.close() |
838 | - return result[0][0] |
839 | - |
840 | - def get_number_of_seasons(self): |
841 | - """ |
842 | - Get number of seasons available on this series |
843 | - @return: Integer |
844 | - """ |
845 | - connection = sqlite.connect(self.config.VIDEO_DB) |
846 | - cursor = connection.cursor() |
847 | - cursor.execute("""SELECT COUNT(DISTINCT season) |
848 | - FROM metadata |
849 | - WHERE series_title=:title""", |
850 | - { "title" : self.get_title() }) |
851 | - result = cursor.fetchall() |
852 | - connection.close() |
853 | - return result[0][0] |
854 | - |
855 | - def get_episodes_from_season(self, season): |
856 | - """ |
857 | - Get all episodes of the season. |
858 | - @param season: Season number (Integer) |
859 | - """ |
860 | - episodes = [] |
861 | - connection = sqlite.connect(self.config.VIDEO_DB) |
862 | - cursor = connection.cursor() |
863 | - cursor.execute("""SELECT filename, episode |
864 | - FROM metadata |
865 | - WHERE series_title=:title |
866 | - AND season=:season |
867 | - ORDER BY episode""", |
868 | - { "title" : self.get_title(), "season" : season }) |
869 | - for row in cursor: |
870 | - episodes.append(TVEpisode(row[0], self)) |
871 | - connection.close() |
872 | - return episodes |
873 | - |
874 | - def get_episode_from_season(self, season, episode): |
875 | - """ |
876 | - Get specific episode from this series. |
877 | - @param season: Season number (Integer) |
878 | - @param episode: Episode number (Integer) |
879 | - @return TVEpisode object |
880 | - """ |
881 | - connection = sqlite.connect(self.config.VIDEO_DB) |
882 | - cursor = connection.cursor() |
883 | - cursor.execute("""SELECT filename |
884 | - FROM metadata |
885 | - WHERE series_title=:title |
886 | - AND episode=:episode |
887 | - AND season=:season""", |
888 | - { "title" : self.get_title(), |
889 | - "season" : season, |
890 | - "episode" : episode }) |
891 | - result = cursor.fetchall() |
892 | - episode = TVEpisode(result[0][0], self) |
893 | - connection.close() |
894 | - return episode |
895 | - |
896 | - def get_episodes(self): |
897 | - """ |
898 | - Get all episodes of this series. |
899 | - @return: List of TVEpisode objects |
900 | - """ |
901 | - episodes = [] |
902 | - connection = sqlite.connect(self.config.VIDEO_DB) |
903 | - cursor = connection.cursor() |
904 | - cursor.execute("""SELECT filename, season, episode |
905 | - FROM metadata |
906 | - WHERE series_title=:title |
907 | - ORDER BY season, episode""", |
908 | - { "title" : self.get_title() }) |
909 | - for row in cursor: |
910 | - episodes.append(TVEpisode(row[0], self)) |
911 | - connection.close() |
912 | - return episodes |
913 | + @property |
914 | + def cover_art_url(self): |
915 | + '''Get the URL to the cover art.''' |
916 | + return os.path.join(self.config.MOVIE_ART_DIR, self.title + ".jpg") |
917 | |
918 | |
919 | class TVEpisode(VideoFilm): |
920 | - """ |
921 | - Objects from this class represents TV-Episode video file. |
922 | - """ |
923 | + '''Representation of a TV show episode.''' |
924 | |
925 | - def __init__(self, filename, series): |
926 | - """ |
927 | - Initialize episode information. |
928 | - @param filename: Name of the video file |
929 | - @param series: TVSeries object |
930 | - """ |
931 | + def __init__(self): |
932 | VideoFilm.__init__(self) |
933 | - connection = sqlite.connect(self.config.VIDEO_DB) |
934 | - cursor = connection.cursor() |
935 | - cursor.execute("""SELECT videofile.filename, hash, length, resolution, |
936 | - title, runtime, genres, rating, year, |
937 | - plot_outline, plot, actor_1, actor_2, |
938 | - actor_3, actor_4, actor_5, writer_1, |
939 | - writer_2, director_1, director_2, |
940 | - series_title, season, episode |
941 | - FROM videofile, metadata |
942 | - WHERE videofile.filename=:fn |
943 | - AND videofile.filename=metadata.filename |
944 | - ORDER BY title""", { "fn" : filename }) |
945 | - result = cursor.fetchall() |
946 | - self.set_filename(result[0][0]) |
947 | - self.set_art_hash(result[0][1]) |
948 | - self.set_length(result[0][2]) |
949 | - self.set_resolution(result[0][3]) |
950 | - self.set_title(result[0][4]) |
951 | - self.set_runtime(result[0][5]) |
952 | - self.set_genres(result[0][6].split(',')) |
953 | - self.set_rating(result[0][7]) |
954 | - self.set_year(result[0][8]) |
955 | - self.set_short_plot(result[0][9]) |
956 | - self.set_plot(result[0][10]) |
957 | - |
958 | - # Actors |
959 | - self.set_actors([]) |
960 | - if len(result[0][11]) > 0: |
961 | - self.get_actors().append(result[0][11]) |
962 | - if len(result[0][12]) > 0: |
963 | - self.get_actors().append(result[0][12]) |
964 | - if len(result[0][13]) > 0: |
965 | - self.get_actors().append(result[0][13]) |
966 | - if len(result[0][14]) > 0: |
967 | - self.get_actors().append(result[0][14]) |
968 | - if len(result[0][15]) > 0: |
969 | - self.get_actors().append(result[0][15]) |
970 | - |
971 | - # Writers |
972 | - self.set_writers([]) |
973 | - if len(result[0][16]) > 0: |
974 | - self.get_writers().append(result[0][16]) |
975 | - if len(result[0][17]) > 0: |
976 | - self.get_writers().append(result[0][17]) |
977 | - |
978 | - # Directors |
979 | - self.set_directors([]) |
980 | - if len(result[0][18]) > 0: |
981 | - self.get_directors().append(result[0][18]) |
982 | - if len(result[0][19]) > 0: |
983 | - self.get_directors().append(result[0][19]) |
984 | - |
985 | - self.__series = series |
986 | - self.__season = result[0][21] |
987 | - self.__episode_number = result[0][22] |
988 | - connection.close() |
989 | - |
990 | - def get_cover_art_url(self): |
991 | - """ |
992 | - Get absolute filename of the cover art image file. |
993 | - @return: String |
994 | - """ |
995 | - return os.path.join(self.config.MOVIE_ART_DIR, |
996 | - self.get_series() + ".jpg") |
997 | - |
998 | - def get_series(self): |
999 | - """ |
1000 | - Get TV-series |
1001 | - @return: TVSeries objects |
1002 | - """ |
1003 | - return self.__series |
1004 | - |
1005 | - def set_series(self, series): |
1006 | - """ |
1007 | - Sets TV-Series |
1008 | - @param series TVSeries |
1009 | - """ |
1010 | - self.__series = series |
1011 | - |
1012 | - def get_episode_number(self): |
1013 | - """ |
1014 | - Get number of the episode |
1015 | - @return: Integer |
1016 | - """ |
1017 | - return int(self.__episode_number) |
1018 | - |
1019 | - def set_episode_number(self, num): |
1020 | - """ |
1021 | - Sets the number of the episode |
1022 | - @param num Integer |
1023 | - """ |
1024 | - self.__episode_number = int(num) |
1025 | - |
1026 | - def get_season(self): |
1027 | - """ |
1028 | - Get number of the season |
1029 | - @return: Interger |
1030 | - """ |
1031 | - return int(self.__season) |
1032 | - |
1033 | - def set_season(self, season): |
1034 | - """ |
1035 | - Sets number of the season |
1036 | - @param season Integer |
1037 | - """ |
1038 | - self.__season = int(season) |
1039 | + self.number = 0 |
1040 | |
1041 | |
1042 | === modified file 'entertainerlib/gui/screens/factory.py' |
1043 | --- entertainerlib/gui/screens/factory.py 2010-04-02 22:28:04 +0000 |
1044 | +++ entertainerlib/gui/screens/factory.py 2010-04-03 23:02:16 +0000 |
1045 | @@ -135,6 +135,7 @@ |
1046 | def _generate_tv_series(self, kwargs): |
1047 | '''Generate a TvSeries screen.''' |
1048 | kwargs['move_to_new_screen_callback'] = self.move_to_new_screen_callback |
1049 | + kwargs['video_library'] = self.video_library |
1050 | return TvSeries(**kwargs) |
1051 | |
1052 | def _generate_tv_episodes(self, kwargs): |
1053 | |
1054 | === modified file 'entertainerlib/gui/screens/movie.py' |
1055 | --- entertainerlib/gui/screens/movie.py 2009-12-22 00:07:29 +0000 |
1056 | +++ entertainerlib/gui/screens/movie.py 2010-04-03 23:02:16 +0000 |
1057 | @@ -45,8 +45,7 @@ |
1058 | |
1059 | # Movie art texture |
1060 | if self.movie.has_cover_art(): |
1061 | - pixbuf = gtk.gdk.pixbuf_new_from_file( |
1062 | - self.movie.get_cover_art_url()) |
1063 | + pixbuf = gtk.gdk.pixbuf_new_from_file(self.movie.cover_art_url) |
1064 | else: |
1065 | pixbuf = gtk.gdk.pixbuf_new_from_file( |
1066 | self.theme.getImage("default_movie_art")) |
1067 | @@ -54,21 +53,21 @@ |
1068 | self.add(movie_art) |
1069 | |
1070 | # Movie title |
1071 | - title = Label(0.04, "title", 0.47, 0.1, self.movie.get_title(), |
1072 | + title = Label(0.04, "title", 0.47, 0.1, self.movie.title, |
1073 | font_weight="bold") |
1074 | title.set_ellipsize(pango.ELLIPSIZE_END) |
1075 | title.set_size(0.5124, 0.05208) |
1076 | self.add(title) |
1077 | |
1078 | # Movie release year |
1079 | - year_text = _("Released in %(year)s") % {'year': self.movie.get_year()} |
1080 | + year_text = _("Released in %(year)s") % {'year': self.movie.year} |
1081 | year = Label(0.032, "subtitle", 0.47, 0.3, year_text) |
1082 | year.set_ellipsize(pango.ELLIPSIZE_END) |
1083 | year.set_size(0.5124, 0.05208) |
1084 | self.add(year) |
1085 | |
1086 | # Show only 2 genres (or one if there is only one) |
1087 | - genres_list = self.movie.get_genres() |
1088 | + genres_list = self.movie.genres |
1089 | if len(genres_list) == 0: |
1090 | genres_text = _("Unknown") |
1091 | else: |
1092 | @@ -76,7 +75,7 @@ |
1093 | |
1094 | # Runtime and genres |
1095 | info_text = _("%(runtime)s min, %(genre)s") % \ |
1096 | - {'runtime': self.movie.get_runtime(), 'genre': genres_text} |
1097 | + {'runtime': self.movie.runtime, 'genre': genres_text} |
1098 | info = Label(0.032, "subtitle", 0.47, 0.24, info_text) |
1099 | info.set_ellipsize(pango.ELLIPSIZE_END) |
1100 | info.set_size(0.5124, 0.05208) |
1101 | @@ -90,7 +89,7 @@ |
1102 | star2.hide() |
1103 | self.add(star2) |
1104 | |
1105 | - for i in range(self.movie.get_rating()): |
1106 | + for i in range(self.movie.rating): |
1107 | tex = clutter.Clone(star) |
1108 | tex.set_position( |
1109 | self.get_abs_x(0.47) + (self.get_abs_x(0.0366) * i), |
1110 | @@ -98,16 +97,16 @@ |
1111 | tex.set_size(self.get_abs_x(0.024), self.get_abs_y(0.04)) |
1112 | self.add(tex) |
1113 | |
1114 | - dark_star = 5 - self.movie.get_rating() |
1115 | + dark_star = 5 - self.movie.rating |
1116 | for i in range(dark_star): |
1117 | tex = clutter.Clone(star2) |
1118 | tex.set_position(self.get_abs_x(0.47) + (self.get_abs_x(0.0366) * \ |
1119 | - (i+ self.movie.get_rating())), self.get_abs_y(0.17)) |
1120 | + (i + self.movie.rating)), self.get_abs_y(0.17)) |
1121 | tex.set_size(self.get_abs_x(0.024), self.get_abs_y(0.04)) |
1122 | self.add(tex) |
1123 | |
1124 | # Plot |
1125 | - plot = Label(0.029, "subtitle", 0, 0, self.movie.get_plot()) |
1126 | + plot = Label(0.029, "subtitle", 0, 0, self.movie.plot) |
1127 | plot.set_justify(True) |
1128 | plot.set_line_wrap_mode(pango.WRAP_WORD) |
1129 | plot.set_line_wrap(True) |
1130 | @@ -118,7 +117,7 @@ |
1131 | # Actors |
1132 | self.add(Label(0.032, "title", 0.33, 0.8, _("Starring"))) |
1133 | |
1134 | - actors_list = self.movie.get_actors() |
1135 | + actors_list = self.movie.actors |
1136 | if len(actors_list) == 0: |
1137 | actors_text = _("Unknown") |
1138 | else: |
1139 | @@ -131,7 +130,7 @@ |
1140 | # Directors |
1141 | self.add(Label(0.032, "title", 0.33, 0.86, _("Directed by"))) |
1142 | |
1143 | - directors_list = self.movie.get_directors() |
1144 | + directors_list = self.movie.directors |
1145 | if len(directors_list) == 0: |
1146 | directors_text = _("Unknown") |
1147 | else: |
1148 | @@ -144,7 +143,7 @@ |
1149 | # Writers |
1150 | self.add(Label(0.032, "title", 0.33, 0.92, _("Written by"))) |
1151 | |
1152 | - writers_list = self.movie.get_writers() |
1153 | + writers_list = self.movie.writers |
1154 | if len(directors_list) == 0: |
1155 | writers_text = _("Unknown") |
1156 | else: |
1157 | |
1158 | === modified file 'entertainerlib/gui/screens/tv_episodes.py' |
1159 | --- entertainerlib/gui/screens/tv_episodes.py 2009-12-22 00:34:27 +0000 |
1160 | +++ entertainerlib/gui/screens/tv_episodes.py 2010-04-03 23:02:16 +0000 |
1161 | @@ -14,18 +14,17 @@ |
1162 | class TvEpisodes(Screen): |
1163 | '''Screen contains list of all episodes of one specific season.''' |
1164 | |
1165 | - def __init__(self, media_player, move_to_new_screen_callback, |
1166 | - season_number, tv_series): |
1167 | + def __init__(self, media_player, move_to_new_screen_callback, episodes, |
1168 | + tv_series): |
1169 | Screen.__init__(self, 'TvEpisodes', move_to_new_screen_callback) |
1170 | |
1171 | + self.episodes = episodes |
1172 | self.media_player = media_player |
1173 | self.theme = self.config.theme |
1174 | self.tv_series = tv_series |
1175 | - self.season_number = season_number |
1176 | |
1177 | # Screen Title (Displayed at the bottom left corner) |
1178 | - screen_title = Label(0.13, "screentitle", 0, 0.87, |
1179 | - self.tv_series.get_title()) |
1180 | + screen_title = Label(0.13, "screentitle", 0, 0.87, self.tv_series.title) |
1181 | self.add(screen_title) |
1182 | |
1183 | self.scroll_area = None |
1184 | @@ -37,8 +36,7 @@ |
1185 | |
1186 | #List indicator |
1187 | self.li = ListIndicator(0.8, 0.9, 0.2, 0.045, ListIndicator.VERTICAL) |
1188 | - self.li.set_maximum( |
1189 | - len(self.tv_series.get_episodes_from_season(self.season_number))) |
1190 | + self.li.set_maximum(len(self.episodes)) |
1191 | self.add(self.li) |
1192 | |
1193 | self.menu.connect("moved", self._update_episode_info) |
1194 | @@ -49,10 +47,9 @@ |
1195 | """Create a list of available seasons.""" |
1196 | menu = TextMenu(0.4978, 0.1563, 0.4393, 0.0781) |
1197 | |
1198 | - episodes = self.tv_series.get_episodes_from_season(self.season_number) |
1199 | episodes_list = [[_("%(num)d. %(title)s") % \ |
1200 | - {'num': episode.get_episode_number(), 'title': episode.get_title()}, |
1201 | - None, episode] for episode in episodes] |
1202 | + {'num': episode.number, 'title': episode.title}, |
1203 | + None, episode] for episode in self.episodes] |
1204 | menu.async_add(episodes_list) |
1205 | |
1206 | menu.active = True |
1207 | @@ -65,7 +62,7 @@ |
1208 | self.thumb.hide() |
1209 | |
1210 | # Thumbnail. Use cover art if thumbnail doesn't exist |
1211 | - thumbnail = self.menu.selected_userdata.get_thumbnail_url() |
1212 | + thumbnail = self.menu.selected_userdata.thumbnail_url |
1213 | if(thumbnail is not None): |
1214 | pixbuf = gtk.gdk.pixbuf_new_from_file(thumbnail) |
1215 | thumb_width = 0.2928 |
1216 | @@ -79,7 +76,7 @@ |
1217 | thumb_y = 0.15 |
1218 | if(self.tv_series.has_cover_art()): |
1219 | pixbuf = gtk.gdk.pixbuf_new_from_file( |
1220 | - self.tv_series.get_cover_art_url()) |
1221 | + self.tv_series.cover_art_url) |
1222 | else: |
1223 | pixbuf = gtk.gdk.pixbuf_new_from_file( |
1224 | self.theme.getImage("default_movie_art")) |
1225 | @@ -97,16 +94,14 @@ |
1226 | |
1227 | # Title |
1228 | self.title = Label(0.04, "title", 0.05, 0.55, |
1229 | - self.menu.selected_userdata.get_title(), |
1230 | - font_weight="bold") |
1231 | + self.menu.selected_userdata.title, font_weight="bold") |
1232 | self.title.set_ellipsize(pango.ELLIPSIZE_END) |
1233 | self.title.set_line_wrap(False) |
1234 | self.title.width = 0.4 |
1235 | self.add(self.title) |
1236 | |
1237 | # Plot |
1238 | - plot = Label(0.029, "subtitle", 0, 0, |
1239 | - self.menu.selected_userdata.get_plot()) |
1240 | + plot = Label(0.029, "subtitle", 0, 0, self.menu.selected_userdata.plot) |
1241 | plot.width = 0.4 |
1242 | |
1243 | self.scroll_area = ScrollArea(0.05, 0.63, 0.4, 0.15, plot) |
1244 | @@ -118,11 +113,10 @@ |
1245 | self.li.set_current(self.menu.selected_index + 1) |
1246 | |
1247 | self._create_thumbnail_texture() |
1248 | - self.title.set_text(self.menu.selected_userdata.get_title()) |
1249 | + self.title.set_text(self.menu.selected_userdata.title) |
1250 | self.title.width = 0.4 |
1251 | |
1252 | - plot = Label(0.029, "subtitle", 0, 0, |
1253 | - self.menu.selected_userdata.get_plot()) |
1254 | + plot = Label(0.029, "subtitle", 0, 0, self.menu.selected_userdata.plot) |
1255 | plot.width = 0.4 |
1256 | self.scroll_area.set_content(plot) |
1257 | |
1258 | |
1259 | === modified file 'entertainerlib/gui/screens/tv_series.py' |
1260 | --- entertainerlib/gui/screens/tv_series.py 2009-07-29 03:09:34 +0000 |
1261 | +++ entertainerlib/gui/screens/tv_series.py 2010-04-03 23:02:16 +0000 |
1262 | @@ -12,15 +12,15 @@ |
1263 | class TvSeries(Screen): |
1264 | '''Screen that contains all seasons of one TV series.''' |
1265 | |
1266 | - def __init__(self, move_to_new_screen_callback, tv_series): |
1267 | + def __init__(self, video_library, move_to_new_screen_callback, tv_series): |
1268 | Screen.__init__(self, 'TvSeries', move_to_new_screen_callback) |
1269 | |
1270 | self.theme = self.config.theme |
1271 | self.tv_series = tv_series |
1272 | + self.video_library = video_library |
1273 | |
1274 | # Screen Title (Displayed at the bottom left corner) |
1275 | - screen_title = Label(0.13, "screentitle", 0, 0.87, |
1276 | - self.tv_series.get_title()) |
1277 | + screen_title = Label(0.13, "screentitle", 0, 0.87, self.tv_series.title) |
1278 | self.add(screen_title) |
1279 | |
1280 | self.art = None |
1281 | @@ -31,7 +31,7 @@ |
1282 | |
1283 | #List indicator |
1284 | self.li = ListIndicator(0.8, 0.9, 0.2, 0.045, ListIndicator.VERTICAL) |
1285 | - self.li.set_maximum(len(self.tv_series.get_seasons())) |
1286 | + self.li.set_maximum(len(self.tv_series.seasons)) |
1287 | self.add(self.li) |
1288 | |
1289 | self.menu.connect("moved", self._update_season_info) |
1290 | @@ -43,7 +43,7 @@ |
1291 | """ |
1292 | menu = TextMenu(0.4978, 0.1563, 0.4393, 0.0781) |
1293 | |
1294 | - seasons = self.tv_series.get_seasons() |
1295 | + seasons = self.tv_series.seasons |
1296 | seasons.sort() |
1297 | |
1298 | seasons_list = [[_("Season %(num)s") % {'num': season}, None, season] \ |
1299 | @@ -60,8 +60,7 @@ |
1300 | displays album cover art. |
1301 | """ |
1302 | if(self.tv_series.has_cover_art()): |
1303 | - pixbuf = gtk.gdk.pixbuf_new_from_file( |
1304 | - self.tv_series.get_cover_art_url()) |
1305 | + pixbuf = gtk.gdk.pixbuf_new_from_file(self.tv_series.cover_art_url) |
1306 | else: |
1307 | pixbuf = gtk.gdk.pixbuf_new_from_file( |
1308 | self.theme.getImage("default_movie_art")) |
1309 | @@ -83,6 +82,8 @@ |
1310 | def _handle_select(self, event=None): |
1311 | '''Handle UserEvent.NAVIGATE_SELECT.''' |
1312 | season = self.menu.selected_userdata |
1313 | - kwargs = { 'tv_series' : self.tv_series, 'season_number' : season } |
1314 | + episodes = self.video_library.get_episodes_from_season( |
1315 | + self.tv_series.title, season) |
1316 | + kwargs = { 'episodes' : episodes, 'tv_series' : self.tv_series } |
1317 | self.callback("tv_episodes", kwargs) |
1318 | |
1319 | |
1320 | === modified file 'entertainerlib/gui/tabs/movies_tab.py' |
1321 | --- entertainerlib/gui/tabs/movies_tab.py 2009-12-21 17:22:33 +0000 |
1322 | +++ entertainerlib/gui/tabs/movies_tab.py 2010-04-03 23:02:16 +0000 |
1323 | @@ -80,7 +80,7 @@ |
1324 | menu.visible_cols = 7 |
1325 | |
1326 | movies = self.video_library.get_movies() |
1327 | - movies_list = [[movie.get_cover_art_url(), movie] for movie in movies] |
1328 | + movies_list = [[movie.cover_art_url, movie] for movie in movies] |
1329 | menu.async_add_videos(movies_list) |
1330 | |
1331 | # Create list indicator |
1332 | @@ -114,17 +114,17 @@ |
1333 | '''Update the movie information labels.''' |
1334 | if self.active: |
1335 | movie = self.menu.selected_userdata |
1336 | - genres = movie.get_genres() |
1337 | + genres = movie.genres |
1338 | if len(genres) > 1: |
1339 | genre = genres[0] + "/" + genres[1] |
1340 | else: |
1341 | genre = genres[0] |
1342 | |
1343 | - self.movie_title.set_text(_("%(title)s (%(year)d)") % \ |
1344 | - {'title': movie.get_title(), 'year': movie.get_year()}) |
1345 | + self.movie_title.set_text(_("%(title)s (%(year)s)") % \ |
1346 | + {'title': movie.title, 'year': movie.year}) |
1347 | self.movie_info.set_text(_("%(min)d min, (%(genre)s)") % \ |
1348 | - {'min': movie.get_runtime(), 'genre': genre}) |
1349 | - self.movie_plot.set_text(movie.get_short_plot()) |
1350 | + {'min': movie.runtime, 'genre': genre}) |
1351 | + self.movie_plot.set_text(movie.short_plot) |
1352 | self.list_indicator.show() |
1353 | self.list_indicator.set_current(self.menu.selected_index + 1) |
1354 | else: |
1355 | |
1356 | === modified file 'entertainerlib/gui/tabs/series_tab.py' |
1357 | --- entertainerlib/gui/tabs/series_tab.py 2009-12-21 17:22:33 +0000 |
1358 | +++ entertainerlib/gui/tabs/series_tab.py 2010-04-03 23:02:16 +0000 |
1359 | @@ -79,7 +79,7 @@ |
1360 | menu.visible_cols = 7 |
1361 | |
1362 | series = self.video_library.get_tv_series() |
1363 | - series_list = [[serie.get_cover_art_url(), serie] for serie in series] |
1364 | + series_list = [[serie.cover_art_url, serie] for serie in series] |
1365 | menu.async_add_videos(series_list) |
1366 | |
1367 | # Create list indicator |
1368 | @@ -107,11 +107,10 @@ |
1369 | if self.active: |
1370 | series = self.menu.selected_userdata |
1371 | info = _("%(season)d Seasons\n%(episode)d Episodes") % {'season': |
1372 | - series.get_number_of_seasons(), 'episode': |
1373 | - series.get_number_of_episodes()} |
1374 | + len(series.seasons), 'episode': series.number_of_episodes} |
1375 | |
1376 | self.series_info.set_text(info) |
1377 | - self.series_title.set_text(series.get_title()) |
1378 | + self.series_title.set_text(series.title) |
1379 | self.list_indicator.show() |
1380 | self.list_indicator.set_current(self.menu.selected_index + 1) |
1381 | else: |
1382 | |
1383 | === modified file 'entertainerlib/gui/tabs/video_clips_tab.py' |
1384 | --- entertainerlib/gui/tabs/video_clips_tab.py 2009-12-21 17:22:33 +0000 |
1385 | +++ entertainerlib/gui/tabs/video_clips_tab.py 2010-04-03 23:02:16 +0000 |
1386 | @@ -79,7 +79,7 @@ |
1387 | menu.visible_cols = 4 |
1388 | |
1389 | clips = self.video_library.get_video_clips() |
1390 | - clips_list = [[clip.get_thumbnail_url(), clip] for clip in clips] |
1391 | + clips_list = [[clip.thumbnail_url, clip] for clip in clips] |
1392 | menu.async_add_clips(clips_list) |
1393 | |
1394 | # Create list indicator |
1395 | @@ -109,7 +109,7 @@ |
1396 | '''Update the VideoClip information labels.''' |
1397 | if self.active: |
1398 | clip = self.menu.selected_userdata |
1399 | - (folder, filename) = os.path.split(clip.get_filename()) |
1400 | + (folder, filename) = os.path.split(clip.filename) |
1401 | self.clip_title.set_text(filename) |
1402 | self.clip_info.set_text(folder) |
1403 | self.list_indicator.show() |
1404 | |
1405 | === modified file 'entertainerlib/tests/mock.py' |
1406 | --- entertainerlib/tests/mock.py 2010-04-02 23:13:48 +0000 |
1407 | +++ entertainerlib/tests/mock.py 2010-04-03 23:02:16 +0000 |
1408 | @@ -84,43 +84,15 @@ |
1409 | '''Mock entertainerlib.client.medialibrary.videos.Movie''' |
1410 | |
1411 | def __init__(self, filename=None): |
1412 | - '''Override init to prevent a database connection''' |
1413 | - |
1414 | - def get_actors(self): |
1415 | - '''See `Movie.get_actors`.''' |
1416 | - return ['Tim Robbins'] |
1417 | - |
1418 | - def get_directors(self): |
1419 | - '''See `Movie.get_directors`.''' |
1420 | - return ['Frank Darabont'] |
1421 | - |
1422 | - def get_genres(self): |
1423 | - '''See `Movie.get_genres`.''' |
1424 | - return ['Drama'] |
1425 | - |
1426 | - def get_plot(self): |
1427 | - '''See `Movie.get_plot`.''' |
1428 | - return 'An innocent man is sent to prison' |
1429 | - |
1430 | - def get_rating(self): |
1431 | - '''See `Movie.get_rating`.''' |
1432 | - return 5 |
1433 | - |
1434 | - def get_runtime(self): |
1435 | - '''See `Movie.get_runtime`.''' |
1436 | - return "" |
1437 | - |
1438 | - def get_title(self): |
1439 | - '''See `Movie.get_title`.''' |
1440 | - return 'The Shawshank Redemption' |
1441 | - |
1442 | - def get_writers(self): |
1443 | - '''See `Movie.get_writers`.''' |
1444 | - return ['Frank Darabont'] |
1445 | - |
1446 | - def get_year(self): |
1447 | - '''See `Movie.get_year`.''' |
1448 | - return 1994 |
1449 | + self.actors = ['Tim Robbins'] |
1450 | + self.directors = ['Frank Darabont'] |
1451 | + self.genres = ['Drama'] |
1452 | + self.plot = 'An innocent man is sent to prison' |
1453 | + self.rating = 5 |
1454 | + self.runtime = '' |
1455 | + self.title = 'The Shawshank Redemption' |
1456 | + self.writers = ['Frank Darabont'] |
1457 | + self.year = 1994 |
1458 | |
1459 | def has_cover_art(self): |
1460 | '''See `Movie.has_cover_art`.''' |
1461 | @@ -158,42 +130,22 @@ |
1462 | |
1463 | def __init__(self, title=None): |
1464 | '''Override init to prevent a database connection''' |
1465 | - |
1466 | - def get_episode_number(self): |
1467 | - '''See `TVEpisode.get_episode_number`.''' |
1468 | - return 1 |
1469 | - |
1470 | - def get_plot(self): |
1471 | - '''See `TVEpisode.get_plot`.''' |
1472 | - return 'Dr. House continues to be a jerk' |
1473 | - |
1474 | - def get_thumbnail_url(self): |
1475 | - '''See `TVEpisode.get_thumbnail_url`.''' |
1476 | + self.number = 1 |
1477 | + self.title = 'Something clever' |
1478 | + self.plot = 'Dr. House continues to be a jerk' |
1479 | + |
1480 | + @property |
1481 | + def thumbnail_url(self): |
1482 | + '''Thumbnail URL getter.''' |
1483 | return None |
1484 | |
1485 | - def get_title(self): |
1486 | - '''See `TVEpisode.get_title`.''' |
1487 | - return 'Something clever' |
1488 | - |
1489 | - |
1490 | class MockTVSeries(TVSeries): |
1491 | '''Mock entertainerlib.client.medialibrary.videos.TVSeries''' |
1492 | |
1493 | def __init__(self, title=None): |
1494 | '''Override init to prevent a database connection''' |
1495 | - |
1496 | - def get_episodes_from_season(self, season_number=1): |
1497 | - '''See `TVSeries.get_episodes_from_season`.''' |
1498 | - mock_episode = MockTVEpisode() |
1499 | - return [mock_episode] |
1500 | - |
1501 | - def get_seasons(self): |
1502 | - '''See `TVSeries.get_seasons`.''' |
1503 | - return [] |
1504 | - |
1505 | - def get_title(self): |
1506 | - '''See `TVSeries.get_title`.''' |
1507 | - return 'House' |
1508 | + self.seasons = [] |
1509 | + self.title = 'House' |
1510 | |
1511 | def has_cover_art(self): |
1512 | '''See `TVSeries.has_cover_art`.''' |
1513 | @@ -205,6 +157,9 @@ |
1514 | def __init__(self): |
1515 | '''Override the intial behavior.''' |
1516 | |
1517 | + def __del__(self): |
1518 | + '''Override the delete behavior.''' |
1519 | + |
1520 | def get_number_of_movies(self): |
1521 | '''See `VideoLibrary.get_number_of_movies`.''' |
1522 | return 0 |
1523 | |
1524 | === modified file 'entertainerlib/tests/test_mediaplayer.py' |
1525 | --- entertainerlib/tests/test_mediaplayer.py 2009-07-14 04:56:55 +0000 |
1526 | +++ entertainerlib/tests/test_mediaplayer.py 2010-04-03 23:02:16 +0000 |
1527 | @@ -19,8 +19,7 @@ |
1528 | |
1529 | self.player = MediaPlayer(clutter.Stage(), 100, 100) |
1530 | self.video_item = VideoItem() |
1531 | - self.video_item.set_filename( |
1532 | - THIS_DIR + '/data/VideoThumbnailer/test.avi') |
1533 | + self.video_item.filename = THIS_DIR + '/data/VideoThumbnailer/test.avi' |
1534 | self.player.set_media(self.video_item) |
1535 | |
1536 | def test_create(self): |
1537 | |
1538 | === modified file 'entertainerlib/tests/test_screenfactory.py' |
1539 | --- entertainerlib/tests/test_screenfactory.py 2010-04-02 23:13:48 +0000 |
1540 | +++ entertainerlib/tests/test_screenfactory.py 2010-04-03 23:02:16 +0000 |
1541 | @@ -28,6 +28,7 @@ |
1542 | from entertainerlib.tests.mock import MockMediaPlayer |
1543 | from entertainerlib.tests.mock import MockMovie |
1544 | from entertainerlib.tests.mock import MockMusicLibrary |
1545 | +from entertainerlib.tests.mock import MockTVEpisode |
1546 | from entertainerlib.tests.mock import MockTVSeries |
1547 | from entertainerlib.tests.mock import MockVideoLibrary |
1548 | |
1549 | @@ -129,7 +130,7 @@ |
1550 | |
1551 | def test__generate_tv_episodes(self): |
1552 | '''Test _generate_tv_episodes returns a TvEpisodes screen''' |
1553 | - self.kwargs['season_number'] = 1 |
1554 | + self.kwargs['episodes'] = [MockTVEpisode()] |
1555 | self.kwargs['tv_series'] = MockTVSeries() |
1556 | screen = self.factory._generate_tv_episodes(self.kwargs) |
1557 | self.assertTrue(isinstance(screen, TvEpisodes)) |