source: trunk/SapphireFrappliance/SapphireVideoPlayer.m @ 497

Revision 497, 5.5 KB checked in by gbooker, 6 years ago (diff)

Some take 2 updates (can playback now if the importer is removed from the main menu).

Line 
1/*
2 * SapphireVideoPlayer.m
3 * Sapphire
4 *
5 * Created by Graham Booker on Jun. 25, 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 "SapphireVideoPlayer.h"
22#import <SapphireCompatClasses/SapphireFrontRowCompat.h>
23#import <QTKit/QTKit.h>
24#import <objc/objc-class.h>
25
26/*This is a private function somewhere, so declare to remove warnings*/
27@interface QTMovie (whoKnows)
28- (BOOL)hasChapters;
29@end
30
31/*These interfaces are to access variables not available*/
32@interface BRQTKitVideoPlayer (privateFunctions)
33- (BRVideo *)gimmieVideo;
34@end
35
36@interface BRVideo (privateFunctions)
37- (QTMovie *)gimmieMovie;
38@end
39
40@implementation BRQTKitVideoPlayer (privateFunctions)
41- (BRVideo *)gimmieVideo
42{
43        Class myClass = [self class];
44        Ivar ret = class_getInstanceVariable(myClass, "_video");
45       
46        return *(BRVideo * *)(((char *)self)+ret->ivar_offset);
47}
48@end
49
50@implementation BRVideo (privateFunctions)
51- (QTMovie *)gimmieMovie
52{
53        Class myClass = [self class];
54        Ivar ret = class_getInstanceVariable(myClass, "_movie");
55       
56        if(![SapphireFrontRowCompat usingTakeTwo])
57                return *(QTMovie * *)(((char *)self)+ret->ivar_offset);
58        Movie mov = *(Movie *)(((char *)self)+ret->ivar_offset);
59        return [QTMovie movieWithQuickTimeMovie:mov disposeWhenDone:NO error:nil];
60}
61@end
62
63#define LOW_SKIP_TIME 5.0f
64
65typedef enum {
66        STATE_COMMAND_RESET,
67        STATE_COMMAND_FORWARD,
68        STATE_COMMAND_BACKWARD,
69} StateCommand;
70
71@implementation SapphireVideoPlayer
72
73- (id)init
74{
75        self = [super init];
76        if(!self)
77                return nil;
78       
79        /* Initial skip times */
80        skipTime = LOW_SKIP_TIME;
81        state = SKIP_STATE_NONE;
82       
83        return self;
84}
85
86- (void)dealloc
87{
88        [resetTimer invalidate];
89        [super dealloc];
90}
91
92- (BOOL)prerollMedia:(NSError * *)fp8
93{
94        BOOL ret = [super prerollMedia:fp8];
95       
96        if(!ret)
97                return ret;
98       
99        /*Check to see if the movie has any chapters by default*/
100        QTMovie *myMovie = [[self gimmieVideo] gimmieMovie];
101        if(![myMovie hasChapters])
102                enabled = TRUE;
103       
104        QTGetTimeInterval([myMovie duration], &duration);
105       
106        return ret;
107}
108
109- (void)setNewTimer
110{
111        /*Reset the skip times after 3 seconds of non use*/
112        [resetTimer invalidate];
113        resetTimer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(resetTimes) userInfo:nil repeats:NO];
114}
115
116- (double)offsetForCommand:(StateCommand)command
117{
118        double ret = 0.0f;
119       
120        switch(command)
121        {
122                case STATE_COMMAND_RESET:
123                        state = SKIP_STATE_NONE;
124                        skipTime = LOW_SKIP_TIME;
125                        break;
126
127                case STATE_COMMAND_FORWARD:
128                        switch(state)
129                        {
130                                case SKIP_STATE_NONE:
131                                case SKIP_STATE_FORWARD_INCREASING:
132                                        state = SKIP_STATE_FORWARD_INCREASING;
133                                        ret = skipTime;
134                                        skipTime *= 2;
135                                        break;
136                                case SKIP_STATE_BACKWARD_INCREASING:
137                                        state = SKIP_STATE_DECREASING;
138                                        skipTime /= 4;
139                                case SKIP_STATE_DECREASING:
140                                        ret = skipTime;
141                                        skipTime = MAX(skipTime / 2, LOW_SKIP_TIME);
142                        }
143                        break;
144                       
145                case STATE_COMMAND_BACKWARD:
146                        switch(state)
147                        {
148                                case SKIP_STATE_NONE:
149                                case SKIP_STATE_BACKWARD_INCREASING:
150                                        state = SKIP_STATE_BACKWARD_INCREASING;
151                                        ret = -skipTime;
152                                        skipTime *= 2;
153                                        break;
154                                case SKIP_STATE_FORWARD_INCREASING:
155                                        state = SKIP_STATE_DECREASING;
156                                        skipTime /= 4;
157                                case SKIP_STATE_DECREASING:
158                                        ret = -skipTime;
159                                        skipTime = MAX(skipTime / 2, LOW_SKIP_TIME);
160                        }
161                        break;
162        }
163        return ret;
164}
165
166- (void)resetTimes
167{
168        /*Reset the times from the timer above*/
169        resetTimer = nil;
170        [self offsetForCommand:STATE_COMMAND_RESET];
171}
172
173- (double)_nextChapterMark
174{
175        /*Get the location of the next chapter mark*/
176        if(!enabled)
177                return [super _nextChapterMark];
178        /*Compute our's*/
179        double current = [self elapsedPlaybackTime];
180        double ret = current + [self offsetForCommand:STATE_COMMAND_FORWARD];
181       
182        if(ret > duration + 10.0f)
183                /*Halve the distance to the end of the file if skipping so much*/
184                ret = (current + duration) / 2;
185       
186        /*Start the reset timer*/
187        [self setNewTimer];
188       
189        return ret;
190}
191
192- (double)getPreviousChapterMarkAndUpdate:(BOOL)update
193{
194        /*Compute our previous chapter*/
195        double current = [self elapsedPlaybackTime];
196        double ret;
197        if(update)
198                ret = current - [self offsetForCommand:STATE_COMMAND_BACKWARD];
199        else if(state == SKIP_STATE_DECREASING)
200                ret = current - skipTime * 2;
201        else
202                ret = current - skipTime / 2;
203       
204        /*Make sure we don't go past the beginning of the file*/
205        if(ret < 0.0f)
206                ret = 0.0f;
207       
208        return ret;
209}
210
211- (double)_previousChapterMark
212{
213        /*Get the location of the previous chapter mark*/
214        if(!enabled)
215                return [super _previousChapterMark];
216       
217        /*Compute our's*/
218        double ret = [self getPreviousChapterMarkAndUpdate:YES];
219       
220        /*Start the reset timer*/
221        [self setNewTimer];
222
223        return ret;
224}
225
226- (double)_virtualChapterMark
227{
228        if(!enabled)
229                return [super _virtualChapterMark];
230        /*If we are enabled, disable the virtual chapter marks*/
231        return 0.0f;
232}
233
234- (double)_currentChapterMark
235{
236        if(!enabled)
237                return [super _currentChapterMark];
238       
239        return [self getPreviousChapterMarkAndUpdate:NO];
240}
241
242@end
Note: See TracBrowser for help on using the repository browser.