Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfQT/XspfQTDocument.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 204 - (hide annotations) (download)
Sun Mar 29 01:45:41 2009 UTC (15 years ago) by masaki
File size: 10536 byte(s)
[Refactoring]preloadingEnabledメソッドをXspfQTDocumentからXpsfQTAppDelegateに移動。
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 masaki 202 #import "XspfQTAppDelegate.h"
11 masaki 72 #import "XspfQTComponent.h"
12     #import "XspfQTMovieWindowController.h"
13     #import "XspfQTPlayListWindowController.h"
14 masaki 171 #import <QTKit/QTKit.h>
15 masaki 2
16 masaki 181 #import "NSURL-XspfQT-Extensions.h"
17     #import "XspfQTMovieLoader.h"
18    
19 masaki 72 @interface XspfQTDocument (Private)
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 33 - (IBAction)togglePlayAndPause:(id)sender
190     {
191     [movieWindowController togglePlayAndPause:sender];
192     }
193 masaki 2 - (IBAction)showPlayList:(id)sender
194     {
195     [playListWindowController showWindow:self];
196     }
197    
198 masaki 116 - (void)setPlaylist:(XspfQTComponent *)newList
199 masaki 2 {
200 masaki 116 if(playlist == newList) return;
201 masaki 2
202 masaki 171 [[playlist childAtIndex:0] removeObserver:self forKeyPath:@"currentTrack"];
203 masaki 116 [playlist autorelease];
204     playlist = [newList retain];
205 masaki 171 [[playlist childAtIndex:0] addObserver:self
206     forKeyPath:@"currentTrack"
207     options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
208     context:NULL];
209 masaki 2 }
210 masaki 116 - (XspfQTComponent *)playlist
211     {
212     return playlist;
213     }
214    
215 masaki 72 - (XspfQTComponent *)trackList
216 masaki 2 {
217 masaki 116 return [playlist childAtIndex:0];
218 masaki 2 }
219    
220 masaki 196 + (NSSet *)keyPathsForValuesAffectingPlayingMovieDuration
221     {
222     return [NSSet setWithObject:@"playingMovie"];
223     }
224 masaki 171 - (void)setPlayingMovie:(QTMovie *)newMovie
225     {
226     // NSLog(@"new movie is %@!!", newMovie);
227     NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
228 masaki 193 if(playingMovie) {
229 masaki 188 [nc removeObserver:self
230     name:nil
231     object:playingMovie];
232     }
233 masaki 171
234     [playingMovie autorelease];
235 masaki 181 playingMovie = [newMovie retain];
236 masaki 196 playingMovieDuration = 0;
237 masaki 171
238 masaki 193 if(playingMovie) {
239 masaki 188 [nc addObserver:self
240     selector:@selector(notifee:)
241     name:QTMovieRateDidChangeNotification
242     object:playingMovie];
243     }
244 masaki 171 }
245     - (QTMovie *)playingMovie
246     {
247     // NSLog(@"%@ is called!!", NSStringFromSelector(_cmd));
248     return playingMovie;
249     }
250 masaki 182 - (NSTimeInterval)playingMovieDuration
251     {
252     if(playingMovieDuration == 0) {
253     QTTime qttime = [[self playingMovie] duration];
254     if(!QTGetTimeInterval(qttime, &playingMovieDuration)) playingMovieDuration = 0;
255     }
256    
257     return playingMovieDuration;
258     }
259 masaki 171 - (void)loadMovie
260     {
261     NSURL *location = [[self trackList] movieLocation];
262    
263 masaki 174 if(playingMovie) {
264     id movieURL = [playingMovie attributeForKey:QTMovieURLAttribute];
265 masaki 181 if([location isEqualUsingLocalhost:movieURL]) return;
266 masaki 174 }
267    
268 masaki 182 [loader setMovieURL:location];
269 masaki 181 [loader load];
270     QTMovie *newMovie = [loader qtMovie];
271     [self setPlayingMovie:newMovie];
272 masaki 171
273     QTTime qttime = [newMovie duration];
274     id t = [NSValueTransformer valueTransformerForName:@"XspfQTTimeDateTransformer"];
275     [[self trackList] setCurrentTrackDuration:[t transformedValue:[NSValue valueWithQTTime:qttime]]];
276 masaki 182
277     didPreloading = NO;
278 masaki 171 }
279 masaki 158 - (void)setPlayingTrackIndex:(unsigned)index
280 masaki 2 {
281 masaki 181 // [self performSelector:@selector(loadMovie) withObject:nil afterDelay:0.0];
282     [self loadMovie];
283 masaki 2 }
284 masaki 171 - (void)observeValueForKeyPath:(NSString *)keyPath
285     ofObject:(id)object
286     change:(NSDictionary *)change
287     context:(void *)context
288     {
289     if([keyPath isEqualToString:@"currentTrack"]) {
290     id trackList = [self trackList];
291     unsigned index = [trackList selectionIndex];
292     [self setPlayingTrackIndex:index];
293     }
294     }
295 masaki 31
296     - (NSData *)outputData
297     {
298     return [[self XMLDocument] XMLDataWithOptions:NSXMLNodePrettyPrint];
299     }
300 masaki 71 - (NSXMLDocument *)XMLDocument
301 masaki 31 {
302 masaki 116 id root = [[self playlist] XMLElement];
303 masaki 31
304     id d = [[[NSXMLDocument alloc] initWithRootElement:root] autorelease];
305     [d setVersion:@"1.0"];
306     [d setCharacterEncoding:@"UTF-8"];
307    
308     return d;
309     }
310 masaki 42
311 masaki 89 - (void)insertComponentFromURL:(NSURL *)url atIndex:(NSUInteger)index
312     {
313     NSString *xmlElem;
314     xmlElem = [NSString stringWithFormat:@"<track><location>%@</location></track>",
315     [url absoluteString]];
316    
317     NSError *error = nil;
318 masaki 117 id new = [XspfQTComponent xspfComponentWithXMLElementString:xmlElem
319     error:&error];
320 masaki 89 if(error) {
321     NSLog(@"%@", error);
322     @throw self;
323     }
324    
325     if(!new) {
326     @throw self;
327     }
328    
329     [self insertComponent:new atIndex:index];
330     }
331 masaki 86 - (void)insertComponent:(XspfQTComponent *)item atIndex:(NSUInteger)index
332 masaki 55 {
333 masaki 83 id undo = [self undoManager];
334 masaki 86 [undo registerUndoWithTarget:self selector:@selector(removeComponent:) object:item];
335 masaki 78 [[self trackList] insertChild:item atIndex:index];
336 masaki 55 }
337 masaki 86 - (void)removeComponent:(XspfQTComponent *)item
338 masaki 55 {
339 masaki 83 NSUInteger index = [[self trackList] indexOfChild:item];
340 masaki 121 if(index == NSNotFound) {
341     NSLog(@"Con not found item (%@)", item);
342     return;
343     }
344 masaki 83
345     id undo = [self undoManager];
346 masaki 86 [[undo prepareWithInvocationTarget:self] insertComponent:item atIndex:index];
347 masaki 55 [[self trackList] removeChild:item];
348     }
349    
350 masaki 141 - (NSData *)dataFromURL:(NSURL *)url error:(NSError **)outError
351     {
352     NSURLRequest *req = [NSURLRequest requestWithURL:url];
353     NSURLResponse *res = nil;
354     NSError *err = nil;
355     NSData *data = [NSURLConnection sendSynchronousRequest:req
356     returningResponse:&res
357     error:&err];
358     if(err) {
359     if(outError) {
360     *outError = err;
361     }
362     return nil;
363     }
364    
365     return data;
366     }
367    
368 masaki 171 - (void)notifee:(id)notification
369     {
370     // NSLog(@"Notifed: name -> (%@)\ndict -> (%@)", [notification name], [notification userInfo]);
371    
372     id track = [[self trackList] currentTrack];
373     NSNumber *rateValue = [[notification userInfo] objectForKey:QTMovieRateDidChangeNotificationParameter];
374     if(rateValue) {
375     float rate = [rateValue floatValue];
376     if(rate == 0) {
377     [track setIsPlayed:NO];
378     } else {
379     [track setIsPlayed:YES];
380     }
381     }
382     }
383    
384 masaki 182 - (void)checkPreload:(NSTimer *)timer
385     {
386 masaki 204 if(![XspfQTApp preloadingEnabled]) return;
387 masaki 182 if(didPreloading) return;
388    
389     NSTimeInterval duration;
390     NSTimeInterval current;
391     QTTime qttime = [playingMovie currentTime];
392     if(!QTGetTimeInterval(qttime, &current)) return;
393    
394     duration = [self playingMovieDuration];
395    
396 masaki 202 if( current / duration > [XspfQTApp beginingPreloadPercent] ) {
397 masaki 182 didPreloading = YES;
398     XspfQTComponent *list = [self trackList];
399     unsigned nextIndex = [list selectionIndex] + 1;
400     unsigned max = [list childrenCount];
401     if(max <= nextIndex) return;
402    
403     XspfQTComponent *nextTrack = [list childAtIndex:nextIndex];
404     NSURL *nextMovieURL = [nextTrack movieLocation];
405     [loader setMovieURL:nextMovieURL];
406     [loader load];
407    
408     // NSLog(@"Start preloading.");
409     }
410     }
411    
412 masaki 31 - (IBAction)dump:(id)sender
413     {
414     NSString *s = [[[NSString alloc] initWithData:[self outputData]
415     encoding:NSUTF8StringEncoding] autorelease];
416    
417     NSLog(@"%@", s);
418     }
419 masaki 2 @end
420    

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