Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfQT/XspfQTDocument.m

Parent Directory Parent Directory | Revision Log Revision Log


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