522b2fa9c441ece30e6dc74b6d59e915e31ad8a5
[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             SimpleGStreamer = _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         self.load_books_path(constants._default_book_path_)
30
31     def get_books_path(self):
32         return self._bookDir
33
34     def load_books_path(self, 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.info("Audiobook was not found")
58             except IOError:
59                 _moduleLogger.info("Audiobook could not be loaded")
60
61     @staticmethod
62     def __format_name(path):
63         if os.path.isfile(path):
64             return os.path.basename(path).rsplit(".", 1)[0]
65         else:
66             return os.path.basename(path)
67
68     def set_book(self, bookPath):
69         oldBookName = self.storage.get_selected()
70         try:
71             bookName = self.__format_name(bookPath)
72             self.storage.select_book(bookName)
73             chapter_num, _ = self.storage.get_time()
74             self.audiobook = Audiobook.Audiobook(
75                 bookPath,
76                 chapter_num
77             )
78         except:
79             self.storage.select_book(oldBookName)
80             raise
81
82         # self.player.set_file(self.audiobook.get_current_chapter())
83         # self.player.seek_time(time) 
84
85         if self.ui is not None:
86             self.ui.set_book(bookPath, self.audiobook.get_cover_img())
87             self.ui.set_chapters(self.audiobook.chapters)
88
89         chapter_title = self.audiobook.chapters[chapter_num]
90         self.set_chapter(chapter_title, True)
91
92     def set_chapter(self, chapter, continuing = False):
93         _moduleLogger.info("set chapter:" + chapter + " : Continuing: " + str(continuing))
94         self.audiobook.set_chapter(chapter)
95         self.player.set_file(self.audiobook.get_current_chapter())
96         if not continuing:
97             self.storage.set_time(self.audiobook.current_chapter, 0)
98
99         if self.ui is not None:
100             self.ui.set_chapter(self.audiobook.current_chapter)
101
102     def previous_chapter(self, *args):
103         _moduleLogger.info("Going back a chapter")
104         self.player.stop()
105         next_file = self.audiobook.get_previous_chapter()
106         if next_file is not False:
107             self.set_chapter(next_file)
108             self.player.play()
109         else:                           # the book is over
110             self.storage.set_time(0, 0)
111
112     def next_chapter(self, *args):
113         _moduleLogger.info("Advancing a chapter")
114         self.player.stop()
115         next_file = self.audiobook.get_next_chapter()
116         if next_file is not False:
117             self.set_chapter(next_file)
118             self.player.play()
119         else:                           # the book is over
120             self.storage.set_time(0, 0)
121
122     def play(self):
123         if self.audiobook is not None:
124             self.player.play()
125             _, target_time = self.storage.get_time()
126             if 0 < target_time:
127                 time.sleep(1)
128                 self.player.seek_time(target_time)
129             #print self.player.elapsed()
130         else:
131             print "No book selected, find one in ", self._bookDir
132
133     def stop(self):
134         position = self.player.elapsed()
135         self.player.stop()
136
137         if self.audiobook is not None:
138             self.storage.set_time(self.audiobook.current_chapter, position)
139
140     def is_playing(self):
141         return self.player.playing
142
143     def sleeptimer(self, secs):
144         #print "sleeper", secs
145         time.sleep(secs)
146         #print "now its time to sleep"
147         self.stop()
148
149     def start_sleeptimer(self, secs):
150         #print "startin sleep"
151         sleep_thread = threading.Thread(target=self.sleeptimer, args=(secs, ))
152         sleep_thread.start()
153         #print "started sleep"
154
155     def get_percentage(self):
156         try:
157             return float(self.player.elapsed()) / float(self.player.duration())
158         except ZeroDivisionError:
159             return 0.0
160
161     def seek_percent(self, ratio):
162         try:
163             target = self.player.duration() * ratio # Calculate where to seek
164             self.player.seek_time(int(target))      # seek
165
166             position = self.player.elapsed()
167             self.storage.set_time(self.audiobook.current_chapter, target) # save position
168             return True
169         except:
170             _moduleLogger.excetion("Seek failed")
171             return False
172
173     def _find_books(self):
174         try:
175             paths = (
176                 os.path.join(self._bookDir, f)
177                 for f in os.listdir(self._bookDir)
178             )
179             return (
180                 path
181                 for path in paths
182                 if Audiobook.is_book(path)
183             )
184         except OSError:
185             return ()