Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfQT/XspfQTDocument.m

Parent Directory Parent Directory | Revision Log Revision Log


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

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