Homepage: <http://handbrake.fr/>.
It may be used under the terms of the GNU General Public License. */
+#include <dlfcn.h>
#import "Controller.h"
#import "HBOutputPanelController.h"
#import "HBPreferencesController.h"
fQueueStatus,fPresetsAdd,fPresetsDelete,fSrcAngleLabel,fSrcAnglePopUp,
fCreateChapterMarkers,fVidTurboPassCheck,fDstMp4LargeFileCheck,fSubForcedCheck,fPresetsOutlineView,
fAudDrcLabel,fDstMp4HttpOptFileCheck,fDstMp4iPodFileCheck,fVidQualityRFField,fVidQualityRFLabel,
- fEncodeStartStopPopUp,fSrcTimeStartEncodingField,fSrcTimeEndEncodingField,fSrcFrameStartEncodingField,fSrcFrameEndEncodingField};
+ fEncodeStartStopPopUp,fSrcTimeStartEncodingField,fSrcTimeEndEncodingField,fSrcFrameStartEncodingField,fSrcFrameEndEncodingField, fLoadChaptersButton, fSaveChaptersButton};
for( unsigned i = 0;
i < sizeof( controls ) / sizeof( NSControl * ); i++ )
if( [detector isVideoDVD] )
{
- int hb_arch;
-#if defined( __LP64__ )
- /* we are 64 bit */
- hb_arch = 64;
-#else
- /* we are 32 bit */
- hb_arch = 32;
-#endif
-
-
// The chosen path was actually on a DVD, so use the raw block
// device path instead.
path = [detector devicePath];
[self writeToActivityLog: "trying to open a physical dvd at: %s", [scanPath UTF8String]];
/* lets check for vlc here to make sure we have a dylib available to use for decrypting */
- NSString *vlcPath = @"/Applications/VLC.app/Contents/MacOS/lib/libdvdcss.2.dylib";
- NSFileManager * fileManager = [NSFileManager defaultManager];
- if ([fileManager fileExistsAtPath:vlcPath] == 0)
- {
- /*vlc not found in /Applications so we set the bool to cancel scanning to 1 */
+ void *dvdcss = dlopen("libdvdcss.2.dylib", RTLD_LAZY);
+ if (dvdcss == NULL)
+ {
+ /*compatible vlc not found, so we set the bool to cancel scanning to 1 */
cancelScanDecrypt = 1;
[self writeToActivityLog: "VLC app not found for decrypting physical dvd"];
int status;
- status = NSRunAlertPanel(@"HandBrake could not find VLC or your VLC is out of date.",@"Please download and install VLC media player in your /Applications folder if you wish to read encrypted DVDs.", @"Get VLC", @"Cancel Scan", @"Attempt Scan Anyway");
+ status = NSRunAlertPanel(@"HandBrake could not find VLC or your VLC is incompatible (Note: 32 bit vlc is not compatible with 64 bit HandBrake and vice-versa).",@"Please download and install VLC media player if you wish to read encrypted DVDs.", @"Get VLC", @"Cancel Scan", @"Attempt Scan Anyway");
[NSApp requestUserAttention:NSCriticalRequest];
if (status == NSAlertDefaultReturn)
/* VLC was found in /Applications so all is well, we can carry on using vlc's libdvdcss.dylib for decrypting if needed */
[self writeToActivityLog: "VLC app found for decrypting physical dvd"];
vlcFound = 1;
+ dlclose(dvdcss);
}
- /* test for architecture of the vlc app */
- NSArray *vlc_architecturesArray = [[NSBundle bundleWithPath:@"/Applications/VLC.app"] executableArchitectures];
- BOOL vlcIntel32bit = NO;
- BOOL vlcIntel64bit = NO;
- BOOL vlcPPC32bit = NO;
- BOOL vlcPPC64bit = NO;
- /* check the available architectures for vlc and note accordingly */
- NSEnumerator *enumerator = [vlc_architecturesArray objectEnumerator];
- id tempObject;
- while (tempObject = [enumerator nextObject])
- {
-
- if ([tempObject intValue] == NSBundleExecutableArchitectureI386)
- {
- vlcIntel32bit = YES;
- }
- if ([tempObject intValue] == NSBundleExecutableArchitectureX86_64)
- {
- vlcIntel64bit = YES;
- }
- if ([tempObject intValue] == NSBundleExecutableArchitecturePPC)
- {
- vlcPPC32bit = YES;
- }
- if ([tempObject intValue] == NSBundleExecutableArchitecturePPC64)
- {
- vlcPPC64bit = YES;
- }
-
- }
- /* Write vlc architecture findings to activity window */
- if (vlcIntel32bit)
- {
- [self writeToActivityLog: " 32-Bit VLC app found for decrypting physical dvd"];
- }
- if (vlcIntel64bit)
- {
- [self writeToActivityLog: " 64-Bit VLC app found for decrypting physical dvd"];
- }
-
-
-
- if (vlcFound && hb_arch == 64 && !vlcIntel64bit && cancelScanDecrypt != 1)
- {
-
- /* we are 64 bit */
-
- /* Appropriate VLC not found, so cancel */
- cancelScanDecrypt = 1;
- [self writeToActivityLog: "This version of HandBrake is 64 bit, 64 bit version of vlc not found, scan cancelled"];
- /*On Screen Notification*/
- int status;
- NSBeep();
- status = NSRunAlertPanel(@"This version of HandBrake is 64 bit, VLC found but not 64 bit!",@"", @"Cancel Scan", @"Attempt Scan Anyway", @"Get 64 bit VLC", nil);
- [NSApp requestUserAttention:NSCriticalRequest];
-
- if (status == NSAlertDefaultReturn)
- {
- /* User chose to cancel the scan */
- [self writeToActivityLog: "cannot open physical dvd VLC found but not 64 bit, scan cancelled"];
- cancelScanDecrypt = 1;
- }
- else if (status == NSAlertAlternateReturn)
- {
- [self writeToActivityLog: "user overrode 64-bit warning trying to open physical dvd without proper decryption"];
- cancelScanDecrypt = 0;
- }
- else
- {
- /* User chose to go download vlc (as they rightfully should) so we send them to the vlc site */
- [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.videolan.org/vlc/download-macosx.html"]];
- }
-
- }
- else if (vlcFound && hb_arch == 32 && !vlcIntel32bit && cancelScanDecrypt != 1)
- {
- /* we are 32 bit */
- /* Appropriate VLC not found, so cancel */
- cancelScanDecrypt = 1;
- [self writeToActivityLog: "This version of HandBrake is 32 bit, 32 bit version of vlc not found, scan cancelled"];
- /*On Screen Notification*/
- int status;
- NSBeep();
- status = NSRunAlertPanel(@"This version of HandBrake is 32 bit, VLC found but not 32 bit!",@"", @"Cancel Scan", @"Attempt Scan Anyway", @"Get 32 bit VLC", nil);
- [NSApp requestUserAttention:NSCriticalRequest];
-
- if (status == NSAlertDefaultReturn)
- {
- /* User chose to cancel the scan */
- [self writeToActivityLog: "cannot open physical dvd VLC found but not 32 bit, scan cancelled"];
- cancelScanDecrypt = 1;
- }
- else if (status == NSAlertAlternateReturn)
- {
- [self writeToActivityLog: "user overrode 32-bit warning trying to open physical dvd without proper decryption"];
- cancelScanDecrypt = 0;
- }
- else
- {
- /* User chose to go download vlc (as they rightfully should) so we send them to the vlc site */
- [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.videolan.org/vlc/download-macosx.html"]];
- }
-
- }
}
if (cancelScanDecrypt == 0)
[self writeToActivityLog: "trying to open a physical dvd at: %s", [scanPath UTF8String]];
/* lets check for vlc here to make sure we have a dylib available to use for decrypting */
- NSString *vlcPath = @"/Applications/VLC.app";
- NSFileManager * fileManager = [NSFileManager defaultManager];
- if ([fileManager fileExistsAtPath:vlcPath] == 0)
- {
+ void *dvdcss = dlopen("libdvdcss.2.dylib", RTLD_LAZY);
+ if (dvdcss == NULL)
+ {
/*vlc not found in /Applications so we set the bool to cancel scanning to 1 */
cancelScanDecrypt = 1;
[self writeToActivityLog: "VLC app not found for decrypting physical dvd"];
else
{
/* VLC was found in /Applications so all is well, we can carry on using vlc's libdvdcss.dylib for decrypting if needed */
+ dlclose(dvdcss);
[self writeToActivityLog: "VLC app found for decrypting physical dvd"];
}
}
[self writeToActivityLog: "Foreign Language Search: %d", 1];
job->indepth_scan = 1;
- if (burned == 1 || job->mux != HB_MUX_MP4)
+
+ if (burned != 1)
{
- if (burned != 1 && job->mux == HB_MUX_MKV)
- {
- job->select_subtitle_config.dest = PASSTHRUSUB;
- }
- else
- {
- job->select_subtitle_config.dest = RENDERSUB;
- }
-
- job->select_subtitle_config.force = force;
- job->select_subtitle_config.default_track = def;
-
+ job->select_subtitle_config.dest = PASSTHRUSUB;
+ }
+ else
+ {
+ job->select_subtitle_config.dest = RENDERSUB;
}
-
+ job->select_subtitle_config.force = force;
+ job->select_subtitle_config.default_track = def;
}
else
{
{
hb_subtitle_config_t sub_config = subt->config;
- if (!burned && job->mux == HB_MUX_MKV &&
- subt->format == PICTURESUB)
+ if ( !burned && subt->format == PICTURESUB )
{
sub_config.dest = PASSTHRUSUB;
}
- else if (!burned && job->mux == HB_MUX_MP4 &&
- subt->format == PICTURESUB)
- {
- // Skip any non-burned vobsubs when output is mp4
- continue;
- }
else if ( burned && subt->format == PICTURESUB )
{
// Only allow one subtitle to be burned into the video
[self writeToActivityLog: "Foreign Language Search: %d", 1];
job->indepth_scan = 1;
- if (burned == 1 || job->mux != HB_MUX_MP4)
+
+ if (burned != 1)
{
- if (burned != 1 && job->mux == HB_MUX_MKV)
- {
- job->select_subtitle_config.dest = PASSTHRUSUB;
- }
- else
- {
- job->select_subtitle_config.dest = RENDERSUB;
- }
-
- job->select_subtitle_config.force = force;
- job->select_subtitle_config.default_track = def;
+ job->select_subtitle_config.dest = PASSTHRUSUB;
+ }
+ else
+ {
+ job->select_subtitle_config.dest = RENDERSUB;
}
-
+ job->select_subtitle_config.force = force;
+ job->select_subtitle_config.default_track = def;
}
else
{
{
hb_subtitle_config_t sub_config = subt->config;
- if (!burned && job->mux == HB_MUX_MKV &&
- subt->format == PICTURESUB)
+ if ( !burned && subt->format == PICTURESUB )
{
sub_config.dest = PASSTHRUSUB;
}
- else if (!burned && job->mux == HB_MUX_MP4 &&
- subt->format == PICTURESUB)
- {
- // Skip any non-burned vobsubs when output is mp4
- continue;
- }
else if ( burned && subt->format == PICTURESUB )
{
// Only allow one subtitle to be burned into the video
}
+#pragma mark -
+#pragma mark Chapter Files Import / Export
+
+- (IBAction) browseForChapterFile: (id) sender
+{
+ /* Open a panel to let the user choose the file */
+ NSOpenPanel * panel = [NSOpenPanel openPanel];
+ /* We get the current file name and path from the destination field here */
+ [panel beginSheetForDirectory: [NSString stringWithFormat:@"%@/",
+ [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"]]
+ file: NULL
+ types: [NSArray arrayWithObjects:@"csv",nil]
+ modalForWindow: fWindow modalDelegate: self
+ didEndSelector: @selector( browseForChapterFileDone:returnCode:contextInfo: )
+ contextInfo: NULL];
+}
+
+- (void) browseForChapterFileDone: (NSOpenPanel *) sheet
+ returnCode: (int) returnCode contextInfo: (void *) contextInfo
+{
+ NSArray *chaptersArray; /* temp array for chapters */
+ NSMutableArray *chaptersMutableArray; /* temp array for chapters */
+ NSString *chapterName; /* temp string from file */
+ int chapters, i;
+
+ if( returnCode == NSOKButton ) /* if they click OK */
+ {
+ chapterName = [[NSString alloc] initWithContentsOfFile:[sheet filename] encoding:NSUTF8StringEncoding error:NULL];
+ chaptersArray = [chapterName componentsSeparatedByString:@"\n"];
+ chaptersMutableArray= [chaptersArray mutableCopy];
+ chapters = [fChapterTitlesDelegate numberOfRowsInTableView:fChapterTable];
+ if ([chaptersMutableArray count] > 0)
+ {
+ /* if last item is empty remove it */
+ if ([[chaptersMutableArray objectAtIndex:[chaptersArray count]-1] length] == 0)
+ {
+ [chaptersMutableArray removeLastObject];
+ }
+ }
+ /* if chapters in table is not equal to array count */
+ if ((unsigned int) chapters != [chaptersMutableArray count])
+ {
+ [sheet close];
+ [[NSAlert alertWithMessageText:NSLocalizedString(@"Unable to load chapter file", @"Unable to load chapter file")
+ defaultButton:NSLocalizedString(@"OK", @"OK")
+ alternateButton:NULL
+ otherButton:NULL
+ informativeTextWithFormat:NSLocalizedString(@"%d chapters expected, %d chapters found in %@", @"%d chapters expected, %d chapters found in %@"),
+ chapters, [chaptersMutableArray count], [[sheet filename] lastPathComponent]] runModal];
+ return;
+ }
+ /* otherwise, go ahead and populate table with array */
+ for (i=0; i<chapters; i++)
+ {
+
+ if([[chaptersMutableArray objectAtIndex:i] length] > 5)
+ {
+ /* avoid a segfault */
+ /* Get the Range.location of the first comma in the line and then put everything after that into chapterTitle */
+ NSRange firstCommaRange = [[chaptersMutableArray objectAtIndex:i] rangeOfString:@","];
+ NSString *chapterTitle = [[chaptersMutableArray objectAtIndex:i] substringFromIndex:firstCommaRange.location + 1];
+ /* Since we store our chapterTitle commas as "\," for the cli, we now need to remove the escaping "\" from the title */
+ chapterTitle = [chapterTitle stringByReplacingOccurrencesOfString:@"\\," withString:@","];
+ [fChapterTitlesDelegate tableView:fChapterTable
+ setObjectValue:chapterTitle
+ forTableColumn:fChapterTableNameColumn
+ row:i];
+ }
+ else
+ {
+ [sheet close];
+ [[NSAlert alertWithMessageText:NSLocalizedString(@"Unable to load chapter file", @"Unable to load chapter file")
+ defaultButton:NSLocalizedString(@"OK", @"OK")
+ alternateButton:NULL
+ otherButton:NULL
+ informativeTextWithFormat:NSLocalizedString(@"%@ was not formatted as expected.", @"%@ was not formatted as expected."), [[sheet filename] lastPathComponent]] runModal];
+ [fChapterTable reloadData];
+ return;
+ }
+ }
+ [fChapterTable reloadData];
+ }
+}
+
+- (IBAction) browseForChapterFileSave: (id) sender
+{
+ NSSavePanel *panel = [NSSavePanel savePanel];
+ /* Open a panel to let the user save to a file */
+ [panel setAllowedFileTypes:[NSArray arrayWithObjects:@"csv",nil]];
+ [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent]
+ file: [[[[fDstFile2Field stringValue] lastPathComponent] stringByDeletingPathExtension]
+ stringByAppendingString:@"-chapters.csv"]
+ modalForWindow: fWindow
+ modalDelegate: self
+ didEndSelector: @selector( browseForChapterFileSaveDone:returnCode:contextInfo: )
+ contextInfo: NULL];
+}
+
+- (void) browseForChapterFileSaveDone: (NSSavePanel *) sheet
+ returnCode: (int) returnCode contextInfo: (void *) contextInfo
+{
+ NSString *chapterName; /* pointer for string for later file-writing */
+ NSString *chapterTitle;
+ NSError *saveError = [[NSError alloc] init];
+ int chapters, i; /* ints for the number of chapters in the table and the loop */
+
+ if( returnCode == NSOKButton ) /* if they clicked OK */
+ {
+ chapters = [fChapterTitlesDelegate numberOfRowsInTableView:fChapterTable];
+ chapterName = [NSString string];
+ for (i=0; i<chapters; i++)
+ {
+ /* put each chapter title from the table into the array */
+ if (i<9)
+ { /* if i is from 0 to 8 (chapters 1 to 9) add two leading zeros */
+ chapterName = [chapterName stringByAppendingFormat:@"00%d,",i+1];
+ }
+ else if (i<99)
+ { /* if i is from 9 to 98 (chapters 10 to 99) add one leading zero */
+ chapterName = [chapterName stringByAppendingFormat:@"0%d,",i+1];
+ }
+ else if (i<999)
+ { /* in case i is from 99 to 998 (chapters 100 to 999) no leading zeros */
+ chapterName = [chapterName stringByAppendingFormat:@"%d,",i+1];
+ }
+
+ chapterTitle = [fChapterTitlesDelegate tableView:fChapterTable objectValueForTableColumn:fChapterTableNameColumn row:i];
+ /* escape any commas in the chapter name with "\," */
+ chapterTitle = [chapterTitle stringByReplacingOccurrencesOfString:@"," withString:@"\\,"];
+ chapterName = [chapterName stringByAppendingString:chapterTitle];
+ if (i+1 != chapters)
+ { /* if not the last chapter */
+ chapterName = [chapterName stringByAppendingString:@ "\n"];
+ }
+
+
+ }
+ /* try to write it to where the user wanted */
+ if (![chapterName writeToFile:[sheet filename]
+ atomically:NO
+ encoding:NSUTF8StringEncoding
+ error:&saveError])
+ {
+ [sheet close];
+ [[NSAlert alertWithError:saveError] runModal];
+ }
+ }
+}
@end