Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfQT/XspfQTDocument.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 197 - (hide annotations) (download)
Sat Mar 28 12:42:09 2009 UTC (15 years ago) by masaki
File size: 10608 byte(s)
プレイリストを開いた後でも、プリロードの有効無効を変更出来るようにした。
1 masaki 2 //
2 masaki 72 // XspfQTDocument.m
3 masaki 2 // XspfQT
4     //
5     // Created by Hori,Masaki on 08/08/29.
6     // Copyright masakih 2008 . All rights reserved.
7     //
8    
9 masaki 72 #import "XspfQTDocument.h"
10     #import "XspfQTComponent.h"
11     #import "XspfQTMovieWindowController.h"
12     #import "XspfQTPlayListWindowController.h"
13 masaki 171 #import <QTKit/QTKit.h>
14 masaki 2
15 masaki 181 #import "NSURL-XspfQT-Extensions.h"
16     #import "XspfQTMovieLoader.h"
17    
18 masaki 72 @interface XspfQTDocument (Private)
19 masaki 197 - (BOOL)preloadingEnabled;
20 masaki 116 - (void)setPlaylist:(XspfQTComponent *)newList;
21     - (XspfQTComponent *)playlist;
22 masaki 31 - (NSXMLDocument *)XMLDocument;
23     - (NSData *)outputData;
24 masaki 173 - (void)setPlayingMovie:(QTMovie *)newMovie;
25 masaki 141 - (NSData *)dataFromURL:(NSURL *)url error:(NSError **)outError;
26 masaki 2 @end
27    
28 masaki 72 @implementation XspfQTDocument
29 masaki 2
30 masaki 72 NSString *XspfQTDocumentWillCloseNotification = @"XspfQTDocumentWillCloseNotification";
31 masaki 61
32 masaki 182 - (id)init
33     {
34     self = [super init];
35     if(self) {
36     loader = [[XspfQTMovieLoader loaderWithMovieURL:nil delegate:nil] retain];
37    
38 masaki 197 // NSLog(@"Enable preloading.");
39     preloadingTimer = [NSTimer scheduledTimerWithTimeInterval:10
40     target:self
41     selector:@selector(checkPreload:)
42     userInfo:nil
43     repeats:YES];
44 masaki 182 // NSLog(@"init was called");
45     }
46    
47     return self;
48     }
49 masaki 95 - (id)initWithType:(NSString *)typeName error:(NSError **)outError
50     {
51     [self init];
52    
53 masaki 116 id newPlaylist = [XspfQTComponent xspfPlaylist];
54     if(!newPlaylist) {
55 masaki 95 [self autorelease];
56     return nil;
57     }
58    
59 masaki 116 [self setPlaylist:newPlaylist];
60 masaki 121 // NSLog(@"new playlist is (%@)%@", NSStringFromClass([[self playlist] class]), [self playlist]);
61 masaki 95
62     return self;
63     }
64 masaki 182 - (void)dealloc
65     {
66     [self setPlayingMovie:nil];
67     [self setPlaylist:nil];
68     [playListWindowController release];
69     [movieWindowController release];
70     [loader release];
71    
72     [super dealloc];
73     }
74 masaki 2
75     - (void)makeWindowControllers
76     {
77 masaki 72 playListWindowController = [[XspfQTPlayListWindowController alloc] init];
78 masaki 2 [self addWindowController:playListWindowController];
79    
80 masaki 72 movieWindowController = [[XspfQTMovieWindowController alloc] init];
81 masaki 42 [movieWindowController setShouldCloseDocument:YES];
82 masaki 2 [self addWindowController:movieWindowController];
83     }
84    
85     - (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
86     {
87 masaki 31 return [self outputData];
88 masaki 2 }
89    
90 masaki 141 - (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError
91     {
92     *outError = nil;
93    
94 masaki 162 if(![typeName isEqualToString:@"QuickTime Movie"]
95 masaki 195 && ![typeName isEqualToString:@"Matroska Video"]
96     && ![typeName isEqualToString:@"DivX Media Format"]) {
97 masaki 141 NSData *data = [self dataFromURL:absoluteURL error:outError];
98     if(!data) return NO;
99    
100     return [self readFromData:data ofType:typeName error:outError];
101     }
102    
103     NSString *xmlElem;
104     xmlElem = [NSString stringWithFormat:@"<track><location>%@</location></track>",
105     [absoluteURL absoluteString]];
106    
107     NSError *error = nil;
108     id new = [XspfQTComponent xspfComponentWithXMLElementString:xmlElem
109     error:&error];
110     if(error) {
111     NSLog(@"%@", error);
112     if(outError) {
113     *outError = error;
114     }
115     return NO;
116     }
117    
118     id pl = [XspfQTComponent xspfPlaylist];
119     if(!pl) {
120     return NO;
121     }
122    
123     [[[pl children] objectAtIndex:0] addChild:new];
124    
125     [self setPlaylist:pl];
126     id t = [self trackList];
127     if(![t title]) {
128     [t setTitle:[[[self fileURL] path] lastPathComponent]];
129     }
130    
131     [self setFileType:@"XML Shareable Playlist Format"];
132     [self setFileURL:nil];
133    
134     return YES;
135     }
136 masaki 2 - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
137     {
138 masaki 141 *outError = nil;
139    
140     if(![typeName isEqualToString:@"XML Shareable Playlist Format"]) {
141     return NO;
142     }
143    
144 masaki 2 NSError *error = nil;
145 masaki 10 NSXMLDocument *d = [[[NSXMLDocument alloc] initWithData:data
146     options:0
147     error:&error] autorelease];
148 masaki 121 if(error) {
149     NSLog(@"%@", error);
150     *outError = error;
151     return NO;
152     }
153 masaki 2 NSXMLElement *root = [d rootElement];
154 masaki 116 id pl = [XspfQTComponent xspfComponemtWithXMLElement:root];
155 masaki 121 if(!pl) {
156     NSLog(@"Can not create XspfQTComponent.");
157     return NO;
158     }
159 masaki 116 [self setPlaylist:pl];
160 masaki 2
161 masaki 116 id t = [self trackList];
162 masaki 39 if(![t title]) {
163 masaki 165 [t setTitle:[[[[self fileURL] path] lastPathComponent] stringByDeletingPathExtension]];
164 masaki 39 }
165 masaki 2
166 masaki 121 // NSLog(@"open playlist is (%@)%@", NSStringFromClass([[self playlist] class]), [self playlist]);
167    
168 masaki 2 return YES;
169     }
170    
171 masaki 42 - (void)close
172     {
173 masaki 61 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
174 masaki 72 [nc postNotificationName:XspfQTDocumentWillCloseNotification object:self];
175 masaki 61
176 masaki 42 [self removeWindowController:playListWindowController];
177     [playListWindowController release];
178     playListWindowController = nil;
179    
180     [self removeWindowController:movieWindowController];
181     [movieWindowController release];
182     movieWindowController = nil;
183    
184 masaki 189 [preloadingTimer invalidate];
185    
186 masaki 42 [super close];
187     }
188    
189 masaki 197 - (BOOL)preloadingEnabled
190     {
191     return [[NSUserDefaults standardUserDefaults] boolForKey:@"EnablePreloading"];
192     }
193 masaki 33 - (IBAction)togglePlayAndPause:(id)sender
194     {
195     [movieWindowController togglePlayAndPause:sender];
196     }
197 masaki 2 - (IBAction)showPlayList:(id)sender
198     {
199     [playListWindowController showWindow:self];
200     }
201    
202 masaki 116 - (void)setPlaylist:(XspfQTComponent *)newList
203 masaki 2 {
204 masaki 116 if(playlist == newList) return;
205 masaki 2
206 masaki 171 [[playlist childAtIndex:0] removeObserver:self forKeyPath:@"currentTrack"];
207 masaki 116 [playlist autorelease];
208     playlist = [newList retain];
209 masaki 171 [[playlist childAtIndex:0] addObserver:self
210     forKeyPath:@"currentTrack"
211     options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
212     context:NULL];
213 masaki 2 }
214 masaki 116 - (XspfQTComponent *)playlist
215     {
216     return playlist;
217     }
218    
219 masaki 72 - (XspfQTComponent *)trackList
220 masaki 2 {
221 masaki 116 return [playlist childAtIndex:0];
222 masaki 2 }
223    
224 masaki 196 + (NSSet *)keyPathsForValuesAffectingPlayingMovieDuration
225     {
226     return [NSSet setWithObject:@"playingMovie"];
227     }
228 masaki 171 - (void)setPlayingMovie:(QTMovie *)newMovie
229     {
230     // NSLog(@"new movie is %@!!", newMovie);
231     NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
232 masaki 193 if(playingMovie) {
233 masaki 188 [nc removeObserver:self
234     name:nil
235     object:playingMovie];
236     }
237 masaki 171
238     [playingMovie autorelease];
239 masaki 181 playingMovie = [newMovie retain];
240 masaki 196 playingMovieDuration = 0;
241 masaki 171
242 masaki 193 if(playingMovie) {
243 masaki 188 [nc addObserver:self
244     selector:@selector(notifee:)
245     name:QTMovieRateDidChangeNotification
246     object:playingMovie];
247     }
248 masaki 171 }
249     - (QTMovie *)playingMovie
250     {
251     // NSLog(@"%@ is called!!", NSStringFromSelector(_cmd));
252     return playingMovie;
253     }
254 masaki 182 - (NSTimeInterval)playingMovieDuration
255     {
256     if(playingMovieDuration == 0) {
257     QTTime qttime = [[self playingMovie] duration];
258     if(!QTGetTimeInterval(qttime, &playingMovieDuration)) playingMovieDuration = 0;
259     }
260    
261     return playingMovieDuration;
262     }
263 masaki 171 - (void)loadMovie
264     {
265     NSURL *location = [[self trackList] movieLocation];
266    
267 masaki 174 if(playingMovie) {
268     id movieURL = [playingMovie attributeForKey:QTMovieURLAttribute];
269 masaki 181 if([location isEqualUsingLocalhost:movieURL]) return;
270 masaki 174 }
271    
272 masaki 182 [loader setMovieURL:location];
273 masaki 181 [loader load];
274     QTMovie *newMovie = [loader qtMovie];
275     [self setPlayingMovie:newMovie];
276 masaki 171
277     QTTime qttime = [newMovie duration];
278     id t = [NSValueTransformer valueTransformerForName:@"XspfQTTimeDateTransformer"];
279     [[self trackList] setCurrentTrackDuration:[t transformedValue:[NSValue valueWithQTTime:qttime]]];
280 masaki 182
281     didPreloading = NO;
282 masaki 171 }
283 masaki 158 - (void)setPlayingTrackIndex:(unsigned)index
284 masaki 2 {
285 masaki 181 // [self performSelector:@selector(loadMovie) withObject:nil afterDelay:0.0];
286     [self loadMovie];
287 masaki 2 }
288 masaki 171 - (void)observeValueForKeyPath:(NSString *)keyPath
289     ofObject:(id)object
290     change:(NSDictionary *)change
291     context:(void *)context
292     {
293     if([keyPath isEqualToString:@"currentTrack"]) {
294     id trackList = [self trackList];
295     unsigned index = [trackList selectionIndex];
296     [self setPlayingTrackIndex:index];
297     }
298     }
299 masaki 31
300     - (NSData *)outputData
301     {
302     return [[self XMLDocument] XMLDataWithOptions:NSXMLNodePrettyPrint];
303     }
304 masaki 71 - (NSXMLDocument *)XMLDocument
305 masaki 31 {
306 masaki 116 id root = [[self playlist] XMLElement];
307 masaki 31
308     id d = [[[NSXMLDocument alloc] initWithRootElement:root] autorelease];
309     [d setVersion:@"1.0"];
310     [d setCharacterEncoding:@"UTF-8"];
311    
312     return d;
313     }
314 masaki 42
315 masaki 89 - (void)insertComponentFromURL:(NSURL *)url atIndex:(NSUInteger)index
316     {
317     NSString *xmlElem;
318     xmlElem = [NSString stringWithFormat:@"<track><location>%@</location></track>",
319     [url absoluteString]];
320    
321     NSError *error = nil;
322 masaki 117 id new = [XspfQTComponent xspfComponentWithXMLElementString:xmlElem
323     error:&error];
324 masaki 89 if(error) {
325     NSLog(@"%@", error);
326     @throw self;
327     }
328    
329     if(!new) {
330     @throw self;
331     }
332    
333     [self insertComponent:new atIndex:index];
334     }
335 masaki 86 - (void)insertComponent:(XspfQTComponent *)item atIndex:(NSUInteger)index
336 masaki 55 {
337 masaki 83 id undo = [self undoManager];
338 masaki 86 [undo registerUndoWithTarget:self selector:@selector(removeComponent:) object:item];
339 masaki 78 [[self trackList] insertChild:item atIndex:index];
340 masaki 55 }
341 masaki 86 - (void)removeComponent:(XspfQTComponent *)item
342 masaki 55 {
343 masaki 83 NSUInteger index = [[self trackList] indexOfChild:item];
344 masaki 121 if(index == NSNotFound) {
345     NSLog(@"Con not found item (%@)", item);
346     return;
347     }
348 masaki 83
349     id undo = [self undoManager];
350 masaki 86 [[undo prepareWithInvocationTarget:self] insertComponent:item atIndex:index];
351 masaki 55 [[self trackList] removeChild:item];
352     }
353    
354 masaki 141 - (NSData *)dataFromURL:(NSURL *)url error:(NSError **)outError
355     {
356     NSURLRequest *req = [NSURLRequest requestWithURL:url];
357     NSURLResponse *res = nil;
358     NSError *err = nil;
359     NSData *data = [NSURLConnection sendSynchronousRequest:req
360     returningResponse:&res
361     error:&err];
362     if(err) {
363     if(outError) {
364     *outError = err;
365     }
366     return nil;
367     }
368    
369     return data;
370     }
371    
372 masaki 171 - (void)notifee:(id)notification
373     {
374     // NSLog(@"Notifed: name -> (%@)\ndict -> (%@)", [notification name], [notification userInfo]);
375    
376     id track = [[self trackList] currentTrack];
377     NSNumber *rateValue = [[notification userInfo] objectForKey:QTMovieRateDidChangeNotificationParameter];
378     if(rateValue) {
379     float rate = [rateValue floatValue];
380     if(rate == 0) {
381     [track setIsPlayed:NO];
382     } else {
383     [track setIsPlayed:YES];
384     }
385     }
386     }
387    
388 masaki 182 - (void)checkPreload:(NSTimer *)timer
389     {
390 masaki 197 if(![self preloadingEnabled]) return;
391 masaki 182 if(didPreloading) return;
392    
393     NSTimeInterval duration;
394     NSTimeInterval current;
395     QTTime qttime = [playingMovie currentTime];
396     if(!QTGetTimeInterval(qttime, &current)) return;
397    
398     duration = [self playingMovieDuration];
399    
400     if( current / duration > 0.85 ) {
401     didPreloading = YES;
402     XspfQTComponent *list = [self trackList];
403     unsigned nextIndex = [list selectionIndex] + 1;
404     unsigned max = [list childrenCount];
405     if(max <= nextIndex) return;
406    
407     XspfQTComponent *nextTrack = [list childAtIndex:nextIndex];
408     NSURL *nextMovieURL = [nextTrack movieLocation];
409     [loader setMovieURL:nextMovieURL];
410     [loader load];
411    
412     // NSLog(@"Start preloading.");
413     }
414     }
415    
416 masaki 31 - (IBAction)dump:(id)sender
417     {
418     NSString *s = [[[NSString alloc] initWithData:[self outputData]
419     encoding:NSUTF8StringEncoding] autorelease];
420    
421     NSLog(@"%@", s);
422     }
423 masaki 2 @end
424    

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26