Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfQT/XspfQTDocument.m

Parent Directory Parent Directory | Revision Log Revision Log


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

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