• R/O
  • SSH
  • HTTPS

xspfqt: Commit


Commit MetaInfo

Révision54 (tree)
l'heure2008-09-14 10:21:31
Auteurmasaki

Message de Log

make branch XspfComponent to simple model.

Change Summary

Modification

--- branches/XspfComponentSimply-branch/XspfPlayListWindowController.m (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfPlayListWindowController.m (revision 54)
@@ -0,0 +1,194 @@
1+//
2+// XspfPlayListWindowController.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/31.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import "XspfPlayListWindowController.h"
10+#import "XspfDocument.h"
11+#import "XspfComponent.h"
12+
13+
14+@interface XspfPlayListWindowController(Private)
15+- (void)setObserveObject:(id)new;
16+@end
17+
18+@implementation XspfPlayListWindowController
19+
20+static NSString *const XspfQTPlayListItemType = @"XspfQTPlayListItemType";
21+
22+- (id)init
23+{
24+ return [super initWithWindowNibName:@"XspfPlayList"];
25+}
26+
27+- (void)awakeFromNib
28+{
29+ [listView setDoubleAction:@selector(changeCurrentTrack:)];
30+ [[self window] setReleasedWhenClosed:NO];
31+
32+ [trackListTree addObserver:self
33+ forKeyPath:@"selection"
34+ options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
35+ context:NULL];
36+ [self setObserveObject:[trackListTree valueForKeyPath:@"selection.self"]];
37+
38+ [listView expandItem:[listView itemAtRow:0]];
39+
40+ [listView registerForDraggedTypes:[NSArray arrayWithObject:XspfQTPlayListItemType]];
41+}
42+- (void)dealloc
43+{
44+ [trackListTree removeObserver:self forKeyPath:@"selection"];
45+ [self setObserveObject:nil];
46+
47+ [super dealloc];
48+}
49+
50+- (IBAction)changeCurrentTrack:(id)sender
51+{
52+ id selections = [trackListTree selectedObjects];
53+ if([selections count] == 0) return;
54+
55+ NSIndexPath *selectionIndexPath = [trackListTree selectionIndexPath];
56+// NSLog(@"Selection %@", selectionIndexPath);
57+// NSLog(@"Selection index %d", [selectionIndexPath indexAtPosition:1]);
58+
59+ if([selectionIndexPath length] > 1) {
60+ [[self document] setPlayTrackindex:[selectionIndexPath indexAtPosition:1]];
61+ }
62+}
63+
64+- (void)keyDown:(NSEvent *)theEvent
65+{
66+ if([theEvent isARepeat]) return;
67+
68+ unsigned short code = [theEvent keyCode];
69+ if(code == 49 /* space bar */) {
70+ [[self document] togglePlayAndPause:self];
71+ }
72+}
73+
74+- (BOOL)windowShouldClose:(id)sender
75+{
76+ [sender orderOut:self];
77+
78+ return NO;
79+}
80+- (void)setObserveObject:(id)new
81+{
82+ if(obseveObject == new) return;
83+
84+ [obseveObject removeObserver:self forKeyPath:@"title"];
85+
86+ obseveObject = new;
87+ [obseveObject addObserver:self
88+ forKeyPath:@"title"
89+ options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
90+ context:NULL];
91+}
92+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
93+{
94+ if([keyPath isEqualToString:@"selection"]) {
95+ id new = [object valueForKeyPath:@"selection.self"];
96+ [self setObserveObject:new];
97+ }
98+
99+ if([keyPath isEqualToString:@"title"]) {
100+ id new = [change objectForKey:NSKeyValueChangeNewKey];
101+ id old = [change objectForKey:NSKeyValueChangeOldKey];
102+
103+ if(new == old) return;
104+ if([new isEqualTo:old]) return;
105+
106+ id um = [[self document] undoManager];
107+ [um registerUndoWithTarget:obseveObject
108+ selector:@selector(setTitle:)
109+ object:old];
110+ }
111+}
112+
113+
114+- (BOOL)outlineView:(NSOutlineView *)outlineView
115+ writeItems:(NSArray *)items
116+ toPasteboard:(NSPasteboard *)pasteboard
117+{
118+ if([items count] > 1) return NO;
119+
120+ id item = [[items objectAtIndex:0] representedObject];
121+
122+ if(![item isKindOfClass:[XspfComponent class]]) {
123+ NSLog(@"Ouch! %@", NSStringFromClass([item class]));
124+ return NO;
125+ }
126+ if(![item isLeaf]) return NO;
127+
128+ NSData *data = [NSKeyedArchiver archivedDataWithRootObject:item];
129+ if(!data) {
130+ NSLog(@"Could not archive.");
131+ return NO;
132+ }
133+
134+ [pasteboard declareTypes:[NSArray arrayWithObject:XspfQTPlayListItemType]
135+ owner:self];
136+ [pasteboard setData:data
137+ forType:XspfQTPlayListItemType];
138+ return YES;
139+}
140+- (NSDragOperation)outlineView:(NSOutlineView *)outlineView
141+ validateDrop:(id <NSDraggingInfo>)info
142+ proposedItem:(id)item
143+ proposedChildIndex:(NSInteger)index
144+{
145+ if([item isLeaf]) {
146+ return NSDragOperationNone;
147+ }
148+
149+ id pb = [info draggingPasteboard];
150+
151+ if(![[pb types] containsObject:XspfQTPlayListItemType]) {
152+ return NSDragOperationNone;
153+ }
154+
155+ return NSDragOperationMove;
156+}
157+- (BOOL)outlineView:(NSOutlineView *)outlineView
158+ acceptDrop:(id <NSDraggingInfo>)info
159+ item:(id)item
160+ childIndex:(NSInteger)index
161+{
162+ if([item isLeaf]) {
163+ return NO;
164+ }
165+
166+ id pb = [info draggingPasteboard];
167+
168+ NSData *data = [pb dataForType:XspfQTPlayListItemType];
169+ if(!data) return NO;
170+
171+ id newItem = [NSKeyedUnarchiver unarchiveObjectWithData:data];
172+ if(!newItem) return NO;
173+
174+ NSLog(@"new item class is %@\n%@", NSStringFromClass([newItem class]), newItem);
175+
176+ return NO;
177+}
178+
179+@end
180+
181+@implementation XspfThowSpacebarKeyDownOutlineView
182+- (void)keyDown:(NSEvent *)theEvent
183+{
184+ unsigned short code = [theEvent keyCode];
185+ if(code == 49 /* space bar */) {
186+ if(_delegate && [_delegate respondsToSelector:@selector(keyDown:)]) {
187+ [_delegate keyDown:theEvent];
188+ }
189+ }
190+
191+ [super keyDown:theEvent];
192+}
193+
194+@end
--- branches/XspfComponentSimply-branch/XspfComponent.h (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfComponent.h (revision 54)
@@ -0,0 +1,58 @@
1+//
2+// XspfComponent.h
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/29.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import <Cocoa/Cocoa.h>
10+#import <QTKit/QTKit.h>
11+
12+@interface XspfComponent : NSObject <NSCoding>
13+{
14+ NSString *title;
15+ BOOL isSelected;
16+ NSIndexPath *selectionIndexPath;
17+
18+ XspfComponent *parent; // not retained.
19+}
20+
21++ (id)xspfComponemtWithXMLElement:(NSXMLElement *)element;
22+- (id)initWithXMLElement:(NSXMLElement *)element; // abstract.
23+
24+- (NSXMLElement *)XMLElement; // abstract.
25+
26+- (QTMovie *)qtMovie;
27+
28+- (void)setTitle:(NSString *)title;
29+- (NSString *)title;
30+
31+// selection for playing.
32+- (BOOL)isSelected;
33+- (void)select;
34+- (void)deselect;
35+- (void)setSelectionIndex:(unsigned)index;
36+- (BOOL)setSelectionIndexPath:(NSIndexPath *)indexPath;
37+- (NSIndexPath *)selectionIndexPath;
38+
39+- (XspfComponent *)currentTrack; // default self;
40+- (void)next; // abstract.
41+- (void)previous; // abstract.
42+
43+- (void)setIsPlayed:(BOOL)state;
44+- (BOOL)isPlayed;
45+
46+- (XspfComponent *)parent;
47+- (NSArray *)children; // default nil.
48+- (unsigned)childrenCount; // default [[self children] count].
49+- (BOOL)isLeaf; // default YES.
50+
51+- (void)addChild:(XspfComponent *)child; // not implemented.
52+- (void)removeChild:(XspfComponent *)child; // not implemented.
53+- (void)insertChild:(XspfComponent *)child atIndex:(unsigned)index; // not implemented.
54+- (void)removeChildAtIndex:(unsigned)index; //not implemented.
55+- (void)setParent:(XspfComponent *)parent; // Do not call directly. call in only -addChild: method.
56+
57+
58+@end
--- branches/XspfComponentSimply-branch/XspfComponent.m (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfComponent.m (revision 54)
@@ -0,0 +1,222 @@
1+//
2+// XspfComponent.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/29.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import "XspfComponent.h"
10+#import "XspfPlaceholderComponent.h"
11+
12+@implementation XspfComponent
13+
14++ (id) allocWithZone:(NSZone *) zone
15+{
16+ if ([self class] == [XspfComponent class]) {
17+ return [XspfPlaceholderComponent sharedInstance];
18+ }
19+
20+ return [super allocWithZone:zone];
21+}
22+
23++ (id)xspfComponemtWithXMLElement:(NSXMLElement *)element
24+{
25+ return [[[self alloc] initWithXMLElement:element] autorelease];
26+}
27+- (id)initWithXMLElement:(NSXMLElement *)element
28+{
29+ [super init];
30+ [self release];
31+
32+ [self doesNotRecognizeSelector:_cmd];
33+
34+ return nil;
35+}
36+- (void)dealloc
37+{
38+ [title release];
39+ [selectionIndexPath release];
40+
41+ [super dealloc];
42+}
43+
44+- (NSXMLElement *)XMLElement
45+{
46+ [self doesNotRecognizeSelector:_cmd];
47+
48+ return nil;
49+}
50+
51+- (QTMovie *)qtMovie
52+{
53+ return nil;
54+}
55+- (NSDate *)duration
56+{
57+ return nil;
58+}
59+- (XspfComponent *)parent
60+{
61+ return parent;
62+}
63+- (NSArray *)children
64+{
65+ return nil;
66+}
67+- (unsigned)childrenCount
68+{
69+ return [[self children] count];
70+}
71+- (BOOL)isLeaf
72+{
73+ return YES;
74+}
75+
76+- (void)setParent:(XspfComponent *)new
77+{
78+ parent = new;
79+}
80+- (void)addChild:(XspfComponent *)child
81+{
82+ [self doesNotRecognizeSelector:_cmd];
83+}
84+- (void)removeChild:(XspfComponent *)child
85+{
86+ [self doesNotRecognizeSelector:_cmd];
87+}
88+- (void)insertChild:(XspfComponent *)child atIndex:(unsigned)index
89+{
90+ [self doesNotRecognizeSelector:_cmd];
91+}
92+- (void)removeChildAtIndex:(unsigned)index
93+{
94+ [self doesNotRecognizeSelector:_cmd];
95+}
96+- (void)setTitle:(NSString *)new
97+{
98+ if(title == new) return;
99+ if([title isEqualTo:new]) return;
100+
101+ [title autorelease];
102+ title = [new copy];
103+}
104+- (NSString *)title
105+{
106+ return title;
107+}
108+- (BOOL)isSelected
109+{
110+ return isSelected;
111+}
112+- (void)select
113+{
114+ [self willChangeValueForKey:@"isSelected"];
115+ isSelected = YES;
116+ [self didChangeValueForKey:@"isSelected"];
117+}
118+- (void)deselect
119+{
120+ [self willChangeValueForKey:@"isSelected"];
121+ isSelected = NO;
122+ [self didChangeValueForKey:@"isSelected"];
123+}
124+- (void)setSelectionIndex:(unsigned)index
125+{
126+ [self doesNotRecognizeSelector:_cmd];
127+
128+ // 現在値と違うなら現在値をdeselect
129+
130+ // 新しい値をselect
131+}
132+- (BOOL)setSelectionIndexPath:(NSIndexPath *)indexPath
133+{
134+ unsigned length = [indexPath length];
135+ if(length == 0) {
136+ return NO;
137+ }
138+ unsigned firstIndex = [indexPath indexAtPosition:0];
139+ if(firstIndex > [self childrenCount]) {
140+ return NO;
141+ }
142+
143+ XspfComponent *firstIndexedChild = [[self children] objectAtIndex:firstIndex];
144+ if(length != 1) {
145+ NSIndexPath *deletedFirstIndex = nil;
146+ unsigned *indexP = NULL;
147+ @try {
148+ indexP = calloc(sizeof(unsigned), length);
149+ if(!indexP) {
150+ [NSException raise:NSMallocException
151+ format:@"Not enough memory"];
152+ }
153+ [indexPath getIndexes:indexP];
154+ deletedFirstIndex = [NSIndexPath indexPathWithIndexes:indexP + 1
155+ length:length - 1];
156+ }
157+ @catch (id ex) {
158+ @throw;
159+ }
160+ @finally{
161+ free(indexP);
162+ }
163+ if(!deletedFirstIndex ||
164+ ![firstIndexedChild setSelectionIndexPath:deletedFirstIndex]) {
165+ return NO;
166+ }
167+ } else {
168+ [self setSelectionIndex:firstIndex];
169+ }
170+ if(!isSelected) {
171+ [self select];
172+ }
173+ [selectionIndexPath autorelease];
174+ selectionIndexPath = [indexPath retain];
175+
176+ return YES;
177+}
178+- (NSIndexPath *)selectionIndexPath
179+{
180+ return selectionIndexPath;
181+}
182+- (void)setIsPlayed:(BOOL)state {} // do nothing.
183+- (BOOL)isPlayed
184+{
185+ return NO;
186+}
187+- (XspfComponent *)currentTrack
188+{
189+ return self;
190+}
191+- (void)next
192+{
193+ [self doesNotRecognizeSelector:_cmd];
194+}
195+- (void)previous
196+{
197+ [self doesNotRecognizeSelector:_cmd];
198+}
199+
200+- (void)encodeWithCoder:(NSCoder *)aCoder
201+{
202+ NSString *string = [[self XMLElement] XMLString];
203+ [aCoder encodeObject:string forKey:@"XspfQTComponentXMLStringCodingKey"];
204+}
205+- (id)initWithCoder:(NSCoder *)aDecoder
206+{
207+ [super init];
208+ [self autorelease];
209+
210+ id string = [aDecoder decodeObjectForKey:@"XspfQTComponentXMLStringCodingKey"];
211+
212+ NSError *error = nil;
213+ NSXMLElement *element = [[[NSXMLElement alloc] initWithXMLString:string error:&error] autorelease];
214+ if(error) {
215+ NSLog(@"%@", error);
216+ return nil;
217+ }
218+
219+ return [[[self class] alloc] initWithXMLElement:element];
220+}
221+
222+@end
--- branches/XspfComponentSimply-branch/XspfMovieWindowController.h (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfMovieWindowController.h (revision 54)
@@ -0,0 +1,42 @@
1+//
2+// XspfMovieWindowController.h
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/31.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import <Cocoa/Cocoa.h>
10+#import <QTKit/QTKit.h>
11+
12+
13+@interface XspfMovieWindowController : NSWindowController
14+{
15+ IBOutlet QTMovieView *qtView;
16+ IBOutlet NSButton *playButton;
17+
18+ NSWindow *fullscreenWindow;
19+ NSRect nomalModeSavedFrame;
20+ BOOL fullScreenMode;
21+
22+ QTMovie *qtMovie;
23+ NSTimer *updateTime;
24+
25+ NSPoint prevMouse;
26+ NSDate *prevMouseMovedDate;
27+
28+ NSSize windowSizeWithoutQTView;
29+}
30+
31+- (IBAction)togglePlayAndPause:(id)sender;
32+- (IBAction)toggleFullScreenMode:(id)sender;
33+- (IBAction)forwardTagValueSecends:(id)sender;
34+- (IBAction)backwardTagValueSecends:(id)sender;
35+- (IBAction)nextTrack:(id)sender;
36+- (IBAction)previousTrack:(id)sender;
37+
38+- (void)play;
39+
40+- (void)setQtMovie:(QTMovie *)qt;
41+- (QTMovie *)qtMovie;
42+@end
--- branches/XspfComponentSimply-branch/XspfAppDelegate.h (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfAppDelegate.h (revision 54)
@@ -0,0 +1,17 @@
1+//
2+// XspfAppDelegate.h
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/31.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import <Cocoa/Cocoa.h>
10+
11+
12+@interface XspfAppDelegate : NSObject
13+{
14+ NSWindow *mainWindowStore;
15+}
16+
17+@end
--- branches/XspfComponentSimply-branch/XspfMovieWindowController.m (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfMovieWindowController.m (revision 54)
@@ -0,0 +1,415 @@
1+//
2+// XspfMovieWindowController.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/31.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import "XspfMovieWindowController.h"
10+#import "XspfDocument.h"
11+#import "XspfComponent.h"
12+#import "XspfFullScreenWindow.h"
13+
14+
15+@interface XspfMovieWindowController (Private)
16+- (NSSize)windowSizeWithoutQTView;
17+- (void)sizeTofitWidnow;
18+- (NSSize)fitSizeToSize:(NSSize)toSize;
19+- (NSWindow *)fullscreenWindow;
20+@end
21+
22+@implementation XspfMovieWindowController
23+
24+#pragma mark ### Static variables ###
25+static const float sVolumeDelta = 0.2;
26+static NSString *const kQTMovieKeyPath = @"trackList.qtMovie";
27+static NSString *const kIsPlayedKeyPath = @"trackList.isPlayed";
28+
29+- (id)init
30+{
31+ if(self = [super initWithWindowNibName:@"XspfDocument"]) {
32+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
33+ [nc addObserver:self
34+ selector:@selector(applicationWillTerminate:)
35+ name:NSApplicationWillTerminateNotification
36+ object:NSApp];
37+
38+ updateTime = [NSTimer scheduledTimerWithTimeInterval:0.3
39+ target:self
40+ selector:@selector(updateTimeIfNeeded:)
41+ userInfo:NULL
42+ repeats:YES];
43+ }
44+
45+ return self;
46+}
47+
48+- (void)dealloc
49+{
50+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
51+ [nc removeObserver:self];
52+
53+ [self setQtMovie:nil];
54+
55+ [fullscreenWindow release];
56+ [updateTime release];
57+ [prevMouseMovedDate release];
58+
59+ [super dealloc];
60+}
61+- (void)awakeFromNib
62+{
63+ prevMouseMovedDate = [[NSDate dateWithTimeIntervalSinceNow:0.0] retain];
64+
65+ id d = [self document];
66+// NSLog(@"Add Observed! %@", d);
67+ [d addObserver:self
68+ forKeyPath:kQTMovieKeyPath
69+ options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
70+ context:NULL];
71+ [d addObserver:self
72+ forKeyPath:kIsPlayedKeyPath
73+ options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
74+ context:NULL];
75+
76+ [self sizeTofitWidnow];
77+ [self play];
78+}
79+
80+#pragma mark ### KVO & KVC ###
81+- (void)observeValueForKeyPath:(NSString *)keyPath
82+ ofObject:(id)object
83+ change:(NSDictionary *)change
84+ context:(void *)context
85+{
86+// NSLog(@"Observed!");
87+ if([keyPath isEqualToString:kQTMovieKeyPath]) {
88+ id new = [change objectForKey:NSKeyValueChangeNewKey];
89+ [self setQtMovie:new];
90+ return;
91+ }
92+ if([keyPath isEqualToString:kIsPlayedKeyPath]) {
93+ id new = [change objectForKey:NSKeyValueChangeNewKey];
94+
95+ if([new boolValue]) {
96+ [playButton setTitle:@"||"];
97+ } else {
98+ [playButton setTitle:@">"];
99+ }
100+ return;
101+ }
102+
103+
104+ [super observeValueForKeyPath:keyPath
105+ ofObject:object
106+ change:change
107+ context:context];
108+}
109+
110+- (void)setQtMovie:(QTMovie *)qt
111+{
112+ if(qtMovie == qt) return;
113+ if([qtMovie isEqual:qt]) return;
114+
115+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
116+
117+ if(qtMovie) {
118+ [nc removeObserver:self name:nil object:qtMovie];
119+ }
120+ if(qt) {
121+ [nc addObserver:self selector:@selector(didEndMovie:) name:QTMovieDidEndNotification object:qt];
122+ }
123+
124+ if(qtMovie) {
125+ [qt setVolume:[qtMovie volume]];
126+ [qt setMuted:[qtMovie muted]];
127+ }
128+ [qtMovie autorelease];
129+ qtMovie = [qt retain];
130+
131+ if(!qtMovie) return;
132+
133+ [self synchronizeWindowTitleWithDocumentName];
134+ [self sizeTofitWidnow];
135+ [self play];
136+}
137+- (QTMovie *)qtMovie
138+{
139+ return qtMovie;
140+}
141+
142+#pragma mark ### Other functions ###
143+- (NSSize)windowSizeWithoutQTView
144+{
145+ if(windowSizeWithoutQTView.width == 0
146+ && windowSizeWithoutQTView.height == 0) {
147+ QTMovie *curMovie = [self qtMovie];
148+ if(!curMovie) return windowSizeWithoutQTView;
149+
150+ NSSize qtViewSize = [qtView frame].size;
151+ NSSize currentWindowSize = [[self window] frame].size;
152+
153+ windowSizeWithoutQTView = NSMakeSize(currentWindowSize.width - qtViewSize.width,
154+ currentWindowSize.height - qtViewSize.height);
155+ }
156+
157+ return windowSizeWithoutQTView;
158+}
159+- (void)sizeTofitWidnow
160+{
161+ id window = [self window];
162+ NSRect frame = [window frame];
163+ NSSize newSize = [self fitSizeToSize:frame.size];
164+ frame.origin.y += frame.size.height - newSize.height;
165+ frame.size = newSize;
166+
167+ [window setFrame:frame display:YES animate:YES];
168+}
169+- (NSSize)fitSizeToSize:(NSSize)toSize
170+{
171+ QTMovie *curMovie = [self qtMovie];
172+ if(!curMovie) return toSize;
173+
174+ // Area size without QTMovieView.
175+ NSSize delta = [self windowSizeWithoutQTView];
176+
177+ NSSize movieSize = [[curMovie attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
178+
179+ float targetViewWidth = toSize.width - delta.width;
180+ float targetViewHeight = targetViewWidth * (movieSize.height / movieSize.width);
181+
182+ targetViewWidth += delta.width;
183+ targetViewHeight += delta.height;
184+
185+ NSSize newSize = NSMakeSize(targetViewWidth, targetViewHeight);
186+
187+ return newSize;
188+}
189+
190+- (void)play
191+{
192+ [qtView performSelectorOnMainThread:@selector(play:) withObject:self waitUntilDone:NO];
193+}
194+- (void)pause
195+{
196+ [qtView performSelectorOnMainThread:@selector(pause:) withObject:self waitUntilDone:NO];
197+}
198+
199+- (void)enterFullScreen
200+{
201+ NSWindow *w = [self fullscreenWindow];
202+
203+ nomalModeSavedFrame = [qtView frame];
204+
205+ [[self window] orderOut:self];
206+ [w setContentView:qtView];
207+
208+// [NSMenu setMenuBarVisible:NO];
209+ SetSystemUIMode (kUIModeAllHidden, kUIOptionAutoShowMenuBar);
210+
211+ [w makeKeyAndOrderFront:self];
212+ [w makeFirstResponder:qtView];
213+}
214+- (void)exitFullScreen
215+{
216+ NSWindow *w = [self fullscreenWindow];
217+
218+ [qtView retain];
219+ {
220+ [qtView removeFromSuperview];
221+ [qtView setFrame:nomalModeSavedFrame];
222+ [[[self window] contentView] addSubview:qtView];
223+ }
224+ [qtView release];
225+
226+ [NSMenu setMenuBarVisible:YES];
227+ [w orderOut:self];
228+ [[self window] makeKeyAndOrderFront:self];
229+ [[self window] makeFirstResponder:qtView];
230+}
231+
232+- (NSWindow *)fullscreenWindow
233+{
234+ if(fullscreenWindow) return fullscreenWindow;
235+
236+ NSRect mainScreenRect = [[NSScreen mainScreen] frame];
237+ fullscreenWindow = [[XspfFullScreenWindow alloc] initWithContentRect:mainScreenRect
238+ styleMask:NSBorderlessWindowMask
239+ backing:NSBackingStoreBuffered
240+ defer:YES];
241+ [fullscreenWindow setReleasedWhenClosed:NO];
242+ [fullscreenWindow setBackgroundColor:[NSColor blackColor]];
243+ [fullscreenWindow setDelegate:self];
244+ [fullscreenWindow setWindowController:self];
245+
246+ return fullscreenWindow;
247+}
248+
249+#pragma mark ### Actions ###
250+- (IBAction)togglePlayAndPause:(id)sender
251+{
252+ if([[self valueForKeyPath:@"document.trackList.isPlayed"] boolValue]) {
253+ [self pause];
254+ } else {
255+ [self play];
256+ }
257+}
258+
259+- (IBAction)turnUpVolume:(id)sender
260+{
261+ NSNumber *cv = [self valueForKeyPath:@"qtMovie.volume"];
262+ cv = [NSNumber numberWithFloat:[cv floatValue] + sVolumeDelta];
263+ [self setValue:cv forKeyPath:@"qtMovie.volume"];
264+}
265+- (IBAction)turnDownVolume:(id)sender
266+{
267+ NSNumber *cv = [self valueForKeyPath:@"qtMovie.volume"];
268+ cv = [NSNumber numberWithFloat:[cv floatValue] - sVolumeDelta];
269+ [self setValue:cv forKeyPath:@"qtMovie.volume"];
270+}
271+- (IBAction)toggleFullScreenMode:(id)sender
272+{
273+ if(fullScreenMode) {
274+ [self exitFullScreen];
275+ fullScreenMode = NO;
276+ } else {
277+ [self enterFullScreen];
278+ fullScreenMode = YES;
279+ }
280+}
281+
282+- (IBAction)forwardTagValueSecends:(id)sender
283+{
284+ if(![sender respondsToSelector:@selector(tag)]) return;
285+
286+ int tag = [sender tag];
287+ if(tag == 0) return;
288+
289+ QTTime current = [[self qtMovie] currentTime];
290+ NSTimeInterval cur;
291+ if(!QTGetTimeInterval(current, &cur)) return;
292+
293+ QTTime new = QTMakeTimeWithTimeInterval(cur + tag);
294+ [[self qtMovie] setCurrentTime:new];
295+}
296+- (IBAction)backwardTagValueSecends:(id)sender
297+{
298+ if(![sender respondsToSelector:@selector(tag)]) return;
299+
300+ int tag = [sender tag];
301+ if(tag == 0) return;
302+
303+ QTTime current = [[self qtMovie] currentTime];
304+ NSTimeInterval cur;
305+ if(!QTGetTimeInterval(current, &cur)) return;
306+
307+ QTTime new = QTMakeTimeWithTimeInterval(cur - tag);
308+ [[self qtMovie] setCurrentTime:new];
309+}
310+- (IBAction)nextTrack:(id)sender
311+{
312+ [qtView pause:sender];
313+ [[[self document] trackList] next];
314+}
315+- (IBAction)previousTrack:(id)sender
316+{
317+ [qtView pause:sender];
318+ [[[self document] trackList] previous];
319+}
320+
321+#pragma mark ### Notification & Timer ###
322+- (void)didEndMovie:(id)notification
323+{
324+ [[[self document] trackList] next];
325+}
326+- (void)updateTimeIfNeeded:(id)timer
327+{
328+ QTMovie *qt = [self qtMovie];
329+ if(qt) {
330+ // force update time indicator.
331+ [qt willChangeValueForKey:@"currentTime"];
332+ [qt didChangeValueForKey:@"currentTime"];
333+ }
334+
335+ // Hide cursor and controller, if mouse didn't move for 3 seconds.
336+ NSPoint mouse = [NSEvent mouseLocation];
337+ if(!NSEqualPoints(prevMouse, mouse)) {
338+ prevMouse = mouse;
339+ [prevMouseMovedDate autorelease];
340+ prevMouseMovedDate = [[NSDate dateWithTimeIntervalSinceNow:0.0] retain];
341+ } else if(fullScreenMode && [prevMouseMovedDate timeIntervalSinceNow] < -3.0 ) {
342+ [NSCursor setHiddenUntilMouseMoves:YES];
343+ //
344+ // hide controller.
345+ }
346+}
347+
348+#pragma mark ### NSResponder ###
349+- (void)cancelOperation:(id)sender
350+{
351+ if(fullScreenMode) {
352+ [self toggleFullScreenMode:self];
353+ }
354+}
355+
356+#pragma mark ### NSMenu valivation ###
357+- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
358+{
359+ if([menuItem action] == @selector(toggleFullScreenMode:)) {
360+ if(fullScreenMode) {
361+ [menuItem setTitle:NSLocalizedString(@"Exit Full Screen", @"Exit Full Screen")];
362+ } else {
363+ [menuItem setTitle:NSLocalizedString(@"Full Screen", @"Full Screen")];
364+ }
365+ return YES;
366+ }
367+// if([menuItem tag] == 10000) {
368+// NSString *title = [self valueForKeyPath:@"document.trackList.currentTrack.title"];
369+// if(title) {
370+// [menuItem setTitle:title];
371+// }
372+// return NO;
373+// }
374+
375+ return YES;
376+}
377+
378+#pragma mark ### NSApplication Delegate ###
379+- (void)applicationWillTerminate:(NSNotification *)notification
380+{
381+ if(fullScreenMode) {
382+ [self toggleFullScreenMode:self];
383+ }
384+ [[self document] removeObserver:self forKeyPath:kQTMovieKeyPath];
385+ [[self document] removeObserver:self forKeyPath:kIsPlayedKeyPath];
386+}
387+
388+#pragma mark ### NSWindow Delegate ###
389+- (BOOL)windowShouldClose:(id)sender
390+{
391+ [qtView pause:self];
392+ [self setQtMovie:nil];
393+
394+ [[self document] removeObserver:self forKeyPath:kQTMovieKeyPath];
395+ [[self document] removeObserver:self forKeyPath:kIsPlayedKeyPath];
396+
397+ [updateTime release];
398+ updateTime = nil;
399+
400+ return YES;
401+}
402+- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize
403+{
404+ return [self fitSizeToSize:frameSize];
405+}
406+- (void)windowDidMove:(NSNotification *)notification
407+{
408+ if(fullscreenWindow && [notification object] == fullscreenWindow) {
409+ NSRect r = [fullscreenWindow frame];
410+ if(!NSEqualPoints(r.origin, NSZeroPoint)) {
411+ [fullscreenWindow setFrameOrigin:NSZeroPoint];
412+ }
413+ }
414+}
415+@end
--- branches/XspfComponentSimply-branch/XspfAppDelegate.m (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfAppDelegate.m (revision 54)
@@ -0,0 +1,123 @@
1+//
2+// XspfAppDelegate.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/31.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import "XspfAppDelegate.h"
10+#import "XspfValueTransformers.h"
11+
12+@implementation XspfAppDelegate
13+
14++ (void)initialize
15+{
16+ [NSValueTransformer setValueTransformer:[[[XspfQTTimeTransformer alloc] init] autorelease]
17+ forName:@"XspfQTTimeTransformer"];
18+ [NSValueTransformer setValueTransformer:[[[XspfQTTimeDateTransformer alloc] init] autorelease]
19+ forName:@"XspfQTTimeDateTransformer"];
20+}
21+
22+- (void)awakeFromNib
23+{
24+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
25+ [nc addObserver:self
26+ selector:@selector(windowDidBecomeMain:)
27+ name:NSWindowDidBecomeMainNotification
28+ object:nil];
29+ [nc addObserver:self
30+ selector:@selector(windowWillClose:)
31+ name:NSWindowWillCloseNotification
32+ object:nil];
33+}
34+- (void)dealloc
35+{
36+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
37+ [nc removeObserver:self];
38+
39+ [super dealloc];
40+}
41+
42+#pragma mark ### Actions ###
43+- (IBAction)playedTrack:(id)sender
44+{
45+ // do noting.
46+}
47+
48+#pragma mark ### NSMenu valivation ###
49+- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
50+{
51+ if([menuItem tag] == 10000) {
52+ NSWindow *m = mainWindowStore;
53+ if(!m) {
54+ m = [NSApp mainWindow];
55+ }
56+ NSString *title = [m valueForKeyPath:@"windowController.document.trackList.currentTrack.title"];
57+ if(title) {
58+ [menuItem setTitle:[NSString stringWithFormat:@"%@ played", title]];
59+ } else {
60+ [menuItem setTitle:@"Played Track Title"];
61+ }
62+ return NO;
63+ }
64+ if(!mainWindowStore) {
65+ return NO;
66+ }
67+
68+ return YES;
69+}
70+- (IBAction)togglePlayAndPause:(id)sender
71+{
72+ [[mainWindowStore windowController] togglePlayAndPause:sender];
73+}
74+- (IBAction)nextTrack:(id)sender
75+{
76+ [[mainWindowStore windowController] nextTrack:sender];
77+}
78+- (IBAction)previousTrack:(id)sender
79+{
80+ [[mainWindowStore windowController] previousTrack:sender];
81+}
82+
83+
84+- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
85+{
86+ return NO;
87+}
88+
89+- (void)storeMainWindow
90+{
91+ mainWindowStore = [NSApp mainWindow];
92+}
93+- (void)unsaveMainWindow
94+{
95+ mainWindowStore = nil;
96+}
97+- (void)applicationWillHide:(NSNotification *)notification
98+{
99+ [self storeMainWindow];
100+}
101+- (void)applicationWillResignActive:(NSNotification *)notification
102+{
103+ [self storeMainWindow];
104+}
105+- (void)applicationDidUnhide:(NSNotification *)notification
106+{
107+ [self unsaveMainWindow];
108+}
109+- (void)applicationDidBecomeActive:(NSNotification *)notification
110+{
111+ [self unsaveMainWindow];
112+}
113+
114+- (void)windowDidBecomeMain:(NSNotification *)notification
115+{
116+ [self storeMainWindow];
117+}
118+- (void)windowWillClose:(NSNotification *)notification
119+{
120+ [self unsaveMainWindow];
121+}
122+
123+@end
--- branches/XspfComponentSimply-branch/XspfTrackList.m (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfTrackList.m (revision 54)
@@ -0,0 +1,210 @@
1+//
2+// XspfTrackList.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/29.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import "XspfTrackList.h"
10+
11+
12+@implementation XspfTrackList
13+- (id)initWithXMLElement:(NSXMLElement *)element
14+{
15+ self = [super init];
16+
17+ NSArray *elems = [element elementsForName:@"title"];
18+ if(elems && [elems count] != 0) {
19+ NSString *t = [[elems objectAtIndex:0] stringValue];
20+ [self setTitle:t];
21+ }
22+
23+ elems = [element elementsForName:@"track"];
24+ if(!elems) {
25+ [self release];
26+ return nil;
27+ }
28+ tracks = [[NSMutableArray alloc] init];
29+
30+ unsigned i, count;
31+ for(i = 0, count = [elems count]; i < count; i++) {
32+ NSXMLElement *trackElem = [elems objectAtIndex:i];
33+ XspfComponent *track = [XspfComponent xspfComponemtWithXMLElement:trackElem];
34+ if(track) {
35+ [self addChild:track];
36+ }
37+ }
38+ [self setCurrentIndex:0];
39+
40+ return self;
41+}
42+- (void)dealloc
43+{
44+ [[self currentTrack] removeObserver:self forKeyPath:@"isPlayed"];
45+
46+ [tracks release];
47+
48+ [super dealloc];
49+}
50+- (NSXMLElement *)XMLElement
51+{
52+ id node = [NSXMLElement elementWithName:@"trackList"];
53+
54+ id titleElem = [NSXMLElement elementWithName:@"title" stringValue:[self title]];
55+ if(titleElem) {
56+ [node addChild:titleElem];
57+ }
58+
59+ NSEnumerator *tracksEnum = [tracks objectEnumerator];
60+ id n;
61+ while(n = [tracksEnum nextObject]) {
62+ [node addChild:[n XMLElement]];
63+ }
64+
65+ return node;
66+}
67+- (void)observeValueForKeyPath:(NSString *)keyPath
68+ ofObject:(id)object
69+ change:(NSDictionary *)change
70+ context:(void *)context
71+{
72+ if([keyPath isEqualToString:@"isPlayed"]) {
73+ [self willChangeValueForKey:@"isPlayed"];
74+ [self didChangeValueForKey:@"isPlayed"];
75+ return;
76+ }
77+
78+ [super observeValueForKeyPath:keyPath
79+ ofObject:object
80+ change:change
81+ context:context];
82+}
83+- (void)setSelectionIndex:(unsigned)index
84+{
85+ [self setCurrentIndex:index];
86+}
87+- (void)setCurrentIndex:(unsigned)index
88+{
89+ unsigned prev;
90+
91+ if(index < 0) return;
92+ if([tracks count] <= index) return;
93+
94+ [self willChangeValueForKey:@"qtMovie"];
95+ [self willChangeValueForKey:@"currentTrack"];
96+ prev = currentIndex;
97+ currentIndex = index;
98+ [self didChangeValueForKey:@"currentTrack"];
99+ [self didChangeValueForKey:@"qtMovie"];
100+
101+ [self willChangeValueForKey:@"isPlayed"];
102+ XspfComponent *t= nil;
103+ @try {
104+ t = [tracks objectAtIndex:prev];
105+ [t removeObserver:self forKeyPath:@"isPlayed"];
106+ }
107+ @catch (id ex) {
108+ if(![[ex name] isEqualToString:NSRangeException]) {
109+ NSLog(@"Exception ### named %@", [ex name]);
110+ @throw;
111+ }
112+ }
113+
114+ if(t) {
115+ [t deselect];
116+ }
117+
118+ XspfComponent *t2 = [self currentTrack];
119+ [t2 select];
120+ [t2 addObserver:self
121+ forKeyPath:@"isPlayed"
122+ options:NSKeyValueObservingOptionNew
123+ context:NULL];
124+ [self didChangeValueForKey:@"isPlayed"];
125+
126+}
127+- (unsigned)currentIndex
128+{
129+ return currentIndex;
130+}
131+
132+- (void)next
133+{
134+ [self setCurrentIndex:[self currentIndex] + 1];
135+}
136+- (void)previous
137+{
138+ [self setCurrentIndex:[self currentIndex] - 1];
139+}
140+- (NSArray *)children
141+{
142+ return tracks;
143+}
144+- (BOOL)isLeaf
145+{
146+ return NO;
147+}
148+
149+// primitive.
150+- (void)insertChild:(XspfComponent *)child atIndex:(unsigned)index
151+{
152+ if(!child) return;
153+ if(![child isKindOfClass:[XspfComponent class]]) {
154+ NSLog(@"addChild: argument class is MUST kind of XspfComponent. "
155+ @"but argument class is %@<%p>.",
156+ NSStringFromClass([child class]), child);
157+ return;
158+ }
159+ [tracks insertObject:child atIndex:index];
160+ [child setParent:self];
161+}
162+// primitive.
163+- (void)removeChild:(XspfComponent *)child
164+{
165+ if(!child) return;
166+ if(![tracks containsObject:child]) return;
167+
168+ [child setParent:nil];
169+ [tracks removeObject:child];
170+}
171+
172+- (void)addChild:(XspfComponent *)child
173+{
174+ unsigned num = [tracks count];
175+ [self insertChild:child atIndex:num];
176+}
177+- (void)removeChildAtIndex:(unsigned)index
178+{
179+ id child = [tracks objectAtIndex:index];
180+ [self removeChild:child];
181+}
182+
183+- (NSString *)description
184+{
185+ return [tracks description];
186+}
187+
188+- (XspfComponent *)currentTrack
189+{
190+ if([tracks count] > currentIndex) {
191+ return [tracks objectAtIndex:currentIndex];
192+ }
193+ return nil;
194+}
195+
196+- (QTMovie *)qtMovie
197+{
198+ return [[self currentTrack] qtMovie];
199+}
200+
201+- (void)setIsPlayed:(BOOL)state {}
202+- (BOOL)isPlayed
203+{
204+ XspfComponent *t = [self currentTrack];
205+ if(t) {
206+ return [t isPlayed];
207+ }
208+ return NO;
209+}
210+@end
--- branches/XspfComponentSimply-branch/XspfTrack.m (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfTrack.m (revision 54)
@@ -0,0 +1,217 @@
1+//
2+// XspfTrack.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/29.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import "XspfTrack.h"
10+
11+@interface XspfTrack (Private)
12+- (void)setSavedDateWithQTTime:(QTTime)qttime;
13+- (NSDate *)duration;
14+@end
15+
16+@implementation XspfTrack
17+- (id)initWithXMLElement:(NSXMLElement *)element
18+{
19+ self = [super init];
20+
21+ NSArray *elems = [element elementsForName:@"location"];
22+ if(!elems || [elems count] == 0) {
23+ [self release];
24+ return nil;
25+ }
26+
27+ NSString *loc = [[elems objectAtIndex:0] stringValue];;
28+ [self setLocationString:loc];
29+
30+ NSString *t;
31+ elems = [element elementsForName:@"title"];
32+ if(!elems || [elems count] == 0) {
33+ t = [[self locationString] lastPathComponent];
34+ } else {
35+ t = [[elems objectAtIndex:0] stringValue];
36+ }
37+ [self setTitle:t];
38+
39+ elems = [element elementsForName:@"duration"];
40+ if(elems && [elems count] != 0) {
41+ t = [[elems objectAtIndex:0] stringValue];
42+ NSTimeInterval ti = [t doubleValue] / 1000;
43+ QTTime q = QTMakeTimeWithTimeInterval(ti);
44+ [self setSavedDateWithQTTime:q];
45+ }
46+
47+ return self;
48+}
49+- (void)dealloc
50+{
51+ [location release];
52+ [movie release];
53+ [savedDate release];
54+
55+ [super dealloc];
56+}
57+- (NSXMLElement *)XMLElement
58+{
59+ id node = [NSXMLElement elementWithName:@"track"];
60+
61+ id locElem = [NSXMLElement elementWithName:@"location" stringValue:[self locationString]];
62+ if(locElem) {
63+ [node addChild:locElem];
64+ }
65+ id titleElem = [NSXMLElement elementWithName:@"title" stringValue:[self title]];
66+ if(titleElem) {
67+ [node addChild:titleElem];
68+ }
69+
70+ id d = [self duration];
71+ if(d) {
72+ NSTimeInterval t = [d timeIntervalSince1970];
73+ t += [[NSTimeZone systemTimeZone] secondsFromGMT];
74+ unsigned long long scaledT = (unsigned long long)t;
75+ scaledT *= 1000;
76+ id durationElem = [NSXMLElement elementWithName:@"duration"
77+ stringValue:[NSString stringWithFormat:@"%qu", scaledT]];
78+ if(durationElem) {
79+ [node addChild:durationElem];
80+ }
81+ }
82+
83+ return node;
84+}
85+- (void)setLocation:(NSURL *)loc
86+{
87+ if(location && ![location isKindOfClass:[NSURL class]]) return;
88+ if(location == loc) return;
89+ if([location isEqualTo:loc]) return;
90+
91+ [location autorelease];
92+ location = [loc retain];
93+}
94+- (NSURL *)location
95+{
96+ return location;
97+}
98+- (void)setLocationString:(NSString *)loc
99+{
100+ [self setLocation:[NSURL URLWithString:loc]];
101+}
102+- (NSString *)locationString
103+{
104+ return [[self location] absoluteString];
105+}
106+
107+- (void)setSavedDateWithQTTime:(QTTime)qttime
108+{
109+ id t = [NSValueTransformer valueTransformerForName:@"XspfQTTimeDateTransformer"];
110+ savedDate = [[t transformedValue:[NSValue valueWithQTTime:qttime]] retain];
111+}
112+- (NSDate *)savedDate
113+{
114+ return savedDate;
115+}
116+- (NSDate *)duration
117+{
118+ if(savedDate) return savedDate;
119+
120+ if(!movie) return nil;
121+
122+ [self setSavedDateWithQTTime:[movie duration]];
123+ return [self savedDate];
124+}
125+- (QTMovie *)qtMovie
126+{
127+ if(![QTMovie canInitWithURL:[self location]]) return nil;
128+
129+ NSError *error = nil;
130+ NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
131+ [self location], QTMovieURLAttribute,
132+ [NSNumber numberWithBool:NO], QTMovieOpenAsyncOKAttribute,
133+ nil];
134+ movie = [[QTMovie alloc] initWithAttributes:attrs error:&error];
135+// movie = [[QTMovie alloc] initWithURL:[self location] error:&error];
136+
137+ {
138+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
139+// [nc addObserver:self
140+// selector:@selector(notifee:)
141+// name:@"QTMoviePrerollCompleteNotification"
142+// object:movie];
143+ [nc addObserver:self
144+ selector:@selector(notifee:)
145+ name:QTMovieRateDidChangeNotification
146+ object:movie];
147+// [nc addObserver:self
148+// selector:@selector(notifee:)
149+// name:@"QTMovieDidEndNotification"
150+// object:movie];
151+ }
152+
153+
154+ [self willChangeValueForKey:@"duration"];
155+ [self didChangeValueForKey:@"duration"];
156+
157+ return movie;
158+}
159+- (void)setIsPlayed:(BOOL)state
160+{
161+ isPlayed = state;
162+}
163+- (BOOL)isPlayed
164+{
165+ return isPlayed;
166+}
167+- (void)next
168+{
169+ [[self parent] next];
170+}
171+- (void)previous
172+{
173+ [[self parent] previous];
174+}
175+
176+- (void)deselect
177+{
178+ [self performSelector:@selector(purgeQTMovie)
179+ withObject:nil
180+ afterDelay:4.5];
181+ [super deselect];
182+}
183+- (void)purgeQTMovie
184+{
185+ NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
186+ [nc removeObserver:self
187+ name:nil
188+ object:movie];
189+
190+// [movie invalidate];
191+ NSLog(@"Purge! retain count is %u", [movie retainCount]);
192+
193+ [movie release];
194+ movie = nil;
195+}
196+
197+- (void)notifee:(id)notification
198+{
199+// NSLog(@"Notifed: name -> (%@)\ndict -> (%@)", [notification name], [notification userInfo]);
200+
201+ NSNumber *rateValue = [[notification userInfo] objectForKey:QTMovieRateDidChangeNotificationParameter];
202+ if(rateValue) {
203+ float rate = [rateValue floatValue];
204+ if(rate == 0) {
205+ [self setIsPlayed:NO];
206+ } else if(rate == 1) {
207+ [self setIsPlayed:YES];
208+ }
209+ }
210+}
211+
212+- (NSString *)description
213+{
214+ return [NSString stringWithFormat:@"Title:(%@)\nLocation:(%@)",
215+ [self title], [self location]];
216+}
217+@end
--- branches/XspfComponentSimply-branch/XspfPlaceholderComponent.m (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfPlaceholderComponent.m (revision 54)
@@ -0,0 +1,78 @@
1+//
2+// XspfPlaceholderComponent.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/09/06.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import "XspfPlaceholderComponent.h"
10+#import "XspfTrackList.h"
11+#import "XspfTrack.h"
12+
13+@implementation XspfPlaceholderComponent
14+static XspfPlaceholderComponent *sharedInstance = nil;
15+
16++ (XspfPlaceholderComponent *)sharedInstance
17+{
18+ @synchronized(self) {
19+ if (sharedInstance == nil) {
20+ [[self alloc] init]; // assignment not done here
21+ }
22+ }
23+ return sharedInstance;
24+}
25+
26++ (id)allocWithZone:(NSZone *)zone
27+{
28+ @synchronized(self) {
29+ if (sharedInstance == nil) {
30+ sharedInstance = [super allocWithZone:zone];
31+ return sharedInstance; // assignment and return on first allocation
32+ }
33+ }
34+ return nil; //on subsequent allocation attempts return nil
35+}
36+
37+- (id)copyWithZone:(NSZone *)zone
38+{
39+ return self;
40+}
41+
42+- (id)retain
43+{
44+ return self;
45+}
46+
47+- (unsigned)retainCount
48+{
49+ return UINT_MAX; //denotes an object that cannot be released
50+}
51+
52+- (void)release
53+{
54+ //do nothing
55+}
56+
57+- (id)autorelease
58+{
59+ return self;
60+}
61+
62+#pragma mark ### initializers ###
63+- (id)initWithXMLElement:(NSXMLElement *)element
64+{
65+ NSString *name = [element name];
66+ if(!name) return nil;
67+ if([name isEqualToString:@""]) return nil;
68+
69+ if([name isEqualToString:@"trackList"]) {
70+ return [[XspfTrackList alloc] initWithXMLElement:element];
71+ }
72+ if([name isEqualToString:@"track"]) {
73+ return [[XspfTrack alloc] initWithXMLElement:element];
74+ }
75+
76+ return nil;
77+}
78+@end
--- branches/XspfComponentSimply-branch/Info.plist (nonexistent)
+++ branches/XspfComponentSimply-branch/Info.plist (revision 54)
@@ -0,0 +1,51 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+<plist version="1.0">
4+<dict>
5+ <key>CFBundleDevelopmentRegion</key>
6+ <string>English</string>
7+ <key>CFBundleDocumentTypes</key>
8+ <array>
9+ <dict>
10+ <key>CFBundleTypeExtensions</key>
11+ <array>
12+ <string>xspf</string>
13+ </array>
14+ <key>CFBundleTypeIconFile</key>
15+ <string></string>
16+ <key>CFBundleTypeName</key>
17+ <string>XML Shareable Playlist Format</string>
18+ <key>CFBundleTypeOSTypes</key>
19+ <array>
20+ <string>????</string>
21+ </array>
22+ <key>CFBundleTypeRole</key>
23+ <string>Editor</string>
24+ <key>NSDocumentClass</key>
25+ <string>XspfDocument</string>
26+ </dict>
27+ </array>
28+ <key>CFBundleExecutable</key>
29+ <string>${EXECUTABLE_NAME}</string>
30+ <key>CFBundleIconFile</key>
31+ <string></string>
32+ <key>CFBundleIdentifier</key>
33+ <string>com.masakih.XspfQT</string>
34+ <key>CFBundleInfoDictionaryVersion</key>
35+ <string>6.0</string>
36+ <key>CFBundleName</key>
37+ <string>${PRODUCT_NAME}</string>
38+ <key>CFBundlePackageType</key>
39+ <string>APPL</string>
40+ <key>CFBundleShortVersionString</key>
41+ <string>1.1</string>
42+ <key>CFBundleSignature</key>
43+ <string>????</string>
44+ <key>CFBundleVersion</key>
45+ <string>%%%%REVISION%%%%</string>
46+ <key>NSMainNibFile</key>
47+ <string>MainMenu</string>
48+ <key>NSPrincipalClass</key>
49+ <string>NSApplication</string>
50+</dict>
51+</plist>
--- branches/XspfComponentSimply-branch/XspfDocument.m (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfDocument.m (revision 54)
@@ -0,0 +1,201 @@
1+//
2+// MyDocument.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/29.
6+// Copyright masakih 2008 . All rights reserved.
7+//
8+
9+#import "XspfDocument.h"
10+#import "XspfComponent.h"
11+#import "XspfMovieWindowController.h"
12+#import "XspfPlayListWindowController.h"
13+
14+@interface XspfDocument (Private)
15+- (void)setTrackList:(XspfComponent *)newList;
16+- (XspfComponent *)trackList;
17+- (NSXMLDocument *)XMLDocument;
18+- (NSData *)outputData;
19+@end
20+
21+@implementation XspfDocument
22+
23+- (id)init
24+{
25+ self = [super init];
26+ if (self) {
27+
28+ // Add your subclass-specific initialization here.
29+ // If an error occurs here, send a [self release] message and return nil.
30+
31+ }
32+ return self;
33+}
34+
35+- (void)makeWindowControllers
36+{
37+ playListWindowController = [[XspfPlayListWindowController alloc] init];
38+ [self addWindowController:playListWindowController];
39+
40+ movieWindowController = [[XspfMovieWindowController alloc] init];
41+ [movieWindowController setShouldCloseDocument:YES];
42+ [self addWindowController:movieWindowController];
43+ [movieWindowController setQtMovie:[[self trackList] qtMovie]];
44+}
45+//- (NSString *)windowNibName
46+//{
47+// // Override returning the nib file name of the document
48+// // If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
49+// return @"MyDocument";
50+//}
51+
52+- (void)windowControllerDidLoadNib:(NSWindowController *)windowController
53+{
54+ [super windowControllerDidLoadNib:windowController];
55+ // Add any code here that needs to be executed once the windowController has loaded the document's window.
56+// [self setQtMovie:[[self trackList] qtMovie]];
57+}
58+
59+- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
60+{
61+ // Insert code here to write your document to data of the specified type. If the given outError != NULL, ensure that you set *outError when returning nil.
62+
63+ // You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
64+
65+ // For applications targeted for Panther or earlier systems, you should use the deprecated API -dataRepresentationOfType:. In this case you can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.
66+
67+ return [self outputData];
68+ //
69+ //
70+ //
71+
72+ if ( outError != NULL ) {
73+ *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
74+ }
75+ return nil;
76+}
77+
78+- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
79+{
80+ // Insert code here to read your document from the given data of the specified type. If the given outError != NULL, ensure that you set *outError when returning NO.
81+
82+ // You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
83+
84+ // For applications targeted for Panther or earlier systems, you should use the deprecated API -loadDataRepresentation:ofType. In this case you can also choose to override -readFromFile:ofType: or -loadFileWrapperRepresentation:ofType: instead.
85+
86+ NSError *error = nil;
87+ NSXMLDocument *d = [[[NSXMLDocument alloc] initWithData:data
88+ options:0
89+ error:&error] autorelease];
90+ NSXMLElement *root = [d rootElement];
91+
92+ NSArray *trackListElems;
93+ trackListElems = [root elementsForName:@"trackList"];
94+ if(!trackListElems || [trackListElems count] < 1) {
95+ if ( outError != NULL ) {
96+ *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
97+ }
98+ return NO;
99+ }
100+
101+ id t = [XspfComponent xspfComponemtWithXMLElement:[trackListElems objectAtIndex:0]];
102+ if(![t title]) {
103+ [t setTitle:[[[self fileURL] path] lastPathComponent]];
104+ }
105+ [self setTrackList:t];
106+// NSLog(@"trackList -> %@", trackList);
107+
108+// [self setQtMovie:[[self trackList] qtMovie]];
109+
110+ return YES;
111+}
112+
113+- (void)dealloc
114+{
115+ [trackList release];
116+ [playListWindowController release];
117+ [movieWindowController release];
118+
119+ [super dealloc];
120+}
121+- (NSString *)displayName
122+{
123+ NSString *trackTitle = [[[self trackList] currentTrack] title];
124+ if(trackTitle) {
125+ return [NSString stringWithFormat:@"%@ - %@",
126+ [super displayName], trackTitle];
127+ }
128+
129+ return [super displayName];
130+}
131+- (void)close
132+{
133+ [self removeWindowController:playListWindowController];
134+ [playListWindowController release];
135+ playListWindowController = nil;
136+
137+ [self removeWindowController:movieWindowController];
138+ [movieWindowController release];
139+ movieWindowController = nil;
140+
141+ [super close];
142+}
143+
144+- (IBAction)togglePlayAndPause:(id)sender
145+{
146+ [movieWindowController togglePlayAndPause:sender];
147+}
148+- (IBAction)showPlayList:(id)sender
149+{
150+ [playListWindowController showWindow:self];
151+}
152+
153+- (void)setTrackList:(XspfComponent *)newList
154+{
155+ if(trackList == newList) return;
156+
157+ [trackList autorelease];
158+ trackList = [newList retain];
159+}
160+- (XspfComponent *)trackList
161+{
162+ return trackList;
163+}
164+
165+- (void)setPlayTrackindex:(unsigned)index
166+{
167+ [[self trackList] setSelectionIndex:index];
168+}
169+
170+- (NSData *)outputData
171+{
172+ return [[self XMLDocument] XMLDataWithOptions:NSXMLNodePrettyPrint];
173+}
174+- (NSXMLDocument *)XMLDocument;
175+{
176+ id element = [[self trackList] XMLElement];
177+
178+ id root = [NSXMLElement elementWithName:@"playlist"];
179+ [root addChild:element];
180+ [root addAttribute:[NSXMLNode attributeWithName:@"version"
181+ stringValue:@"0"]];
182+ [root addAttribute:[NSXMLNode attributeWithName:@"xmlns"
183+ stringValue:@"http://xspf.org/ns/0/"]];
184+
185+
186+ id d = [[[NSXMLDocument alloc] initWithRootElement:root] autorelease];
187+ [d setVersion:@"1.0"];
188+ [d setCharacterEncoding:@"UTF-8"];
189+
190+ return d;
191+}
192+
193+- (IBAction)dump:(id)sender
194+{
195+ NSString *s = [[[NSString alloc] initWithData:[self outputData]
196+ encoding:NSUTF8StringEncoding] autorelease];
197+
198+ NSLog(@"%@", s);
199+}
200+@end
201+
--- branches/XspfComponentSimply-branch/XspfPlayListWindowController.h (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfPlayListWindowController.h (revision 54)
@@ -0,0 +1,23 @@
1+//
2+// XspfPlayListWindowController.h
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/31.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import <Cocoa/Cocoa.h>
10+
11+@interface XspfPlayListWindowController : NSWindowController
12+{
13+ IBOutlet NSOutlineView *listView;
14+ IBOutlet NSTreeController *trackListTree;
15+
16+ id obseveObject;
17+}
18+
19+@end
20+
21+
22+@interface XspfThowSpacebarKeyDownOutlineView : NSOutlineView
23+@end
--- branches/XspfComponentSimply-branch/Makefile (nonexistent)
+++ branches/XspfComponentSimply-branch/Makefile (revision 54)
@@ -0,0 +1,56 @@
1+// encoding=utf-8
2+PRODUCT_NAME=XspfQT
3+PRODUCT_EXTENSION=app
4+BUILD_PATH=./build
5+DEPLOYMENT=Release
6+APP_BUNDLE=$(PRODUCT_NAME).$(PRODUCT_EXTENSION)
7+APP=$(BUILD_PATH)/$(DEPLOYMENT)/$(APP_BUNDLE)
8+APP_NAME=$(BUILD_PATH)/$(DEPLOYMENT)/$(PRODUCT_NAME)
9+INFO_PLIST=Info.plist
10+
11+URL_XspfQT = svn+ssh://macmini/usr/local/svnrepos/XspfQT
12+HEAD = $(URL_XspfQT)/XspfQT
13+TAGS_DIR = $(URL_XspfQT)/tags
14+
15+VER_CMD=grep -A1 'CFBundleShortVersionString' $(INFO_PLIST) | tail -1 | tr -d "'\t</string>"
16+VERSION=$(shell $(VER_CMD))
17+
18+all:
19+ @echo do nothig.
20+ @echo use target tagging
21+
22+tagging: update_svn
23+ @echo "Tagging the $(VERSION) (x) release of XspfQT project."
24+ REV=`LC_ALL=C svn info | awk '/Last Changed Rev/ {print $$4}'` ; \
25+ echo svn copy $(HEAD) $(TAGS_DIR)/release-$(VERSION).$${REV}
26+
27+Localizable: BSTRADocument.m
28+ genstrings -o English.lproj $<
29+ (cd English.lproj; ${MAKE} $@;)
30+ genstrings -o Japanese.lproj $<
31+ (cd Japanese.lproj; ${MAKE} $@;)
32+
33+checkLocalizable:
34+ (cd English.lproj; ${MAKE} $@;)
35+ (cd Japanese.lproj; ${MAKE} $@;)
36+
37+release: updateRevision
38+ xcodebuild -configuration $(DEPLOYMENT)
39+ $(MAKE) restorInfoPlist
40+
41+package: release
42+ REV=`LC_ALL=C svn info | awk '/Last Changed Rev/ {print $$4}'`; \
43+ ditto -ck -rsrc --keepParent $(APP) $(APP_NAME)-$(VERSION)-$${REV}.zip
44+
45+updateRevision: update_svn
46+ if [ ! -f $(INFO_PLIST).bak ] ; then cp $(INFO_PLIST) $(INFO_PLIST).bak ; fi ; \
47+ REV=`LC_ALL=C svn info | awk '/Last Changed Rev/ {print $$4}'` ; \
48+ sed -e "s/%%%%REVISION%%%%/$${REV}/" $(INFO_PLIST) > $(INFO_PLIST).r ; \
49+ mv -f $(INFO_PLIST).r $(INFO_PLIST) ; \
50+
51+restorInfoPlist:
52+ if [ -f $(INFO_PLIST).bak ] ; then mv -f $(INFO_PLIST).bak $(INFO_PLIST) ; fi
53+
54+update_svn:
55+ svn up
56+
--- branches/XspfComponentSimply-branch/XspfDocument.h (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfDocument.h (revision 54)
@@ -0,0 +1,32 @@
1+//
2+// MyDocument.h
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/29.
6+// Copyright masakih 2008 . All rights reserved.
7+//
8+
9+
10+#import <Cocoa/Cocoa.h>
11+#import <QTKit/QTKit.h>
12+
13+@class XspfComponent;
14+@class XspfMovieWindowController;
15+
16+@interface XspfDocument : NSDocument
17+{
18+ XspfComponent* trackList;
19+ XspfMovieWindowController *movieWindowController;
20+ NSWindowController *playListWindowController;
21+}
22+
23+- (IBAction)togglePlayAndPause:(id)sender;
24+- (IBAction)showPlayList:(id)sender;
25+- (IBAction)dump:(id)sender;
26+
27+- (void)setTrackList:(XspfComponent *)newList;
28+- (XspfComponent *)trackList;
29+
30+- (void)setPlayTrackindex:(unsigned)index;
31+
32+@end
--- branches/XspfComponentSimply-branch/XspfTrackList.h (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfTrackList.h (revision 54)
@@ -0,0 +1,23 @@
1+//
2+// XspfTrackList.h
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/29.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import <Cocoa/Cocoa.h>
10+#import "XspfComponent.h"
11+
12+
13+@interface XspfTrackList : XspfComponent
14+{
15+ NSMutableArray *tracks;
16+
17+ unsigned currentIndex;
18+}
19+
20+- (void)setCurrentIndex:(unsigned)index;
21+- (unsigned)currentIndex;
22+
23+@end
--- branches/XspfComponentSimply-branch/XspfTrack.h (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfTrack.h (revision 54)
@@ -0,0 +1,32 @@
1+//
2+// XspfTrack.h
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/29.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import <Cocoa/Cocoa.h>
10+#import <QTKit/QTKit.h>
11+#import "XspfComponent.h"
12+
13+
14+@interface XspfTrack : XspfComponent
15+{
16+ NSURL *location;
17+
18+ QTMovie *movie;
19+
20+ NSDate *savedDate;
21+
22+ BOOL isPlayed;
23+}
24+
25+- (void)setLocation:(NSURL *)location;
26+- (void)setLocationString:(NSString *)location;
27+- (NSURL *)location;
28+- (NSString *)locationString;
29+
30+- (void)purgeQTMovie;
31+
32+@end
--- branches/XspfComponentSimply-branch/XspfPlaceholderComponent.h (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfPlaceholderComponent.h (revision 54)
@@ -0,0 +1,17 @@
1+//
2+// XspfPlaceholderComponent.h
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/09/06.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import <Cocoa/Cocoa.h>
10+#import "XspfComponent.h"
11+
12+@interface XspfPlaceholderComponent : XspfComponent
13+{
14+
15+}
16++ (XspfPlaceholderComponent *)sharedInstance;
17+@end
--- branches/XspfComponentSimply-branch/main.m (nonexistent)
+++ branches/XspfComponentSimply-branch/main.m (revision 54)
@@ -0,0 +1,14 @@
1+//
2+// main.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/29.
6+// Copyright masakih 2008 . All rights reserved.
7+//
8+
9+#import <Cocoa/Cocoa.h>
10+
11+int main(int argc, char *argv[])
12+{
13+ return NSApplicationMain(argc, (const char **) argv);
14+}
--- branches/XspfComponentSimply-branch/XspfFullScreenWindow.h (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfFullScreenWindow.h (revision 54)
@@ -0,0 +1,17 @@
1+//
2+// XspfFullScreenWindow.h
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/31.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import <Cocoa/Cocoa.h>
10+
11+
12+@interface XspfFullScreenWindow : NSWindow
13+{
14+
15+}
16+
17+@end
--- branches/XspfComponentSimply-branch/XspfFullScreenWindow.m (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfFullScreenWindow.m (revision 54)
@@ -0,0 +1,26 @@
1+//
2+// XspfFullScreenWindow.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/31.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import "XspfFullScreenWindow.h"
10+
11+
12+@implementation XspfFullScreenWindow
13+- (BOOL)canBecomeKeyWindow
14+{
15+ return YES;
16+}
17+- (void)cancelOperation:(id)sender
18+{
19+ id d = [self delegate];
20+ if(d && [d respondsToSelector:_cmd]) {
21+ [d performSelector:_cmd withObject:sender];
22+ }
23+
24+ [super cancelOperation:sender];
25+}
26+@end
--- branches/XspfComponentSimply-branch/XspfValueTransformers.h (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfValueTransformers.h (revision 54)
@@ -0,0 +1,15 @@
1+//
2+// XspfValueTransformers.h
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/31.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import <Cocoa/Cocoa.h>
10+
11+
12+@interface XspfQTTimeTransformer : NSValueTransformer
13+@end
14+@interface XspfQTTimeDateTransformer : NSValueTransformer
15+@end
--- branches/XspfComponentSimply-branch/XspfValueTransformers.m (nonexistent)
+++ branches/XspfComponentSimply-branch/XspfValueTransformers.m (revision 54)
@@ -0,0 +1,103 @@
1+//
2+// XspfValueTransformers.m
3+// XspfQT
4+//
5+// Created by Hori,Masaki on 08/08/31.
6+// Copyright 2008 masakih. All rights reserved.
7+//
8+
9+#import <QTKit/QTKit.h>
10+
11+#import "XspfValueTransformers.h"
12+
13+
14+@implementation XspfQTTimeTransformer
15++ (Class)transformedValueClass
16+{
17+ return [NSNumber class];
18+}
19++ (BOOL)allowsReverseTransformation
20+{
21+ return YES;
22+}
23+- (id)transformedValue:(id)value
24+{
25+ if(!value) return nil;
26+
27+// static first = YES;
28+// if(first) {
29+// first = NO;
30+// NSLog(@"%@ in value class -> %@", NSStringFromSelector(_cmd), NSStringFromClass([value class]));
31+// NSLog(@"value -> %@", value);
32+// }
33+
34+ QTTime t = [value QTTimeValue];
35+ NSTimeInterval res;
36+
37+ if(!QTGetTimeInterval(t, &res)) {return nil;}
38+
39+ return [NSNumber numberWithDouble:res];
40+}
41+- (id)reverseTransformedValue:(id)value
42+{
43+ if(!value) return nil;
44+
45+// static first = YES;
46+// if(first) {
47+// first = NO;
48+// NSLog(@"%@ in value class -> %@", NSStringFromSelector(_cmd), NSStringFromClass([value class]));
49+// NSLog(@"value -> %@", value);
50+// }
51+
52+ QTTime t = QTMakeTimeWithTimeInterval([value doubleValue]);
53+
54+ return [NSValue valueWithQTTime:t];
55+}
56+@end
57+
58+@implementation XspfQTTimeDateTransformer
59++ (Class)transformedValueClass
60+{
61+ return [NSDate class];
62+}
63++ (BOOL)allowsReverseTransformation
64+{
65+ return NO;
66+}
67+- (id)transformedValue:(id)value
68+{
69+ if(!value) return nil;
70+
71+// static first = YES;
72+// if(first) {
73+// first = NO;
74+// NSLog(@"%@ in value class -> %@", NSStringFromSelector(_cmd), NSStringFromClass([value class]));
75+// NSLog(@"value -> %@", value);
76+// }
77+
78+ QTTime t = [value QTTimeValue];
79+ NSTimeInterval res;
80+
81+ if(!QTGetTimeInterval(t, &res)) {return nil;}
82+
83+ res -= [[NSTimeZone systemTimeZone] secondsFromGMT];
84+
85+ return [NSDate dateWithTimeIntervalSince1970:res];
86+}
87+//- (id)reverseTransformedValue:(id)value
88+//{
89+// if(!value) return nil;
90+//
91+// static first = YES;
92+// if(first) {
93+// first = NO;
94+// NSLog(@"%@ in value class -> %@", NSStringFromSelector(_cmd), NSStringFromClass([value class]));
95+// NSLog(@"value -> %@", value);
96+// }
97+// NSTimeInterval val = [value timeIntervalSinceReferenceDate];
98+// val += [[NSTimeZone systemTimeZone] secondsFromGMT];
99+// QTTime t = QTMakeTimeWithTimeInterval(val);
100+//
101+// return [NSValue valueWithQTTime:t];
102+//}
103+@end
\ No newline at end of file
Afficher sur ancien navigateur de dépôt.