Skip to content

Commit

Permalink
Movie scanner implemented
Browse files Browse the repository at this point in the history
Implemented scanner to find audio and subtitle languages (downstream code to use this information not implemented yet)

Changed HBBPreset to use NSASCIIStringEncoding rather than NSUTF8StringEncoding to avoid awkward retry for random failures
  • Loading branch information
taglia committed Jan 16, 2012
1 parent d991c19 commit 32561e6
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 49 deletions.
6 changes: 6 additions & 0 deletions HandBrakeBatch.xcodeproj/project.pbxproj
Expand Up @@ -18,6 +18,7 @@
0E6C285C14C288BC004A0FE5 /* iso639-2.db in Resources */ = {isa = PBXBuildFile; fileRef = 0E6C285B14C288BC004A0FE5 /* iso639-2.db */; }; 0E6C285C14C288BC004A0FE5 /* iso639-2.db in Resources */ = {isa = PBXBuildFile; fileRef = 0E6C285B14C288BC004A0FE5 /* iso639-2.db */; };
0E6C285F14C289DE004A0FE5 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E6C285E14C289DE004A0FE5 /* libsqlite3.dylib */; }; 0E6C285F14C289DE004A0FE5 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E6C285E14C289DE004A0FE5 /* libsqlite3.dylib */; };
0E6C286214C29515004A0FE5 /* HBBLangData.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E6C286114C29515004A0FE5 /* HBBLangData.m */; }; 0E6C286214C29515004A0FE5 /* HBBLangData.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E6C286114C29515004A0FE5 /* HBBLangData.m */; };
0E933F9D14C47C8000A5BB1D /* HBBVideoScan.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E933F9C14C47C8000A5BB1D /* HBBVideoScan.m */; };
0E987E2113E4062C00A99716 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E987E2013E4062C00A99716 /* Preferences.xib */; }; 0E987E2113E4062C00A99716 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E987E2013E4062C00A99716 /* Preferences.xib */; };
0E987E2413E4083900A99716 /* HBBPreferencesController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E987E2313E4083900A99716 /* HBBPreferencesController.m */; }; 0E987E2413E4083900A99716 /* HBBPreferencesController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E987E2313E4083900A99716 /* HBBPreferencesController.m */; };
0E9B490A136C874000FCDC68 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 0E9B4909136C874000FCDC68 /* Icon.icns */; }; 0E9B490A136C874000FCDC68 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 0E9B4909136C874000FCDC68 /* Icon.icns */; };
Expand Down Expand Up @@ -78,6 +79,8 @@
0E6C285E14C289DE004A0FE5 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = SDKs/MacOSX10.6.sdk/usr/lib/libsqlite3.dylib; sourceTree = DEVELOPER_DIR; }; 0E6C285E14C289DE004A0FE5 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = SDKs/MacOSX10.6.sdk/usr/lib/libsqlite3.dylib; sourceTree = DEVELOPER_DIR; };
0E6C286014C29515004A0FE5 /* HBBLangData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBBLangData.h; sourceTree = "<group>"; }; 0E6C286014C29515004A0FE5 /* HBBLangData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBBLangData.h; sourceTree = "<group>"; };
0E6C286114C29515004A0FE5 /* HBBLangData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBBLangData.m; sourceTree = "<group>"; }; 0E6C286114C29515004A0FE5 /* HBBLangData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBBLangData.m; sourceTree = "<group>"; };
0E933F9B14C47C8000A5BB1D /* HBBVideoScan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBBVideoScan.h; sourceTree = "<group>"; };
0E933F9C14C47C8000A5BB1D /* HBBVideoScan.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBBVideoScan.m; sourceTree = "<group>"; };
0E987E2013E4062C00A99716 /* Preferences.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = "<group>"; }; 0E987E2013E4062C00A99716 /* Preferences.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = Preferences.xib; sourceTree = "<group>"; };
0E987E2213E4083900A99716 /* HBBPreferencesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBBPreferencesController.h; sourceTree = "<group>"; }; 0E987E2213E4083900A99716 /* HBBPreferencesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBBPreferencesController.h; sourceTree = "<group>"; };
0E987E2313E4083900A99716 /* HBBPreferencesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBBPreferencesController.m; sourceTree = "<group>"; }; 0E987E2313E4083900A99716 /* HBBPreferencesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBBPreferencesController.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -202,6 +205,8 @@
0E49A76713764A1500FB3B77 /* HBBPresets.m */, 0E49A76713764A1500FB3B77 /* HBBPresets.m */,
0E108B69136C47F200168057 /* HBBProgressController.h */, 0E108B69136C47F200168057 /* HBBProgressController.h */,
0E108B6A136C47F200168057 /* HBBProgressController.m */, 0E108B6A136C47F200168057 /* HBBProgressController.m */,
0E933F9B14C47C8000A5BB1D /* HBBVideoScan.h */,
0E933F9C14C47C8000A5BB1D /* HBBVideoScan.m */,
0E549260136C49BD0094563F /* xib */, 0E549260136C49BD0094563F /* xib */,
0EEC80461369B4EA00D05124 /* Supporting Files */, 0EEC80461369B4EA00D05124 /* Supporting Files */,
); );
Expand Down Expand Up @@ -309,6 +314,7 @@
0E49A76813764A1500FB3B77 /* HBBPresets.m in Sources */, 0E49A76813764A1500FB3B77 /* HBBPresets.m in Sources */,
0E987E2413E4083900A99716 /* HBBPreferencesController.m in Sources */, 0E987E2413E4083900A99716 /* HBBPreferencesController.m in Sources */,
0E6C286214C29515004A0FE5 /* HBBLangData.m in Sources */, 0E6C286214C29515004A0FE5 /* HBBLangData.m in Sources */,
0E933F9D14C47C8000A5BB1D /* HBBVideoScan.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
Expand Down
Binary file not shown.
92 changes: 43 additions & 49 deletions HandBrakeBatch/HBBPresets.m
Expand Up @@ -37,66 +37,60 @@ - (void)initPresets {


// Check if HB's custom presets are present // Check if HB's custom presets are present
// If presets are present, let's parse them // If presets are present, let's parse them
// Sometimes the "manicure.rb" script returns an empty list. We try 5 times to be sure this won't be visible by the user (unless the preset file is corrupted)
int retries = 5;
if ([[NSFileManager defaultManager] fileExistsAtPath:presetPath]) { if ([[NSFileManager defaultManager] fileExistsAtPath:presetPath]) {
do { // Initialize NSTask
// Initialize NSTask NSTask *simpleTask = [[NSTask alloc] init];
NSTask *simpleTask = [[NSTask alloc] init]; NSPipe *outputPipe = [NSPipe pipe];
NSPipe *outputPipe = [NSPipe pipe]; [simpleTask setStandardOutput: outputPipe];
[simpleTask setStandardOutput: outputPipe]; [simpleTask setStandardError: [simpleTask standardOutput]];
[simpleTask setStandardError: [simpleTask standardOutput]]; [simpleTask setLaunchPath: @"/usr/bin/ruby"];
[simpleTask setLaunchPath: @"/usr/bin/ruby"];

// Get path of manicure.rb
// Get path of manicure.rb NSString *manicure = [[NSBundle mainBundle] pathForResource:@"manicure" ofType:@"rb"];
NSString *manicure = [[NSBundle mainBundle] pathForResource:@"manicure" ofType:@"rb"]; [simpleTask setCurrentDirectoryPath:[manicure stringByDeletingLastPathComponent]];
[simpleTask setCurrentDirectoryPath:[manicure stringByDeletingLastPathComponent]];

// Build argument array
// Build argument array NSArray *arguments = [NSArray arrayWithObjects:manicure, @"-p", nil];
NSArray *arguments = [NSArray arrayWithObjects:manicure, @"-p", nil]; [simpleTask setArguments: arguments];
[simpleTask setArguments: arguments];

// Run task
// Run task [simpleTask launch];
[simpleTask launch]; [simpleTask waitUntilExit];
[simpleTask waitUntilExit];

NSFileHandle *output = [outputPipe fileHandleForReading];
NSFileHandle *output = [outputPipe fileHandleForReading]; NSData *data = [output readDataToEndOfFile];
NSData *data = [output readDataToEndOfFile]; NSString *rawOutput = [NSString stringWithCString:[data bytes] encoding:NSASCIIStringEncoding];
NSString *rawOutput = [NSString stringWithUTF8String:[data bytes]]; NSArray *outputLines = [rawOutput componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
NSArray *outputLines = [rawOutput componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

for (NSString *currentLine in outputLines) {
for (NSString *currentLine in outputLines) { // Ignore empty lines and folders (all preset lines contain a +)
// Ignore empty lines and folders (all preset lines contain a +) // Only one level of folders is supported
// Only one level of folders is supported if ([currentLine length] > 4) {
if ([currentLine length] > 4) { int offset;
int offset;

if ([currentLine characterAtIndex:0] == '+')
if ([currentLine characterAtIndex:0] == '+') offset=0;
offset=0; else if ([currentLine characterAtIndex:3] == '+')
else if ([currentLine characterAtIndex:3] == '+') offset=3;
offset=3; else
else continue;
continue;


NSRange separator = [currentLine rangeOfString:@": "]; NSRange separator = [currentLine rangeOfString:@": "];


NSString *name = [[currentLine substringToIndex:separator.location] substringFromIndex:offset+2]; NSString *name = [[currentLine substringToIndex:separator.location] substringFromIndex:offset+2];
NSString *args = [currentLine substringFromIndex:separator.location+separator.length]; NSString *args = [currentLine substringFromIndex:separator.location+separator.length];


[tempDict setObject:args forKey:name]; [tempDict setObject:args forKey:name];
} }
} }
retries--;
} while (retries > 0 && [tempDict count] == 0);
} }


// Preset file probably corrupted // Preset file probably corrupted
if ( [tempDict count] == 0 ) { if ( [tempDict count] == 0 ) {
for (NSString *currentPreset in defaultPresets) { for (NSString *currentPreset in defaultPresets) {
[tempDict setObject:[NSString stringWithFormat:@"--preset %@", currentPreset] forKey:currentPreset]; [tempDict setObject:[NSString stringWithFormat:@"--preset %@", currentPreset] forKey:currentPreset];
} }
if (retries == 0) NSBeginAlertSheet(@"Unable to read HandBrake custom presets", @"Ok", nil, nil, nil, nil, NULL, NULL, NULL, @"The custom preset file might be corrupted, the application will show the default presets only.");
NSBeginAlertSheet(@"Unable to read HandBrake custom presets", @"Ok", nil, nil, nil, nil, NULL, NULL, NULL, @"The custom preset file might be corrupted, the application will show the default presets only.");
} }


// Initialize the preset dictionary // Initialize the preset dictionary
Expand Down
5 changes: 5 additions & 0 deletions HandBrakeBatch/HBBProgressController.m
Expand Up @@ -11,6 +11,7 @@
#import <Growl/Growl.h> #import <Growl/Growl.h>
#import "HBBProgressController.h" #import "HBBProgressController.h"
#import "HBBPresets.h" #import "HBBPresets.h"
#import "HBBVideoScan.h"


#define FILES_OK 0 #define FILES_OK 0
#define FILE_EXISTS 1 #define FILE_EXISTS 1
Expand Down Expand Up @@ -68,6 +69,10 @@ -(void) prepareTask {


NSString *inputFilePath = [[currentQueue objectAtIndex:0] inputPath]; NSString *inputFilePath = [[currentQueue objectAtIndex:0] inputPath];


// Scan input file
HBBVideoScan *scanner = [[HBBVideoScan alloc] initWithFile:inputFilePath];
[scanner scan];

NSString *outputFilePath = [outputFolder stringByAppendingPathComponent:[[[inputFilePath stringByDeletingPathExtension] stringByAppendingPathExtension:fileExtension] lastPathComponent]]; NSString *outputFilePath = [outputFolder stringByAppendingPathComponent:[[[inputFilePath stringByDeletingPathExtension] stringByAppendingPathExtension:fileExtension] lastPathComponent]];


// Deal with EyeTV files // Deal with EyeTV files
Expand Down
26 changes: 26 additions & 0 deletions HandBrakeBatch/HBBVideoScan.h
@@ -0,0 +1,26 @@
//
// HBBVideoScan.h
// HandBrakeBatch
//
// Created by Cesare Tagliaferri on 16/01/2012.
// This file is part of the HandBrakeBatch source code.
// Homepage: <http://www.osomac.com/>.
// It may be used under the terms of the GNU General Public License.
//

#import <Foundation/Foundation.h>

@interface HBBVideoScan : NSObject {
NSString *fileName;
NSMutableArray *audioLanguages;
NSMutableArray *subtitleLanguages;
}

@property (assign)NSString *fileName;
@property (readonly)NSArray *audioLanguages;
@property (readonly)NSArray *subtitleLanguages;

-(id)initWithFile:(NSString *)path;
-(void)scan;

@end
83 changes: 83 additions & 0 deletions HandBrakeBatch/HBBVideoScan.m
@@ -0,0 +1,83 @@
//
// HBBVideoScan.m
// HandBrakeBatch
//
// Created by Cesare Tagliaferri on 16/01/2012.
// This file is part of the HandBrakeBatch source code.
// Homepage: <http://www.osomac.com/>.
// It may be used under the terms of the GNU General Public License.
//

#import "HBBVideoScan.h"

@implementation HBBVideoScan

@synthesize fileName, audioLanguages, subtitleLanguages;

-(id)initWithFile:(NSString *)path {
self = [self init];

[self setFileName:path];

return self;
}

- (id)init {
self = [super init];

if (self) {
audioLanguages = [[NSMutableArray alloc] init];
subtitleLanguages = [[NSMutableArray alloc] init];
}

return self;
}

-(void)scan {
NSTask *task = [[NSTask alloc] init];
NSPipe *stdOutPipe = [NSPipe pipe];

[task setStandardOutput:stdOutPipe];
[task setStandardError: [task standardOutput]];

// No perf issues here, so we always use the 32 bit version
[task setLaunchPath:[[NSBundle mainBundle] pathForResource:@"HandBrakeCLI_32" ofType:@""]];

// Setting arguments
[task setArguments:[NSArray arrayWithObjects:@"--scan", @"-i", fileName, nil]];

// Executing scan
[task launch];
[task waitUntilExit];

NSData *output = [[stdOutPipe fileHandleForReading] readDataToEndOfFile];

NSString *stringData = [NSString stringWithCString:[output bytes] encoding:NSASCIIStringEncoding];

NSArray *outputLines = [stringData componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

NSUInteger audioIndex = [outputLines indexOfObject:@" + audio tracks:"];
NSUInteger subtitleIndex = [outputLines indexOfObject:@" + subtitle tracks:"];

// Reset languages
[audioLanguages removeAllObjects];
[subtitleLanguages removeAllObjects];

while ([[outputLines objectAtIndex:++audioIndex] characterAtIndex:4] == '+') {
NSRange range = [[outputLines objectAtIndex:audioIndex] rangeOfString:@"iso639-2: "];
[audioLanguages addObject:[[outputLines objectAtIndex:audioIndex] substringWithRange:NSMakeRange(range.location + range.length, 3)]];
}
while ([[outputLines objectAtIndex:++subtitleIndex] characterAtIndex:4] == '+') {
NSRange range = [[outputLines objectAtIndex:audioIndex] rangeOfString:@"iso639-2: "];
[audioLanguages addObject:[[outputLines objectAtIndex:audioIndex] substringWithRange:NSMakeRange(range.location + range.length, 3)]];
}

for (NSString *aLang in audioLanguages) {
NSLog(@"Audio language found: %@", aLang);
}
for (NSString *sLang in subtitleLanguages) {
NSLog(@"Subtitle language found: %@", sLang);
}
}

@end

0 comments on commit 32561e6

Please sign in to comment.