]> git.sesse.net Git - vlc/blob - projects/macosx/framework/Examples/FlashVideoDownloader/Controller.m
80490a94c70d71ff8217ebe3aa490db0d1a9b1b0
[vlc] / projects / macosx / framework / Examples / FlashVideoDownloader / Controller.m
1 #import "Controller.h"
2
3
4 /**********************************************************
5  * First off, some value transformer to easily play with
6  * bindings
7  */
8 @interface VLCFloat10000FoldTransformer : NSObject
9 @end
10
11 @implementation VLCFloat10000FoldTransformer
12
13 + (Class)transformedValueClass
14 {
15     return [NSNumber class];
16 }
17
18 + (BOOL)allowsReverseTransformation
19 {
20     return YES;
21 }
22
23 - (id)transformedValue:(id)value
24 {
25     if( !value ) return nil;
26  
27     if(![value respondsToSelector: @selector(floatValue)])
28     {
29         [NSException raise: NSInternalInconsistencyException
30                     format: @"Value (%@) does not respond to -floatValue.",
31         [value class]];
32         return nil;
33     }
34  
35     return [NSNumber numberWithFloat: [value floatValue]*10000.];
36 }
37
38 - (id)reverseTransformedValue:(id)value
39 {
40     if( !value ) return nil;
41  
42     if(![value respondsToSelector: @selector(floatValue)])
43     {
44         [NSException raise: NSInternalInconsistencyException
45                     format: @"Value (%@) does not respond to -floatValue.",
46         [value class]];
47         return nil;
48     }
49  
50     return [NSNumber numberWithFloat: [value floatValue]/10000.];
51 }
52 @end
53
54
55 /**********************************************************
56  * @implementation Controller
57  */
58 @interface Controller ()
59 @property (retain,readwrite) NSString * outputFolderPath;
60 @end
61
62 @implementation Controller
63 - (id)init
64 {
65     if(self = [super init])
66     {
67         [self bind:@"outputFolderPath" toObject:[NSUserDefaultsController sharedUserDefaultsController]
68               withKeyPath:@"values.outputFolderPath" options:nil]; 
69         [[[NSUserDefaultsController sharedUserDefaultsController] values] bind:@"outputFolderPath" toObject:self
70               withKeyPath:@"outputFolderPath" options:nil]; 
71         VLCFloat10000FoldTransformer *float100fold;
72         float100fold = [[[VLCFloat10000FoldTransformer alloc] init] autorelease];
73         [NSValueTransformer setValueTransformer:(id)float100fold forName:@"Float10000FoldTransformer"];
74         self.media = nil;
75         self.streamSession = nil;
76         selectedStreamOutput = [[NSNumber alloc] initWithInt:0];
77         self.remoteURLAsString = [NSString stringWithString:@"http://youtube.com/watch?v=IXpx2OEWBdA&feature=bz303"];
78         outputFilePath = nil;
79         if( !self.outputFolderPath || [self.outputFolderPath isKindOfClass:[NSNull class]])
80             self.outputFolderPath = [@"~/Movies/Flash Video Converted" stringByExpandingTildeInPath];
81     }
82     return self;
83 }
84
85 - (void)dealloc
86 {
87     [outputFilePath release];
88     [remoteURLAsString release];
89     [streamSession release];
90     [media release];
91     [super dealloc];
92 }
93
94 @synthesize streamSession;
95 @synthesize selectedStreamOutput;
96 @synthesize media;
97 @synthesize outputFolderPath;
98
99 - (void)awakeFromNib
100 {
101     [window setShowsResizeIndicator:NO];
102     [NSApp setDelegate: self];
103 }
104
105 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
106 {
107     [VLCLibrary sharedLibrary];
108 }
109
110 - (NSString *)remoteURLAsString
111 {
112     return remoteURLAsString;
113 }
114
115 - (void)setRemoteURLAsString:(NSString *)newURLAsString
116 {
117     [remoteURLAsString release];
118     remoteURLAsString = [[newURLAsString copy] retain];
119     media = [[newURLAsString copy] retain];
120     [self setMedia:[VLCMedia mediaWithPath:newURLAsString]];
121 }
122
123 + (NSSet *)keyPathsForValuesAffectingOutputFilePath
124 {
125     return [NSSet setWithObjects:@"media.metaDictionary.title", nil];
126 }
127
128 - (void)freezeOutputFilePath
129 {
130     [outputFilePath release];
131     outputFilePath = nil;
132     outputFilePath = [self outputFilePath];
133     [outputFilePath retain];
134 }
135
136 - (NSString *)outputFilePath
137 {
138     if(outputFilePath)
139         return [outputFilePath copy];
140     VLCMedia * aMedia = self.streamSession ? self.streamSession.media ? self.streamSession.media : self.media : self.media;
141     NSString * name = [[[aMedia metaDictionary] objectForKey:@"title"] lastPathComponent];
142     NSString * extension = [selectedStreamOutput intValue] == 2 ? @"mpeg" : @"mp4";
143     NSString * path = [NSString stringWithFormat:@"%@/%@.%@", self.outputFolderPath, name, extension ];
144     int i;
145     for( i = 0; [[NSFileManager defaultManager] fileExistsAtPath:path]; i ++)
146     {
147         path = [NSString stringWithFormat:@"%@/%@ %d.%@", self.outputFolderPath, name, i, extension ];
148         if( i > 256 )
149         {
150             /* Don't got too far */
151             /* FIXME: Be nicer with the user and give him a choice for the new name */
152             NSRunAlertPanelRelativeToWindow(@"File already exists",
153                 [NSString stringWithFormat:
154                     @"File '%@', already exists. The old one will be deleted when the OK button will be pressed", path],
155                 @"OK", nil, nil, window);
156             break;
157         }
158     }
159     return path;
160 }
161
162
163 - (IBAction)convert:(id)sender
164 {
165     VLCStreamOutput * streamOutput;
166     [self.streamSession removeObserver:self forKeyPath:@"isComplete"];
167
168     self.streamSession = [VLCStreamSession streamSession];
169     [self freezeOutputFilePath];
170
171     if([selectedStreamOutput intValue] == 2)
172     {
173         streamOutput = [VLCStreamOutput mpeg2StreamOutputWithFilePath:[self outputFilePath]];
174     }
175     else if([selectedStreamOutput intValue] == 1)
176     {
177         streamOutput = [VLCStreamOutput mpeg4StreamOutputWithFilePath:[self outputFilePath]];
178     }
179     else
180         streamOutput = [VLCStreamOutput ipodStreamOutputWithFilePath:[self outputFilePath]];
181
182     /* Make sure we are exporting to a well known directory */
183     [[NSFileManager defaultManager] createDirectoryAtPath:self.outputFolderPath attributes:nil];
184
185     [self.streamSession setStreamOutput:streamOutput];
186     [self.streamSession setMedia:self.media];
187     [self.streamSession startStreaming];
188
189     [self.streamSession addObserver:self forKeyPath:@"isComplete" options:NSKeyValueObservingOptionNew context:nil];
190
191     /* Show the new view */
192     [[window contentView] addSubview:workingView];
193     NSRect frame = [workingView frame];
194     frame.origin.y -= NSHeight([window contentRectForFrameRect:[window frame]]) + 20.f;
195     [workingView setFrame:frame];
196     [[window animator] setFrame:NSMakeRect([window frame].origin.x, [window frame].origin.y-NSHeight([workingView frame]), NSWidth([window frame]), NSHeight([window frame])+NSHeight([workingView frame])) display:YES];
197 }
198
199 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
200 {
201     if([keyPath isEqualToString:@"isComplete"])
202     {
203         if([self.streamSession isComplete])
204         {
205             /* Notify the user */
206             [[NSSound soundNamed:@"Glass"] play];
207
208             /* Set the icon */
209             [openConvertedFileButton setImage:[[NSWorkspace sharedWorkspace] iconForFile:[self outputFilePath]]];
210             
211             /* Rename the link with a nicer name */
212             NSString * oldPath = [self outputFilePath];
213             [self freezeOutputFilePath];
214             [[NSFileManager defaultManager] moveItemAtPath:oldPath toPath:[self outputFilePath] error:NULL];
215         }
216         return;
217     }
218     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
219 }
220
221 - (IBAction)openConvertedFile:(id)sender
222 {
223     [[NSWorkspace sharedWorkspace] openFile:[self outputFilePath]];
224 }
225
226 - (IBAction)pickOutputFolderPath:(id)sender;
227 {
228     NSOpenPanel * panel = [NSOpenPanel openPanel];
229     [panel setCanChooseFiles:NO];
230     [panel setCanChooseDirectories:YES];
231     [panel setAllowsMultipleSelection:NO];
232     [panel beginSheetForDirectory:self.outputFolderPath file:nil types:nil modalForWindow:[sender window] modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:nil];
233 }
234
235 - (void)openPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode  contextInfo:(void  *)contextInfo
236 {
237     if(returnCode != NSOKButton || ![[panel filenames] count])
238         return;
239     self.outputFolderPath = [[panel filenames] objectAtIndex:0];
240 }
241
242 - (IBAction)openConvertedEnclosingFolder:(id)sender
243 {
244     [[NSWorkspace sharedWorkspace] selectFile:[self outputFilePath] inFileViewerRootedAtPath:[[self outputFilePath] stringByDeletingLastPathComponent]];
245 }
246
247 - (IBAction)cancel:(id)sender
248 {
249     [self.streamSession stop];
250 }
251
252 @end