Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /XspfQT/XspfQTDocument.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 306 - (hide annotations) (download)
Wed Feb 17 13:34:41 2010 UTC (14 years, 2 months ago) by masaki
File size: 12462 byte(s)
[Mod] XspfQTComponentを外部のHMXSPFComponentを使用するように変更。
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 306 #import "HMXSPFComponent.h"
13 masaki 72 #import "XspfQTMovieWindowController.h"
14     #import "XspfQTPlayListWindowController.h"
15 masaki 171 #import <QTKit/QTKit.h>
16 masaki 2
17 masaki 306 #import "NSURL-HMExtensions.h"
18 masaki 181 #import "XspfQTMovieLoader.h"
19 masaki 269 #import "XspfQTValueTransformers.h"
20 masaki 181
21 masaki 298 #import "XspfQTMovieTimer.h"
22 masaki 207
23 masaki 298
24 masaki 207 #pragma mark #### Global Variables ####
25     /********* Global variables *******/
26     NSString *XspfQTDocumentWillCloseNotification = @"XspfQTDocumentWillCloseNotification";
27    
28     /**********************************/
29    
30 masaki 72 @interface XspfQTDocument (Private)
31 masaki 306 - (void)setPlaylist:(HMXSPFComponent *)newList;
32     - (HMXSPFComponent *)playlist;
33 masaki 31 - (NSXMLDocument *)XMLDocument;
34 masaki 173 - (void)setPlayingMovie:(QTMovie *)newMovie;
35 masaki 141 - (NSData *)dataFromURL:(NSURL *)url error:(NSError **)outError;
36 masaki 274
37     inline static BOOL isXspfFileType(NSString *typeName);
38     inline static BOOL isReadableMovieType(NSString *typeName);
39 masaki 2 @end
40    
41 masaki 207 static NSString *XspfDocumentType = @"XML Shareable Playlist Format";
42     static NSString *QuickTimeMovieDocumentType = @"QuickTime Movie";
43     static NSString *MatroskaVideoDocumentType = @"Matroska Video";
44     static NSString *DivXMediaFormatDocumentType = @"DivX Media Format";
45    
46 masaki 224 static NSString *XspfUTI = @"com.masakih.xspf";
47    
48 masaki 244 static NSString *XspfQTCurrentTrackKey = @"currentTrack";
49    
50 masaki 72 @implementation XspfQTDocument
51 masaki 2
52 masaki 298 static XspfQTMovieTimer* timer = nil;
53     + (void)initialize
54     {
55     timer = [[XspfQTMovieTimer movieTimer] retain];
56     }
57    
58 masaki 182 - (id)init
59     {
60     self = [super init];
61     if(self) {
62     loader = [[XspfQTMovieLoader loaderWithMovieURL:nil delegate:nil] retain];
63     }
64    
65     return self;
66     }
67 masaki 95 - (id)initWithType:(NSString *)typeName error:(NSError **)outError
68     {
69     [self init];
70    
71 masaki 306 id newPlaylist = [HMXSPFComponent xspfPlaylist];
72 masaki 116 if(!newPlaylist) {
73 masaki 95 [self autorelease];
74     return nil;
75     }
76    
77 masaki 116 [self setPlaylist:newPlaylist];
78 masaki 95
79     return self;
80     }
81 masaki 182 - (void)dealloc
82     {
83     [self setPlayingMovie:nil];
84     [self setPlaylist:nil];
85     [playListWindowController release];
86     [movieWindowController release];
87     [loader release];
88    
89     [super dealloc];
90     }
91 masaki 2
92     - (void)makeWindowControllers
93     {
94 masaki 72 playListWindowController = [[XspfQTPlayListWindowController alloc] init];
95 masaki 2 [self addWindowController:playListWindowController];
96    
97 masaki 72 movieWindowController = [[XspfQTMovieWindowController alloc] init];
98 masaki 42 [movieWindowController setShouldCloseDocument:YES];
99 masaki 2 [self addWindowController:movieWindowController];
100 masaki 298
101     [timer put:self];
102 masaki 2 }
103    
104     - (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
105     {
106 masaki 243 return [[self XMLDocument] XMLDataWithOptions:NSXMLNodePrettyPrint];
107 masaki 2 }
108    
109 masaki 141 - (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError
110     {
111 masaki 274 if(!isReadableMovieType(typeName)) {
112 masaki 141 NSData *data = [self dataFromURL:absoluteURL error:outError];
113     if(!data) return NO;
114    
115     return [self readFromData:data ofType:typeName error:outError];
116     }
117    
118 masaki 306 id new = [HMXSPFComponent xspfTrackWithLocation:absoluteURL];
119 masaki 279 if(!new) {
120 masaki 141 if(outError) {
121 masaki 279 *outError = [NSError errorWithDomain:@"XspfQTErrorDomain" code:1 userInfo:nil];
122 masaki 141 }
123     return NO;
124     }
125    
126 masaki 306 id pl = [HMXSPFComponent xspfPlaylist];
127 masaki 141 if(!pl) {
128     return NO;
129     }
130    
131     [[[pl children] objectAtIndex:0] addChild:new];
132    
133     [self setPlaylist:pl];
134     id t = [self trackList];
135     if(![t title]) {
136     [t setTitle:[[[self fileURL] path] lastPathComponent]];
137     }
138    
139 masaki 207 [self setFileType:XspfDocumentType];
140 masaki 141 [self setFileURL:nil];
141    
142     return YES;
143     }
144 masaki 2 - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
145     {
146 masaki 274 if(!isXspfFileType(typeName)) {
147 masaki 141 return NO;
148     }
149    
150 masaki 2 NSError *error = nil;
151 masaki 10 NSXMLDocument *d = [[[NSXMLDocument alloc] initWithData:data
152     options:0
153     error:&error] autorelease];
154 masaki 121 if(error) {
155     NSLog(@"%@", error);
156 masaki 272 if(outError) {
157     *outError = error;
158     }
159 masaki 121 return NO;
160     }
161 masaki 2 NSXMLElement *root = [d rootElement];
162 masaki 306 id pl = [HMXSPFComponent xspfComponemtWithXMLElement:root];
163 masaki 121 if(!pl) {
164 masaki 306 NSLog(@"Can not create HMXSPFComponent.");
165 masaki 121 return NO;
166     }
167 masaki 116 [self setPlaylist:pl];
168 masaki 2
169 masaki 116 id t = [self trackList];
170 masaki 39 if(![t title]) {
171 masaki 165 [t setTitle:[[[[self fileURL] path] lastPathComponent] stringByDeletingPathExtension]];
172 masaki 39 }
173 masaki 272
174 masaki 2 return YES;
175     }
176    
177 masaki 42 - (void)close
178     {
179 masaki 61 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
180 masaki 72 [nc postNotificationName:XspfQTDocumentWillCloseNotification object:self];
181 masaki 61
182 masaki 42 [self removeWindowController:playListWindowController];
183     [playListWindowController release];
184     playListWindowController = nil;
185    
186     [self removeWindowController:movieWindowController];
187     [movieWindowController release];
188     movieWindowController = nil;
189 masaki 298
190 masaki 42 [super close];
191     }
192    
193 masaki 269 #pragma mark### Actions ###
194 masaki 33 - (IBAction)togglePlayAndPause:(id)sender
195     {
196     [movieWindowController togglePlayAndPause:sender];
197     }
198 masaki 2 - (IBAction)showPlayList:(id)sender
199     {
200     [playListWindowController showWindow:self];
201     }
202 masaki 281 - (IBAction)setThumbnailFrame:(id)sender
203 masaki 269 {
204 masaki 306 HMXSPFComponent *currentTrack = [[self trackList] currentTrack];
205 masaki 269 QTTime currentQTTime = [playingMovie currentTime];
206    
207     NSTimeInterval currentTI;
208     QTGetTimeInterval(currentQTTime, &currentTI);
209    
210 masaki 306 HMXSPFComponent *prevThumbnailTrack = [playlist thumbnailTrack];
211 masaki 281 NSTimeInterval ti = [playlist thumbnailTimeInterval];
212 masaki 269
213 masaki 281 [playlist setThumbnailComponent:currentTrack timeIntarval:currentTI];
214 masaki 269
215     id undo = [self undoManager];
216 masaki 281 if(prevThumbnailTrack) {
217     [[undo prepareWithInvocationTarget:playlist] setThumbnailComponent:prevThumbnailTrack timeIntarval:ti];
218     [undo setActionName:NSLocalizedString(@"Change Thumbnail frame.", @"Undo Action Name Change Thumbnail frame")];
219 masaki 269 } else {
220 masaki 281 [[undo prepareWithInvocationTarget:playlist] removeThumbnailFrame];
221     [undo setActionName:NSLocalizedString(@"Add Thumbnail frame.", @"Undo Action Name Add Thumbnail frame")];
222 masaki 269 }
223     }
224 masaki 281 - (IBAction)removeThumbnail:(id)sender
225 masaki 269 {
226 masaki 306 HMXSPFComponent *prevThumbnailTrack = [playlist thumbnailTrack];
227 masaki 281 NSTimeInterval ti = [playlist thumbnailTimeInterval];
228 masaki 269
229 masaki 281 [playlist removeThumbnailFrame];
230 masaki 269
231 masaki 281 if(prevThumbnailTrack) {
232 masaki 269 id undo = [self undoManager];
233 masaki 281 [[undo prepareWithInvocationTarget:playlist] setThumbnailComponent:prevThumbnailTrack timeIntarval:ti];
234     [undo setActionName:NSLocalizedString(@"Remove Thumbnail frame.", @"Undo Action Name Remove Thumbnail frame")];
235 masaki 269 }
236     }
237     - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
238     {
239     SEL action = [menuItem action];
240    
241 masaki 281 if(action == @selector(removeThumbnail:)) {
242 masaki 306 HMXSPFComponent *component = [playlist thumbnailTrack];
243 masaki 269 if(!component) return NO;
244     }
245    
246     return YES;
247     }
248 masaki 2
249 masaki 306 - (void)setPlaylist:(HMXSPFComponent *)newList
250 masaki 2 {
251 masaki 116 if(playlist == newList) return;
252 masaki 2
253 masaki 244 [[playlist childAtIndex:0] removeObserver:self forKeyPath:XspfQTCurrentTrackKey];
254 masaki 116 [playlist autorelease];
255     playlist = [newList retain];
256 masaki 171 [[playlist childAtIndex:0] addObserver:self
257 masaki 244 forKeyPath:XspfQTCurrentTrackKey
258 masaki 171 options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
259     context:NULL];
260 masaki 2 }
261 masaki 306 - (HMXSPFComponent *)playlist
262 masaki 116 {
263     return playlist;
264     }
265    
266 masaki 306 - (HMXSPFComponent *)trackList
267 masaki 2 {
268 masaki 116 return [playlist childAtIndex:0];
269 masaki 2 }
270    
271 masaki 196 + (NSSet *)keyPathsForValuesAffectingPlayingMovieDuration
272     {
273     return [NSSet setWithObject:@"playingMovie"];
274     }
275 masaki 171 - (void)setPlayingMovie:(QTMovie *)newMovie
276     {
277     NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
278 masaki 193 if(playingMovie) {
279 masaki 188 [nc removeObserver:self
280     name:nil
281     object:playingMovie];
282     }
283 masaki 171
284     [playingMovie autorelease];
285 masaki 181 playingMovie = [newMovie retain];
286 masaki 196 playingMovieDuration = 0;
287 masaki 171
288 masaki 193 if(playingMovie) {
289 masaki 188 [nc addObserver:self
290     selector:@selector(notifee:)
291     name:QTMovieRateDidChangeNotification
292     object:playingMovie];
293     }
294 masaki 171 }
295     - (QTMovie *)playingMovie
296     {
297     return playingMovie;
298     }
299 masaki 182 - (NSTimeInterval)playingMovieDuration
300     {
301     if(playingMovieDuration == 0) {
302     QTTime qttime = [[self playingMovie] duration];
303     if(!QTGetTimeInterval(qttime, &playingMovieDuration)) playingMovieDuration = 0;
304     }
305    
306     return playingMovieDuration;
307     }
308 masaki 171 - (void)loadMovie
309     {
310     NSURL *location = [[self trackList] movieLocation];
311    
312 masaki 174 if(playingMovie) {
313     id movieURL = [playingMovie attributeForKey:QTMovieURLAttribute];
314 masaki 181 if([location isEqualUsingLocalhost:movieURL]) return;
315 masaki 174 }
316    
317 masaki 182 [loader setMovieURL:location];
318 masaki 181 [loader load];
319     QTMovie *newMovie = [loader qtMovie];
320     [self setPlayingMovie:newMovie];
321 masaki 171
322     QTTime qttime = [newMovie duration];
323     id t = [NSValueTransformer valueTransformerForName:@"XspfQTTimeDateTransformer"];
324     [[self trackList] setCurrentTrackDuration:[t transformedValue:[NSValue valueWithQTTime:qttime]]];
325 masaki 182
326     didPreloading = NO;
327 masaki 171 }
328 masaki 242
329 masaki 171 - (void)observeValueForKeyPath:(NSString *)keyPath
330     ofObject:(id)object
331     change:(NSDictionary *)change
332     context:(void *)context
333     {
334 masaki 244 if([keyPath isEqualToString:XspfQTCurrentTrackKey]) {
335 masaki 242 [self loadMovie];
336 masaki 171 }
337     }
338 masaki 31
339 masaki 71 - (NSXMLDocument *)XMLDocument
340 masaki 31 {
341 masaki 116 id root = [[self playlist] XMLElement];
342 masaki 31
343     id d = [[[NSXMLDocument alloc] initWithRootElement:root] autorelease];
344     [d setVersion:@"1.0"];
345     [d setCharacterEncoding:@"UTF-8"];
346    
347     return d;
348     }
349 masaki 42
350 masaki 89 - (void)insertComponentFromURL:(NSURL *)url atIndex:(NSUInteger)index
351     {
352 masaki 306 id new = [HMXSPFComponent xspfTrackWithLocation:url];
353 masaki 89 if(!new) {
354     @throw self;
355     }
356    
357     [self insertComponent:new atIndex:index];
358     }
359 masaki 306 - (void)insertComponent:(HMXSPFComponent *)item atIndex:(NSUInteger)index
360 masaki 55 {
361 masaki 83 id undo = [self undoManager];
362 masaki 86 [undo registerUndoWithTarget:self selector:@selector(removeComponent:) object:item];
363 masaki 78 [[self trackList] insertChild:item atIndex:index];
364 masaki 261 [undo setActionName:NSLocalizedString(@"Insert Movie", @"Undo Action Name Insert Movie")];
365 masaki 55 }
366 masaki 306 - (void)removeComponent:(HMXSPFComponent *)item
367 masaki 55 {
368 masaki 83 NSUInteger index = [[self trackList] indexOfChild:item];
369 masaki 121 if(index == NSNotFound) {
370 masaki 269 NSLog(@"Can not found item (%@)", item);
371 masaki 121 return;
372     }
373 masaki 83
374     id undo = [self undoManager];
375 masaki 86 [[undo prepareWithInvocationTarget:self] insertComponent:item atIndex:index];
376 masaki 55 [[self trackList] removeChild:item];
377 masaki 261 [undo setActionName:NSLocalizedString(@"Remove Movie", @"Undo Action Name Remove Movie")];
378 masaki 55 }
379 masaki 247 - (void)moveComponentFromIndex:(NSUInteger)from toIndex:(NSUInteger)to
380     {
381     id undo = [self undoManager];
382     [[undo prepareWithInvocationTarget:self] moveComponentFromIndex:to toIndex:from];
383     [[self trackList] moveChildFromIndex:from toIndex:to];
384 masaki 261 [undo setActionName:NSLocalizedString(@"Move Movie", @"Undo Action Name Move Movie")];
385 masaki 247 }
386 masaki 306 - (void)moveComponent:(HMXSPFComponent *)item toIndex:(NSUInteger)index
387 masaki 247 {
388     NSUInteger from = [[self trackList] indexOfChild:item];
389     if(from == NSNotFound) return;
390     [self moveComponentFromIndex:from toIndex:index];
391     }
392 masaki 55
393 masaki 141 - (NSData *)dataFromURL:(NSURL *)url error:(NSError **)outError
394     {
395     NSURLRequest *req = [NSURLRequest requestWithURL:url];
396     NSURLResponse *res = nil;
397     NSError *err = nil;
398     NSData *data = [NSURLConnection sendSynchronousRequest:req
399     returningResponse:&res
400     error:&err];
401     if(err) {
402     if(outError) {
403     *outError = err;
404     }
405     return nil;
406     }
407    
408     return data;
409     }
410    
411 masaki 171 - (void)notifee:(id)notification
412     {
413     // NSLog(@"Notifed: name -> (%@)\ndict -> (%@)", [notification name], [notification userInfo]);
414    
415     id track = [[self trackList] currentTrack];
416     NSNumber *rateValue = [[notification userInfo] objectForKey:QTMovieRateDidChangeNotificationParameter];
417     if(rateValue) {
418     float rate = [rateValue floatValue];
419     if(rate == 0) {
420     [track setIsPlayed:NO];
421     } else {
422     [track setIsPlayed:YES];
423     }
424     }
425     }
426    
427 masaki 298 // call from XspfQTMovieTimer.
428 masaki 182 - (void)checkPreload:(NSTimer *)timer
429     {
430 masaki 205 if(![XspfQTPref preloadingEnabled]) return;
431 masaki 182 if(didPreloading) return;
432    
433     NSTimeInterval duration;
434     NSTimeInterval current;
435     QTTime qttime = [playingMovie currentTime];
436     if(!QTGetTimeInterval(qttime, &current)) return;
437    
438     duration = [self playingMovieDuration];
439    
440 masaki 205 if( current / duration > [XspfQTPref beginingPreloadPercent] ) {
441 masaki 182 didPreloading = YES;
442 masaki 306 HMXSPFComponent *list = [self trackList];
443 masaki 303 NSUInteger nextIndex = [list selectionIndex] + 1;
444     NSUInteger max = [list childrenCount];
445 masaki 182 if(max <= nextIndex) return;
446    
447 masaki 306 HMXSPFComponent *nextTrack = [list childAtIndex:nextIndex];
448 masaki 182 NSURL *nextMovieURL = [nextTrack movieLocation];
449     [loader setMovieURL:nextMovieURL];
450     [loader load];
451     }
452     }
453    
454 masaki 274 inline static BOOL isXspfFileType(NSString *typeName)
455     {
456     return [typeName isEqualToString:XspfDocumentType] || [typeName isEqualToString:XspfUTI];
457     }
458     inline static BOOL isReadableMovieType(NSString *typeName)
459     {
460     return [typeName isEqualToString:QuickTimeMovieDocumentType]
461     || [typeName isEqualToString:MatroskaVideoDocumentType]
462     || [typeName isEqualToString:DivXMediaFormatDocumentType];
463     }
464    
465 masaki 2 @end
466    

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