Fixing some tabs
[nqaap] / src / opt / Nqa-Audiobook-player / Player.py
1 import os
2 import threading
3 import time
4 import logging
5
6 import constants
7 import hildonize
8 import Audiobook
9 import FileStorage
10
11
12 _moduleLogger = logging.getLogger(__name__)
13
14
15 class Player(object):
16
17     def __init__(self, ui):
18         self.storage = FileStorage.FileStorage(path = constants._data_path_)
19         if hildonize.IS_HILDON_SUPPORTED and not hildonize.IS_FREMANTLE_SUPPORTED:
20             import SimpleOSSOPlayer as _SimplePlayer
21             SimplePlayer = _SimplePlayer # silence PyFlakes
22         else:
23             import SimpleGStreamer as SimplePlayer
24         self.player = SimplePlayer.SimplePlayer(self.next_chapter)
25         self.ui = ui
26         self.audiobook = None
27         self._bookDir = None
28         self._bookPaths = {}
29
30     def get_books_path(self):
31         return self._bookDir
32
33     def load_books_path(self, booksPath):
34         _moduleLogger.info("Loading books %s" % booksPath)
35         if self.audiobook is not None:
36             position = self.player.elapsed()
37             self.storage.set_time(self.audiobook.current_chapter, position)
38
39         self._bookDir = booksPath
40
41         self._bookPaths = dict(
42             (self.__format_name(bookPath), bookPath)
43             for bookPath in self._find_books()
44         )
45         if self.ui is not None:
46             bookPaths = self._bookPaths.values()
47             bookPaths.sort()
48             self.ui.set_books(bookPaths)
49
50         lastBookName = self.storage.get_selected()
51         if lastBookName is not None:
52             _moduleLogger.info("continuing book: %s" % lastBookName)
53             try:
54                 bookPath = self._bookPaths[lastBookName]
55                 self.set_book(bookPath)
56             except KeyError:
57                 _moduleLogger.exception("Audiobook was not found")
58             except IndexError:
59                 _moduleLogger.exception("Chapter was not found")
60             except IOError:
61                 _moduleLogger.exception("Audiobook could not be loaded")
62             except Exception:
63                 _moduleLogger.exception("Can you say 'confusion'?")
64
65     @staticmethod
66     def __format_name(path):
67         if os.path.isfile(path):
68             return os.path.basename(path).rsplit(".", 1)[0]
69         else:
70             return os.path.basename(path)
71
72     def set_book(self, bookPath):
73         oldBookName = self.storage.get_selected()
74         try:
75             bookName = self.__format_name(bookPath)
76             self.storage.select_book(bookName)
77             chapter_num, _ = self.storage.get_time()
78             self.audiobook = Audiobook.Audiobook(
79                 bookPath,
80                 chapter_num
81             )
82         except:
83             self.storage.select_book(oldBookName)
84             raise
85
86         # self.player.set_file(self.audiobook.get_current_chapter())
87         # self.player.seek_time(time) 
88
89         if self.ui is not None:
90             self.ui.set_book(bookPath, self.audiobook.get_cover_img())
91             self.ui.set_chapters(self.audiobook.chapters)
92
93         chapter_title = self.audiobook.chapters[self.audiobook.current_chapter]
94         self.set_chapter(chapter_title, True)
95
96     def set_chapter(self, chapter, continuing = False):
97         _moduleLogger.info("set chapter:" + chapter + " : Continuing: " + str(continuing))
98         self.audiobook.set_chapter(chapter)
99         self.player.set_file(self.audiobook.get_current_chapter())
100         if not continuing:
101             self.storage.set_time(self.audiobook.current_chapter, 0)
102
103         if self.ui is not None:
104             self.ui.set_chapter(self.audiobook.current_chapter)
105
106     def previous_chapter(self, *args):
107         _moduleLogger.info("Going back a chapter")
108         self.player.stop()
109         next_file = self.audiobook.get_previous_chapter()
110         if next_file is not False:
111             self.set_chapter(next_file)
112             self.player.play()
113         else:                           # the book is over
114             self.storage.set_time(0, 0)
115
116     def next_chapter(self, *args):
117         _moduleLogger.info("Advancing a chapter")
118         self.player.stop()
119         next_file = self.audiobook.get_next_chapter()
120         if next_file is not False:
121             self.set_chapter(next_file)
122             self.player.play()
123         else:                           # the book is over
124             self.storage.set_time(0, 0)
125
126     def play(self):
127         if self.audiobook is not None:
128             self.player.play()
129             _, target_time = self.storage.get_time()
130             if 0 < target_time:
131                 time.sleep(1)
132                 self.player.seek_time(target_time)
133             #print self.player.elapsed()
134         else:
135             print "No book selected, find one in ", self._bookDir
136
137     def stop(self):
138         position = self.player.elapsed()
139         self.player.stop()
140
141         if self.audiobook is not None:
142             self.storage.set_time(self.audiobook.current_chapter, position)
143
144     def is_playing(self):
145         return self.player.playing
146
147     def sleeptimer(self, secs):
148         #print "sleeper", secs
149         time.sleep(secs)
150         #print "now its time to sleep"
151         self.stop()
152
153     def start_sleeptimer(self, secs):
154         #print "startin sleep"
155         sleep_thread = threading.Thread(target=self.sleeptimer, args=(secs, ))
156         sleep_thread.start()
157         #print "started sleep"
158
159     def get_percentage(self):
160         try:
161             return float(self.player.elapsed()) / float(self.player.duration())
162         except ZeroDivisionError:
163             return 0.0
164
165     def seek_percent(self, ratio):
166         try:
167             target = int(self.player.duration() * ratio) # Calculate where to seek
168             self.player.seek_time(target)      # seek
169
170             position = self.player.elapsed()
171             self.storage.set_time(self.audiobook.current_chapter, target) # save position
172             return True
173         except:
174             _moduleLogger.exception("Seek failed")
175             return False
176
177     def _find_books(self):
178         try:
179             paths = (
180                 os.path.join(self._bookDir, f)
181                 for f in os.listdir(self._bookDir)
182             )
183             return (
184                 path
185                 for path in paths
186                 if Audiobook.is_book(path)
187             )
188         except OSError:
189             return ()