4 /**********************************************************
5 * First off, some value transformer to easily play with
8 @interface VLCFloat10000FoldTransformer : NSObject
11 @implementation VLCFloat10000FoldTransformer
13 + (Class)transformedValueClass
15 return [NSNumber class];
18 + (BOOL)allowsReverseTransformation
23 - (id)transformedValue:(id)value
25 if( !value ) return nil;
27 if(![value respondsToSelector: @selector(floatValue)])
29 [NSException raise: NSInternalInconsistencyException
30 format: @"Value (%@) does not respond to -floatValue.",
35 return [NSNumber numberWithFloat: [value floatValue]*10000.];
38 - (id)reverseTransformedValue:(id)value
40 if( !value ) return nil;
42 if(![value respondsToSelector: @selector(floatValue)])
44 [NSException raise: NSInternalInconsistencyException
45 format: @"Value (%@) does not respond to -floatValue.",
50 return [NSNumber numberWithFloat: [value floatValue]/10000.];
55 /**********************************************************
56 * @implementation Controller
58 @interface Controller ()
59 @property (retain,readwrite) NSString * outputFolderPath;
62 @implementation Controller
65 if(self = [super init])
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"];
75 self.streamSession = nil;
76 selectedStreamOutput = [[NSNumber alloc] initWithInt:0];
77 self.remoteURLAsString = [NSString stringWithString:@"http://youtube.com/watch?v=IXpx2OEWBdA&feature=bz303"];
79 if( !self.outputFolderPath || [self.outputFolderPath isKindOfClass:[NSNull class]])
80 self.outputFolderPath = [@"~/Movies/Flash Video Converted" stringByExpandingTildeInPath];
87 [outputFilePath release];
88 [remoteURLAsString release];
89 [streamSession release];
94 @synthesize streamSession;
95 @synthesize selectedStreamOutput;
97 @synthesize outputFolderPath;
101 [window setShowsResizeIndicator:NO];
102 [NSApp setDelegate: self];
105 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
107 [VLCLibrary sharedLibrary];
110 - (NSString *)remoteURLAsString
112 return remoteURLAsString;
115 - (void)setRemoteURLAsString:(NSString *)newURLAsString
117 [remoteURLAsString release];
118 remoteURLAsString = [[newURLAsString copy] retain];
119 media = [[newURLAsString copy] retain];
120 [self setMedia:[VLCMedia mediaWithPath:newURLAsString]];
123 + (NSSet *)keyPathsForValuesAffectingOutputFilePath
125 return [NSSet setWithObjects:@"media.metaDictionary.title", nil];
128 - (void)freezeOutputFilePath
130 [outputFilePath release];
131 outputFilePath = nil;
132 outputFilePath = [self outputFilePath];
133 [outputFilePath retain];
136 - (NSString *)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 ];
145 for( i = 0; [[NSFileManager defaultManager] fileExistsAtPath:path]; i ++)
147 path = [NSString stringWithFormat:@"%@/%@ %d.%@", self.outputFolderPath, name, i, extension ];
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);
163 - (IBAction)convert:(id)sender
165 VLCStreamOutput * streamOutput;
166 [self.streamSession removeObserver:self forKeyPath:@"isComplete"];
168 self.streamSession = [VLCStreamSession streamSession];
169 [self freezeOutputFilePath];
171 if([selectedStreamOutput intValue] == 2)
173 streamOutput = [VLCStreamOutput mpeg2StreamOutputWithFilePath:[self outputFilePath]];
175 else if([selectedStreamOutput intValue] == 1)
177 streamOutput = [VLCStreamOutput mpeg4StreamOutputWithFilePath:[self outputFilePath]];
180 streamOutput = [VLCStreamOutput ipodStreamOutputWithFilePath:[self outputFilePath]];
182 /* Make sure we are exporting to a well known directory */
183 [[NSFileManager defaultManager] createDirectoryAtPath:self.outputFolderPath attributes:nil];
185 [self.streamSession setStreamOutput:streamOutput];
186 [self.streamSession setMedia:self.media];
187 [self.streamSession startStreaming];
189 [self.streamSession addObserver:self forKeyPath:@"isComplete" options:NSKeyValueObservingOptionNew context:nil];
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];
199 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
201 if([keyPath isEqualToString:@"isComplete"])
203 if([self.streamSession isComplete])
205 /* Notify the user */
206 [[NSSound soundNamed:@"Glass"] play];
209 [openConvertedFileButton setImage:[[NSWorkspace sharedWorkspace] iconForFile:[self outputFilePath]]];
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];
218 [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
221 - (IBAction)openConvertedFile:(id)sender
223 [[NSWorkspace sharedWorkspace] openFile:[self outputFilePath]];
226 - (IBAction)pickOutputFolderPath:(id)sender;
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];
235 - (void)openPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo
237 if(returnCode != NSOKButton || ![[panel filenames] count])
239 self.outputFolderPath = [[panel filenames] objectAtIndex:0];
242 - (IBAction)openConvertedEnclosingFolder:(id)sender
244 [[NSWorkspace sharedWorkspace] selectFile:[self outputFilePath] inFileViewerRootedAtPath:[[self outputFilePath] stringByDeletingLastPathComponent]];
247 - (IBAction)cancel:(id)sender
249 [self.streamSession stop];