source: trunk/SapphireFrappliance/Players/SapphireAudioPlayer.m @ 948

Revision 948, 7.6 KB checked in by gbooker, 4 years ago (diff)

Protect against some exceptions being thrown

Line 
1/*
2 * SapphireAudioPlayer.m
3 * Sapphire
4 *
5 * Created by Graham Booker on Jul. 28, 2007.
6 * Copyright 2007 Sapphire Development Team and/or www.nanopi.net
7 * All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License as published by the Free Software Foundation; either version 3 of the License,
11 * or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
14 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 * Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with this program; if not,
18 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 */
20
21#import <SapphireCompatClasses/SapphireFrontRowCompat.h>
22#import "SapphireAudioPlayer.h"
23#import "SapphireAudioMedia.h"
24#import "SapphireFileMetaData.h"
25#import "SapphireVideoPlayerController.h"
26#import <QTKit/QTKit.h>
27
28#define SKIP_INTERVAL 0.5
29#define SKIP_ACCELL 0.5 * SKIP_INTERVAL
30
31@interface BRMusicPlayer (compat)
32-(BOOL)setMedia:(id)media inTrackList:(id)trackList error:(NSError **)error;
33-(BOOL)setMediaAtIndex:(long)index inTrackList:(id)trackList error:(NSError **)error;
34@end
35
36//Stolen from ATVFiles
37typedef enum {
38        BRMusicPlayerStateStopped = 0,
39        BRMusicPlayerStatePaused = 1,
40        BRMusicPlayerStatePlaying = 3,
41        BRMusicPlayerStateSeekingForward = 4,
42        BRMusicPlayerStateSeekingBack = 7
43} BRMusicPlayerState;
44
45@interface SapphireAudioPlayer (private)
46- (void)setState:(int)newState;
47- (void)stopUITimer;
48- (void)setSkipTimer;
49- (void)doSkip:(NSTimer *)timer;
50- (void)stopSkip;
51- (void)updateUI:(NSTimer *)Timer;
52- (void)setPlayerState:(BRMusicPlayerState)newState;
53@end
54
55@implementation SapphireAudioPlayer
56
57- (id) init {
58        self = [super init];
59        if (self == nil)
60                return nil;
61
62        state = 0;
63
64        return self;
65}
66
67- (void) dealloc
68{
69        [movie release];
70        [self stopUITimer];
71        [self stopSkip];
72        [myMedia release];
73        [myTrackList release];
74        [super dealloc];
75}
76
77- (int)playerState
78{
79        return state;
80}
81
82- (void)setMedia:(SapphireAudioMedia *)media inTracklist:(NSArray *)tracklist error:(NSError * *)error
83{
84        SapphireFrontRowCompatATVVersion version = [SapphireFrontRowCompat atvVersion];
85        if(version >= SapphireFrontRowCompatATVVersion2Dot3)
86                [super setMediaAtIndex:[tracklist indexOfObject:media] inTrackList:tracklist error:error];
87        else if (version >= SapphireFrontRowCompatATVVersion2Dot2)
88                [super setMedia:media inTrackList:tracklist error:error];
89        else
90                [super setMedia:media inTracklist:tracklist error:error];
91       
92        [myMedia release];
93        [myTrackList release];
94        myMedia = [media retain];
95        myTrackList = [tracklist retain];
96       
97        if(error != NULL && *error == nil)
98        {
99                soundState = enablePassthrough([media fileMetaData]);
100                movie = [[QTMovie alloc] initWithURL:[NSURL URLWithString:[media mediaURL]] error:error];
101                [media setMovie:movie];
102                [self setElapsedPlaybackTime:[media bookmarkTimeInSeconds]];
103        }
104        [[NSNotificationCenter defaultCenter] postNotificationName:kBRMediaPlayerCurrentAssetChanged object:media];
105        [[NSNotificationCenter defaultCenter] postNotificationName:@"BRMPCurrentAssetChanged" object:media];
106}
107
108- (SapphireAudioMedia *)media
109{
110        return myMedia;
111}
112
113- (NSArray *)tracklist
114{
115        return myTrackList;
116}
117
118- (float)elapsedPlaybackTime
119{
120        QTTime current = [movie currentTime];
121        double ret = 0.0;
122        QTGetTimeInterval(current, &ret);
123        return (float)ret;
124}
125
126- (double)elapsedTime
127{
128        return [self elapsedPlaybackTime];
129}
130
131- (void)setElapsedPlaybackTime:(float)time
132{
133        QTTime newTime = QTMakeTimeWithTimeInterval((double)time);
134        [movie setCurrentTime:newTime];
135        [self updateUI:nil];
136}
137
138- (double)trackDuration
139{
140        QTTime duration = [movie duration];
141        double ret = 0.0;
142        QTGetTimeInterval(duration, &ret);
143        return (float)ret;
144}
145
146- (NSString *)currentChapterTitle
147{
148        return [movie attributeForKey:QTMovieDisplayNameAttribute];
149}
150
151- (BOOL)initiatePlayback:(NSError * *)error
152{
153        [movie stop];
154        [movie gotoBeginning];
155        return YES;
156}
157
158-(void)setState:(int)newState error:(NSError **)error
159{
160        [self setPlayerState:newState];
161}
162
163- (void)setState:(int)newState
164{
165        [self setPlayerState:newState];
166}
167
168- (void)setPlayerState:(BRMusicPlayerState)newState
169{
170        state = newState;
171        switch (state) {
172                case BRMusicPlayerStatePlaying:
173                {
174                        id media = [self media];
175                        [[NSNotificationCenter defaultCenter] postNotificationName:kBRMediaPlayerCurrentAssetChanged object:media];
176                        [[NSNotificationCenter defaultCenter] postNotificationName:@"BRMPCurrentAssetChanged" object:media];
177                        [self stopSkip];
178                        [self stopUITimer];
179                        updateTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateUI:) userInfo:nil repeats:YES];
180                        [movie play];
181                        break;
182                }
183                case BRMusicPlayerStatePaused:
184                        [self stopSkip];
185                        [self stopUITimer];
186                        [movie stop];
187                        break;
188                case BRMusicPlayerStateStopped:
189                        [self stopSkip];
190                        [self stopUITimer];
191                        [movie stop];
192                        SapphireFileMetaData *file = [(SapphireAudioMedia *)[self media] fileMetaData];
193                        if(![file objectHasBeenDeleted])
194                        {
195                                float elapsed = [self elapsedPlaybackTime];
196                                float duration = [self trackDuration];
197                                /*Get the resume time to save*/
198                                if(elapsed < duration - 2)
199                                        [file setResumeTimeValue:elapsed];
200                                else
201                                        [file setResumeTime:nil];
202                               
203                                if(elapsed / duration > 0.9f)
204                                /*Mark as watched and reload info*/
205                                        [file setWatchedValue:YES];
206                        }
207                        teardownPassthrough(soundState);
208                        break;
209                case BRMusicPlayerStateSeekingBack:
210                        [self setSkipTimer];
211                        skipSpeed = -1;
212                        break;
213                case BRMusicPlayerStateSeekingForward:
214                        [self setSkipTimer];
215                        skipSpeed = 1;
216                        break;
217                default:
218                        NSLog(@"I was told to go into state %d", newState);
219                        break;
220        }
221        [[NSNotificationCenter defaultCenter] postNotificationName:@"BRMPStateChanged" object:self];
222        [[NSNotificationCenter defaultCenter] postNotificationName:kBRMediaPlayerStateChanged object:self];
223}
224
225- (void)play
226{
227        [self setPlayerState:BRMusicPlayerStatePlaying];
228}
229
230- (void)pause
231{
232        [self setPlayerState:BRMusicPlayerStatePaused];
233}
234
235- (void)stop
236{
237        [self setPlayerState:BRMusicPlayerStateStopped];
238}
239
240- (void)stopUITimer
241{
242        [updateTimer invalidate];
243        updateTimer = nil;
244}
245
246- (void)pressAndHoldLeftArrow
247{
248        [self setPlayerState:BRMusicPlayerStateSeekingBack];
249}
250
251- (void)pressAndHoldRightArrow
252{
253        [self setPlayerState:BRMusicPlayerStateSeekingForward];
254}
255
256- (void)setSkipTimer
257{
258        [self stopSkip];
259        skipTimer = [NSTimer scheduledTimerWithTimeInterval:SKIP_INTERVAL target:self selector:@selector(doSkip:) userInfo:nil repeats:YES];
260        [self doSkip:nil];
261}
262
263- (void)doSkip:(NSTimer *)timer
264{
265        float time = [self elapsedPlaybackTime];
266        if(skipSpeed < 0)
267        {
268                time += skipSpeed * SKIP_INTERVAL * 3;
269                skipSpeed = MAX(skipSpeed - SKIP_ACCELL, -16);
270        }
271        else
272        {
273                time += skipSpeed * SKIP_INTERVAL * 2;
274                skipSpeed = MIN(skipSpeed + SKIP_ACCELL, 16);
275        }
276        double duration = [self trackDuration];
277        if(time < 0)
278        {
279                time = 0;
280                [self stopSkip];
281        }
282        else if(time > duration)
283        {
284                time = duration;
285        }
286        [self setElapsedPlaybackTime:time];
287        [self updateUI:timer];
288}
289
290- (void)stopSkip
291{
292        skipSpeed = 0;
293        [skipTimer invalidate];
294        skipTimer = nil;
295}
296
297- (void)resume
298{
299        [self play];
300}
301
302- (void)leftArrowClick
303{
304        [movie gotoBeginning];
305        [self updateUI:nil];
306}
307
308- (void)rightArrowClick
309{
310        [movie gotoEnd];
311        [self updateUI:nil];
312}
313
314- (void)updateUI:(NSTimer *)Timer
315{
316        if([self elapsedPlaybackTime] >= [self trackDuration])
317                [self stop];
318        [[NSNotificationCenter defaultCenter] postNotificationName:@"BRMPPlaybackProgressChanged" object:self];
319        [[NSNotificationCenter defaultCenter] postNotificationName:kBRMediaPlayerPlaybackProgressChanged object:self];
320}
321
322@end
Note: See TracBrowser for help on using the repository browser.