123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- /*****************************************************************************
- * Copyright (C) 2007-2012 Pierre d'Herbemont and VideoLAN
- *
- * Authors: Pierre d'Herbemont
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
- #import "Controller.h"
- /**********************************************************
- * First off, some value transformer to easily play with
- * bindings
- */
- @interface VLCFloat10000FoldTransformer : NSObject
- @end
- @implementation VLCFloat10000FoldTransformer
- + (Class)transformedValueClass
- {
- return [NSNumber class];
- }
- + (BOOL)allowsReverseTransformation
- {
- return YES;
- }
- - (id)transformedValue:(id)value
- {
- if( !value ) return nil;
- if(![value respondsToSelector: @selector(floatValue)])
- {
- [NSException raise: NSInternalInconsistencyException
- format: @"Value (%@) does not respond to -floatValue.",
- [value class]];
- return nil;
- }
- return [NSNumber numberWithFloat: [value floatValue]*10000.];
- }
- - (id)reverseTransformedValue:(id)value
- {
- if( !value ) return nil;
- if(![value respondsToSelector: @selector(floatValue)])
- {
- [NSException raise: NSInternalInconsistencyException
- format: @"Value (%@) does not respond to -floatValue.",
- [value class]];
- return nil;
- }
- return [NSNumber numberWithFloat: [value floatValue]/10000.];
- }
- @end
- /**********************************************************
- * @implementation Controller
- */
- @interface Controller ()
- @property (retain,readwrite) NSString * outputFolderPath;
- @end
- @implementation Controller
- - (id)init
- {
- if(self = [super init])
- {
- [self bind:@"outputFolderPath" toObject:[NSUserDefaultsController sharedUserDefaultsController]
- withKeyPath:@"values.outputFolderPath" options:nil];
- [[[NSUserDefaultsController sharedUserDefaultsController] values] bind:@"outputFolderPath" toObject:self
- withKeyPath:@"outputFolderPath" options:nil];
- VLCFloat10000FoldTransformer *float100fold;
- float100fold = [[[VLCFloat10000FoldTransformer alloc] init] autorelease];
- [NSValueTransformer setValueTransformer:(id)float100fold forName:@"Float10000FoldTransformer"];
- self.media = nil;
- self.streamSession = nil;
- selectedStreamOutput = [[NSNumber alloc] initWithInt:0];
- self.remoteURLAsString = @"http://youtube.com/watch?v=IXpx2OEWBdA&feature=bz303";
- outputFilePath = nil;
- if( !self.outputFolderPath || [self.outputFolderPath isKindOfClass:[NSNull class]])
- self.outputFolderPath = [@"~/Movies/Flash Video Converted" stringByExpandingTildeInPath];
- }
- return self;
- }
- - (void)dealloc
- {
- [outputFilePath release];
- [remoteURLAsString release];
- [streamSession release];
- [media release];
- [super dealloc];
- }
- @synthesize streamSession;
- @synthesize selectedStreamOutput;
- @synthesize media;
- @synthesize outputFolderPath;
- - (void)awakeFromNib
- {
- [window setShowsResizeIndicator:NO];
- [NSApp setDelegate: self];
- }
- - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
- {
- [VLCLibrary sharedLibrary];
- }
- - (NSString *)remoteURLAsString
- {
- return remoteURLAsString;
- }
- - (void)setRemoteURLAsString:(NSString *)newURLAsString
- {
- [remoteURLAsString release];
- remoteURLAsString = [[newURLAsString copy] retain];
- media = [[newURLAsString copy] retain];
- [self setMedia:[VLCMedia mediaWithPath:newURLAsString]];
- }
- + (NSSet *)keyPathsForValuesAffectingOutputFilePath
- {
- return [NSSet setWithObjects:@"media.metaDictionary.title", nil];
- }
- - (void)freezeOutputFilePath
- {
- [outputFilePath release];
- outputFilePath = nil;
- outputFilePath = [self outputFilePath];
- [outputFilePath retain];
- }
- - (NSString *)outputFilePath
- {
- if(outputFilePath)
- return [outputFilePath copy];
- VLCMedia * aMedia = self.streamSession ? self.streamSession.media ? self.streamSession.media : self.media : self.media;
- NSString * name = [[[aMedia metaDictionary] objectForKey:@"title"] lastPathComponent];
- NSString * extension = [selectedStreamOutput intValue] == 2 ? @"mpeg" : @"mp4";
- NSString * path = [NSString stringWithFormat:@"%@/%@.%@", self.outputFolderPath, name, extension ];
- int i;
- for( i = 0; [[NSFileManager defaultManager] fileExistsAtPath:path]; i ++)
- {
- path = [NSString stringWithFormat:@"%@/%@ %d.%@", self.outputFolderPath, name, i, extension ];
- if( i > 256 )
- {
- /* Don't got too far */
- /* FIXME: Be nicer with the user and give him a choice for the new name */
- NSRunAlertPanelRelativeToWindow(@"File already exists",
- [NSString stringWithFormat:
- @"File '%@', already exists. The old one will be deleted when the OK button will be pressed", path],
- @"OK", nil, nil, window);
- break;
- }
- }
- return path;
- }
- - (IBAction)convert:(id)sender
- {
- VLCStreamOutput * streamOutput;
- [self.streamSession removeObserver:self forKeyPath:@"isComplete"];
- self.streamSession = [VLCStreamSession streamSession];
- [self freezeOutputFilePath];
- if([selectedStreamOutput intValue] == 2)
- {
- streamOutput = [VLCStreamOutput mpeg2StreamOutputWithFilePath:[self outputFilePath]];
- }
- else if([selectedStreamOutput intValue] == 1)
- {
- streamOutput = [VLCStreamOutput mpeg4StreamOutputWithFilePath:[self outputFilePath]];
- }
- else
- streamOutput = [VLCStreamOutput ipodStreamOutputWithFilePath:[self outputFilePath]];
- /* Make sure we are exporting to a well known directory */
- [[NSFileManager defaultManager] createDirectoryAtPath:self.outputFolderPath attributes:nil];
- [self.streamSession setStreamOutput:streamOutput];
- [self.streamSession setMedia:self.media];
- [self.streamSession startStreaming];
- [self.streamSession addObserver:self forKeyPath:@"isComplete" options:NSKeyValueObservingOptionNew context:nil];
- /* Show the new view */
- [[window contentView] addSubview:workingView];
- NSRect frame = [workingView frame];
- frame.origin.y -= NSHeight([window contentRectForFrameRect:[window frame]]) + 20.f;
- [workingView setFrame:frame];
- [[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];
- }
- - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
- {
- if([keyPath isEqualToString:@"isComplete"])
- {
- if([self.streamSession isComplete])
- {
- /* Notify the user */
- [[NSSound soundNamed:@"Glass"] play];
- /* Set the icon */
- [openConvertedFileButton setImage:[[NSWorkspace sharedWorkspace] iconForFile:[self outputFilePath]]];
- /* Rename the link with a nicer name */
- NSString * oldPath = [self outputFilePath];
- [self freezeOutputFilePath];
- [[NSFileManager defaultManager] moveItemAtPath:oldPath toPath:[self outputFilePath] error:NULL];
- }
- return;
- }
- [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
- }
- - (IBAction)openConvertedFile:(id)sender
- {
- [[NSWorkspace sharedWorkspace] openFile:[self outputFilePath]];
- }
- - (IBAction)pickOutputFolderPath:(id)sender;
- {
- NSOpenPanel * panel = [NSOpenPanel openPanel];
- [panel setCanChooseFiles:NO];
- [panel setCanChooseDirectories:YES];
- [panel setAllowsMultipleSelection:NO];
- [panel beginSheetForDirectory:self.outputFolderPath file:nil types:nil modalForWindow:[sender window] modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:nil];
- }
- - (void)openPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo
- {
- if(returnCode != NSOKButton || ![[panel filenames] count])
- return;
- self.outputFolderPath = [[panel filenames] objectAtIndex:0];
- }
- - (IBAction)openConvertedEnclosingFolder:(id)sender
- {
- [[NSWorkspace sharedWorkspace] selectFile:[self outputFilePath] inFileViewerRootedAtPath:[[self outputFilePath] stringByDeletingLastPathComponent]];
- }
- - (IBAction)cancel:(id)sender
- {
- [self.streamSession stop];
- }
- @end
|