summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--macosx/Controller.h16
-rw-r--r--macosx/Controller.m1585
-rw-r--r--macosx/English.lproj/MainMenu.xib16
-rw-r--r--macosx/HBAudio.h2
-rw-r--r--macosx/HBAudio.m25
-rw-r--r--macosx/HBAudioController.h4
-rw-r--r--macosx/HBAudioController.m94
-rw-r--r--macosx/HBAudioDefaults.h6
-rw-r--r--macosx/HBAudioDefaults.m32
-rw-r--r--macosx/HBAudioTrackPreset.h2
-rw-r--r--macosx/HBAudioTrackPreset.m20
-rw-r--r--macosx/HBCore.h9
-rw-r--r--macosx/HBCore.m64
-rw-r--r--macosx/HBFilters+UIAdditions.h5
-rw-r--r--macosx/HBFilters+UIAdditions.m116
-rw-r--r--macosx/HBFilters.h15
-rw-r--r--macosx/HBFilters.m151
-rw-r--r--macosx/HBJob+UIAdditions.h6
-rw-r--r--macosx/HBJob+UIAdditions.m38
-rw-r--r--macosx/HBJob.h8
-rw-r--r--macosx/HBJob.m118
-rw-r--r--macosx/HBPicture+UIAdditions.h1
-rw-r--r--macosx/HBPicture+UIAdditions.m19
-rw-r--r--macosx/HBPicture.h9
-rw-r--r--macosx/HBPicture.m93
-rw-r--r--macosx/HBPresetCoding.h15
-rw-r--r--macosx/HBQueueController.h12
-rw-r--r--macosx/HBQueueController.mm428
-rw-r--r--macosx/HBRange.h2
-rw-r--r--macosx/HBRange.m20
-rw-r--r--macosx/HBSubtitlesController.h4
-rw-r--r--macosx/HBSubtitlesController.m89
-rw-r--r--macosx/HBSubtitlesDefaults.h6
-rw-r--r--macosx/HBSubtitlesDefaults.m24
-rw-r--r--macosx/HBTitle.m48
-rw-r--r--macosx/HBVideo.h9
-rw-r--r--macosx/HBVideo.m178
-rw-r--r--macosx/HandBrake.xcodeproj/project.pbxproj2
-rw-r--r--macosx/NSCodingMacro.h2
39 files changed, 1214 insertions, 2079 deletions
diff --git a/macosx/Controller.h b/macosx/Controller.h
index cb7610f26..a2a92ba47 100644
--- a/macosx/Controller.h
+++ b/macosx/Controller.h
@@ -144,15 +144,12 @@
int fPendingCount; // Number of various kinds of job groups in fJobGroups.
int fWorkingCount;
- NSInteger fqueueEditRescanItemNum; // queue array item to be reloaded into the main window
pid_t pidNum; // The pid number for this instance
NSString * currentQueueEncodeNameString;
/* integer to set to determine the previous state
of encode 0==idle, 1==encoding, 2==cancelled*/
int fEncodeState;
- BOOL applyQueueToScan;
- NSString * browsedSourceDisplayName;
/* Dock progress variables */
double dockIconProgress;
@@ -164,7 +161,6 @@
- (IBAction) showSourceTitleScanPanel: (id) sender;
- (IBAction) closeSourceTitleScanPanel: (id) sender;
- (void) performScan:(NSString *) scanPath scanTitleNum: (NSInteger) scanTitleNum;
-- (IBAction) showNewScan: (id) sender;
- (void) enableUI: (BOOL) enable;
@@ -174,7 +170,6 @@
- (IBAction) titlePopUpChanged: (id) sender;
- (IBAction) chapterPopUpChanged: (id) sender;
-- (IBAction) formatPopUpChanged: (id) sender;
- (IBAction) autoSetM4vExtension: (id) sender;
- (IBAction) browseFile: (id) sender;
@@ -184,10 +179,6 @@
- (void)pictureSettingsDidChange;
- (IBAction) openMainWindow: (id) sender;
-/* Text summaries of various settings */
-- (NSString*) pictureSettingsSummary;
-- (NSString*) muxerOptionsSummary;
-
/* Add All titles to the queue */
- (IBAction) addAllTitlesToQueue: (id) sender;
- (void) addAllTitlesToQueueAlertDone: (NSWindow *) sheet
@@ -199,15 +190,13 @@
- (void) closeQueueFSEvent;
- (void) loadQueueFile;
- (void) reloadQueue;
-- (NSDictionary *)createQueueFileItem;
- (void)saveQueueFileItem;
- (void) incrementQueueItemDone:(NSInteger) queueItemDoneIndexNum;
- (void) performNewQueueScan:(NSString *) scanPath scanTitleNum: (NSInteger) scanTitleNum;
- (void) processNewQueueEncode;
- (void) clearQueueEncodedItems;
/* Queue Editing */
-- (IBAction)applyQueueSettingsToMainWindow:(id)sender;
-- (IBAction)rescanQueueItemToMainWindow:(NSString *) scanPath scanTitleNum: (NSUInteger) scanTitleNum selectedQueueItem: (NSUInteger) selectedQueueItem;
+- (IBAction)rescanQueueItemToMainWindow:(NSUInteger) selectedQueueItem;
- (void) removeQueueFileItem:(NSUInteger) queueItemToRemove;
@@ -227,7 +216,6 @@
- (IBAction) Rip: (id) sender;
- (void) overWriteAlertDone: (NSWindow *) sheet
returnCode: (int) returnCode contextInfo: (void *) contextInfo;
-- (void) doRip;
- (IBAction) Cancel: (id) sender;
- (void) doCancelCurrentJob;
@@ -244,9 +232,7 @@
- (IBAction) browseImportPresetFile: (id) sender;
/* Manage User presets */
-- (IBAction) customSettingUsed: (id) sender;
- (IBAction) showAddPresetPanel: (id) sender;
-
- (IBAction)selectDefaultPreset:(id)sender;
- (IBAction)addFactoryPresets:(id)sender;
diff --git a/macosx/Controller.m b/macosx/Controller.m
index 17055ff64..9aa015781 100644
--- a/macosx/Controller.m
+++ b/macosx/Controller.m
@@ -7,7 +7,6 @@
#import "Controller.h"
#import "HBOutputPanelController.h"
#import "HBPreferencesController.h"
-#import "HBDVDDetector.h"
#import "HBPresetsManager.h"
#import "HBPreset.h"
#import "HBPreviewController.h"
@@ -18,9 +17,7 @@
#import "HBAddPresetController.h"
#import "HBPicture+UIAdditions.h"
-
-#import "HBAudioDefaults.h"
-#import "HBSubtitlesDefaults.h"
+#import "HBFilters+UIAdditions.h"
#import "HBCore.h"
#import "HBJob.h"
@@ -30,9 +27,14 @@
@interface HBController () <HBPresetsViewControllerDelegate, HBPreviewControllerDelegate>
+@property (nonatomic, copy) NSString *browsedSourceDisplayName;
+
// The current job.
@property (nonatomic, retain) HBJob *job;
+// The job to be applied from the queue.
+@property (nonatomic, retain) HBJob *jobFromQueue;
+
// The current selected preset.
@property (nonatomic, retain) HBPreset *selectedPreset;
@property (nonatomic) BOOL customPreset;
@@ -124,13 +126,13 @@
[fPreviewController setCore:self.core];
- [fQueueController setHandle:self.queueCore.hb_handle];
+ [fQueueController setCore:self.queueCore];
[fQueueController setHBController:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(autoSetM4vExtension:) name:HBMixdownChangedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pictureSettingsDidChange) name:HBPictureChangedNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pictureSettingsDidChange) name:HBFiltersChangedNotification object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(formatPopUpChanged:) name:HBContainerChangedNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(formatChanged:) name:HBContainerChangedNotification object:nil];
}
return self;
@@ -296,13 +298,28 @@
{
if (self.core.state != HBStateScanning)
{
- [browsedSourceDisplayName release];
- browsedSourceDisplayName = [filePath.lastPathComponent retain];
-
+ self.browsedSourceDisplayName = filePath.lastPathComponent;
[self performScan:filePath scanTitleNum:0];
}
}
+- (void)setJob:(HBJob *)job
+{
+ // Set the jobs info to the view controllers
+ fPictureController.picture = job.picture;
+ fPictureController.filters = job.filters;
+ fPreviewController.job = job;
+
+ fVideoController.video = job.video;
+ fAudioController.job = job;
+ fSubtitlesViewController.job = job;
+ fChapterTitlesController.job = job;
+
+ // Retain the new job
+ [_job autorelease];
+ _job = [job retain];
+}
+
#pragma mark -
#pragma mark Multiple Instances
@@ -468,7 +485,6 @@
[self closeQueueFSEvent];
[currentQueueEncodeNameString release];
- [browsedSourceDisplayName release];
[outputPanel release];
[fQueueController release];
[fPreviewController release];
@@ -479,6 +495,7 @@
self.core = nil;
self.queueCore = nil;
+ self.browsedSourceDisplayName = nil;
[HBCore closeGlobal];
}
@@ -563,13 +580,6 @@
keyEquivalent:@""];
[menuItem setTag:container->format];
}
- // select the first container
- [fDstFormatPopUp selectItemAtIndex:0];
- [self formatPopUpChanged:nil];
-
- [fDstFile2Field setStringValue:[NSString
- stringWithFormat:@"%@/Desktop/Movie.mp4",
- NSHomeDirectory()]];
/* Bottom */
[fStatusField setStringValue: @""];
@@ -711,7 +721,7 @@
fScanIndicator.doubleValue = 0.0;
[HBUtilities writeToActivityLog:"ScanDone state received from fHandle"];
- [self showNewScan:nil];
+ [self showNewScan];
[[fWindow toolbar] validateVisibleItems];
}];
}
@@ -794,8 +804,9 @@
NSString *pass_desc;
if (p.job_cur == 1 && p.job_count > 1)
{
- if (QueueFileArray[currentQueueEncodeIndex][@"SubtitleList"] &&
- [[QueueFileArray[currentQueueEncodeIndex][@"SubtitleList"] firstObject][keySubTrackIndex] intValue] == -1)
+ HBJob *queueJob = QueueFileArray[currentQueueEncodeIndex];
+ if (queueJob.subtitlesTracks.count &&
+ [[queueJob.subtitlesTracks firstObject][keySubTrackIndex] intValue] == -1)
{
pass_desc = NSLocalizedString(@"(subtitle scan)", @"");
}
@@ -940,7 +951,8 @@
{
NSString *pathOfFinishedEncode;
// Get the output file name for the finished encode
- pathOfFinishedEncode = [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"DestinationPath"];
+ HBJob *finishedJob = QueueFileArray[currentQueueEncodeIndex];
+ pathOfFinishedEncode = finishedJob.destURL.path;
// Both the Growl Alert and Sending to tagger can be done as encodes roll off the queue
if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Growl Notification"] ||
@@ -1057,7 +1069,7 @@
if (action == @selector(Rip:))
{
[toolbarItem setImage: [NSImage imageNamed: @"encode"]];
- if (hb_count(self.core.hb_handle) > 0)
+ if (QueueFileArray.count > 0)
[toolbarItem setLabel: @"Start Queue"];
else
[toolbarItem setLabel: @"Start"];
@@ -1284,9 +1296,6 @@
{
if (result == NSOKButton)
{
- // Free display name allocated previously by this code
- [browsedSourceDisplayName release];
-
NSURL *scanURL = panel.URL;
// we set the last searched source directory in the prefs here
[[NSUserDefaults standardUserDefaults] setURL:scanURL.URLByDeletingLastPathComponent forKey:@"LastSourceDirectoryURL"];
@@ -1320,7 +1329,7 @@
// we set the source display name in the title selection dialogue
[fSrcDsplyNameTitleScan setStringValue:displayTitlescanSourceName];
// we set the attempted scans display name for main window to displayTitlescanSourceName
- browsedSourceDisplayName = [displayTitlescanSourceName retain];
+ self.browsedSourceDisplayName = displayTitlescanSourceName;
// We show the actual sheet where the user specifies the title to be scanned
// as we are going to do a title specific scan
@@ -1340,7 +1349,7 @@
{
[HBUtilities writeToActivityLog:"trying to open eyetv package"];
// We're looking at an EyeTV package - try to open its enclosed .mpg media file
- browsedSourceDisplayName = [url.URLByDeletingPathExtension.lastPathComponent retain];
+ self.browsedSourceDisplayName = url.URLByDeletingPathExtension.lastPathComponent;
NSString *mpgname;
NSUInteger n = [[[url path] stringByAppendingString: @"/"]
completePathIntoString: &mpgname caseSensitive: YES
@@ -1363,14 +1372,14 @@
else if ([[url pathExtension] isEqualToString: @"dvdmedia"])
{
/* path IS a package - but dvdmedia packages can be treaded like normal directories */
- browsedSourceDisplayName = [[[url URLByDeletingPathExtension] lastPathComponent] retain];
+ self.browsedSourceDisplayName = url.URLByDeletingPathExtension.lastPathComponent;
[HBUtilities writeToActivityLog:"trying to open dvdmedia package"];
[self performScan:[url path] scanTitleNum:0];
}
else
{
/* The package is not an eyetv package, try to open it anyway */
- browsedSourceDisplayName = [[url lastPathComponent] retain];
+ self.browsedSourceDisplayName = url.lastPathComponent;
[HBUtilities writeToActivityLog:"not a known to package"];
[self performScan:[url path] scanTitleNum:0];
}
@@ -1382,16 +1391,15 @@
{
[HBUtilities writeToActivityLog:"trying to open video_ts folder (video_ts folder chosen)"];
/* If VIDEO_TS Folder is chosen, choose its parent folder for the source display name*/
- browsedSourceDisplayName = [[[url URLByDeletingLastPathComponent] lastPathComponent] retain];
+ self.browsedSourceDisplayName = url.URLByDeletingLastPathComponent.lastPathComponent;
}
else
{
[HBUtilities writeToActivityLog:"trying to open video_ts folder (parent directory chosen)"];
/* if not the VIDEO_TS Folder, we can assume the chosen folder is the source name */
/* make sure we remove any path extension as this can also be an '.mpg' file */
- browsedSourceDisplayName = [[url lastPathComponent] retain];
+ self.browsedSourceDisplayName = url.lastPathComponent;
}
- applyQueueToScan = NO;
[self performScan:[url path] scanTitleNum:0];
}
}
@@ -1417,17 +1425,15 @@
if(sender == fScanSrcTitleOpenButton)
{
- /* We setup the scan status in the main window to indicate a source title scan */
+ // We setup the scan status in the main window to indicate a source title scan
[fSrcDVD2Field setStringValue: @"Opening a new source titleā€¦"];
[fScanIndicator setHidden: NO];
[fScanHorizontalLine setHidden: YES];
[fScanIndicator setIndeterminate: YES];
[fScanIndicator startAnimation: nil];
- /* We use the performScan method to actually perform the specified scan passing the path and the title
- * to be scanned
- */
- applyQueueToScan = NO;
+ // We use the performScan method to actually perform the specified scan passing the path and the title
+ // to be scanned
[self performScan:[fScanSrcTitlePathField stringValue] scanTitleNum:[fScanSrcTitleNumField intValue]];
}
}
@@ -1436,23 +1442,13 @@
- (void)performScan:(NSString *)scanPath scanTitleNum:(NSInteger)scanTitleNum
{
// Save the current settings
- if (self.job) {
+ if (self.job)
+ {
self.selectedPreset = [self createPresetFromCurrentSettings];
}
- // Notify anyone interested (audio/subtitles/chapters controller) that there's no title
- fPictureController.picture = nil;
- fPictureController.filters = nil;
- fPreviewController.job = nil;
-
- fAudioController.job = nil;
- fSubtitlesViewController.job = nil;
- fVideoController.video = nil;
- fChapterTitlesController.job = nil;
-
self.job = nil;
-
- [self enableUI: NO];
+ [self enableUI:NO];
NSError *outError = NULL;
NSURL *fileURL = [NSURL fileURLWithPath:scanPath];
@@ -1510,16 +1506,16 @@
}
}
-- (IBAction) showNewScan:(id)sender
+- (void)showNewScan
{
if (!self.core.titles.count)
{
// We display a message if a valid source was not chosen
- [fSrcDVD2Field setStringValue: @"No Valid Source Found"];
+ fSrcDVD2Field.stringValue = @"No Valid Source Found";
}
else
{
- if (applyQueueToScan == YES)
+ if (self.jobFromQueue)
{
// we are a rescan of an existing queue item and need to apply the queued settings to the scan
[HBUtilities writeToActivityLog: "showNewScan: This is a queued item rescan"];
@@ -1534,39 +1530,11 @@
for (HBTitle *title in self.core.titles)
{
// Set Source Name at top of window with the browsedSourceDisplayName grokked right before -performScan
- if (!browsedSourceDisplayName)
+ if (!self.browsedSourceDisplayName)
{
- browsedSourceDisplayName = @"NoNameDetected";
- }
- [fSrcDVD2Field setStringValue:browsedSourceDisplayName];
-
- // use the correct extension based on the container
- int videoContainer = (int)[[fDstFormatPopUp selectedItem] tag];
- const char *ext = hb_container_get_default_extension(videoContainer);
-
- // If its a queue rescan for edit, get the queue item output path
- // if not, its a new source scan.
- // Check to see if the last destination has been set,use if so, if not, use Desktop
- if (applyQueueToScan == YES)
- {
- [fDstFile2Field setStringValue: [NSString stringWithFormat:@"%@", QueueFileArray[fqueueEditRescanItemNum][@"DestinationPath"]]];
- }
- else if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
- {
- [fDstFile2Field setStringValue: [NSString stringWithFormat:
- @"%@/%@.%s", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[browsedSourceDisplayName stringByDeletingPathExtension],ext]];
- }
- else
- {
- [fDstFile2Field setStringValue: [NSString stringWithFormat:
- @"%@/Desktop/%@.%s", NSHomeDirectory(),[browsedSourceDisplayName stringByDeletingPathExtension],ext]];
- }
-
- // set m4v extension if necessary - do not override user-specified .mp4 extension
- if ((videoContainer & HB_MUX_MASK_MP4) && (applyQueueToScan != YES))
- {
- [self autoSetM4vExtension:sender];
+ self.browsedSourceDisplayName = @"NoNameDetected";
}
+ fSrcDVD2Field.stringValue = self.browsedSourceDisplayName;
[fSrcTitlePopUp addItemWithTitle:title.description];
@@ -1577,7 +1545,7 @@
}
}
- // Select the first item is nothing i selected
+ // Select the first item is nothing is selected
if (!fSrcTitlePopUp.selectedItem)
{
[fSrcTitlePopUp selectItemAtIndex:0];
@@ -1587,8 +1555,6 @@
[self enableUI:YES];
[self titlePopUpChanged:nil];
- [self encodeStartStopPopUpChanged:nil];
-
// Open preview window now if it was visible when HB was closed
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PreviewWindowIsOpen"])
[self showPreviewWindow:nil];
@@ -1597,11 +1563,12 @@
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PictureSizeWindowIsOpen"])
[self showPicturePanel:nil];
- if (applyQueueToScan == YES)
+ if (self.jobFromQueue)
{
- // we are a rescan of an existing queue item and need to apply the queued settings to the scan
- [HBUtilities writeToActivityLog: "showNewScan: calling applyQueueSettingsToMainWindow"];
- [self applyQueueSettingsToMainWindow:nil];
+ [fPresetsView deselect];
+ [self pictureSettingsDidChange];
+
+ self.jobFromQueue = nil;
}
}
}
@@ -1612,20 +1579,19 @@
- (IBAction)browseFile:(id)sender
{
// Open a panel to let the user choose and update the text field
- NSSavePanel * panel = [NSSavePanel savePanel];
+ NSSavePanel *panel = [NSSavePanel savePanel];
// We get the current file name and path from the destination field here
- NSString *destinationDirectory = fDstFile2Field.stringValue.stringByDeletingLastPathComponent;
- [panel setDirectoryURL:[NSURL fileURLWithPath:destinationDirectory]];
- [panel setNameFieldStringValue:[[fDstFile2Field stringValue] lastPathComponent]];
+ [panel setDirectoryURL:self.job.destURL.URLByDeletingLastPathComponent];
+ [panel setNameFieldStringValue:self.job.destURL.lastPathComponent];
[panel beginSheetModalForWindow:fWindow completionHandler:^(NSInteger result) {
if (result == NSFileHandlingPanelOKButton)
{
- fDstFile2Field.stringValue = panel.URL.path;
+ self.job.destURL = panel.URL;
// Save this path to the prefs so that on next browse destination window it opens there
- NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
+ NSString *destinationDirectory = [panel.URL.path stringByDeletingLastPathComponent];
[[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
}
}];
@@ -1663,8 +1629,16 @@ static void queueFSEventStreamCallback(
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
- HBController *hb = (HBController *)clientCallBackInfo;
- [hb reloadQueue];
+ if (numEvents >= 1)
+ {
+ // Reload the queue only if one of the following events happened.
+ FSEventStreamEventFlags flags = eventFlags[0];
+ if (flags & (kFSEventStreamEventFlagItemCreated | kFSEventStreamEventFlagItemRemoved | kFSEventStreamEventFlagItemRenamed | kFSEventStreamEventFlagItemModified))
+ {
+ HBController *hb = (HBController *)clientCallBackInfo;
+ [hb reloadQueue];
+ }
+ }
}
- (void)initQueueFSEvent
@@ -1691,7 +1665,7 @@ static void queueFSEventStreamCallback(
pathsToWatch,
kFSEventStreamEventIdSinceNow,
latency,
- kFSEventStreamCreateFlagIgnoreSelf
+ kFSEventStreamCreateFlagIgnoreSelf | kFSEventStreamCreateFlagMarkSelf
);
CFRelease(pathsToWatch);
@@ -1710,35 +1684,42 @@ static void queueFSEventStreamCallback(
- (void)loadQueueFile
{
- /* We declare the default NSFileManager into fileManager */
+ // We declare the default NSFileManager into fileManager
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *appSupportPath = [HBUtilities appSupportPath];
- /* We define the location of the user presets file */
- QueueFile = [[appSupportPath stringByAppendingPathComponent:@"Queue/Queue.plist"] retain];
+ // We define the location of the user presets file
+ QueueFile = [[appSupportPath stringByAppendingPathComponent:@"Queue/Queue.hbqueue"] retain];
- /* We check for the Queue.plist */
- if( ![fileManager fileExistsAtPath:QueueFile] )
+ // We check for the Queue.plist
+ if (![fileManager fileExistsAtPath:QueueFile])
{
- if( ![fileManager fileExistsAtPath:[appSupportPath stringByAppendingPathComponent:@"Queue"]] )
+ if (![fileManager fileExistsAtPath:[appSupportPath stringByAppendingPathComponent:@"Queue"]])
{
[fileManager createDirectoryAtPath:[appSupportPath stringByAppendingPathComponent:@"Queue"] withIntermediateDirectories:YES attributes:nil error:NULL];
}
-
[fileManager createFileAtPath:QueueFile contents:nil attributes:nil];
}
- QueueFileArray = [[NSMutableArray alloc] initWithContentsOfFile:QueueFile];
- /* lets check to see if there is anything in the queue file .plist */
- if( QueueFileArray == nil )
+ @try
+ {
+ QueueFileArray = [[NSKeyedUnarchiver unarchiveObjectWithFile:QueueFile] retain];
+ }
+ @catch (NSException *exception)
+ {
+ [HBUtilities writeToActivityLog:"failed to read the queue to disk"];
+ }
+
+ // lets check to see if there is anything in the queue file .plist
+ if (QueueFileArray == nil)
{
- /* if not, then lets initialize an empty array */
+ // if not, then lets initialize an empty array
QueueFileArray = [[NSMutableArray alloc] init];
}
else
{
- /* ONLY clear out encoded items if we are single instance */
- if( hbInstanceNum == 1 )
+ // ONLY clear out encoded items if we are single instance
+ if (hbInstanceNum == 1)
{
[self clearQueueEncodedItems];
}
@@ -1749,31 +1730,41 @@ static void queueFSEventStreamCallback(
{
[HBUtilities writeToActivityLog:"Queue reloaded"];
- NSMutableArray * tempQueueArray = [[NSMutableArray alloc] initWithContentsOfFile:QueueFile];
+ NSMutableArray *tempQueueArray = nil;;
+ @try
+ {
+ tempQueueArray = [NSKeyedUnarchiver unarchiveObjectWithFile:QueueFile];
+ }
+ @catch (NSException *exception)
+ {
+ tempQueueArray = nil;
+ [HBUtilities writeToActivityLog:"failed to read the queue to disk"];
+ }
+
[QueueFileArray setArray:tempQueueArray];
- [tempQueueArray release];
- /* Send Fresh QueueFileArray to fQueueController to update queue window */
- [fQueueController setQueueArray: QueueFileArray];
+ // Send Fresh QueueFileArray to fQueueController to update queue window
+ [fQueueController setQueueArray:QueueFileArray];
[self getQueueStats];
}
- (void)addQueueFileItem
{
- [QueueFileArray addObject:[self createQueueFileItem]];
+ [QueueFileArray addObject:[[self.job copy] autorelease]];
[self saveQueueFileItem];
-
}
-- (void) removeQueueFileItem:(NSUInteger) queueItemToRemove
+- (void)removeQueueFileItem:(NSUInteger)queueItemToRemove
{
[QueueFileArray removeObjectAtIndex:queueItemToRemove];
[self saveQueueFileItem];
-
}
- (void)saveQueueFileItem
{
- [QueueFileArray writeToFile:QueueFile atomically:YES];
+ if (![NSKeyedArchiver archiveRootObject:QueueFileArray toFile:QueueFile])
+ {
+ [HBUtilities writeToActivityLog:"failed to write the queue to disk"];
+ }
[fQueueController setQueueArray: QueueFileArray];
[self getQueueStats];
}
@@ -1783,39 +1774,30 @@ static void queueFSEventStreamCallback(
*/
- (void)getQueueStats
{
- /* lets get the stats on the status of the queue array */
-
+ // lets get the stats on the status of the queue array
fPendingCount = 0;
fWorkingCount = 0;
- /* We use a number system to set the encode status of the queue item
- * in controller.mm
- * 0 == already encoded
- * 1 == is being encoded
- * 2 == is yet to be encoded
- * 3 == cancelled
- */
-
int i = 0;
- for (NSDictionary *thisQueueDict in QueueFileArray)
+ for (HBJob *job in QueueFileArray)
{
- if ([[thisQueueDict objectForKey:@"Status"] intValue] == 1) // being encoded
+ if (job.state == HBJobStateWorking) // being encoded
{
fWorkingCount++;
- /* check to see if we are the instance doing this encoding */
- if ([thisQueueDict objectForKey:@"EncodingPID"] && [[thisQueueDict objectForKey:@"EncodingPID"] intValue] == pidNum)
+ // check to see if we are the instance doing this encoding
+ if (job.pidId == pidNum)
{
currentQueueEncodeIndex = i;
}
}
- if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2) // pending
+ if (job.state == HBJobStateReady) // pending
{
fPendingCount++;
}
i++;
}
- /* Set the queue status field in the main window */
+ // Set the queue status field in the main window
NSString *string;
if (fPendingCount == 0)
{
@@ -1833,63 +1815,58 @@ static void queueFSEventStreamCallback(
[fQueueStatus setStringValue:string];
}
-/* Used to get the next pending queue item index and return it if found */
+/**
+ * Used to get the next pending queue item index and return it if found
+ */
- (NSInteger)getNextPendingQueueIndex
{
- /* initialize nextPendingIndex to -1, this value tells incrementQueueItemDone that there are no pending items in the queue */
+ // initialize nextPendingIndex to -1, this value tells incrementQueueItemDone that there are no pending items in the queue
NSInteger nextPendingIndex = -1;
BOOL nextPendingFound = NO;
- for (id tempObject in QueueFileArray)
+ for (HBJob *job in QueueFileArray)
{
- NSDictionary *thisQueueDict = tempObject;
- if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2 && nextPendingFound == NO) // pending
+ if (job.state == HBJobStateReady && nextPendingFound == NO) // pending
{
nextPendingFound = YES;
- nextPendingIndex = [QueueFileArray indexOfObject: tempObject];
+ nextPendingIndex = [QueueFileArray indexOfObject:job];
[HBUtilities writeToActivityLog: "getNextPendingQueueIndex next pending encode index is:%d", nextPendingIndex];
}
}
return nextPendingIndex;
}
-/* This method will set any item marked as encoding back to pending
+/**
+ * This method will set any item marked as encoding back to pending
* currently used right after a queue reload
*/
- (void) setQueueEncodingItemsAsPending
{
- NSMutableArray *tempArray;
- tempArray = [NSMutableArray array];
- /* we look here to see if the preset is we move on to the next one */
- for (id tempObject in QueueFileArray)
+ for (HBJob *job in QueueFileArray)
{
- /* We want to keep any queue item that is pending or was previously being encoded */
- if ([[tempObject objectForKey:@"Status"] intValue] == 1 || [[tempObject objectForKey:@"Status"] intValue] == 2)
+ // We want to keep any queue item that is pending or was previously being encoded
+ if (job.state == HBJobStateWorking || job.state == HBJobStateReady)
{
- /* If the queue item is marked as "encoding" (1)
- * then change its status back to pending (2) which effectively
- * puts it back into the queue to be encoded
- */
- if ([[tempObject objectForKey:@"Status"] intValue] == 1)
+ // If the queue item is marked as "working"
+ // then change its status back to ready which effectively
+ // puts it back into the queue to be encoded
+ if (job.state == HBJobStateWorking)
{
- [tempObject setObject:[NSNumber numberWithInt: 2] forKey:@"Status"];
+ job.state = HBJobStateReady;
}
- [tempArray addObject:tempObject];
}
}
-
- [QueueFileArray setArray:tempArray];
+
[self saveQueueFileItem];
}
-
-/* This method will clear the queue of any encodes that are not still pending
- * this includes both successfully completed encodes as well as cancelled encodes */
+/**
+ * This method will clear the queue of any encodes that are not still pending
+ * this includes both successfully completed encodes as well as cancelled encodes
+ */
- (void) clearQueueEncodedItems
{
- NSMutableArray *tempArray;
- tempArray = [NSMutableArray array];
- /* we look here to see if the preset is we move on to the next one */
- for (id tempObject in QueueFileArray)
+ NSMutableArray *tempArray = [NSMutableArray array];
+ for (HBJob *job in QueueFileArray)
{
/* If the queue item is either completed (0) or cancelled (3) from the
* last session, then we put it in tempArray to be deleted from QueueFileArray.
@@ -1898,9 +1875,9 @@ static void queueFSEventStreamCallback(
* from a previous session, we can conlude that HB was either shutdown, or crashed
* during the encodes so we keep it and tell the user in the "Load Queue Alert"
*/
- if ([[tempObject objectForKey:@"Status"] intValue] == 0 || [[tempObject objectForKey:@"Status"] intValue] == 3)
+ if (job.state == HBJobStateCompleted || job.state == HBJobStateCanceled)
{
- [tempArray addObject:tempObject];
+ [tempArray addObject:job];
}
}
@@ -1908,178 +1885,30 @@ static void queueFSEventStreamCallback(
[self saveQueueFileItem];
}
-/* This method will clear the queue of all encodes. effectively creating an empty queue */
+/**
+ * This method will clear the queue of all encodes. effectively creating an empty queue
+ */
- (void) clearQueueAllItems
{
- NSMutableArray *tempArray;
- tempArray = [NSMutableArray array];
- /* we look here to see if the preset is we move on to the next one */
- for (id tempObject in QueueFileArray)
+ NSMutableArray *tempArray = [NSMutableArray array];
+ // we look here to see if the preset is we move on to the next one
+ for (HBJob *job in QueueFileArray)
{
- [tempArray addObject:tempObject];
+ [tempArray addObject:job];
}
[QueueFileArray removeObjectsInArray:tempArray];
[self saveQueueFileItem];
}
-/* This method will duplicate prepareJob however into the
- * queue .plist instead of into the job structure so it can
- * be recalled later */
-- (NSDictionary *)createQueueFileItem
-{
- NSMutableDictionary *queueFileJob = [[NSMutableDictionary alloc] init];
-
- hb_title_t *title = self.job.title.hb_title;
-
- /* We use a number system to set the encode status of the queue item
- * 0 == already encoded
- * 1 == is being encoded
- * 2 == is yet to be encoded
- * 3 == cancelled
- */
- [queueFileJob setObject:[NSNumber numberWithInt:2] forKey:@"Status"];
- /* Source and Destination Information */
-
- [queueFileJob setObject:[NSString stringWithUTF8String: title->path] forKey:@"SourcePath"];
- [queueFileJob setObject:[[fSrcDVD2Field stringValue] lastPathComponent] forKey:@"SourceName"];
- [queueFileJob setObject:[NSNumber numberWithInt:title->index] forKey:@"TitleNumber"];
- [queueFileJob setObject:[NSNumber numberWithInteger:[fSrcAnglePopUp indexOfSelectedItem] + 1] forKey:@"TitleAngle"];
-
- /* Determine and set a variable to tell hb what start and stop times to use (chapters, seconds or frames) */
- if( [fEncodeStartStopPopUp indexOfSelectedItem] == 0 )
- {
- [queueFileJob setObject:[NSNumber numberWithInt:0] forKey:@"fEncodeStartStop"];
- }
- else if ([fEncodeStartStopPopUp indexOfSelectedItem] == 1)
- {
- [queueFileJob setObject:[NSNumber numberWithInt:1] forKey:@"fEncodeStartStop"];
- }
- else if ([fEncodeStartStopPopUp indexOfSelectedItem] == 2)
- {
- [queueFileJob setObject:[NSNumber numberWithInt:2] forKey:@"fEncodeStartStop"];
- }
- /* Chapter encode info */
- [queueFileJob setObject:[NSNumber numberWithInteger:[fSrcChapterStartPopUp indexOfSelectedItem] + 1] forKey:@"ChapterStart"];
- [queueFileJob setObject:[NSNumber numberWithInteger:[fSrcChapterEndPopUp indexOfSelectedItem] + 1] forKey:@"ChapterEnd"];
- /* Time (pts) encode info */
- [queueFileJob setObject:[NSNumber numberWithInt:[fSrcTimeStartEncodingField intValue]] forKey:@"StartSeconds"];
- [queueFileJob setObject:[NSNumber numberWithInt:[fSrcTimeEndEncodingField intValue] - [fSrcTimeStartEncodingField intValue]] forKey:@"StopSeconds"];
- /* Frame number encode info */
- [queueFileJob setObject:[NSNumber numberWithInt:[fSrcFrameStartEncodingField intValue]] forKey:@"StartFrame"];
- [queueFileJob setObject:[NSNumber numberWithInt:[fSrcFrameEndEncodingField intValue] - [fSrcFrameStartEncodingField intValue]] forKey:@"StopFrame"];
-
-
- /* The number of seek points equals the number of seconds announced in the title as that is our current granularity */
- int title_duration_seconds = (title->hours * 3600) + (title->minutes * 60) + (title->seconds);
- [queueFileJob setObject:[NSNumber numberWithInt:title_duration_seconds] forKey:@"SourceTotalSeconds"];
-
- [queueFileJob setObject:[fDstFile2Field stringValue] forKey:@"DestinationPath"];
-
- /* Lets get the preset info if there is any */
- [queueFileJob setObject:[fPresetSelectedDisplay stringValue] forKey:@"PresetName"];
-
- [queueFileJob setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
- /* Chapter Markers*/
- /* If we are encoding by chapters and we have only one chapter or a title without chapters, set chapter markers to off.
- Leave them on if we're doing point to point encoding, as libhb supports chapters when doing p2p. */
- if ([fEncodeStartStopPopUp indexOfSelectedItem] == 0 &&
- [fSrcChapterStartPopUp indexOfSelectedItem] == [fSrcChapterEndPopUp indexOfSelectedItem])
- {
- [queueFileJob setObject:[NSNumber numberWithInt:0] forKey:@"ChapterMarkers"];
- }
- else
- {
- [queueFileJob setObject:@(self.job.chaptersEnabled) forKey:@"ChapterMarkers"];
- }
-
- /* We need to get the list of chapter names to put into an array and store
- * in our queue, so they can be reapplied in prepareJob when this queue
- * item comes up if Chapter Markers is set to on.
- */
- [queueFileJob setObject:[[self.job.chapterTitles copy] autorelease] forKey:@"ChapterNames"];
-
- /* Mux mp4 with http optimization */
- [queueFileJob setObject:[NSNumber numberWithInteger:[fDstMp4HttpOptFileCheck state]] forKey:@"Mp4HttpOptimize"];
- /* Add iPod uuid atom */
- [queueFileJob setObject:[NSNumber numberWithInteger:[fDstMp4iPodFileCheck state]] forKey:@"Mp4iPodCompatible"];
-
- /* Codecs */
- /* Video encoder */
- [self.job.video prepareVideoForQueueFileJob:queueFileJob];
-
- /* Picture Sizing */
- [self.job.picture preparePictureForQueueFileJob:queueFileJob];
-
- /* Text summaries of various settings */
- [queueFileJob setObject:[NSString stringWithString:[self pictureSettingsSummary]]
- forKey:@"PictureSettingsSummary"];
- [queueFileJob setObject:self.job.filters.summary
- forKey:@"PictureFiltersSummary"];
- [queueFileJob setObject:[NSString stringWithString:[self muxerOptionsSummary]]
- forKey:@"MuxerOptionsSummary"];
-
- /* Picture Filters */
- HBFilters *filters = self.job.filters;
- queueFileJob[@"PictureDetelecine"] = @(filters.detelecine);
- queueFileJob[@"PictureDetelecineCustom"] = filters.detelecineCustomString;
-
- queueFileJob[@"PictureDecombDeinterlace"] = @(filters.useDecomb);
- queueFileJob[@"PictureDecomb"] = @(filters.decomb);
- queueFileJob[@"PictureDecombCustom"] = filters.decombCustomString;
-
- queueFileJob[@"PictureDeinterlace"] = @(filters.deinterlace);
- queueFileJob[@"PictureDeinterlaceCustom"] = filters.deinterlaceCustomString;
-
- queueFileJob[@"PictureDenoise"] = filters.denoise;
- queueFileJob[@"PictureDenoisePreset"] = filters.denoisePreset;
- queueFileJob[@"PictureDenoiseTune"] = filters.denoiseTune;
- queueFileJob[@"PictureDenoiseCustom"] = filters.denoiseCustomString;
-
- queueFileJob[@"PictureDeblock"] = [NSString stringWithFormat:@"%ld",(long)filters.deblock];
- queueFileJob[@"VideoGrayScale"] = [NSString stringWithFormat:@"%ld",(long)filters.grayscale];
-
- /* Audio Defaults */
- NSMutableDictionary *audioDefaults = [NSMutableDictionary dictionary];
- [self.job.audioDefaults prepareAudioDefaultsForPreset:audioDefaults];
- queueFileJob[@"AudioDefaults"] = audioDefaults;
-
- /* Audio */
- NSMutableArray *audioArray = [[NSMutableArray alloc] initWithArray:[fAudioController audioTracks] copyItems:YES];
- [queueFileJob setObject:audioArray forKey:@"AudioList"];
- [audioArray release];
-
- /* Subtitles Defaults */
- NSMutableDictionary *subtitlesDefaults = [NSMutableDictionary dictionary];
- [self.job.subtitlesDefaults prepareSubtitlesDefaultsForPreset:subtitlesDefaults];
- queueFileJob[@"SubtitlesDefaults"] = subtitlesDefaults;
-
- /* Subtitles */
- NSMutableArray *subtitlesArray = [[NSMutableArray alloc] initWithArray:[fSubtitlesViewController subtitles] copyItems:YES];
- [queueFileJob setObject:subtitlesArray forKey:@"SubtitleList"];
- [subtitlesArray release];
-
- /* Now we go ahead and set the "job->values in the plist for passing right to fQueueEncodeLibhb */
- [queueFileJob setObject:[NSNumber numberWithInteger:[[fDstFormatPopUp selectedItem] tag]] forKey:@"JobFileFormatMux"];
-
- /* Codecs */
- /* Framerate */
- [queueFileJob setObject:[NSNumber numberWithInt:title->vrate.num] forKey:@"JobVrate"];
- [queueFileJob setObject:[NSNumber numberWithInt:title->vrate.den] forKey:@"JobVrateBase"];
-
- /* we need to auto relase the queueFileJob and return it */
- [queueFileJob autorelease];
- return queueFileJob;
-
-}
-
-/* this is actually called from the queue controller to modify the queue array and return it back to the queue controller */
+/**
+ * this is actually called from the queue controller to modify the queue array and return it back to the queue controller
+ */
- (void)moveObjectsInQueueArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex
{
NSUInteger index = [indexSet lastIndex];
NSUInteger aboveInsertIndexCount = 0;
-
-
+
NSUInteger removeIndex;
if (index >= insertIndex)
@@ -2098,22 +1927,22 @@ static void queueFSEventStreamCallback(
[QueueFileArray insertObject:object atIndex:insertIndex];
[object release];
- /* We save all of the Queue data here
- * and it also gets sent back to the queue controller*/
+ // We save all of the Queue data here
+ // and it also gets sent back to the queue controller
[self saveQueueFileItem];
}
-
#pragma mark -
#pragma mark Queue Job Processing
-- (void) incrementQueueItemDone:(NSInteger) queueItemDoneIndexNum
+- (void)incrementQueueItemDone:(NSInteger)queueItemDoneIndexNum
{
- /* Mark the encode just finished as done (status 0)*/
- [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:0] forKey:@"Status"];
-
- /* We save all of the Queue data here */
+ // Mark the encode just finished as done (status 0)
+ HBJob *queueJob = QueueFileArray[currentQueueEncodeIndex];
+ queueJob.state = HBJobStateCompleted;
+
+ // We save all of the Queue data here
[self saveQueueFileItem];
/* Since we have now marked a queue item as done
@@ -2126,790 +1955,103 @@ static void queueFSEventStreamCallback(
/* If we still have more pending items in our queue, lets go to the next one */
if (newQueueItemIndex >= 0 && newQueueItemIndex < queueItems)
{
- /*Set our currentQueueEncodeIndex now to the newly found Pending encode as we own it */
+ // Set our currentQueueEncodeIndex now to the newly found Pending encode as we own it
currentQueueEncodeIndex = newQueueItemIndex;
- /* now we mark the queue item as Status = 1 ( being encoded ) so another instance can not come along and try to scan it while we are scanning */
- [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:1] forKey:@"Status"];
+ // now we mark the queue item as Status = 1 ( being encoded ) so another instance can not come along and try to scan it while we are scanning
+ queueJob = QueueFileArray[currentQueueEncodeIndex];
+ queueJob.state = HBJobStateWorking;
[HBUtilities writeToActivityLog: "incrementQueueItemDone new pending items found: %d", currentQueueEncodeIndex];
[self saveQueueFileItem];
- /* now we can go ahead and scan the new pending queue item */
- [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]];
-
+ queueJob = QueueFileArray[currentQueueEncodeIndex];
+ // now we can go ahead and scan the new pending queue item
+ [self performNewQueueScan:queueJob.fileURL.path scanTitleNum:queueJob.titleIdx];
}
else
{
[HBUtilities writeToActivityLog: "incrementQueueItemDone there are no more pending encodes"];
- /* Done encoding, allow system sleep for the encode handle */
- /*
- * Since there are no more items to encode, go to queueCompletedAlerts
- * for user specified alerts after queue completed
- */
+ // Since there are no more items to encode, go to queueCompletedAlerts
+ // for user specified alerts after queue completed
[self queueCompletedAlerts];
}
}
-/* Here we actually tell hb_scan to perform the source scan, using the path to source and title number*/
+/**
+ * Here we actually tell hb_scan to perform the source scan, using the path to source and title number
+ */
- (void) performNewQueueScan:(NSString *) scanPath scanTitleNum: (NSInteger) scanTitleNum
{
- /* Tell HB to output a new activity log file for this encode */
- [outputPanel startEncodeLog:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"DestinationPath"]];
-
- /* We now flag the queue item as being owned by this instance of HB using the PID */
- [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:pidNum] forKey:@"EncodingPID"];
- /* Get the currentQueueEncodeNameString from the queue item to display in the status field */
- currentQueueEncodeNameString = [[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"DestinationPath"] lastPathComponent]retain];
- /* We save all of the Queue data here */
+ HBJob *queueJob = QueueFileArray[currentQueueEncodeIndex];
+ // Tell HB to output a new activity log file for this encode
+ [outputPanel startEncodeLog:[queueJob.destURL.path stringByDeletingLastPathComponent]];
+
+ // We now flag the queue item as being owned by this instance of HB using the PID
+ queueJob.pidId = pidNum;
+ // Get the currentQueueEncodeNameString from the queue item to display in the status field */
+ currentQueueEncodeNameString = [[queueJob.destURL.path lastPathComponent]retain];
+ // We save all of the Queue data here
[self saveQueueFileItem];
- /*
- * Only scan 10 previews before an encode - additional previews are
- * only useful for autocrop and static previews, which are already taken
- * care of at this point
- */
+ // Only scan 10 previews before an encode - additional previews are
+ // only useful for autocrop and static previews, which are already taken care of at this point
NSURL *fileURL = [NSURL fileURLWithPath:scanPath];
[self.queueCore scan:fileURL titleNum:scanTitleNum previewsNum:10 minTitleDuration:0];
}
-/* This assumes that we have re-scanned and loaded up a new queue item to send to libhb as fQueueEncodeLibhb */
-- (void) processNewQueueEncode
+/**
+ * This assumes that we have re-scanned and loaded up a new queue item to send to libhb as fQueueEncodeLibhb
+ */
+- (void)processNewQueueEncode
{
- hb_list_t * list = hb_get_titles( self.queueCore.hb_handle );
- hb_title_t * title = (hb_title_t *) hb_list_item( list,0 ); // is always zero since now its a single title scan
- hb_job_t * job = hb_job_init(title);
-
- if( !hb_list_count( list ) )
- {
- [HBUtilities writeToActivityLog: "processNewQueueEncode WARNING nothing found in the title list"];
- }
-
- NSMutableDictionary * queueToApply = [QueueFileArray objectAtIndex:currentQueueEncodeIndex];
- [HBUtilities writeToActivityLog: "Preset: %s", [[queueToApply objectForKey:@"PresetName"] UTF8String]];
- [HBUtilities writeToActivityLog: "processNewQueueEncode number of passes expected is: %d", ([[queueToApply objectForKey:@"VideoTwoPass"] intValue] + 1)];
- hb_job_set_file(job, [[queueToApply objectForKey:@"DestinationPath"] UTF8String]);
- [self prepareJob:job];
-
- /*
- * If scanning we need to do some extra setup of the job.
- */
- if (job->indepth_scan == 1)
- {
- char *encoder_preset_tmp = job->encoder_preset != NULL ? strdup(job->encoder_preset) : NULL;
- char *encoder_tune_tmp = job->encoder_tune != NULL ? strdup(job->encoder_tune) : NULL;
- char *encoder_options_tmp = job->encoder_options != NULL ? strdup(job->encoder_options) : NULL;
- char *encoder_profile_tmp = job->encoder_profile != NULL ? strdup(job->encoder_profile) : NULL;
- char *encoder_level_tmp = job->encoder_level != NULL ? strdup(job->encoder_level) : NULL;
- /*
- * When subtitle scan is enabled do a fast pre-scan job
- * which will determine which subtitles to enable, if any.
- */
- hb_job_set_encoder_preset (job, NULL);
- hb_job_set_encoder_tune (job, NULL);
- hb_job_set_encoder_options(job, NULL);
- hb_job_set_encoder_profile(job, NULL);
- hb_job_set_encoder_level (job, NULL);
- job->pass = -1;
- hb_add(self.queueCore.hb_handle, job);
- /*
- * reset the advanced settings
- */
- hb_job_set_encoder_preset (job, encoder_preset_tmp);
- hb_job_set_encoder_tune (job, encoder_tune_tmp);
- hb_job_set_encoder_options(job, encoder_options_tmp);
- hb_job_set_encoder_profile(job, encoder_profile_tmp);
- hb_job_set_encoder_level (job, encoder_level_tmp);
- free(encoder_preset_tmp);
- free(encoder_tune_tmp);
- free(encoder_options_tmp);
- free(encoder_profile_tmp);
- free(encoder_level_tmp);
- }
+ HBJob *queueJob = QueueFileArray[currentQueueEncodeIndex];
-
- if ([[queueToApply objectForKey:@"VideoTwoPass"] intValue] == 1)
+ if (self.queueCore.titles.count)
{
- job->indepth_scan = 0;
- job->pass = 1;
- hb_add(self.queueCore.hb_handle, job);
- job->pass = 2;
- hb_add(self.queueCore.hb_handle, job);
-
+ // Reset the title in the job.
+ queueJob.title = self.queueCore.titles[0];
+
+ // We should be all setup so let 'er rip
+ [self.queueCore encodeJob:queueJob];
+ fEncodeState = 1;
+
+ // Lets mark our new encode as 1 or "Encoding"
+ queueJob.state = HBJobStateWorking;
+ [self saveQueueFileItem];
}
else
{
- job->indepth_scan = 0;
- job->pass = 0;
- hb_add(self.queueCore.hb_handle, job);
+ [HBUtilities writeToActivityLog: "processNewQueueEncode WARNING nothing found in the title list"];
}
-
- NSString *destinationDirectory = [[queueToApply objectForKey:@"DestinationPath"] stringByDeletingLastPathComponent];
- [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
- /* Lets mark our new encode as 1 or "Encoding" */
- [queueToApply setObject:[NSNumber numberWithInt:1] forKey:@"Status"];
- [self saveQueueFileItem];
-
- /* libhb makes a copy of the job. So we need to free any resource
- * that were allocated in construction of the job. This empties
- * the audio, subtitle, and filter lists */
- hb_job_close(&job);
-
- /* We should be all setup so let 'er rip */
- [self doRip];
}
#pragma mark -
#pragma mark Queue Item Editing
/* Rescans the chosen queue item back into the main window */
-- (void)rescanQueueItemToMainWindow:(NSString *) scanPath scanTitleNum: (NSUInteger) scanTitleNum selectedQueueItem: (NSUInteger) selectedQueueItem
-{
- fqueueEditRescanItemNum = selectedQueueItem;
- [HBUtilities writeToActivityLog: "rescanQueueItemToMainWindow: Re-scanning queue item at index:%d",fqueueEditRescanItemNum];
- applyQueueToScan = YES;
- /* Make sure we release the display name before reassigning it */
- [browsedSourceDisplayName release];
- /* Set the browsedSourceDisplayName for showNewScan */
- browsedSourceDisplayName = [[[QueueFileArray objectAtIndex:fqueueEditRescanItemNum] objectForKey:@"SourceName"] retain];
- [self performScan:scanPath scanTitleNum:scanTitleNum];
-}
-
-
-/* We use this method after a queue item rescan for edit.
- * it largely mirrors -selectPreset in terms of structure.
- * Assumes that a queue item has been reloaded into the main window.
- */
-- (IBAction)applyQueueSettingsToMainWindow:(id)sender
+- (void)rescanQueueItemToMainWindow:(NSUInteger)selectedQueueItem
{
- NSDictionary *queueToApply = [QueueFileArray objectAtIndex:fqueueEditRescanItemNum];
-
- if (queueToApply)
- {
- [HBUtilities writeToActivityLog: "applyQueueSettingsToMainWindow: queue item found"];
- }
- /* Set title number and chapters */
- /* since the queue only scans a single title, its already been selected in showNewScan
- so do not try to reset it here. However if we do decide to do full source scans on
- a queue edit rescan, we would need it. So leaving in for now but commenting out. */
- self.job.range.chapterStart = [[queueToApply objectForKey:@"ChapterStart"] intValue] - 1;
- self.job.range.chapterStop = [[queueToApply objectForKey:@"ChapterEnd"] intValue] - 1;
-
- /* File Format */
- [fDstFormatPopUp selectItemWithTag:[queueToApply[@"JobFileFormatMux"] integerValue]];
- [self formatPopUpChanged:nil];
-
- /* Chapter Markers*/
- self.job.chaptersEnabled = [[queueToApply objectForKey:@"ChapterMarkers"] boolValue];
- [fChapterTitlesController addChaptersFromQueue:[queueToApply objectForKey:@"ChapterNames"]];
-
- /* Mux mp4 with http optimization */
- [fDstMp4HttpOptFileCheck setState:[[queueToApply objectForKey:@"Mp4HttpOptimize"] intValue]];
-
- /* Set the state of ipod compatible with Mp4iPodCompatible. Only for x264*/
- [fDstMp4iPodFileCheck setState:[[queueToApply objectForKey:@"Mp4iPodCompatible"] intValue]];
-
- /* video encoder */
- [self.job.video applyVideoSettingsFromQueue:queueToApply];
-
- /* Audio Defaults */
- [self.job.audioDefaults applySettingsFromPreset:queueToApply[@"AudioDefaults"]];
-
- /* Audio */
- /* Now lets add our new tracks to the audio list here */
- [fAudioController addTracksFromQueue:[queueToApply objectForKey:@"AudioList"]];
-
- /* Subtitles Defaults */
- [self.job.subtitlesDefaults applySettingsFromPreset:queueToApply[@"SubtitlesDefaults"]];
-
- /* Subtitles */
- [fSubtitlesViewController addTracksFromQueue:[queueToApply objectForKey:@"SubtitleList"]];
-
- /* Picture Settings */
- [self.job.picture applyPictureSettingsFromQueue:queueToApply];
-
- /* Filters */
- HBFilters *filters = self.job.filters;
-
- /* We only allow *either* Decomb or Deinterlace. So check for the PictureDecombDeinterlace key. */
- filters.useDecomb = YES;
- filters.decomb = 0;
- filters.deinterlace = 0;
- if ([queueToApply[@"PictureDecombDeinterlace"] intValue] == 1)
- {
- /* we are using decomb */
- /* Decomb */
- if ([queueToApply[@"PictureDecomb"] intValue] > 0)
- {
- filters.decomb = [queueToApply[@"PictureDecomb"] intValue];
-
- /* if we are using "Custom" in the decomb setting, also set the custom string*/
- if ([queueToApply[@"PictureDecomb"] intValue] == 1)
- {
- filters.decombCustomString = queueToApply[@"PictureDecombCustom"];
- }
- }
- }
- else
- {
- /* We are using Deinterlace */
- /* Deinterlace */
- if ([queueToApply[@"PictureDeinterlace"] intValue] > 0)
- {
- filters.useDecomb = NO;
- filters.deinterlace = [queueToApply[@"PictureDeinterlace"] intValue];
- /* if we are using "Custom" in the deinterlace setting, also set the custom string*/
- if ([queueToApply[@"PictureDeinterlace"] intValue] == 1)
- {
- filters.deinterlaceCustomString = queueToApply[@"PictureDeinterlaceCustom"];
- }
- }
- }
-
- /* Detelecine */
- if ([queueToApply[@"PictureDetelecine"] intValue] > 0)
- {
- filters.detelecine = [queueToApply[@"PictureDetelecine"] intValue];
- /* if we are using "Custom" in the detelecine setting, also set the custom string*/
- if ([queueToApply[@"PictureDetelecine"] intValue] == 1)
- {
- filters.detelecineCustomString = queueToApply[@"PictureDetelecineCustom"];
- }
- }
- else
- {
- filters.detelecine = 0;
- }
-
- /* Denoise */
- filters.denoise = queueToApply[@"PictureDenoise"];
- filters.denoisePreset = queueToApply[@"PictureDenoisePreset"];
- filters.denoiseTune = queueToApply[@"PictureDenoiseTune"];
- filters.denoiseCustomString = queueToApply[@"PictureDenoiseCustom"];
+ [HBUtilities writeToActivityLog:"rescanQueueItemToMainWindow: Re-scanning queue item at index:%d", selectedQueueItem];
- /* Deblock */
- if ([queueToApply[@"PictureDeblock"] intValue] == 1)
- {
- /* if its a one, then its the old on/off deblock, set on to 5*/
- filters.deblock = 5;
- }
- else
- {
- /* use the settings intValue */
- filters.deblock = [queueToApply[@"PictureDeblock"] intValue];
- }
-
- filters.grayscale = [queueToApply[@"VideoGrayScale"] boolValue];
+ // Set the browsedSourceDisplayName for showNewScan
+ self.jobFromQueue = QueueFileArray[selectedQueueItem];
+ self.browsedSourceDisplayName = self.jobFromQueue.fileURL.lastPathComponent;
- // Updates the previews window and summary strings
- [self pictureSettingsDidChange];
-
- [fPresetSelectedDisplay setStringValue:queueToApply[@"PresetName"]];
- [fPresetsView deselect];
+ [self performScan:self.jobFromQueue.fileURL.path scanTitleNum:self.jobFromQueue.titleIdx];
- /* Now that source is loaded and settings applied, delete the queue item from the queue */
- [HBUtilities writeToActivityLog: "applyQueueSettingsToMainWindow: deleting queue item:%d",fqueueEditRescanItemNum];
- [self removeQueueFileItem:fqueueEditRescanItemNum];
+ // Now that source is loaded and settings applied, delete the queue item from the queue
+ [HBUtilities writeToActivityLog: "applyQueueSettingsToMainWindow: deleting queue item:%d", selectedQueueItem];
+ [self removeQueueFileItem:selectedQueueItem];
}
#pragma mark -
#pragma mark Job Handling
-- (void) prepareJob:(hb_job_t *)job
-{
- NSDictionary * queueToApply = [QueueFileArray objectAtIndex:currentQueueEncodeIndex];
-
- hb_list_t * list = hb_get_titles(self.queueCore.hb_handle);
- hb_title_t * title = (hb_title_t *) hb_list_item( list,0 ); // is always zero since now its a single title scan
-
- hb_audio_config_t * audio;
- hb_filter_object_t * filter;
- /* Title Angle for dvdnav */
- job->angle = [[queueToApply objectForKey:@"TitleAngle"] intValue];
-
- if([[queueToApply objectForKey:@"fEncodeStartStop"] intValue] == 0)
- {
- /* Chapter selection */
- [HBUtilities writeToActivityLog: "Start / Stop set to chapters"];
- job->chapter_start = [[queueToApply objectForKey:@"ChapterStart"] intValue];
- job->chapter_end = [[queueToApply objectForKey:@"ChapterEnd"] intValue];
- }
- else if ([[queueToApply objectForKey:@"fEncodeStartStop"] intValue] == 1)
- {
- /* we are pts based start / stop */
- [HBUtilities writeToActivityLog: "Start / Stop set to secondsā€¦"];
-
- /* Point A to Point B. Time to time in seconds.*/
- /* get the start seconds from the start seconds field */
- int start_seconds = [[queueToApply objectForKey:@"StartSeconds"] intValue];
- job->pts_to_start = start_seconds * 90000LL;
- /* Stop seconds is actually the duration of encode, so subtract the end seconds from the start seconds */
- int stop_seconds = [[queueToApply objectForKey:@"StopSeconds"] intValue];
- job->pts_to_stop = stop_seconds * 90000LL;
-
- }
- else if ([[queueToApply objectForKey:@"fEncodeStartStop"] intValue] == 2)
- {
- /* we are frame based start / stop */
- [HBUtilities writeToActivityLog: "Start / Stop set to framesā€¦"];
-
- /* Point A to Point B. Frame to frame */
- /* get the start frame from the start frame field */
- int start_frame = [[queueToApply objectForKey:@"StartFrame"] intValue];
- job->frame_to_start = start_frame;
- /* get the frame to stop on from the end frame field */
- int stop_frame = [[queueToApply objectForKey:@"StopFrame"] intValue];
- job->frame_to_stop = stop_frame;
-
- }
-
-
-
-
- /* Format (Muxer) and Video Encoder */
- job->mux = [[queueToApply objectForKey:@"JobFileFormatMux"] intValue];
- job->vcodec = [[queueToApply objectForKey:@"JobVideoEncoderVcodec"] intValue];
-
- /* We set http optimized mp4 here */
- if( [[queueToApply objectForKey:@"Mp4HttpOptimize"] intValue] == 1 )
- {
- job->mp4_optimize = 1;
- }
- else
- {
- job->mp4_optimize = 0;
- }
-
-
- /* We set the chapter marker extraction here based on the format being
- mpeg4 or mkv and the checkbox being checked */
- if ([[queueToApply objectForKey:@"ChapterMarkers"] intValue] == 1)
- {
- job->chapter_markers = 1;
-
- /* now lets get our saved chapter names out the array in the queue file
- * and insert them back into the title chapter list. We have it here,
- * because unless we are inserting chapter markers there is no need to
- * spend the overhead of iterating through the chapter names array imo
- * Also, note that if for some reason we don't apply chapter names, the
- * chapters just come out 001, 002, etc. etc.
- */
-
- NSArray *chapterNamesArray = [queueToApply objectForKey:@"ChapterNames"];
- int i = 0;
- for (id tempObject in chapterNamesArray)
- {
- hb_chapter_t *chapter = (hb_chapter_t *) hb_list_item( job->list_chapter, i );
- if( chapter != NULL )
- {
- hb_chapter_set_title( chapter, [tempObject UTF8String] );
- }
- i++;
- }
- }
- else
- {
- job->chapter_markers = 0;
- }
-
- if (job->vcodec == HB_VCODEC_X264 || job->vcodec == HB_VCODEC_X265)
- {
- /* iPod 5G atom */
- job->ipod_atom = ([[queueToApply objectForKey:@"Mp4iPodCompatible"]
- intValue] == 1);
-
- /* set fastfirstpass if 2-pass and Turbo are enabled */
- if ([[queueToApply objectForKey:@"VideoTwoPass"] intValue] == 1)
- {
- job->fastfirstpass = ([[queueToApply objectForKey:@"VideoTurboTwoPass"]
- intValue] == 1);
- }
-
- /* advanced x264 options */
- NSString *tmpString;
- // translate zero-length strings to NULL for libhb
- const char *encoder_preset = NULL;
- const char *encoder_tune = NULL;
- const char *encoder_options = NULL;
- const char *encoder_profile = NULL;
- const char *encoder_level = NULL;
- if ([[queueToApply objectForKey:@"x264UseAdvancedOptions"] intValue])
- {
- // we are using the advanced panel
- if ([(tmpString = [queueToApply objectForKey:@"x264Option"]) length])
- {
- encoder_options = [tmpString UTF8String];
- }
- }
- else
- {
- // we are using the x264 preset system
- if ([(tmpString = [queueToApply objectForKey:@"VideoTune"]) length])
- {
- encoder_tune = [tmpString UTF8String];
- }
- if ([(tmpString = [queueToApply objectForKey:@"VideoOptionExtra"]) length])
- {
- encoder_options = [tmpString UTF8String];
- }
- if ([(tmpString = [queueToApply objectForKey:@"VideoProfile"]) length])
- {
- encoder_profile = [tmpString UTF8String];
- }
- if ([(tmpString = [queueToApply objectForKey:@"VideoLevel"]) length])
- {
- encoder_level = [tmpString UTF8String];
- }
- encoder_preset = [[queueToApply objectForKey:@"VideoPreset"] UTF8String];
- }
- hb_job_set_encoder_preset (job, encoder_preset);
- hb_job_set_encoder_tune (job, encoder_tune);
- hb_job_set_encoder_options(job, encoder_options);
- hb_job_set_encoder_profile(job, encoder_profile);
- hb_job_set_encoder_level (job, encoder_level);
- }
- else if (job->vcodec & HB_VCODEC_FFMPEG_MASK)
- {
- hb_job_set_encoder_options(job,
- [[queueToApply objectForKey:@"VideoOptionExtra"]
- UTF8String]);
- }
-
- /* Picture Size Settings */
- job->par.num = [[queueToApply objectForKey:@"PicturePARPixelWidth"] intValue];
- job->par.den = [[queueToApply objectForKey:@"PicturePARPixelHeight"] intValue];
-
- /* Video settings */
- /* Framerate */
- int fps_mode, fps_num, fps_den;
- if ([[queueToApply objectForKey:@"JobIndexVideoFramerate"] intValue] > 0)
- {
- /* a specific framerate has been chosen */
- fps_num = 27000000;
- fps_den = (int)[[queueToApply objectForKey:@"JobIndexVideoFramerate"] intValue];
- if ([[queueToApply objectForKey:@"VideoFramerateMode"] isEqualToString:@"cfr"])
- {
- // CFR
- fps_mode = 1;
- }
- else
- {
- // PFR
- fps_mode = 2;
- }
- }
- else
- {
- /* same as source */
- fps_num = [[queueToApply objectForKey:@"JobVrate"] intValue];
- fps_den = [[queueToApply objectForKey:@"JobVrateBase"] intValue];
- if ([[queueToApply objectForKey:@"VideoFramerateMode"] isEqualToString:@"cfr"])
- {
- // CFR
- fps_mode = 1;
- }
- else
- {
- // VFR
- fps_mode = 0;
- }
- }
-
- if ( [[queueToApply objectForKey:@"VideoQualityType"] intValue] != 2 )
- {
- job->vquality = -1.0;
- job->vbitrate = [[queueToApply objectForKey:@"VideoAvgBitrate"] intValue];
- }
- if ( [[queueToApply objectForKey:@"VideoQualityType"] intValue] == 2 )
- {
- job->vquality = [[queueToApply objectForKey:@"VideoQualitySlider"] floatValue];
- job->vbitrate = 0;
-
- }
-
- job->grayscale = [[queueToApply objectForKey:@"VideoGrayScale"] intValue];
-
- // Map the settings in the dictionaries for the SubtitleList array to match title->list_subtitle
- BOOL one_burned = NO;
- int i = 0;
-
- NSArray *subtitles = [queueToApply objectForKey:@"SubtitleList"];
- for (id subtitleDict in subtitles)
- {
- int subtitle = [subtitleDict[keySubTrackIndex] intValue];
- int force = [subtitleDict[keySubTrackForced] intValue];
- int burned = [subtitleDict[keySubTrackBurned] intValue];
- int def = [subtitleDict[keySubTrackDefault] intValue];
-
- // if i is 0, then we are in the first item of the subtitles which we need to
- // check for the "Foreign Audio Search" which would be keySubTrackIndex of -1
-
- // if we are on the first track and using "Foreign Audio Search"
- if (i == 0 && subtitle == -1)
- {
- [HBUtilities writeToActivityLog: "Foreign Language Search: %d", 1];
-
- job->indepth_scan = 1;
-
- if (burned != 1)
- {
- 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
- {
- // if we are getting the subtitles from an external srt file
- if ([subtitleDict[keySubTrackType] intValue] == SRTSUB)
- {
- hb_subtitle_config_t sub_config;
-
- sub_config.offset = [subtitleDict[keySubTrackSrtOffset] intValue];
-
- // we need to srncpy file name and codeset
- strncpy(sub_config.src_filename, [subtitleDict[keySubTrackSrtFilePath] UTF8String], 255);
- sub_config.src_filename[255] = 0;
- strncpy(sub_config.src_codeset, [subtitleDict[keySubTrackSrtCharCode] UTF8String], 39);
- sub_config.src_codeset[39] = 0;
-
- if( !burned && hb_subtitle_can_pass( SRTSUB, job->mux ) )
- {
- sub_config.dest = PASSTHRUSUB;
- }
- else if( hb_subtitle_can_burn( SRTSUB ) )
- {
- // Only allow one subtitle to be burned into the video
- if( one_burned )
- continue;
- one_burned = TRUE;
- sub_config.dest = RENDERSUB;
- }
-
- sub_config.force = 0;
- sub_config.default_track = def;
- hb_srt_add( job, &sub_config, [subtitleDict[keySubTrackLanguageIsoCode] UTF8String]);
- continue;
- }
-
- /* We are setting a source subtitle so access the source subtitle info */
- hb_subtitle_t * subt = (hb_subtitle_t *) hb_list_item( title->list_subtitle, subtitle );
-
- if( subt != NULL )
- {
- hb_subtitle_config_t sub_config = subt->config;
-
- if( !burned && hb_subtitle_can_pass( subt->source, job->mux ) )
- {
- sub_config.dest = PASSTHRUSUB;
- }
- else if( hb_subtitle_can_burn( subt->source ) )
- {
- // Only allow one subtitle to be burned into the video
- if( one_burned )
- continue;
- one_burned = TRUE;
- sub_config.dest = RENDERSUB;
- }
-
- sub_config.force = force;
- sub_config.default_track = def;
- hb_subtitle_add( job, &sub_config, subtitle );
- }
- }
- i++;
- }
- if( one_burned )
- {
- filter = hb_filter_init( HB_FILTER_RENDER_SUB );
- hb_add_filter( job, filter, [[NSString stringWithFormat:@"%d:%d:%d:%d",
- job->crop[0], job->crop[1],
- job->crop[2], job->crop[3]] UTF8String] );
- }
-
- /* Auto Defaults */
- NSDictionary *audioDefaults = queueToApply[@"AudioDefaults"];
-
- job->acodec_copy_mask = 0;
-
- if ([audioDefaults[@"AudioAllowAACPass"] boolValue])
- {
- job->acodec_copy_mask |= HB_ACODEC_FFAAC;
- }
- if ([audioDefaults[@"AudioAllowAC3Pass"] boolValue])
- {
- job->acodec_copy_mask |= HB_ACODEC_AC3;
- }
- if ([audioDefaults[@"AudioAllowDTSHDPass"] boolValue])
- {
- job->acodec_copy_mask |= HB_ACODEC_DCA_HD;
- }
- if ([audioDefaults[@"AudioAllowDTSPass"] boolValue])
- {
- job->acodec_copy_mask |= HB_ACODEC_DCA;
- }
- if ([audioDefaults[@"AudioAllowMP3Pass"] boolValue])
- {
- job->acodec_copy_mask |= HB_ACODEC_MP3;
- }
- job->acodec_fallback = hb_audio_encoder_get_from_name([audioDefaults[@"AudioEncoderFallback"] UTF8String]);
-
- /* Audio tracks and mixdowns */
- /* Now lets add our new tracks to the audio list here */
- for (NSDictionary *audioDict in [queueToApply objectForKey:@"AudioList"])
- {
- audio = (hb_audio_config_t *)calloc(1, sizeof(*audio));
- hb_audio_config_init(audio);
- audio->in.track = [audioDict[@"Track"] intValue];
- /* We go ahead and assign values to our audio->out.<properties> */
- audio->out.track = audio->in.track;
- audio->out.codec = [audioDict[@"JobEncoder"] intValue];
- audio->out.compression_level = hb_audio_compression_get_default(audio->out.codec);
- audio->out.mixdown = [audioDict[@"JobMixdown"] intValue];
- audio->out.normalize_mix_level = 0;
- audio->out.bitrate = [audioDict[@"JobBitrate"] intValue];
- audio->out.samplerate = [audioDict[@"JobSamplerate"] intValue];
- audio->out.dynamic_range_compression = [audioDict[@"TrackDRCSlider"] doubleValue];
- audio->out.gain = [audioDict[@"TrackGainSlider"] doubleValue];
- audio->out.dither_method = hb_audio_dither_get_default();
-
- hb_audio_add(job, audio);
- free(audio);
- }
-
- /* Now lets call the filters if applicable.
- * The order of the filters is critical
- */
- /* Detelecine */
- filter = hb_filter_init( HB_FILTER_DETELECINE );
- if ([[queueToApply objectForKey:@"PictureDetelecine"] intValue] == 1)
- {
- /* use a custom detelecine string */
- hb_add_filter( job, filter, [[queueToApply objectForKey:@"PictureDetelecineCustom"] UTF8String] );
- }
- else if ([[queueToApply objectForKey:@"PictureDetelecine"] intValue] == 2)
- {
- /* Use libhb's default values */
- hb_add_filter( job, filter, NULL );
- }
-
- if ([[queueToApply objectForKey:@"PictureDecombDeinterlace"] intValue] == 1)
- {
- /* Decomb */
- filter = hb_filter_init( HB_FILTER_DECOMB );
- if ([[queueToApply objectForKey:@"PictureDecomb"] intValue] == 1)
- {
- /* use a custom decomb string */
- hb_add_filter( job, filter, [[queueToApply objectForKey:@"PictureDecombCustom"] UTF8String] );
- }
- else if ([[queueToApply objectForKey:@"PictureDecomb"] intValue] == 2)
- {
- /* use libhb defaults */
- hb_add_filter( job, filter, NULL );
- }
- else if ([[queueToApply objectForKey:@"PictureDecomb"] intValue] == 3)
- {
- /* use old defaults (decomb fast) */
- hb_add_filter( job, filter, "7:2:6:9:1:80" );
- }
- else if ([[queueToApply objectForKey:@"PictureDecomb"] intValue] == 4)
- {
- /* decomb 3 with bobbing enabled */
- hb_add_filter( job, filter, "455" );
- }
- }
- else
- {
- /* Deinterlace */
- filter = hb_filter_init( HB_FILTER_DEINTERLACE );
- if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 1)
- {
- /* we add the custom string if present */
- hb_add_filter( job, filter, [[queueToApply objectForKey:@"PictureDeinterlaceCustom"] UTF8String] );
- }
- else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 2)
- {
- /* Run old deinterlacer fd by default */
- hb_add_filter( job, filter, "0" );
- }
- else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 3)
- {
- /* Yadif mode 0 (without spatial deinterlacing) */
- hb_add_filter( job, filter, "1" );
- }
- else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 4)
- {
- /* Yadif (with spatial deinterlacing) */
- hb_add_filter( job, filter, "3" );
- }
- else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 5)
- {
- /* Yadif (with spatial deinterlacing and bobbing) */
- hb_add_filter( job, filter, "15" );
- }
- }
- /* Denoise */
- if (![queueToApply[@"PictureDenoise"] isEqualToString:@"off"])
- {
- int filter_id = HB_FILTER_HQDN3D;
- if ([queueToApply[@"PictureDenoise"] isEqualToString:@"nlmeans"])
- filter_id = HB_FILTER_NLMEANS;
-
- if ([queueToApply[@"PictureDenoisePreset"] isEqualToString:@"none"])
- {
- const char *filter_str;
- filter_str = [queueToApply[@"PictureDenoiseCustom"] UTF8String];
- filter = hb_filter_init(filter_id);
- hb_add_filter(job, filter, filter_str);
- }
- else
- {
- const char *filter_str, *preset, *tune;
- preset = [queueToApply[@"PictureDenoisePreset"] UTF8String];
- tune = [queueToApply[@"PictureDenoiseTune"] UTF8String];
- filter_str = hb_generate_filter_settings(filter_id, preset, tune);
- filter = hb_filter_init(filter_id);
- hb_add_filter(job, filter, filter_str);
- }
- }
-
- /* Deblock (uses pp7 default) */
- /* NOTE: even though there is a valid deblock setting of 0 for the filter, for
- * the macgui's purposes a value of 0 actually means to not even use the filter
- * current hb_filter_deblock.settings valid ranges are from 5 - 15
- */
- filter = hb_filter_init( HB_FILTER_DEBLOCK );
- if ([[queueToApply objectForKey:@"PictureDeblock"] intValue] != 0)
- {
- hb_add_filter( job, filter, [[queueToApply objectForKey:@"PictureDeblock"] UTF8String] );
- }
-
- /* Add Crop/Scale filter */
- filter = hb_filter_init(HB_FILTER_CROP_SCALE);
- hb_add_filter( job, filter, [[NSString stringWithFormat:@"%d:%d:%d:%d:%d:%d",
- [queueToApply[@"PictureWidth"] intValue], [queueToApply[@"PictureHeight"] intValue],
- [queueToApply[@"PictureTopCrop"] intValue], [queueToApply[@"PictureBottomCrop"] intValue],
- [queueToApply[@"PictureLeftCrop"] intValue], [queueToApply[@"PictureRightCrop"] intValue]] UTF8String] );
-
- /* Add framerate shaping filter */
- filter = hb_filter_init(HB_FILTER_VFR);
- hb_add_filter(job, filter, [[NSString stringWithFormat:@"%d:%d:%d",
- fps_mode, fps_num, fps_den] UTF8String]);
-
- [HBUtilities writeToActivityLog: "prepareJob exiting"];
-}
-
-
-
/* addToQueue: puts up an alert before ultimately calling doAddToQueue
*/
-- (IBAction) addToQueue: (id) sender
+- (IBAction)addToQueue:(id)sender
{
- /* We get the destination directory from the destination field here */
- NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
- /* We check for a valid destination here */
+ // We get the destination directory from the destination field here
+ NSString *destinationDirectory = self.job.destURL.path.stringByDeletingLastPathComponent;
+ // We check for a valid destination here
if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
{
NSAlert *alert = [[NSAlert alloc] init];
@@ -2926,29 +2068,28 @@ static void queueFSEventStreamCallback(
BOOL fileExistsInQueue;
fileExistsInQueue = NO;
- /* We check for and existing file here */
- if([[NSFileManager defaultManager] fileExistsAtPath: [fDstFile2Field stringValue]])
+ // We check for and existing file here
+ if([[NSFileManager defaultManager] fileExistsAtPath:self.job.destURL.path])
{
fileExists = YES;
}
- /* We now run through the queue and make sure we are not overwriting an exisiting queue item */
- for (id tempObject in QueueFileArray)
+ // We now run through the queue and make sure we are not overwriting an exisiting queue item
+ for (HBJob *job in QueueFileArray)
{
- NSDictionary *thisQueueDict = tempObject;
- if ([[thisQueueDict objectForKey:@"DestinationPath"] isEqualToString: [fDstFile2Field stringValue]])
+ if ([job.destURL isEqualTo:self.job.destURL])
{
fileExistsInQueue = YES;
}
}
- if(fileExists == YES)
+ if (fileExists == YES)
{
NSAlert *alert = [NSAlert alertWithMessageText:@"File already exists."
defaultButton:@"Cancel"
alternateButton:@"Overwrite"
otherButton:nil
- informativeTextWithFormat:@"Do you want to overwrite %@?", [fDstFile2Field stringValue]];
+ informativeTextWithFormat:@"Do you want to overwrite %@?", self.job.destURL.path];
[alert setAlertStyle:NSCriticalAlertStyle];
[alert beginSheetModalForWindow:fWindow modalDelegate:self didEndSelector:@selector( overwriteAddToQueueAlertDone:returnCode:contextInfo: ) contextInfo:NULL];
@@ -2960,7 +2101,7 @@ static void queueFSEventStreamCallback(
defaultButton:@"Cancel"
alternateButton:@"Overwrite"
otherButton:nil
- informativeTextWithFormat:@"Do you want to overwrite %@?", [fDstFile2Field stringValue]];
+ informativeTextWithFormat:@"Do you want to overwrite %@?", self.job.destURL.path];
[alert setAlertStyle:NSCriticalAlertStyle];
[alert beginSheetModalForWindow:fWindow modalDelegate:self didEndSelector:@selector( overwriteAddToQueueAlertDone:returnCode:contextInfo: ) contextInfo:NULL];
@@ -2983,11 +2124,9 @@ static void queueFSEventStreamCallback(
- (void) doAddToQueue
{
- [self addQueueFileItem ];
+ [self addQueueFileItem];
}
-
-
/* Rip: puts up an alert before ultimately calling doRip
*/
- (IBAction) Rip: (id) sender
@@ -3000,23 +2139,23 @@ static void queueFSEventStreamCallback(
return;
}
- /* We check to see if we need to warn the user that the computer will go to sleep
- or shut down when encoding is finished */
- [self remindUserOfSleepOrShutdown];
+ // We check to see if we need to warn the user that the computer will go to sleep
+ // or shut down when encoding is finished
+ [self remindUserOfSleepOrShutdown];
// If there are pending jobs in the queue, then this is a rip the queue
if (fPendingCount > 0)
{
currentQueueEncodeIndex = [self getNextPendingQueueIndex];
- /* here lets start the queue with the first pending item */
- [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]];
+ // here lets start the queue with the first pending item
+ HBJob *queueJob = QueueFileArray[currentQueueEncodeIndex];
+ [self performNewQueueScan:queueJob.fileURL.path scanTitleNum:queueJob.titleIdx];
return;
}
// Before adding jobs to the queue, check for a valid destination.
-
- NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
+ NSString *destinationDirectory = self.job.destURL.path.stringByDeletingLastPathComponent;
if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
{
NSAlert *alert = [[NSAlert alloc] init];
@@ -3027,14 +2166,14 @@ static void queueFSEventStreamCallback(
return;
}
- /* We check for duplicate name here */
- if( [[NSFileManager defaultManager] fileExistsAtPath:[fDstFile2Field stringValue]] )
+ // We check for duplicate name here
+ if( [[NSFileManager defaultManager] fileExistsAtPath:self.job.destURL.path] )
{
NSAlert *alert = [NSAlert alertWithMessageText:@"File already exists."
defaultButton:@"Cancel"
alternateButton:@"Overwrite"
otherButton:nil
- informativeTextWithFormat:@"Do you want to overwrite %@?", [fDstFile2Field stringValue]];
+ informativeTextWithFormat:@"Do you want to overwrite %@?", self.job.destURL.path];
[alert setAlertStyle:NSCriticalAlertStyle];
[alert beginSheetModalForWindow:fWindow modalDelegate:self didEndSelector:@selector( overWriteAlertDone:returnCode:contextInfo: ) contextInfo:NULL];
@@ -3049,10 +2188,10 @@ static void queueFSEventStreamCallback(
[self doAddToQueue];
}
- /* go right to processing the new queue encode */
+ // go right to processing the new queue encode
currentQueueEncodeIndex = [self getNextPendingQueueIndex];
- [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]];
-
+ HBJob *queueJob = QueueFileArray[currentQueueEncodeIndex];
+ [self performNewQueueScan:queueJob.fileURL.path scanTitleNum:queueJob.titleIdx];
}
}
@@ -3064,18 +2203,18 @@ static void queueFSEventStreamCallback(
{
if( returnCode == NSAlertAlternateReturn )
{
- /* if there are no jobs in the queue, then add this one to the queue and rip
- otherwise, just rip the queue */
- if( fPendingCount == 0 )
+ // if there are no jobs in the queue, then add this one to the queue and rip
+ // otherwise, just rip the queue
+ if (fPendingCount == 0)
{
[self doAddToQueue];
}
- NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
+ NSString *destinationDirectory = [self.job.destURL.path stringByDeletingLastPathComponent];
[[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
currentQueueEncodeIndex = [self getNextPendingQueueIndex];
- [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]];
-
+ HBJob *queueJob = QueueFileArray[currentQueueEncodeIndex];
+ [self performNewQueueScan:queueJob.fileURL.path scanTitleNum:queueJob.titleIdx];
}
}
@@ -3122,15 +2261,6 @@ static void queueFSEventStreamCallback(
}
-- (void) doRip
-{
- /* Let libhb do the job */
- [self.queueCore start];
- /* set the fEncodeState State */
- fEncodeState = 1;
-}
-
-
//------------------------------------------------------------------------------------
// Displays an alert asking user if the want to cancel encoding of current job.
// Cancel: returns immediately after posting the alert. Later, when the user
@@ -3193,13 +2323,12 @@ static void queueFSEventStreamCallback(
- (void) doCancelCurrentJob
{
// Stop the current job.
-
[self.queueCore stop];
fEncodeState = 2; // don't alert at end of processing since this was a cancel
// now that we've stopped the currently encoding job, lets mark it as cancelled
- [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:3] forKey:@"Status"];
+ [QueueFileArray[currentQueueEncodeIndex] setState:HBJobStateCanceled];
// and as always, save it in Queue.plist
/* We save all of the Queue data here */
[self saveQueueFileItem];
@@ -3214,13 +2343,14 @@ static void queueFSEventStreamCallback(
{
/*Set our currentQueueEncodeIndex now to the newly found Pending encode as we own it */
currentQueueEncodeIndex = newQueueItemIndex;
- /* now we mark the queue item as Status = 1 ( being encoded ) so another instance can not come along and try to scan it while we are scanning */
- [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:1] forKey:@"Status"];
+ /* now we mark the queue item as worling so another instance can not come along and try to scan it while we are scanning */
+ [QueueFileArray[currentQueueEncodeIndex] setState:HBJobStateWorking];
[HBUtilities writeToActivityLog: "incrementQueueItemDone new pending items found: %d", currentQueueEncodeIndex];
[self saveQueueFileItem];
- /* now we can go ahead and scan the new pending queue item */
- [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]];
+ HBJob *queueJob = QueueFileArray[currentQueueEncodeIndex];
+ // now we can go ahead and scan the new pending queue item
+ [self performNewQueueScan:queueJob.fileURL.path scanTitleNum:queueJob.titleIdx];
}
else
{
@@ -3235,7 +2365,7 @@ static void queueFSEventStreamCallback(
fEncodeState = 2; // don't alert at end of processing since this was a cancel
// now that we've stopped the currently encoding job, lets mark it as cancelled
- [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:3] forKey:@"Status"];
+ [QueueFileArray[currentQueueEncodeIndex] setState:HBJobStateCanceled];
// and as always, save it in Queue.plist
/* We save all of the Queue data here */
[self saveQueueFileItem];
@@ -3278,22 +2408,21 @@ static void queueFSEventStreamCallback(
- (void) doAddAllTitlesToQueue
{
-
- /* first get the currently selected index so we can choose it again after cycling through the available titles. */
+ // first get the currently selected index so we can choose it again after cycling through the available titles.
NSInteger currentlySelectedTitle = [fSrcTitlePopUp indexOfSelectedItem];
/* For each title in the fSrcTitlePopUp, select it */
- for( int i = 0; i < [fSrcTitlePopUp numberOfItems]; i++ )
+ for (int i = 0; i < [fSrcTitlePopUp numberOfItems]; i++)
{
[fSrcTitlePopUp selectItemAtIndex:i];
- /* Now call titlePopUpChanged to load it up */
+ // Now call titlePopUpChanged to load it up
[self titlePopUpChanged:nil];
- /* now add the title to the queue */
+ // now add the title to the queue
[self addToQueue:nil];
}
- /* Now that we are done, reselect the previously selected title.*/
+ // Now that we are done, reselect the previously selected title.
[fSrcTitlePopUp selectItemAtIndex: currentlySelectedTitle];
- /* Now call titlePopUpChanged to load it up */
+ // Now call titlePopUpChanged to load it up
[self titlePopUpChanged:nil];
}
@@ -3318,10 +2447,8 @@ static void queueFSEventStreamCallback(
videoCodec:self.job.video.encoder];
// Swap the old one with the new one
- [fDstFile2Field setStringValue: [NSString stringWithFormat:@"%@/%@.%@",
- [[fDstFile2Field stringValue] stringByDeletingLastPathComponent],
- fileName,
- [[fDstFile2Field stringValue] pathExtension]]];
+ self.job.destURL = [[self.job.destURL URLByDeletingLastPathComponent] URLByAppendingPathComponent:
+ [NSString stringWithFormat:@"%@.%@", fileName, self.job.destURL.pathExtension]];
}
- (IBAction) titlePopUpChanged: (id) sender
@@ -3332,58 +2459,63 @@ static void queueFSEventStreamCallback(
self.selectedPreset = [self createPresetFromCurrentSettings];
}
- HBTitle *hbtitle = self.core.titles[fSrcTitlePopUp.indexOfSelectedItem];
- HBJob *job = [[[HBJob alloc] initWithTitle:hbtitle
- andPreset:self.selectedPreset] autorelease];
-
- // Set the jobs info to the view controllers
- fPictureController.picture = job.picture;
- fPictureController.filters = job.filters;
- fPreviewController.job = job;
+ HBTitle *title = self.core.titles[fSrcTitlePopUp.indexOfSelectedItem];
- fVideoController.video = job.video;
- fAudioController.job = job;
- fSubtitlesViewController.job = job;
- fChapterTitlesController.job = job;
+ // Check if we are reapplying a job from the queue, or creating a new one
+ if (self.jobFromQueue)
+ {
+ self.jobFromQueue.title = title;
+ self.job = self.jobFromQueue;
+ }
+ else
+ {
+ self.job = [[[HBJob alloc] initWithTitle:title andPreset:self.selectedPreset] autorelease];
- // Set Auto Crop to on upon selecting a new title
- job.picture.autocrop = YES;
+ // use the correct extension based on the container
+ const char *ext = hb_container_get_default_extension(self.job.container);
- self.job = job;
+ // Check to see if the last destination has been set,use if so, if not, use Desktop
+ if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
+ {
+ NSURL *fileURL = [NSURL fileURLWithPath:[[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"]];
+ fileURL = [fileURL URLByAppendingPathComponent:self.browsedSourceDisplayName.stringByDeletingPathExtension];
+ fileURL = [fileURL URLByAppendingPathExtension:@(ext)];
+ self.job.destURL = fileURL;
+ }
+ else
+ {
+ self.job.destURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/Desktop/%@.%s",
+ NSHomeDirectory(),
+ self.browsedSourceDisplayName.stringByDeletingPathExtension,
+ ext]];
+ }
- hb_title_t *title = hbtitle.hb_title;
+ // set m4v extension if necessary - do not override user-specified .mp4 extension
+ if (self.job.container & HB_MUX_MASK_MP4)
+ {
+ [self autoSetM4vExtension:nil];
+ }
+ }
// If we are a stream type and a batch scan, grok the output file name from title->name upon title change
- if ((title->type == HB_STREAM_TYPE || title->type == HB_FF_STREAM_TYPE) && self.core.titles.count > 1)
+ if ((title.hb_title->type == HB_STREAM_TYPE || title.hb_title->type == HB_FF_STREAM_TYPE) && self.core.titles.count > 1)
{
// we set the default name according to the new title->name
- [fDstFile2Field setStringValue: [NSString stringWithFormat:
- @"%@/%@.%@", [[fDstFile2Field stringValue] stringByDeletingLastPathComponent],
- [NSString stringWithUTF8String: title->name],
- [[fDstFile2Field stringValue] pathExtension]]];
-
+ self.job.destURL = [[self.job.destURL URLByDeletingLastPathComponent] URLByAppendingPathComponent:
+ [NSString stringWithFormat:@"%@.%@", title.name, self.job.destURL.pathExtension]];
+
// Change the source to read out the parent folder also
- [fSrcDVD2Field setStringValue:[NSString stringWithFormat:@"%@/%@", browsedSourceDisplayName,[NSString stringWithUTF8String: title->name]]];
+ fSrcDVD2Field.stringValue = [NSString stringWithFormat:@"%@/%@", self.browsedSourceDisplayName, title.name];
}
- [self chapterPopUpChanged:nil];
-
- [fSrcAnglePopUp removeAllItems];
-
- for (int i = 0; i < hbtitle.angles; i++)
+ // apply the current preset
+ if (!self.jobFromQueue)
{
- [fSrcAnglePopUp addItemWithTitle:[NSString stringWithFormat: @"%d", i + 1]];
- }
- [fSrcAnglePopUp selectItemAtIndex: 0];
+ // Set Auto Crop to on upon selecting a new title
+ self.job.picture.autocrop = YES;
- // If Auto Naming is on. We create an output filename of dvd name - title number
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"])
- {
- [self updateFileName];
- }
-
- // apply the current preset
- [self applyPreset:self.selectedPreset];
+ [self applyPreset:self.selectedPreset];
+ }
}
- (IBAction) encodeStartStopPopUpChanged: (id) sender;
@@ -3449,20 +2581,20 @@ static void queueFSEventStreamCallback(
}
}
-- (IBAction) formatPopUpChanged: (id) sender
+- (void)formatChanged:(NSNotification *)notification
{
- NSString *string = [fDstFile2Field stringValue];
- int videoContainer = self.job.container;
- const char *ext = NULL;
-
- // set the file extension
- ext = hb_container_get_default_extension(videoContainer);
- [fDstFile2Field setStringValue:[NSString stringWithFormat:@"%@.%s",
- [string stringByDeletingPathExtension],
- ext]];
- if (videoContainer & HB_MUX_MASK_MP4)
+ if (self.job)
{
- [self autoSetM4vExtension:sender];
+ int videoContainer = self.job.container;
+
+ // set the file extension
+ const char *ext = hb_container_get_default_extension(videoContainer);
+ self.job.destURL = [[self.job.destURL URLByDeletingPathExtension] URLByAppendingPathExtension:@(ext)];
+
+ if (videoContainer & HB_MUX_MASK_MP4)
+ {
+ [self autoSetM4vExtension:notification];
+ }
}
}
@@ -3486,28 +2618,30 @@ static void queueFSEventStreamCallback(
extension = @"m4v";
}
- if ([extension isEqualTo: [[fDstFile2Field stringValue] pathExtension]] )
+ if ([extension isEqualTo:self.job.destURL.pathExtension])
+ {
return;
+ }
else
- [fDstFile2Field setStringValue: [NSString stringWithFormat:@"%@.%@",
- [[fDstFile2Field stringValue] stringByDeletingPathExtension], extension]];
+ {
+ self.job.destURL = [[self.job.destURL URLByDeletingPathExtension] URLByAppendingPathExtension:extension];
+ }
}
-/* Method to determine if we should change the UI
-To reflect whether or not a Preset is being used or if
-the user is using "Custom" settings by determining the sender*/
-- (IBAction) customSettingUsed: (id) sender
+/**
+ * Method to determine if we should change the UI
+ * To reflect whether or not a Preset is being used or if
+ * the user is using "Custom" settings by determining the sender
+ */
+- (void)customSettingUsed
{
- if ([sender stringValue])
- {
- /* Deselect the currently selected Preset if there is one*/
- [fPresetsView deselect];
- /* Change UI to show "Custom" settings are being used */
- [fPresetSelectedDisplay setStringValue: @"Custom"];
- self.customPreset = YES;
- }
+ // Deselect the currently selected Preset if there is one*/
+ [fPresetsView deselect];
+ // Change UI to show "Custom" settings are being used */
+ fPresetSelectedDisplay.stringValue = NSLocalizedString(@"Custom", @"");
+ self.customPreset = YES;
- /* If Auto Naming is on it might need to be update if it includes the quality token */
+ // If Auto Naming is on it might need to be update if it includes the quality token
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"])
{
[self updateFileName];
@@ -3523,54 +2657,13 @@ the user is using "Custom" settings by determining the sender*/
- (void)pictureSettingsDidChange
{
// align picture settings and video filters in the UI using tabs
- fVideoController.pictureSettings = [self pictureSettingsSummary];
+ fVideoController.pictureSettings = self.job.picture.summary;
fVideoController.pictureFilters = self.job.filters.summary;
[fPreviewController reloadPreviews];
}
#pragma mark -
-#pragma mark - Text Summaries
-
-- (NSString *)pictureSettingsSummary
-{
- NSMutableString *summary = [NSMutableString stringWithString:@""];
- if (self.job.picture)
- {
- HBPicture *pict = self.job.picture;
- [summary appendString:pict.info];
- if (pict.anamorphicMode != HB_ANAMORPHIC_STRICT)
- {
- // anamorphic is not Strict, show the modulus
- [summary appendFormat:@", Modulus: %d", pict.modulus];
- }
- [summary appendFormat:@", Crop: %s %d/%d/%d/%d",
- pict.autocrop ? "Auto" : "Custom",
- pict.cropTop, pict.cropBottom,
- pict.cropLeft, pict.cropRight];
- }
- return [NSString stringWithString:summary];
-}
-
-- (NSString *) muxerOptionsSummary
-{
- NSMutableString *summary = [NSMutableString stringWithString:@""];
- if ((self.job.container & HB_MUX_MASK_MP4) && self.job.mp4HttpOptimize)
- {
- [summary appendString:@" - Web optimized"];
- }
- if ((self.job.container & HB_MUX_MASK_MP4) && self.job.mp4iPodCompatible)
- {
- [summary appendString:@" - iPod 5G support"];
- }
- if ([summary hasPrefix:@" - "])
- {
- [summary deleteCharactersInRange:NSMakeRange(0, 3)];
- }
- return [NSString stringWithString:summary];
-}
-
-#pragma mark -
#pragma mark Open New Windows
- (IBAction) openHomepage: (id) sender
@@ -3686,6 +2779,12 @@ the user is using "Custom" settings by determining the sender*/
// Subtitles
[fSubtitlesViewController applySettingsFromPreset:chosenPreset];
+ // If Auto Naming is on. We create an output filename of dvd name - title number
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"])
+ {
+ [self updateFileName];
+ }
+
[self pictureSettingsDidChange];
}
}
diff --git a/macosx/English.lproj/MainMenu.xib b/macosx/English.lproj/MainMenu.xib
index 439f95472..0b3ce8117 100644
--- a/macosx/English.lproj/MainMenu.xib
+++ b/macosx/English.lproj/MainMenu.xib
@@ -152,6 +152,7 @@
</popUpButtonCell>
<accessibility description="Angle"/>
<connections>
+ <binding destination="240" name="content" keyPath="self.job.angles" id="oFZ-d6-aeJ"/>
<binding destination="5676" name="hidden" keyPath="values.UseDvdNav" id="8xq-AL-yDc">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
@@ -245,11 +246,18 @@
<textField verticalHuggingPriority="750" id="1561">
<rect key="frame" x="56" y="455" width="782" height="19"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
- <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="left" drawsBackground="YES" id="4919">
+ <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" continuous="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="left" drawsBackground="YES" id="4919">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
+ <connections>
+ <binding destination="240" name="value" keyPath="self.job.destURL" id="f8U-7W-7gP">
+ <dictionary key="options">
+ <string key="NSValueTransformerName">HBURLTransformer</string>
+ </dictionary>
+ </binding>
+ </connections>
</textField>
<textField hidden="YES" verticalHuggingPriority="750" id="5491">
<rect key="frame" x="581" y="492" width="54" height="19"/>
@@ -409,8 +417,8 @@
<accessibility description="Start Chapter"/>
<connections>
<action selector="chapterPopUpChanged:" target="240" id="1615"/>
- <binding destination="240" name="content" keyPath="self.job.range.chapters" id="6kP-TS-bEc"/>
<binding destination="240" name="selectedIndex" keyPath="self.job.range.chapterStart" previousBinding="6kP-TS-bEc" id="U76-2W-TvD"/>
+ <binding destination="240" name="content" keyPath="self.job.range.chapters" id="6kP-TS-bEc"/>
</connections>
</popUpButton>
<popUpButton verticalHuggingPriority="750" id="1548">
@@ -428,8 +436,8 @@
<accessibility description="End Chapter"/>
<connections>
<action selector="chapterPopUpChanged:" target="240" id="1616"/>
- <binding destination="240" name="content" keyPath="self.job.range.chapters" id="Yqp-Sg-lBf"/>
<binding destination="240" name="selectedIndex" keyPath="self.job.range.chapterStop" previousBinding="Yqp-Sg-lBf" id="4k2-Sm-RoJ"/>
+ <binding destination="240" name="content" keyPath="self.job.range.chapters" id="Yqp-Sg-lBf"/>
</connections>
</popUpButton>
</subviews>
@@ -973,7 +981,7 @@ DQ
<outlet property="fChaptersTitlesTab" destination="1989" id="oUt-8L-Ag2"/>
<outlet property="fDstBrowseButton" destination="1562" id="1578"/>
<outlet property="fDstFile1Field" destination="1552" id="1596"/>
- <outlet property="fDstFile2Field" destination="1561" id="1585"/>
+ <outlet property="fDstFile2Field" destination="1561" id="N8U-j2-c00"/>
<outlet property="fDstFormatField" destination="1556" id="1583"/>
<outlet property="fDstFormatPopUp" destination="1557" id="1584"/>
<outlet property="fDstMp4HttpOptFileCheck" destination="4579" id="4581"/>
diff --git a/macosx/HBAudio.h b/macosx/HBAudio.h
index a54c4ac24..14b191646 100644
--- a/macosx/HBAudio.h
+++ b/macosx/HBAudio.h
@@ -18,7 +18,7 @@ extern NSString *keyAudioMixdown;
extern NSString *keyAudioSamplerate;
extern NSString *keyAudioBitrate;
-@interface HBAudio : NSObject <NSCoding>
+@interface HBAudio : NSObject <NSCoding, NSCopying>
@property (nonatomic, retain) NSDictionary *track;
@property (nonatomic, retain) NSDictionary *codec;
diff --git a/macosx/HBAudio.m b/macosx/HBAudio.m
index 6eae9a1f6..be50a51b3 100644
--- a/macosx/HBAudio.m
+++ b/macosx/HBAudio.m
@@ -575,6 +575,31 @@ static NSMutableArray *masterBitRateArray = nil;
return retval;
}
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone
+{
+ HBAudio *copy = [[[self class] alloc] init];
+
+ if (copy)
+ {
+ copy->_track = [_track copy];
+ copy->_codec = [_codec copy];
+ copy->_mixdown = [_mixdown copy];
+ copy->_sampleRate = [_sampleRate copy];
+ copy->_bitRate = [_bitRate copy];
+ copy->_drc = [_drc copy];
+ copy->_gain = [_gain copy];
+ copy->_videoContainerTag = [_videoContainerTag copy];
+
+ copy->_codecs = [_codecs copy];
+ copy->_mixdowns = [_mixdowns copy];
+ copy->_bitRates = [_bitRates copy];
+ }
+
+ return copy;
+}
+
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)coder
diff --git a/macosx/HBAudioController.h b/macosx/HBAudioController.h
index 878f23a88..2476bdfbb 100644
--- a/macosx/HBAudioController.h
+++ b/macosx/HBAudioController.h
@@ -33,11 +33,7 @@ extern NSString *HBMixdownChangedNotification;
@property (nonatomic, readwrite, assign) HBJob *job;
-// Get the list of audio tracks
-@property (readonly, nonatomic, copy) NSArray *audioTracks;
-
- (void) applySettingsFromPreset:(NSDictionary *)preset;
-- (void) addTracksFromQueue: (NSArray *) queueArray;
- (BOOL) anyCodecMatches: (int) aCodecValue;
- (void) settingTrackToNone: (HBAudio *) newNoneTrack;
diff --git a/macosx/HBAudioController.m b/macosx/HBAudioController.m
index bc2b6e45d..0c1c49293 100644
--- a/macosx/HBAudioController.m
+++ b/macosx/HBAudioController.m
@@ -114,96 +114,9 @@ NSString *HBMixdownChangedNotification = @"HBMixdownChangedNotification";
#pragma mark -
#pragma mark HBController Support
-- (NSArray *)audioTracks
-
-{
- NSMutableArray *tracksArray = [NSMutableArray array];
-
- NSUInteger audioArrayCount = [self countOfAudioArray];
- for (NSUInteger counter = 0; counter < audioArrayCount; counter++)
- {
- HBAudio *anAudio = [self objectInAudioArrayAtIndex: counter];
- if ([anAudio enabled])
- {
- NSMutableDictionary *dict = [NSMutableDictionary dictionary];
- NSNumber *sampleRateToUse = ([anAudio.sampleRate[keyAudioSamplerate] intValue] == 0 ?
- anAudio.track[keyAudioInputSampleRate] :
- anAudio.sampleRate[keyAudioSamplerate]);
-
- dict[@"Track"] = @([anAudio.track[keyAudioTrackIndex] intValue] -1);
- dict[@"TrackDescription"] = anAudio.track[keyAudioTrackName];
- dict[@"Encoder"] = anAudio.codec[keyAudioCodecName];
- dict[@"Mixdown"] = anAudio.mixdown[keyAudioMixdownName];
- dict[@"Samplerate"] = anAudio.sampleRate[keyAudioSampleRateName];
- dict[@"Bitrate"] = anAudio.bitRate[keyAudioBitrateName];
-
- // output is not passthru so apply gain
- if (!([[anAudio codec][keyAudioCodec] intValue] & HB_ACODEC_PASS_FLAG))
- {
- dict[@"TrackGainSlider"] = anAudio.gain;
- }
- else
- {
- // output is passthru - the Gain dial is disabled so don't apply its value
- dict[@"TrackGainSlider"] = @0;
- }
-
- if (hb_audio_can_apply_drc([anAudio.track[keyAudioInputCodec] intValue],
- [anAudio.track[keyAudioInputCodecParam] intValue],
- [anAudio.codec[keyAudioCodec] intValue]))
- {
- dict[@"TrackDRCSlider"] = anAudio.drc;
- }
- else
- {
- // source isn't AC3 or output is passthru - the DRC dial is disabled so don't apply its value
- dict[@"TrackDRCSlider"] = @0;
- }
-
- dict[@"JobEncoder"] = anAudio.codec[keyAudioCodec];
- dict[@"JobMixdown"] = anAudio.mixdown[keyAudioMixdown];
- dict[@"JobSamplerate"] = sampleRateToUse;
- dict[@"JobBitrate"] = anAudio.bitRate[keyAudioBitrate];
-
- [tracksArray addObject:dict];
- }
- }
-
- return tracksArray;
-}
-
-- (void) addTracksFromQueue: (NSArray *) queueArray
-
-{
- // Reinitialize the configured list of audio tracks
- [self _clearAudioArray];
-
- // The following is the pattern to follow, but with Audio%dTrack being the key to seek...
- // Can we assume that there will be no skip in the data?
- for (NSDictionary *audioDict in queueArray)
- {
- HBAudio *newAudio = [[HBAudio alloc] init];
- [newAudio setController: self];
- [self insertObject: newAudio inAudioArrayAtIndex: [self countOfAudioArray]];
- [newAudio setVideoContainerTag: [self videoContainerTag]];
- [newAudio setTrackFromIndex: [audioDict[@"Track"] intValue] + 1];
- [newAudio setCodecFromName: audioDict[@"Encoder"]];
- [newAudio setMixdownFromName: audioDict[@"Mixdown"]];
- [newAudio setSampleRateFromName: audioDict[@"Samplerate"]];
- [newAudio setBitRateFromName: audioDict[@"Bitrate"]];
- [newAudio setDrc: audioDict[@"TrackDRCSlider"]];
- [newAudio setGain: audioDict[@"TrackGainSlider"]];
- [newAudio release];
- }
-
- [self switchingTrackFromNone: nil]; // see if we need to add one to the list
-}
-
- (void)applySettingsFromPreset:(NSDictionary *)preset
{
- [self.settings applySettingsFromPreset:preset];
[self.settings validateEncoderFallbackForVideoContainer:[self.videoContainerTag intValue]];
-
[self addTracksFromDefaults:NO];
}
@@ -507,6 +420,13 @@ NSString *HBMixdownChangedNotification = @"HBMixdownChangedNotification";
[newTrackArray addObject: noneTrack];
[newTrackArray addObjectsFromArray:job.title.audioTracks];
self.masterTrackArray = newTrackArray;
+
+ // Readd the controller reference to the audio tracks.
+ for (HBAudio *audioTrack in audioArray)
+ {
+ audioTrack.controller = self;
+ }
+
[self switchingTrackFromNone: nil]; // this ensures there is a None track at the end of the list
}
else
diff --git a/macosx/HBAudioDefaults.h b/macosx/HBAudioDefaults.h
index a2e30a318..a99ff05d3 100644
--- a/macosx/HBAudioDefaults.h
+++ b/macosx/HBAudioDefaults.h
@@ -5,6 +5,7 @@
It may be used under the terms of the GNU General Public License. */
#import <Foundation/Foundation.h>
+#import "HBPresetCoding.h"
typedef NS_ENUM(NSUInteger, HBAudioTrackSelectionBehavior) {
HBAudioTrackSelectionBehaviorNone,
@@ -16,7 +17,7 @@ typedef NS_ENUM(NSUInteger, HBAudioTrackSelectionBehavior) {
* HBAudioSettings
* Stores the audio defaults settings.
*/
-@interface HBAudioDefaults : NSObject <NSCoding>
+@interface HBAudioDefaults : NSObject <NSCoding, NSCopying, HBPresetCoding>
@property (nonatomic, readwrite) HBAudioTrackSelectionBehavior trackSelectionBehavior;
@property (nonatomic, readwrite, retain) NSMutableArray *trackSelectionLanguages;
@@ -34,9 +35,6 @@ typedef NS_ENUM(NSUInteger, HBAudioTrackSelectionBehavior) {
@property(nonatomic, readonly) NSArray *audioEncoderFallbacks;
-- (void)applySettingsFromPreset:(NSDictionary *)preset;
-- (void)prepareAudioDefaultsForPreset:(NSMutableDictionary *)preset;
-
- (void)validateEncoderFallbackForVideoContainer:(int)container;
@end
diff --git a/macosx/HBAudioDefaults.m b/macosx/HBAudioDefaults.m
index 3628b5564..d6b184f33 100644
--- a/macosx/HBAudioDefaults.m
+++ b/macosx/HBAudioDefaults.m
@@ -70,7 +70,7 @@
return nil;
}
-- (void)applySettingsFromPreset:(NSDictionary *)preset
+- (void)applyPreset:(NSDictionary *)preset
{
// Track selection behavior
if ([preset[@"AudioTrackSelectionBehavior"] isEqualToString:@"first"])
@@ -165,7 +165,7 @@
}
}
-- (void)prepareAudioDefaultsForPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(NSMutableDictionary *)preset
{
// Track selection behavior
if (self.trackSelectionBehavior == HBAudioTrackSelectionBehaviorFirst)
@@ -241,6 +241,34 @@
self.container = container;
}
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone
+{
+ HBAudioDefaults *copy = [[[self class] alloc] init];
+
+ if (copy)
+ {
+ copy->_trackSelectionBehavior = _trackSelectionBehavior;
+ [copy->_trackSelectionLanguages release];
+ copy->_trackSelectionLanguages = [_trackSelectionLanguages mutableCopy];
+
+ [copy->_tracksArray release];
+ copy->_tracksArray = [[NSMutableArray alloc] initWithArray:_tracksArray copyItems:YES];
+
+ copy->_allowAACPassthru = _allowAACPassthru;
+ copy->_allowAC3Passthru = _allowAC3Passthru;
+ copy->_allowDTSHDPassthru = _allowDTSHDPassthru;
+ copy->_allowDTSPassthru = _allowDTSPassthru;
+ copy->_allowMP3Passthru = _allowMP3Passthru;
+
+ copy->_encoderFallback = _encoderFallback;
+ copy->_secondaryEncoderMode = _secondaryEncoderMode;
+ }
+
+ return copy;
+}
+
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)coder
diff --git a/macosx/HBAudioTrackPreset.h b/macosx/HBAudioTrackPreset.h
index 967351715..12ded68c8 100644
--- a/macosx/HBAudioTrackPreset.h
+++ b/macosx/HBAudioTrackPreset.h
@@ -13,7 +13,7 @@
* a KVO enabled class used in the Audio Defaults panels,
* automatically validates the values.
*/
-@interface HBAudioTrackPreset : NSObject <NSCoding>
+@interface HBAudioTrackPreset : NSObject <NSCoding, NSCopying>
/**
* track properties.
diff --git a/macosx/HBAudioTrackPreset.m b/macosx/HBAudioTrackPreset.m
index 7d5cc2e90..60e10986b 100644
--- a/macosx/HBAudioTrackPreset.m
+++ b/macosx/HBAudioTrackPreset.m
@@ -217,6 +217,26 @@ static void *HBAudioEncoderContex = &HBAudioEncoderContex;
return retval;
}
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone
+{
+ HBAudioTrackPreset *copy = [[[self class] alloc] init];
+
+ if (copy)
+ {
+ copy->_encoder = _encoder;
+ copy->_mixdown = _mixdown;
+ copy->_sampleRate = _sampleRate;
+ copy->_bitRate = _bitRate;
+
+ copy->_gain = _gain;
+ copy->_drc = _drc;
+ }
+
+ return copy;
+}
+
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)coder
diff --git a/macosx/HBCore.h b/macosx/HBCore.h
index a0a831e5b..f78c26c55 100644
--- a/macosx/HBCore.h
+++ b/macosx/HBCore.h
@@ -8,6 +8,8 @@
#include "hb.h"
+@class HBJob;
+
// These constants specify the current state of HBCore.
typedef NS_ENUM(NSUInteger, HBState) {
HBStateIdle = HB_STATE_IDLE, ///< HB is doing nothing
@@ -111,6 +113,13 @@ extern NSString *HBCoreMuxingNotification;
@property (nonatomic, readonly) NSArray *titles;
/**
+ * Starts an asynchronous encoding session with the passed job.
+ *
+ * @param job the job to encode.
+ */
+- (void)encodeJob:(HBJob *)job;
+
+/**
* Starts the libhb encoding session.
*
* This method must be called after all jobs have been added.
diff --git a/macosx/HBCore.m b/macosx/HBCore.m
index 84fc15cd5..fb46f20de 100644
--- a/macosx/HBCore.m
+++ b/macosx/HBCore.m
@@ -5,7 +5,7 @@
It may be used under the terms of the GNU General Public License. */
#import "HBCore.h"
-#import "HBTitle.h"
+#import "HBJob.h"
#import "HBDVDDetector.h"
#import "HBUtilities.h"
@@ -231,6 +231,68 @@ NSString *HBCoreMuxingNotification = @"HBCoreMuxingNotification";
#pragma mark - Encodes
+- (void)encodeJob:(HBJob *)job
+{
+ hb_job_t *hb_job = job.hb_job;
+
+ [HBUtilities writeToActivityLog: "processNewQueueEncode number of passes expected is: %d", (job.video.twoPass + 1)];
+ hb_job_set_file(hb_job, job.destURL.fileSystemRepresentation);
+
+ // If scanning we need to do some extra setup of the job.
+ if (hb_job->indepth_scan == 1)
+ {
+ char *encoder_preset_tmp = hb_job->encoder_preset != NULL ? strdup(hb_job->encoder_preset) : NULL;
+ char *encoder_tune_tmp = hb_job->encoder_tune != NULL ? strdup(hb_job->encoder_tune) : NULL;
+ char *encoder_options_tmp = hb_job->encoder_options != NULL ? strdup(hb_job->encoder_options) : NULL;
+ char *encoder_profile_tmp = hb_job->encoder_profile != NULL ? strdup(hb_job->encoder_profile) : NULL;
+ char *encoder_level_tmp = hb_job->encoder_level != NULL ? strdup(hb_job->encoder_level) : NULL;
+ /*
+ * When subtitle scan is enabled do a fast pre-scan job
+ * which will determine which subtitles to enable, if any.
+ */
+ hb_job_set_encoder_preset (hb_job, NULL);
+ hb_job_set_encoder_tune (hb_job, NULL);
+ hb_job_set_encoder_options(hb_job, NULL);
+ hb_job_set_encoder_profile(hb_job, NULL);
+ hb_job_set_encoder_level (hb_job, NULL);
+ hb_job->pass = -1;
+ hb_add(self.hb_handle, hb_job);
+ /*
+ * reset the advanced settings
+ */
+ hb_job_set_encoder_preset (hb_job, encoder_preset_tmp);
+ hb_job_set_encoder_tune (hb_job, encoder_tune_tmp);
+ hb_job_set_encoder_options(hb_job, encoder_options_tmp);
+ hb_job_set_encoder_profile(hb_job, encoder_profile_tmp);
+ hb_job_set_encoder_level (hb_job, encoder_level_tmp);
+ free(encoder_preset_tmp);
+ free(encoder_tune_tmp);
+ free(encoder_options_tmp);
+ free(encoder_profile_tmp);
+ free(encoder_level_tmp);
+ }
+
+ if (job.video.twoPass)
+ {
+ hb_job->indepth_scan = 0;
+ hb_job->pass = 1;
+ hb_add(self.hb_handle, hb_job);
+ hb_job->pass = 2;
+ hb_add(self.hb_handle, hb_job);
+ }
+ else
+ {
+ hb_job->indepth_scan = 0;
+ hb_job->pass = 0;
+ hb_add(self.hb_handle, hb_job);
+ }
+
+ // Free the job
+ hb_job_close(&hb_job);
+
+ [self start];
+}
+
- (void)start
{
// Start the timer to handle libhb state changes
diff --git a/macosx/HBFilters+UIAdditions.h b/macosx/HBFilters+UIAdditions.h
index a84e652d9..8b79a2056 100644
--- a/macosx/HBFilters+UIAdditions.h
+++ b/macosx/HBFilters+UIAdditions.h
@@ -24,6 +24,11 @@
@property (nonatomic, readonly) NSArray *denoisePresets;
@property (nonatomic, readonly) NSArray *denoiseTunes;
+/**
+ * A textual summary of the filters settings.
+ */
+@property (nonatomic, readonly) NSString *summary;
+
@end
/**
diff --git a/macosx/HBFilters+UIAdditions.m b/macosx/HBFilters+UIAdditions.m
index 88fbc9e37..aae7b6bb5 100644
--- a/macosx/HBFilters+UIAdditions.m
+++ b/macosx/HBFilters+UIAdditions.m
@@ -141,4 +141,120 @@ extern NSDictionary *_HandBrake_nlmeansTunesDict;
return @[@"None", @"Film", @"Grain", @"High Motion", @"Animation"];
}
+- (NSString *)summary
+{
+ NSMutableString *summary = [NSMutableString string];
+
+ /* Detelecine */
+ switch (self.detelecine)
+ {
+ case 1:
+ [summary appendFormat:@" - Detelecine (%@)", self.detelecineCustomString];
+ break;
+
+ case 2:
+ [summary appendString:@" - Detelecine (Default)"];
+ break;
+
+ default:
+ break;
+ }
+
+ if (self.useDecomb)
+ {
+ /* Decomb */
+ switch (self.decomb)
+ {
+ case 1:
+ [summary appendFormat:@" - Decomb (%@)", self.decombCustomString];
+ break;
+
+ case 2:
+ [summary appendString:@" - Decomb (Default)"];
+ break;
+
+ case 3:
+ [summary appendString:@" - Decomb (Fast)"];
+ break;
+
+ case 4:
+ [summary appendString:@" - Decomb (Bob)"];
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* Deinterlace */
+ switch (self.deinterlace)
+ {
+ case 1:
+ [summary appendFormat:@" - Deinterlace (%@)", self.deinterlaceCustomString];
+ break;
+
+ case 2:
+ [summary appendString:@" - Deinterlace (Fast)"];
+ break;
+
+ case 3:
+ [summary appendString:@" - Deinterlace (Slow)"];
+ break;
+
+ case 4:
+ [summary appendString:@" - Deinterlace (Slower)"];
+ break;
+
+ case 5:
+ [summary appendString:@" - Deinterlace (Bob)"];
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Deblock */
+ if (self.deblock > 0)
+ {
+ [summary appendFormat:@" - Deblock (%ld)", self.deblock];
+ }
+
+ /* Denoise */
+ if (![self.denoise isEqualToString:@"off"])
+ {
+ [summary appendFormat:@" - Denoise (%@", [[_HandBrake_denoiseTypesDict allKeysForObject:self.denoise] firstObject]];
+ if (![self.denoisePreset isEqualToString:@"none"])
+ {
+ [summary appendFormat:@", %@", [[_HandBrake_denoisePresetsDict allKeysForObject:self.denoisePreset] firstObject]];
+
+ if ([self.denoise isEqualToString:@"nlmeans"])
+ {
+ [summary appendFormat:@", %@", [[_HandBrake_nlmeansTunesDict allKeysForObject:self.denoiseTune] firstObject]];
+ }
+ }
+ else
+ {
+ [summary appendFormat:@", %@", self.denoiseCustomString];
+ }
+
+ [summary appendString:@")"];
+
+ }
+
+ /* Grayscale */
+ if (self.grayscale)
+ {
+ [summary appendString:@" - Grayscale"];
+ }
+
+ if ([summary hasPrefix:@" - "])
+ {
+ [summary deleteCharactersInRange:NSMakeRange(0, 3)];
+ }
+
+ return [NSString stringWithString:summary];
+}
+
@end
diff --git a/macosx/HBFilters.h b/macosx/HBFilters.h
index 81777259b..e64808a78 100644
--- a/macosx/HBFilters.h
+++ b/macosx/HBFilters.h
@@ -5,20 +5,20 @@
It may be used under the terms of the GNU General Public License. */
#import <Foundation/Foundation.h>
+#import "HBPresetCoding.h"
extern NSString * const HBFiltersChangedNotification;
/**
* Filters settings.
*/
-@interface HBFilters : NSObject <NSCoding>
-
-- (void)prepareFiltersForPreset:(NSMutableDictionary *)preset;
-- (void)applySettingsFromPreset:(NSDictionary *)preset;
+@interface HBFilters : NSObject <NSCoding, NSCopying, HBPresetCoding>
@property (nonatomic, readwrite) NSInteger detelecine;
@property (nonatomic, readwrite, copy) NSString *detelecineCustomString;
+@property (nonatomic, readwrite) BOOL useDecomb;
+
@property (nonatomic, readwrite) NSInteger deinterlace;
@property (nonatomic, readwrite, copy) NSString *deinterlaceCustomString;
@@ -33,11 +33,4 @@ extern NSString * const HBFiltersChangedNotification;
@property (nonatomic, readwrite) NSInteger deblock;
@property (nonatomic, readwrite) BOOL grayscale;
-@property (nonatomic, readwrite) BOOL useDecomb;
-
-/**
- * A textual summary of the filters settings.
- */
-@property (nonatomic, readonly) NSString *summary;
-
@end
diff --git a/macosx/HBFilters.m b/macosx/HBFilters.m
index b09ab7d27..86ec87180 100644
--- a/macosx/HBFilters.m
+++ b/macosx/HBFilters.m
@@ -199,6 +199,37 @@ NSDictionary *_HandBrake_nlmeansTunesDict;
[self postChangedNotification];
}
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone
+{
+ HBFilters *copy = [[[self class] alloc] init];
+
+ if (copy)
+ {
+ copy->_detelecine = _detelecine;
+ copy->_detelecineCustomString = [_detelecineCustomString copy];
+
+ copy->_deinterlace = _deinterlace;
+ copy->_deinterlaceCustomString = [_deinterlaceCustomString copy];
+
+ copy->_decomb = _decomb;
+ copy->_decombCustomString = [_decombCustomString copy];
+
+ copy->_denoise = [_denoise copy];
+ copy->_denoisePreset = [_denoisePreset copy];
+ copy->_denoiseTune = [_denoiseTune copy];
+ copy->_denoiseCustomString = [_denoiseCustomString copy];
+
+ copy->_deblock = _deblock;
+ copy->_grayscale = _grayscale;
+
+ copy->_useDecomb = _useDecomb;
+ }
+
+ return copy;
+}
+
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)coder
@@ -255,7 +286,7 @@ NSDictionary *_HandBrake_nlmeansTunesDict;
#pragma mark - Presets and queue
-- (void)prepareFiltersForPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(NSMutableDictionary *)preset
{
preset[@"PictureDecombDeinterlace"] = @(self.useDecomb);
@@ -277,7 +308,7 @@ NSDictionary *_HandBrake_nlmeansTunesDict;
preset[@"VideoGrayScale"] = @(self.grayscale);
}
-- (void)applySettingsFromPreset:(NSDictionary *)preset
+- (void)applyPreset:(NSDictionary *)preset
{
self.notificationsEnabled = NO;
@@ -394,120 +425,4 @@ NSDictionary *_HandBrake_nlmeansTunesDict;
self.notificationsEnabled = YES;
}
-- (NSString *)summary
-{
- NSMutableString *summary = [NSMutableString string];
-
- /* Detelecine */
- switch (self.detelecine)
- {
- case 1:
- [summary appendFormat:@" - Detelecine (%@)", self.detelecineCustomString];
- break;
-
- case 2:
- [summary appendString:@" - Detelecine (Default)"];
- break;
-
- default:
- break;
- }
-
- if (self.useDecomb)
- {
- /* Decomb */
- switch (self.decomb)
- {
- case 1:
- [summary appendFormat:@" - Decomb (%@)", self.decombCustomString];
- break;
-
- case 2:
- [summary appendString:@" - Decomb (Default)"];
- break;
-
- case 3:
- [summary appendString:@" - Decomb (Fast)"];
- break;
-
- case 4:
- [summary appendString:@" - Decomb (Bob)"];
- break;
-
- default:
- break;
- }
- }
- else
- {
- /* Deinterlace */
- switch (self.deinterlace)
- {
- case 1:
- [summary appendFormat:@" - Deinterlace (%@)", self.deinterlaceCustomString];
- break;
-
- case 2:
- [summary appendString:@" - Deinterlace (Fast)"];
- break;
-
- case 3:
- [summary appendString:@" - Deinterlace (Slow)"];
- break;
-
- case 4:
- [summary appendString:@" - Deinterlace (Slower)"];
- break;
-
- case 5:
- [summary appendString:@" - Deinterlace (Bob)"];
- break;
-
- default:
- break;
- }
- }
-
- /* Deblock */
- if (self.deblock > 0)
- {
- [summary appendFormat:@" - Deblock (%ld)", self.deblock];
- }
-
- /* Denoise */
- if (![self.denoise isEqualToString:@"off"])
- {
- [summary appendFormat:@" - Denoise (%@", [[_HandBrake_denoiseTypesDict allKeysForObject:self.denoise] firstObject]];
- if (![self.denoisePreset isEqualToString:@"none"])
- {
- [summary appendFormat:@", %@", [[_HandBrake_denoisePresetsDict allKeysForObject:self.denoisePreset] firstObject]];
-
- if ([self.denoise isEqualToString:@"nlmeans"])
- {
- [summary appendFormat:@", %@", [[_HandBrake_nlmeansTunesDict allKeysForObject:self.denoiseTune] firstObject]];
- }
- }
- else
- {
- [summary appendFormat:@", %@", self.denoiseCustomString];
- }
-
- [summary appendString:@")"];
-
- }
-
- /* Grayscale */
- if (self.grayscale)
- {
- [summary appendString:@" - Grayscale"];
- }
-
- if ([summary hasPrefix:@" - "])
- {
- [summary deleteCharactersInRange:NSMakeRange(0, 3)];
- }
-
- return [NSString stringWithString:summary];
-}
-
@end
diff --git a/macosx/HBJob+UIAdditions.h b/macosx/HBJob+UIAdditions.h
index 357f87cc5..c7d78ddc8 100644
--- a/macosx/HBJob+UIAdditions.h
+++ b/macosx/HBJob+UIAdditions.h
@@ -10,5 +10,9 @@
@interface HBJob (UIAdditions)
@property (nonatomic, readonly) BOOL mp4OptionsEnabled;
+@property (nonatomic, readonly) NSArray *angles;
-@end \ No newline at end of file
+@end
+
+@interface HBURLTransformer : NSValueTransformer
+@end
diff --git a/macosx/HBJob+UIAdditions.m b/macosx/HBJob+UIAdditions.m
index 29836553a..6e5bf030a 100644
--- a/macosx/HBJob+UIAdditions.m
+++ b/macosx/HBJob+UIAdditions.m
@@ -21,4 +21,42 @@
}
}
+- (NSArray *)angles
+{
+ NSMutableArray *angles = [NSMutableArray array];
+ for (int i = 0; i < self.title.angles; i++)
+ {
+ [angles addObject:[NSString stringWithFormat: @"%d", i + 1]];
+ }
+ return angles;
+}
+
+@end
+
+@implementation HBURLTransformer
+
++ (Class)transformedValueClass
+{
+ return [NSString class];
+}
+
+- (id)transformedValue:(id)value
+{
+ if (value)
+ return [value path];
+ else
+ return nil;
+}
+
++ (BOOL)allowsReverseTransformation
+{
+ return YES;
+}
+
+- (id)reverseTransformedValue:(id)value
+{
+ return [NSURL fileURLWithPath:value];
+}
+
@end
+
diff --git a/macosx/HBJob.h b/macosx/HBJob.h
index 9a32c07c1..b3866f037 100644
--- a/macosx/HBJob.h
+++ b/macosx/HBJob.h
@@ -14,6 +14,8 @@
#import "HBPicture.h"
#import "HBFilters.h"
+#import "HBAudio.h"
+
#import "HBAudioDefaults.h"
#import "HBSubtitlesDefaults.h"
@@ -42,9 +44,11 @@ typedef NS_ENUM(NSUInteger, HBJobState) {
/**
* Current state of the job.
*/
-@property (nonatomic, readonly) HBJobState state;
+@property (nonatomic, readwrite) HBJobState state;
-@property (nonatomic, readonly) HBTitle *title;
+@property (nonatomic, readwrite, assign) HBTitle *title;
+@property (nonatomic, readonly) int titleIdx;
+@property (nonatomic, readwrite) int pidId;
// Urls
@property (nonatomic, readonly) NSURL *fileURL;
diff --git a/macosx/HBJob.m b/macosx/HBJob.m
index 271075dfa..8e26f7275 100644
--- a/macosx/HBJob.m
+++ b/macosx/HBJob.m
@@ -16,12 +16,6 @@
NSString *HBContainerChangedNotification = @"HBContainerChangedNotification";
NSString *keyContainerTag = @"keyContainerTag";
-@interface HBJob ()
-
-@property (nonatomic, readonly) int titleIdx;
-
-@end
-
@implementation HBJob
- (instancetype)initWithTitle:(HBTitle *)title andPreset:(HBPreset *)preset
@@ -64,42 +58,27 @@ NSString *keyContainerTag = @"keyContainerTag";
self.container = hb_container_get_from_name(hb_container_sanitize_name([content[@"FileFormat"] UTF8String]));
- // Mux mp4 with http optimization
+ // MP4 specifics options.
self.mp4HttpOptimize = [content[@"Mp4HttpOptimize"] boolValue];
self.mp4iPodCompatible = [content[@"Mp4iPodCompatible"] boolValue];
// Chapter Markers
self.chaptersEnabled = [content[@"ChapterMarkers"] boolValue];
- [@[self.audioDefaults, self.subtitlesDefaults, self.video, self.picture, self.filters] makeObjectsPerformSelector:@selector(applySettingsFromPreset:)
+ [@[self.audioDefaults, self.subtitlesDefaults, self.filters, self.picture, self.video, ] makeObjectsPerformSelector:@selector(applyPreset:)
withObject:content];
}
- (void)applyCurrentSettingsToPreset:(NSMutableDictionary *)dict
{
dict[@"FileFormat"] = @(hb_container_get_name(self.container));
-
dict[@"ChapterMarkers"] = @(self.chaptersEnabled);
-
- // Mux mp4 with http optimization
+ // MP4 specifics options.
dict[@"Mp4HttpOptimize"] = @(self.mp4HttpOptimize);
- // Add iPod uuid atom
dict[@"Mp4iPodCompatible"] = @(self.mp4iPodCompatible);
- // Video encoder
- [self.video prepareVideoForPreset:dict];
-
- // Picture Filters
- [self.filters prepareFiltersForPreset:dict];
-
- // Picture Size
- [self.picture preparePictureForPreset:dict];
-
- // Audio
- [self.audioDefaults prepareAudioDefaultsForPreset:dict];
-
- // Subtitles
- [self.subtitlesDefaults prepareSubtitlesDefaultsForPreset:dict];
+ [@[self.video, self.filters, self.picture, self.audioDefaults, self.subtitlesDefaults] makeObjectsPerformSelector:@selector(writeToPreset:)
+ withObject:dict];
}
- (void)setContainer:(int)container
@@ -114,6 +93,13 @@ NSString *keyContainerTag = @"keyContainerTag";
userInfo:@{keyContainerTag: @(self.container)}]];
}
+- (void)setTitle:(HBTitle *)title
+{
+ _title = title;
+ self.range.title = title;
+ self.picture.title = title;
+}
+
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *retval = nil;
@@ -131,13 +117,18 @@ NSString *keyContainerTag = @"keyContainerTag";
[_audioTracks release];
[_subtitlesTracks release];
+ [_fileURL release];
+ [_destURL release];
+
+ [_range release];
[_video release];
[_picture release];
[_filters release];
[_audioDefaults release];
[_subtitlesDefaults release];
- [_fileURL release];
+
+ [_chapterTitles release];
[super dealloc];
}
@@ -342,9 +333,6 @@ NSString *keyContainerTag = @"keyContainerTag";
for (NSDictionary *subtitleDict in self.subtitlesTracks)
{
- if (i == self.subtitlesTracks.count - 1)
- continue;
-
int subtitle = [subtitleDict[keySubTrackIndex] intValue];
int force = [subtitleDict[keySubTrackForced] intValue];
int burned = [subtitleDict[keySubTrackBurned] intValue];
@@ -523,19 +511,20 @@ NSString *keyContainerTag = @"keyContainerTag";
// Detelecine
hb_filter_object_t *filter;
- filter = hb_filter_init(HB_FILTER_DETELECINE);
if (self.filters.detelecine == 1)
{
+ filter = hb_filter_init(HB_FILTER_DETELECINE);
// use a custom detelecine string
hb_add_filter(job, filter, self.filters.detelecineCustomString.UTF8String);
}
else if (self.filters.detelecine == 2)
{
+ filter = hb_filter_init(HB_FILTER_DETELECINE);
// Use libhb's default values
hb_add_filter(job, filter, NULL);
}
- if (self.filters.useDecomb)
+ if (self.filters.useDecomb && self.filters.decomb)
{
// Decomb
filter = hb_filter_init(HB_FILTER_DECOMB);
@@ -560,7 +549,7 @@ NSString *keyContainerTag = @"keyContainerTag";
hb_add_filter(job, filter, "455");
}
}
- else
+ else if (self.filters.deinterlace)
{
// Deinterlace
filter = hb_filter_init(HB_FILTER_DEINTERLACE);
@@ -619,9 +608,9 @@ NSString *keyContainerTag = @"keyContainerTag";
// NOTE: even though there is a valid deblock setting of 0 for the filter, for
// the macgui's purposes a value of 0 actually means to not even use the filter
// current hb_filter_deblock.settings valid ranges are from 5 - 15
- filter = hb_filter_init(HB_FILTER_DEBLOCK);
if (self.filters.deblock != 0)
{
+ filter = hb_filter_init(HB_FILTER_DEBLOCK);
hb_add_filter(job, filter, [NSString stringWithFormat:@"%ld", (long)self.filters.deblock].UTF8String);
}
@@ -640,6 +629,56 @@ NSString *keyContainerTag = @"keyContainerTag";
return job;
}
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone
+{
+ HBJob *copy = [[[self class] alloc] init];
+
+ if (copy)
+ {
+ copy->_state = HBJobStateReady;
+ copy->_titleIdx = _titleIdx;
+ copy->_pidId = _pidId;
+
+ copy->_fileURL = [_fileURL copy];
+ copy->_destURL = [_destURL copy];
+
+ copy->_container = _container;
+ copy->_angle = _angle;
+ copy->_mp4HttpOptimize = _mp4HttpOptimize;
+ copy->_mp4iPodCompatible = _mp4iPodCompatible;
+
+ copy->_range = [_range copy];
+ copy->_video = [_video copy];
+ copy->_picture = [_picture copy];
+ copy->_filters = [_filters copy];
+
+ // Copy the tracks, but not the last one because it's empty.
+ copy->_audioTracks = [[NSMutableArray alloc] init];
+ [_audioTracks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+ if (idx < _audioTracks.count - 1)
+ {
+ [copy->_audioTracks addObject:[[obj copy] autorelease]];
+ }
+ }];
+ copy->_subtitlesTracks = [[NSMutableArray alloc] init];
+ [_subtitlesTracks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+ if (idx < _subtitlesTracks.count - 1)
+ {
+ [copy->_subtitlesTracks addObject:[[obj copy] autorelease]];
+ }
+ }];
+ copy->_chaptersEnabled = _chaptersEnabled;
+ copy->_chapterTitles = [[NSMutableArray alloc] initWithArray:_chapterTitles copyItems:YES];
+
+ copy->_audioDefaults = [_audioDefaults copy];
+ copy->_subtitlesDefaults = [_subtitlesDefaults copy];
+ }
+
+ return copy;
+}
+
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)coder
@@ -648,6 +687,7 @@ NSString *keyContainerTag = @"keyContainerTag";
encodeInt(_state);
encodeInt(_titleIdx);
+ encodeInt(_pidId);
encodeObject(_fileURL);
encodeObject(_destURL);
@@ -678,6 +718,7 @@ NSString *keyContainerTag = @"keyContainerTag";
decodeInt(_state);
decodeInt(_titleIdx);
+ decodeInt(_pidId);
decodeObject(_fileURL);
decodeObject(_destURL);
@@ -692,6 +733,8 @@ NSString *keyContainerTag = @"keyContainerTag";
decodeObject(_picture);
decodeObject(_filters);
+ _video.job = self;
+
decodeObject(_audioTracks);
decodeObject(_subtitlesTracks);
@@ -704,11 +747,4 @@ NSString *keyContainerTag = @"keyContainerTag";
return self;
}
-#pragma mark - NSCopying
-
-- (instancetype)copyWithZone:(NSZone *)zone
-{
- return nil;
-}
-
@end
diff --git a/macosx/HBPicture+UIAdditions.h b/macosx/HBPicture+UIAdditions.h
index 367127870..e19d627d2 100644
--- a/macosx/HBPicture+UIAdditions.h
+++ b/macosx/HBPicture+UIAdditions.h
@@ -13,6 +13,7 @@
* UI enabled bindings
*/
@property (nonatomic, readonly) NSString *info;
+@property (nonatomic, readonly) NSString *summary;
@property (nonatomic, readonly) int maxWidth;
@property (nonatomic, readonly) int maxHeight;
diff --git a/macosx/HBPicture+UIAdditions.m b/macosx/HBPicture+UIAdditions.m
index 04a4a5afd..e07e30667 100644
--- a/macosx/HBPicture+UIAdditions.m
+++ b/macosx/HBPicture+UIAdditions.m
@@ -86,4 +86,23 @@
return sizeInfo;
}
+- (NSString *)summary
+{
+ NSMutableString *summary = [NSMutableString stringWithString:@""];
+ [summary appendString:self.info];
+
+ if (self.anamorphicMode != HB_ANAMORPHIC_STRICT)
+ {
+ // anamorphic is not Strict, show the modulus
+ [summary appendFormat:@", Modulus: %d", self.modulus];
+ }
+
+ [summary appendFormat:@", Crop: %s %d/%d/%d/%d",
+ self.autocrop ? "Auto" : "Custom",
+ self.cropTop, self.cropBottom,
+ self.cropLeft, self.cropRight];
+
+ return [[summary copy] autorelease];
+}
+
@end
diff --git a/macosx/HBPicture.h b/macosx/HBPicture.h
index e68fa627c..ce63e68c2 100644
--- a/macosx/HBPicture.h
+++ b/macosx/HBPicture.h
@@ -5,6 +5,7 @@
It may be used under the terms of the GNU General Public License. */
#import <Foundation/Foundation.h>
+#import "HBPresetCoding.h"
@class HBTitle;
@@ -13,16 +14,10 @@ extern NSString * const HBPictureChangedNotification;
/**
* HBPicture
*/
-@interface HBPicture : NSObject <NSCoding>
+@interface HBPicture : NSObject <NSCoding, NSCopying, HBPresetCoding>
- (instancetype)initWithTitle:(HBTitle *)title;
-- (void)applyPictureSettingsFromQueue:(NSDictionary *)queueToApply;
-- (void)preparePictureForQueueFileJob:(NSMutableDictionary *)queueFileJob;
-
-- (void)preparePictureForPreset:(NSMutableDictionary *)preset;
-- (void)applySettingsFromPreset:(NSDictionary *)preset;
-
@property (nonatomic, readwrite) int width;
@property (nonatomic, readwrite) int height;
diff --git a/macosx/HBPicture.m b/macosx/HBPicture.m
index 1719eeb1a..c758580a0 100644
--- a/macosx/HBPicture.m
+++ b/macosx/HBPicture.m
@@ -413,6 +413,35 @@ NSString * const HBPictureChangedNotification = @"HBPictureChangedNotification";
[self postChangedNotification];
}
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone
+{
+ HBPicture *copy = [[[self class] alloc] init];
+
+ if (copy)
+ {
+ copy->_width = _width;
+ copy->_height = _height;
+
+ copy->_keepDisplayAspect = _keepDisplayAspect;
+ copy->_anamorphicMode = _anamorphicMode;
+ copy->_modulus = _modulus;
+
+ copy->_displayWidth = _displayWidth;
+ copy->_parWidth = _parWidth;
+ copy->_parHeight = _parHeight;
+
+ copy->_autocrop = _autocrop;
+ copy->_cropTop = _cropTop;
+ copy->_cropBottom = _cropBottom;
+ copy->_cropLeft = _cropLeft;
+ copy->_cropRight = _cropRight;
+ }
+
+ return copy;
+}
+
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)coder
@@ -463,7 +492,7 @@ NSString * const HBPictureChangedNotification = @"HBPictureChangedNotification";
#pragma mark - Presets/Queue
-- (void)preparePictureForPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(NSMutableDictionary *)preset
{
preset[@"PictureKeepRatio"] = @(self.keepDisplayAspect);
preset[@"PicturePAR"] = @(self.anamorphicMode);
@@ -478,7 +507,7 @@ NSString * const HBPictureChangedNotification = @"HBPictureChangedNotification";
preset[@"PictureRightCrop"] = @(self.cropRight);
}
-- (void)applySettingsFromPreset:(NSDictionary *)preset
+- (void)applyPreset:(NSDictionary *)preset
{
self.validating = YES;
hb_title_t *title = self.title.hb_title;
@@ -607,64 +636,4 @@ NSString * const HBPictureChangedNotification = @"HBPictureChangedNotification";
self.validating = NO;
}
-- (void)preparePictureForQueueFileJob:(NSMutableDictionary *)queueFileJob
-{
- queueFileJob[@"PictureWidth"] = @(self.width);
- queueFileJob[@"PictureHeight"] = @(self.height);
-
- queueFileJob[@"PictureKeepRatio"] = @(self.keepDisplayAspect);
- queueFileJob[@"PicturePAR"] = @(self.anamorphicMode);
-
- queueFileJob[@"PictureModulus"] = @(self.modulus);
-
- queueFileJob[@"PicturePARPixelWidth"] = @(self.parWidth);
- queueFileJob[@"PicturePARPixelHeight"] = @(self.parHeight);
-
- queueFileJob[@"PictureAutoCrop"] = @(self.autocrop);
- queueFileJob[@"PictureTopCrop"] = @(self.cropTop);
- queueFileJob[@"PictureBottomCrop"] = @(self.cropBottom);
- queueFileJob[@"PictureLeftCrop"] = @(self.cropLeft);
- queueFileJob[@"PictureRightCrop"] = @(self.cropRight);
-}
-
-- (void)applyPictureSettingsFromQueue:(NSDictionary *)queueToApply
-{
- self.validating = YES;
- /* If Cropping is set to custom, then recall all four crop values from
- when the preset was created and apply them */
- if ([queueToApply[@"PictureAutoCrop"] intValue] == 0)
- {
- self.autocrop = NO;
-
- /* Here we use the custom crop values saved at the time the preset was saved */
- self.cropTop = [queueToApply[@"PictureTopCrop"] intValue];
- self.cropBottom = [queueToApply[@"PictureBottomCrop"] intValue];
- self.cropLeft = [queueToApply[@"PictureLeftCrop"] intValue];
- self.cropRight = [queueToApply[@"PictureRightCrop"] intValue];
-
- }
- else /* if auto crop has been saved in preset, set to auto and use post scan auto crop */
- {
- self.autocrop = YES;
-
- hb_title_t *title = self.title.hb_title;
-
- /* Here we use the auto crop values determined right after scan */
- self.cropTop = title->crop[0];
- self.cropBottom = title->crop[1];
- self.cropLeft = title->crop[2];
- self.cropRight = title->crop[3];
-
- }
-
- self.anamorphicMode = [[queueToApply objectForKey:@"PicturePAR"] intValue];
- self.modulus = [[queueToApply objectForKey:@"PictureModulus"] intValue];
- self.keepDisplayAspect = [[queueToApply objectForKey:@"PictureKeepRatio"] intValue];
- self.width = [[queueToApply objectForKey:@"PictureWidth"] intValue];
- self.height = [[queueToApply objectForKey:@"PictureHeight"] intValue];
-
- self.validating = NO;
- [self validateSettings];
-}
-
@end
diff --git a/macosx/HBPresetCoding.h b/macosx/HBPresetCoding.h
new file mode 100644
index 000000000..f1464c0b2
--- /dev/null
+++ b/macosx/HBPresetCoding.h
@@ -0,0 +1,15 @@
+/* HBPresetCoding.h $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#import <Foundation/Foundation.h>
+
+@protocol HBPresetCoding <NSObject>
+
+- (void)applyPreset:(NSDictionary *)preset;
+- (void)writeToPreset:(NSMutableDictionary *)preset;
+
+
+@end \ No newline at end of file
diff --git a/macosx/HBQueueController.h b/macosx/HBQueueController.h
index 4a366224f..41f76698b 100644
--- a/macosx/HBQueueController.h
+++ b/macosx/HBQueueController.h
@@ -1,27 +1,21 @@
-/* HBQueueController
+/* HBQueueController.h
This file is part of the HandBrake source code.
Homepage: <http://handbrake.fr/>.
It may be used under the terms of the GNU General Public License. */
-
#import <Cocoa/Cocoa.h>
-#include "hb.h"
@class HBController;
+@class HBCore;
@interface HBQueueController : NSWindowController <NSToolbarDelegate, NSWindowDelegate>
- (void)setPidNum: (int)myPidnum;
-- (void)setHandle: (hb_handle_t *)handle;
+- (void)setCore: (HBCore *)core;
- (void)setHBController: (HBController *)controller;
- (void)setQueueArray: (NSMutableArray *)QueueFileArray;
-
-/* Animate the icon for the current encode */
-- (void) animateWorkingEncodeIconInQueue;
-- (void) startAnimatingCurrentWorkingEncodeInQueue;
-- (void) stopAnimatingCurrentJobGroupInQueue;
- (void)setQueueStatusString: (NSString *)statusString;
- (IBAction)showQueueWindow: (id)sender;
diff --git a/macosx/HBQueueController.mm b/macosx/HBQueueController.mm
index d81870793..82bc7d83f 100644
--- a/macosx/HBQueueController.mm
+++ b/macosx/HBQueueController.mm
@@ -5,12 +5,18 @@
It may be used under the terms of the GNU General Public License. */
#import "HBQueueController.h"
+#import "HBCore.h"
#import "Controller.h"
#import "HBQueueOutlineView.h"
#import "HBImageAndTextCell.h"
#import "HBUtilities.h"
+#import "HBJob.h"
+
+#import "HBPicture+UIAdditions.h"
+#import "HBFilters+UIAdditions.h"
+
#define HB_ROW_HEIGHT_TITLE_ONLY 17.0
// Pasteboard type for or drag operations
@@ -39,7 +45,6 @@
@interface HBQueueController () <HBQueueOutlineViewDelegate>
{
- hb_handle_t *fQueueEncodeLibhb; // reference to libhb
HBController *fHBController; // reference to HBController
NSMutableArray *fJobGroups; // mirror image of the queue array from controller.mm
@@ -70,6 +75,8 @@
NSDictionary *shortHeightAttr;
}
+@property (nonatomic, readonly) HBCore *queueCore;
+
/* control encodes in the window */
- (IBAction)removeSelectedQueueItem: (id)sender;
- (IBAction)revealSelectedQueueItem: (id)sender;
@@ -110,40 +117,31 @@
[fOutlineView reloadData];
- /* lets get the stats on the status of the queue array */
+ // lets get the stats on the status of the queue array
fPendingCount = 0;
fWorkingCount = 0;
-
- /* We use a number system to set the encode status of the queue item
- * in controller.mm
- * 0 == already encoded
- * 1 == is being encoded
- * 2 == is yet to be encoded
- * 3 == cancelled
- */
+
int i = 0;
- NSDictionary *thisQueueDict = nil;
- for (id tempObject in fJobGroups)
+ for (HBJob *job in fJobGroups)
{
- thisQueueDict = tempObject;
- if ([thisQueueDict[@"Status"] intValue] == 1) // being encoded
+ if (job.state == HBJobStateWorking) // being encoded
{
fWorkingCount++;
- /* we have an encoding job so, lets start the animation timer */
- if (thisQueueDict[@"EncodingPID"] && [thisQueueDict[@"EncodingPID"] intValue] == pidNum)
+ // we have an encoding job so, lets start the animation timer
+ if (job.pidId == pidNum)
{
fEncodingQueueItem = i;
}
}
- if ([thisQueueDict[@"Status"] intValue] == 2) // pending
+ if (job.state == HBJobStateReady) // pending
{
fPendingCount++;
}
i++;
}
-
- /* Set the queue status field in the queue window */
+
+ // Set the queue status field in the queue window
NSMutableString *string;
if (fPendingCount == 0)
{
@@ -199,9 +197,9 @@
//------------------------------------------------------------------------------------
// Receive HB handle
//------------------------------------------------------------------------------------
-- (void)setHandle: (hb_handle_t *)handle
+- (void)setCore: (HBCore *)core
{
- fQueueEncodeLibhb = handle;
+ _queueCore = core;
}
//------------------------------------------------------------------------------------
@@ -267,16 +265,14 @@
// Optional method: This message is sent to us since we are the target of some
// toolbar item actions.
- if (!fQueueEncodeLibhb) return NO;
+ if (!self.queueCore) return NO;
BOOL enable = NO;
-
- hb_state_t s;
- hb_get_state2 (fQueueEncodeLibhb, &s);
+ HBState s = self.queueCore.state;
if ([[toolbarItem itemIdentifier] isEqualToString:@"HBQueueStartCancelToolbarIdentifier"])
{
- if ((s.state == HB_STATE_PAUSED) || (s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
+ if ((s == HBStatePaused) || (s == HBStateWorking) || (s == HBStateMuxing))
{
enable = YES;
[toolbarItem setImage:[NSImage imageNamed: @"stopencode"]];
@@ -303,7 +299,7 @@
if ([[toolbarItem itemIdentifier] isEqualToString:@"HBQueuePauseResumeToolbarIdentifier"])
{
- if (s.state == HB_STATE_PAUSED)
+ if (s == HBStatePaused)
{
enable = YES;
[toolbarItem setImage:[NSImage imageNamed: @"encode"]];
@@ -311,7 +307,7 @@
[toolbarItem setToolTip: @"Resume Encoding"];
}
- else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
+ else if ((s == HBStateWorking) || (s == HBStateMuxing))
{
enable = YES;
[toolbarItem setImage:[NSImage imageNamed: @"pauseencode"]];
@@ -348,13 +344,13 @@
{
NSIndexSet *targetedRow = [fOutlineView targetedRowIndexes];
NSUInteger row = [targetedRow firstIndex];
- if( row == NSNotFound )
+ if (row == NSNotFound)
return;
/* if this is a currently encoding job, we need to be sure to alert the user,
* to let them decide to cancel it first, then if they do, we can come back and
* remove it */
- if ([fJobGroups[row][@"Status"] integerValue] == 1)
+ if ([fJobGroups[row] state] == HBJobStateWorking)
{
/* We pause the encode here so that it doesn't finish right after and then
* screw up the sync while the window is open
@@ -383,8 +379,8 @@
}
else
{
- /* since we are not a currently encoding item, we can just be removed */
- [fHBController removeQueueFileItem:row];
+ // since we are not a currently encoding item, we can just be removed
+ [fHBController removeQueueFileItem:row];
}
}
@@ -437,16 +433,17 @@
//------------------------------------------------------------------------------------
- (IBAction)toggleStartCancel: (id)sender
{
- if (!fQueueEncodeLibhb) return;
+ if (!self.queueCore) return;
- hb_state_t s;
- hb_get_state2 (fQueueEncodeLibhb, &s);
-
- if ((s.state == HB_STATE_PAUSED) || (s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
+ HBState s = self.queueCore.state;
+ if ((s == HBStatePaused) || (s == HBStateWorking) || (s == HBStateMuxing))
+ {
[fHBController Cancel: self];
-
+ }
else if (fPendingCount > 0)
+ {
[fHBController Rip: NULL];
+ }
}
//------------------------------------------------------------------------------------
@@ -454,24 +451,21 @@
//------------------------------------------------------------------------------------
- (IBAction)togglePauseResume: (id)sender
{
- if (!fQueueEncodeLibhb) return;
-
- hb_state_t s;
- hb_get_state2 (fQueueEncodeLibhb, &s);
-
- if (s.state == HB_STATE_PAUSED)
+ if (!self.queueCore) return;
+
+ HBState s = self.queueCore.state;
+ if (s == HBStatePaused)
{
- hb_resume (fQueueEncodeLibhb);
+ [self.queueCore resume];
[self startAnimatingCurrentWorkingEncodeInQueue];
}
- else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
+ else if ((s == HBStateWorking) || (s == HBStateMuxing))
{
- hb_pause (fQueueEncodeLibhb);
+ [self.queueCore pause];
[self stopAnimatingCurrentJobGroupInQueue];
}
}
-
//------------------------------------------------------------------------------------
// Send the selected queue item back to the main window for rescan and possible edit.
//------------------------------------------------------------------------------------
@@ -486,14 +480,14 @@
/* if this is a currently encoding job, we need to be sure to alert the user,
* to let them decide to cancel it first, then if they do, we can come back and
* remove it */
-
- if ([fJobGroups[row][@"Status"] integerValue] == 1)
+
+ HBJob *job = fJobGroups[row];
+ if (job.state == HBJobStateWorking)
{
- /* We pause the encode here so that it doesn't finish right after and then
- * screw up the sync while the window is open
- */
- [fHBController Pause:NULL];
- NSString *alertTitle = [NSString stringWithFormat:NSLocalizedString(@"Stop This Encode and Remove It ?", nil)];
+ // We pause the encode here so that it doesn't finish right after and then
+ // screw up the sync while the window is open
+ [fHBController Pause:NULL];
+ NSString *alertTitle = [NSString stringWithFormat:NSLocalizedString(@"Stop This Encode and Remove It ?", nil)];
// Which window to attach the sheet to?
NSWindow *docWindow = nil;
if ([sender respondsToSelector: @selector(window)])
@@ -517,10 +511,7 @@
else
{
/* since we are not a currently encoding item, we can just be cancelled */
- [fHBController rescanQueueItemToMainWindow:fJobGroups[row][@"SourcePath"]
- scanTitleNum:[fJobGroups[row][@"TitleNumber"] integerValue]
- selectedQueueItem:row];
-
+ [fHBController rescanQueueItemToMainWindow:row];
}
}
@@ -721,45 +712,45 @@
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
/* Below should be put into a separate method but I am way too f'ing lazy right now */
- NSMutableAttributedString * finalString = [[NSMutableAttributedString alloc] initWithString: @""];
-
+ NSMutableAttributedString *finalString = [[NSMutableAttributedString alloc] initWithString: @""];
+ HBJob *job = item;
+
/* First line, we should strip the destination path and just show the file name and add the title num and chapters (if any) */
- NSString * summaryInfo;
+ NSString *summaryInfo;
- NSString * titleString = [NSString stringWithFormat:@"Title %d", [item[@"TitleNumber"] intValue]];
+ NSString *titleString = [NSString stringWithFormat:@"Title %d", job.titleIdx];
- NSString * startStopString = @"";
- if ([item[@"fEncodeStartStop"] intValue] == 0)
+ NSString *startStopString = @"";
+ if (job.range.type == HBRangeTypeChapters)
{
- /* Start Stop is chapters */
- startStopString = ([item[@"ChapterStart"] intValue] == [item[@"ChapterEnd"] intValue]) ?
- [NSString stringWithFormat:@"Chapter %d", [item[@"ChapterStart"] intValue]] :
- [NSString stringWithFormat:@"Chapters %d through %d", [item[@"ChapterStart"] intValue], [item[@"ChapterEnd"] intValue]];
+ // Start Stop is chapters
+ startStopString = (job.range.chapterStart == job.range.chapterStop) ?
+ [NSString stringWithFormat:@"Chapter %d", job.range.chapterStart] :
+ [NSString stringWithFormat:@"Chapters %d through %d", job.range.chapterStart, job.range.chapterStop];
}
- else if ([item[@"fEncodeStartStop"] intValue] == 1)
+ else if (job.range.type == HBRangeTypeSeconds)
{
- /* Start Stop is seconds */
- startStopString = [NSString stringWithFormat:@"Seconds %d through %d", [item[@"StartSeconds"] intValue], [item[@"StartSeconds"] intValue] + [item[@"StopSeconds"] intValue]];
+ // Start Stop is seconds
+ startStopString = [NSString stringWithFormat:@"Seconds %d through %d", job.range.secondsStart, job.range.secondsStop];
}
- else if ([item[@"fEncodeStartStop"] intValue] == 2)
+ else if (job.range.type == HBRangeTypeFrames)
{
- /* Start Stop is Frames */
- startStopString = [NSString stringWithFormat:@"Frames %d through %d", [item[@"StartFrame"] intValue], [item[@"StartFrame"] intValue] + [item[@"StopFrame"] intValue]];
+ // Start Stop is Frames
+ startStopString = [NSString stringWithFormat:@"Frames %d through %d", job.range.frameStart, job.range.frameStop];
}
-
- NSString * passesString = @"";
- /* check to see if our first subtitle track is Foreign Language Search, in which case there is an in depth scan */
- if ([item[@"SubtitleList"] count] && [item[@"SubtitleList"][0][@"keySubTrackIndex"] intValue] == -1)
+ NSString *passesString = @"";
+ // check to see if our first subtitle track is Foreign Language Search, in which case there is an in depth scan
+ if (job.subtitlesTracks.count && [job.subtitlesTracks[0][@"keySubTrackIndex"] intValue] == -1)
{
- passesString = [passesString stringByAppendingString:@"1 Foreign Language Search Pass - "];
+ passesString = [passesString stringByAppendingString:@"1 Foreign Language Search Pass - "];
}
- if ([item[@"VideoTwoPass"] intValue] == 0)
+ if (job.video.twoPass == YES)
{
passesString = [passesString stringByAppendingString:@"1 Video Pass"];
}
else
{
- if ([item[@"VideoTurboTwoPass"] intValue] == 1)
+ if (job.video.turboTwoPass == YES)
{
passesString = [passesString stringByAppendingString:@"2 Video Passes First Turbo"];
}
@@ -768,197 +759,206 @@
passesString = [passesString stringByAppendingString:@"2 Video Passes"];
}
}
-
- [finalString appendString:[NSString stringWithFormat:@"%@", item[@"SourceName"]] withAttributes:titleAttr];
-
+
+ [finalString appendString:[NSString stringWithFormat:@"%@", job.fileURL.path.lastPathComponent] withAttributes:titleAttr];
+
+
/* lets add the output file name to the title string here */
- NSString * outputFilenameString = [item[@"DestinationPath"] lastPathComponent];
+ NSString *outputFilenameString = job.destURL.lastPathComponent;
summaryInfo = [NSString stringWithFormat: @" (%@, %@, %@) -> %@", titleString, startStopString, passesString, outputFilenameString];
-
- [finalString appendString:[NSString stringWithFormat:@"%@\n", summaryInfo] withAttributes:detailAttr];
-
+
+ [finalString appendString:[NSString stringWithFormat:@"%@\n", summaryInfo] withAttributes:detailAttr];
+
// Insert a short-in-height line to put some white space after the title
[finalString appendString:@"\n" withAttributes:shortHeightAttr];
// End of Title Stuff
-
- /* Second Line (Preset Name)*/
- [finalString appendString: @"Preset: " withAttributes:detailBoldAttr];
- [finalString appendString:[NSString stringWithFormat:@"%@\n", item[@"PresetName"]] withAttributes:detailAttr];
-
- /* Third Line (Format Summary) */
- NSString * audioCodecSummary = @""; // This seems to be set by the last track we have available...
- /* Lets also get our audio track detail since we are going through the logic for use later */
- NSMutableArray *audioDetails = [NSMutableArray arrayWithCapacity: [item[@"AudioList"] count]];
+ // Second Line (Preset Name)
+ // FIXME
+ //[finalString appendString: @"Preset: " withAttributes:detailBoldAttr];
+ //[finalString appendString:[NSString stringWithFormat:@"%@\n", item[@"PresetName"]] withAttributes:detailAttr];
+
+
+ // Third Line (Format Summary)
+ NSString *audioCodecSummary = @""; // This seems to be set by the last track we have available...
+ // Lets also get our audio track detail since we are going through the logic for use later
+
+ NSMutableArray *audioDetails = [NSMutableArray arrayWithCapacity:job.audioTracks.count];
BOOL autoPassthruPresent = NO;
- for (NSDictionary *audioTrack in item[@"AudioList"])
+ for (HBAudio *audioTrack in job.audioTracks)
{
- audioCodecSummary = [NSString stringWithFormat: @"%@", audioTrack[@"Encoder"]];
- NSNumber *drc = audioTrack[@"TrackDRCSlider"];
- NSNumber *gain = audioTrack[@"TrackGainSlider"];
+ audioCodecSummary = [NSString stringWithFormat: @"%@", audioTrack.codec[keyAudioCodecName]];
+ NSNumber *drc = audioTrack.drc;
+ NSNumber *gain = audioTrack.gain;
NSString *detailString = [NSString stringWithFormat: @"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps), DRC: %@, Gain: %@",
- audioTrack[@"TrackDescription"],
- audioTrack[@"Encoder"],
- audioTrack[@"Mixdown"],
- audioTrack[@"Samplerate"],
- audioTrack[@"Bitrate"],
+ audioTrack.track[keyAudioTrackName],
+ audioTrack.codec[keyAudioCodecName],
+ audioTrack.mixdown[keyAudioMixdownName],
+ audioTrack.sampleRate[keyAudioSampleRateName],
+ audioTrack.bitRate[keyAudioBitrateName],
(0.0 < [drc floatValue]) ? (NSObject *)drc : (NSObject *)@"Off",
(0.0 != [gain floatValue]) ? (NSObject *)gain : (NSObject *)@"Off"
];
[audioDetails addObject: detailString];
// check if we have an Auto Passthru output track
- if ([audioTrack[@"Encoder"] isEqualToString: @"Auto Passthru"])
+ if ([audioTrack.codec[keyAudioCodecName] isEqualToString: @"Auto Passthru"])
{
autoPassthruPresent = YES;
}
}
- NSString * jobFormatInfo;
- if ([item[@"ChapterMarkers"] intValue] == 1)
- jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video %@ Audio, Chapter Markers\n", item[@"FileFormat"], item[@"VideoEncoder"], audioCodecSummary];
+ NSString *jobFormatInfo;
+ if (job.chaptersEnabled)
+ jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video %@ Audio, Chapter Markers\n",
+ @(hb_container_get_name(job.container)), @(hb_video_encoder_get_name(job.video.encoder)), audioCodecSummary];
else
- jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video %@ Audio\n", item[@"FileFormat"], item[@"VideoEncoder"], audioCodecSummary];
-
+ jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video %@ Audio\n",
+ @(hb_container_get_name(job.container)), @(hb_video_encoder_get_name(job.video.encoder)), audioCodecSummary];
[finalString appendString: @"Format: " withAttributes:detailBoldAttr];
[finalString appendString: jobFormatInfo withAttributes:detailAttr];
-
- /* Optional String for muxer options */
- if ([item[@"MuxerOptionsSummary"] length])
+
+ // Optional String for muxer options
+ NSMutableString *containerOptions = [NSMutableString stringWithString:@""];
+ if ((job.container & HB_MUX_MASK_MP4) && job.mp4HttpOptimize)
+ {
+ [containerOptions appendString:@" - Web optimized"];
+ }
+ if ((job.container & HB_MUX_MASK_MP4) && job.mp4iPodCompatible)
+ {
+ [containerOptions appendString:@" - iPod 5G support"];
+ }
+ if ([containerOptions hasPrefix:@" - "])
+ {
+ [containerOptions deleteCharactersInRange:NSMakeRange(0, 3)];
+ }
+ if (containerOptions.length)
{
- NSString *containerOptions = [NSString stringWithFormat:@"%@",
- item[@"MuxerOptionsSummary"]];
[finalString appendString:@"Container Options: " withAttributes:detailBoldAttr];
[finalString appendString:containerOptions withAttributes:detailAttr];
[finalString appendString:@"\n" withAttributes:detailAttr];
}
-
- /* Fourth Line (Destination Path)*/
+
+ // Fourth Line (Destination Path)
[finalString appendString: @"Destination: " withAttributes:detailBoldAttr];
- [finalString appendString: item[@"DestinationPath"] withAttributes:detailAttr];
+ [finalString appendString: job.destURL.path withAttributes:detailAttr];
[finalString appendString:@"\n" withAttributes:detailAttr];
-
- /* Fifth Line Picture Details*/
- NSString *pictureInfo = [NSString stringWithFormat:@"%@",
- item[@"PictureSettingsSummary"]];
- if ([item[@"PictureKeepRatio"] intValue] == 1)
+
+
+ // Fifth Line Picture Details
+ NSString *pictureInfo = [NSString stringWithFormat:@"%@", job.picture.summary];
+ if (job.picture.keepDisplayAspect)
{
pictureInfo = [pictureInfo stringByAppendingString:@" Keep Aspect Ratio"];
}
[finalString appendString:@"Picture: " withAttributes:detailBoldAttr];
[finalString appendString:pictureInfo withAttributes:detailAttr];
[finalString appendString:@"\n" withAttributes:detailAttr];
-
+
/* Optional String for Picture Filters */
- if ([item[@"PictureFiltersSummary"] length])
+ if (job.filters.summary.length)
{
- NSString *pictureFilters = [NSString stringWithFormat:@"%@",
- item[@"PictureFiltersSummary"]];
+ NSString *pictureFilters = [NSString stringWithFormat:@"%@", job.filters.summary];
[finalString appendString:@"Filters: " withAttributes:detailBoldAttr];
[finalString appendString:pictureFilters withAttributes:detailAttr];
[finalString appendString:@"\n" withAttributes:detailAttr];
}
+
+ // Sixth Line Video Details
+ NSString * videoInfo = [NSString stringWithFormat:@"Encoder: %@", @(hb_video_encoder_get_name(job.video.encoder))];
- /* Sixth Line Video Details*/
- NSString * videoInfo;
- videoInfo = [NSString stringWithFormat:@"Encoder: %@", item[@"VideoEncoder"]];
-
- /* for framerate look to see if we are using vfr detelecine */
- if ([item[@"JobIndexVideoFramerate"] intValue] == 0)
+ // for framerate look to see if we are using vfr detelecine
+ if (job.video.frameRate == 0)
{
- if ([item[@"VideoFramerateMode"] isEqualToString:@"vfr"])
+ if (job.video.frameRateMode == 0)
{
- /* we are using same as source with vfr detelecine */
+ // we are using same as source with vfr detelecine
videoInfo = [NSString stringWithFormat:@"%@ Framerate: Same as source (Variable Frame Rate)", videoInfo];
}
else
{
- /* we are using a variable framerate without dropping frames */
+ // we are using a variable framerate without dropping frames
videoInfo = [NSString stringWithFormat:@"%@ Framerate: Same as source (Constant Frame Rate)", videoInfo];
}
}
else
{
- /* we have a specified, constant framerate */
- if ([item[@"VideoFramerateMode"] isEqualToString:@"pfr"])
+ // we have a specified, constant framerate
+ if (job.video.frameRate == 0)
{
- videoInfo = [NSString stringWithFormat:@"%@ Framerate: %@ (Peak Frame Rate)", videoInfo ,item[@"VideoFramerate"]];
+ videoInfo = [NSString stringWithFormat:@"%@ Framerate: %@ (Peak Frame Rate)", videoInfo, @(hb_video_framerate_get_name(job.video.frameRate))];
}
else
{
- videoInfo = [NSString stringWithFormat:@"%@ Framerate: %@ (Constant Frame Rate)", videoInfo ,item[@"VideoFramerate"]];
+ videoInfo = [NSString stringWithFormat:@"%@ Framerate: %@ (Constant Frame Rate)", videoInfo, @(hb_video_framerate_get_name(job.video.frameRate))];
}
}
-
- if ([item[@"VideoQualityType"] intValue] == 0)// Target Size MB
- {
- videoInfo = [NSString stringWithFormat:@"%@ Target Size: %@(MB) (%d(kbps) abr)", videoInfo ,item[@"VideoTargetSize"],[item[@"VideoAvgBitrate"] intValue]];
- }
- else if ([item[@"VideoQualityType"] intValue] == 1) // ABR
+
+
+ if (job.video.qualityType == 0) // ABR
{
- videoInfo = [NSString stringWithFormat:@"%@ Bitrate: %d(kbps)", videoInfo ,[item[@"VideoAvgBitrate"] intValue]];
+ videoInfo = [NSString stringWithFormat:@"%@ Bitrate: %d(kbps)", videoInfo, job.video.avgBitrate];
}
else // CRF
{
- videoInfo = [NSString stringWithFormat:@"%@ Constant Quality: %.2f", videoInfo ,[item[@"VideoQualitySlider"] floatValue]];
+ videoInfo = [NSString stringWithFormat:@"%@ Constant Quality: %.2f", videoInfo ,job.video.quality];
}
-
+
[finalString appendString: @"Video: " withAttributes:detailBoldAttr];
[finalString appendString: videoInfo withAttributes:detailAttr];
[finalString appendString:@"\n" withAttributes:detailAttr];
-
- if ([item[@"VideoEncoder"] isEqualToString: @"H.264 (x264)"] || [item[@"VideoEncoder"] isEqualToString: @"H.265 (x265)"])
+
+
+ if (job.video.encoder == HB_VCODEC_X264 || job.video.encoder == HB_VCODEC_X265)
{
- /* we are using x264/x265 */
+ // we are using x264/x265
NSString *encoderPresetInfo = @"";
- if ([item[@"x264UseAdvancedOptions"] intValue])
+ if (job.video.advancedOptions)
{
// we are using the old advanced panel
- if (item[@"x264Option"] &&
- [item[@"x264Option"] length])
+ if (job.video.videoOptionExtra.length)
{
- encoderPresetInfo = [encoderPresetInfo stringByAppendingString: item[@"x264Option"]];
+ encoderPresetInfo = [encoderPresetInfo stringByAppendingString:job.video.videoOptionExtra];
}
else
{
- encoderPresetInfo = [encoderPresetInfo stringByAppendingString: @"default settings"];
+ encoderPresetInfo = [encoderPresetInfo stringByAppendingString:@"default settings"];
}
}
else
{
// we are using the x264 system
- encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@"Preset: %@", item[@"VideoPreset"]]];
- if ([item[@"VideoTune"] length])
+ encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@"Preset: %@", job.video.preset]];
+ if (job.video.tune.length)
{
- encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Tune: %@", item[@"VideoTune"]]];
+ encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Tune: %@", job.video.tune]];
}
- if ([item[@"VideoOptionExtra"] length])
+ if (job.video.videoOptionExtra.length)
{
- encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Options: %@", item[@"VideoOptionExtra"]]];
+ encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Options: %@", job.video.videoOptionExtra]];
}
- if ([item[@"VideoProfile"] length])
+ if (job.video.profile.length)
{
- encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Profile: %@", item[@"VideoProfile"]]];
+ encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Profile: %@", job.video.profile]];
}
- if ([item[@"VideoLevel"] length])
+ if (job.video.level.length)
{
- encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Level: %@", item[@"VideoLevel"]]];
+ encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Level: %@", job.video.level]];
}
}
[finalString appendString: @"Encoder Options: " withAttributes:detailBoldAttr];
[finalString appendString: encoderPresetInfo withAttributes:detailAttr];
[finalString appendString:@"\n" withAttributes:detailAttr];
}
- else if (![item[@"VideoEncoder"] isEqualToString: @"VP3 (Theora)"])
+ else
{
- /* we are using libavcodec */
+ // we are using libavcodec
NSString *lavcInfo = @"";
- if (item[@"VideoOptionExtra"] &&
- [item[@"VideoOptionExtra"] length])
+ if (job.video.videoOptionExtra.length)
{
- lavcInfo = [lavcInfo stringByAppendingString: item[@"VideoOptionExtra"]];
+ lavcInfo = [lavcInfo stringByAppendingString:job.video.videoOptionExtra];
}
else
{
@@ -969,62 +969,63 @@
[finalString appendString:@"\n" withAttributes:detailAttr];
}
- /* Seventh Line Audio Details*/
+
+ // Seventh Line Audio Details
int audioDetailCount = 0;
for (NSString *anAudioDetail in audioDetails) {
audioDetailCount++;
- if (0 < [anAudioDetail length]) {
+ if (anAudioDetail.length) {
[finalString appendString: [NSString stringWithFormat: @"Audio Track %d ", audioDetailCount] withAttributes: detailBoldAttr];
[finalString appendString: anAudioDetail withAttributes: detailAttr];
[finalString appendString: @"\n" withAttributes: detailAttr];
}
}
- /* Eigth Line Auto Passthru Details */
+ // Eigth Line Auto Passthru Details
// only print Auto Passthru settings if we have an Auro Passthru output track
if (autoPassthruPresent == YES)
{
NSString *autoPassthruFallback = @"", *autoPassthruCodecs = @"";
- NSDictionary *audioDefaults = item[@"AudioDefaults"];
- autoPassthruFallback = [autoPassthruFallback stringByAppendingString: audioDefaults[@"AudioEncoderFallback"]];
- if (0 < [audioDefaults[@"AudioAllowAACPass"] intValue])
+ HBAudioDefaults *audioDefaults = job.audioDefaults;
+ autoPassthruFallback = [autoPassthruFallback stringByAppendingString:@(hb_audio_encoder_get_name(audioDefaults.encoderFallback))];
+ if (audioDefaults.allowAACPassthru)
{
- autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString: @"AAC"];
+ autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@"AAC"];
}
- if (0 < [audioDefaults[@"AudioAllowAC3Pass"] intValue])
+ if (audioDefaults.allowAC3Passthru)
{
- if (0 < [autoPassthruCodecs length])
+ if (autoPassthruCodecs.length)
{
- autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString: @", "];
+ autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@", "];
}
- autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString: @"AC3"];
+ autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@"AC3"];
}
- if (0 < [audioDefaults[@"AudioAllowDTSHDPass"] intValue])
+ if (audioDefaults.allowDTSHDPassthru)
{
- if (0 < [autoPassthruCodecs length])
+ if (autoPassthruCodecs.length)
{
- autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString: @", "];
+ autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@", "];
}
- autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString: @"DTS-HD"];
+ autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@"DTS-HD"];
}
- if (0 < [audioDefaults[@"AudioAllowDTSPass"] intValue])
+ if (audioDefaults.allowDTSPassthru)
{
- if (0 < [autoPassthruCodecs length])
+ if (autoPassthruCodecs.length)
{
- autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString: @", "];
+ autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@", "];
}
- autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString: @"DTS"];
+ autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@"DTS"];
}
- if (0 < [audioDefaults[@"AudioAllowMP3Pass"] intValue])
+ if (audioDefaults.allowMP3Passthru)
{
- if (0 < [autoPassthruCodecs length])
+ if (autoPassthruCodecs.length)
{
- autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString: @", "];
+ autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@", "];
}
- autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString: @"MP3"];
+ autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@"MP3"];
}
[finalString appendString: @"Auto Passthru Codecs: " withAttributes: detailBoldAttr];
- if (0 < [autoPassthruCodecs length])
+ if (autoPassthruCodecs.length)
{
[finalString appendString: autoPassthruCodecs withAttributes: detailAttr];
}
@@ -1037,22 +1038,22 @@
[finalString appendString: autoPassthruFallback withAttributes: detailAttr];
[finalString appendString: @"\n" withAttributes: detailAttr];
}
-
- /* Ninth Line Subtitle Details */
- for (id tempObject in item[@"SubtitleList"])
+
+ // Ninth Line Subtitle Details
+ for (NSDictionary *track in job.subtitlesTracks)
{
/* remember that index 0 of Subtitles can contain "Foreign Audio Search*/
[finalString appendString: @"Subtitle: " withAttributes:detailBoldAttr];
- [finalString appendString: tempObject[@"keySubTrackName"] withAttributes:detailAttr];
- if ([tempObject[@"keySubTrackForced"] intValue] == 1)
+ [finalString appendString: track[@"keySubTrackName"] withAttributes:detailAttr];
+ if ([track[@"keySubTrackForced"] intValue] == 1)
{
[finalString appendString: @" - Forced Only" withAttributes:detailAttr];
}
- if ([tempObject[@"keySubTrackBurned"] intValue] == 1)
+ if ([track[@"keySubTrackBurned"] intValue] == 1)
{
[finalString appendString: @" - Burned In" withAttributes:detailAttr];
}
- if ([tempObject[@"keySubTrackDefault"] intValue] == 1)
+ if ([track[@"keySubTrackDefault"] intValue] == 1)
{
[finalString appendString: @" - Default" withAttributes:detailAttr];
}
@@ -1065,15 +1066,16 @@
}
else if ([[tableColumn identifier] isEqualToString:@"icon"])
{
- if ([item[@"Status"] intValue] == 0)
+ HBJob *job = item;
+ if (job.state == HBJobStateCompleted)
{
return [NSImage imageNamed:@"EncodeComplete"];
}
- else if ([item[@"Status"] intValue] == 1)
+ else if (job.state == HBJobStateWorking)
{
return [NSImage imageNamed: [NSString stringWithFormat: @"EncodeWorking%d", fAnimationIndex]];
}
- else if ([item[@"Status"] intValue] == 3)
+ else if (job.state == HBJobStateCanceled)
{
return [NSImage imageNamed:@"EncodeCanceled"];
}
@@ -1081,7 +1083,6 @@
{
return [NSImage imageNamed:@"JobSmall"];
}
-
}
else
{
@@ -1103,8 +1104,9 @@
{
[cell setEnabled: YES];
BOOL highlighted = [outlineView isRowSelected:[outlineView rowForItem: item]] && [[outlineView window] isKeyWindow] && ([[outlineView window] firstResponder] == outlineView);
-
- if ([item[@"Status"] intValue] == 0 || ([item[@"Status"] intValue] == 1 && [item[@"EncodingPID"] intValue] != pidNum))
+
+ HBJob *job = item;
+ if (job.state == HBJobStateWorking && job.pidId != pidNum)
{
[cell setAction: @selector(revealSelectedQueueItem:)];
if (highlighted)
@@ -1152,7 +1154,7 @@
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
{
// Dragging is only allowed of the pending items.
- if ([items[0][@"Status"] integerValue] != 2) // 2 is pending
+ if ([items[0] state] != HBJobStateReady) // 2 is pending
{
return NO;
}
@@ -1206,7 +1208,7 @@
{
NSMutableIndexSet *moveItems = [NSMutableIndexSet indexSet];
- for( id obj in fDraggedNodes )
+ for (id obj in fDraggedNodes)
[moveItems addIndex:[fJobGroups indexOfObject:obj]];
// Successful drop, we use moveObjectsInQueueArray:... in fHBController
diff --git a/macosx/HBRange.h b/macosx/HBRange.h
index 65a185ec1..bbffb2ede 100644
--- a/macosx/HBRange.h
+++ b/macosx/HBRange.h
@@ -14,7 +14,7 @@ typedef NS_ENUM(NSUInteger, HBRangeType) {
HBRangeTypeSeconds,
};
-@interface HBRange : NSObject <NSCoding>
+@interface HBRange : NSObject <NSCoding, NSCopying>
- (instancetype)initWithTitle:(HBTitle *)title;
diff --git a/macosx/HBRange.m b/macosx/HBRange.m
index 731fcebf7..83df24b66 100644
--- a/macosx/HBRange.m
+++ b/macosx/HBRange.m
@@ -77,6 +77,26 @@
return retval;
}
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone
+{
+ HBRange *copy = [[[self class] alloc] init];
+
+ if (copy)
+ {
+ copy->_type = _type;
+ copy->_chapterStart = _chapterStart;
+ copy->_chapterStop = _chapterStop;
+ copy->_secondsStart = _secondsStart;
+ copy->_secondsStop = _secondsStop;
+ copy->_frameStart = _frameStart;
+ copy->_frameStop = _frameStop;
+ }
+
+ return copy;
+}
+
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)coder
diff --git a/macosx/HBSubtitlesController.h b/macosx/HBSubtitlesController.h
index d44d514b1..56fc0dcb8 100644
--- a/macosx/HBSubtitlesController.h
+++ b/macosx/HBSubtitlesController.h
@@ -29,12 +29,8 @@ extern NSString *keySubTrackSrtCharCode;
*/
@interface HBSubtitlesController : NSViewController <HBViewValidation>
-- (void)addTracksFromQueue:(NSArray *)queueSubtitleArray;
- (void)applySettingsFromPreset:(NSDictionary *)preset;
@property (nonatomic, readwrite, assign) HBJob *job;
-// Get the list of subtitles tracks
-@property (readonly, nonatomic, copy) NSArray *subtitles;
-
@end
diff --git a/macosx/HBSubtitlesController.m b/macosx/HBSubtitlesController.m
index 05eafa537..590093f5a 100644
--- a/macosx/HBSubtitlesController.m
+++ b/macosx/HBSubtitlesController.m
@@ -113,38 +113,22 @@ NSString *keySubTrackLanguageIndex = @"keySubTrackLanguageIndex";
{
self.subtitleArray = job.subtitlesTracks;
self.settings = job.subtitlesDefaults;
- hb_title_t *title = job.title.hb_title;
+ self.subtitleSourceArray = [[job.title.subtitlesTracks mutableCopy] autorelease];
- /* now populate the array with the source subtitle track info */
- NSMutableArray *forcedSourceNamesArray = [[NSMutableArray alloc] init];
- for (int i = 0; i < hb_list_count(title->list_subtitle); i++)
+ NSMutableArray *forcedSourceNamesArray = [NSMutableArray array];
+ for (NSDictionary *dict in self.subtitleSourceArray)
{
- hb_subtitle_t *subtitle = (hb_subtitle_t *)hb_list_item(title->list_subtitle, i);
-
- /* Human-readable representation of subtitle->source */
- NSString *bitmapOrText = subtitle->format == PICTURESUB ? @"Bitmap" : @"Text";
- NSString *subSourceName = @(hb_subsource_name(subtitle->source));
-
- /* if the subtitle track can be forced, add its source name to the array */
- if (hb_subtitle_can_force(subtitle->source) && [forcedSourceNamesArray containsObject:subSourceName] == NO)
+ enum subsource source = [dict[keySubTrackType] intValue];
+ NSString *subSourceName = @(hb_subsource_name(source));
+ // if the subtitle track can be forced, add its source name to the array
+ if (hb_subtitle_can_force(source) && [forcedSourceNamesArray containsObject:subSourceName] == NO)
{
[forcedSourceNamesArray addObject:subSourceName];
}
-
- // Use the native language name if available
- iso639_lang_t *language = lang_for_code2(subtitle->iso639_2);
- NSString *nativeLanguage = strlen(language->native_name) ? @(language->native_name) : @(language->eng_name);
-
- /* create a dictionary of source subtitle information to store in our array */
- [self.subtitleSourceArray addObject:@{keySubTrackName: [NSString stringWithFormat:@"%d: %@ (%@) (%@)", i, nativeLanguage, bitmapOrText, subSourceName],
- keySubTrackIndex: @(i),
- keySubTrackType: @(subtitle->source),
- keySubTrackLanguage: nativeLanguage,
- keySubTrackLanguageIsoCode: @(subtitle->iso639_2)}];
}
- /* now set the name of the Foreign Audio Search track */
- if ([forcedSourceNamesArray count])
+ // now set the name of the Foreign Audio Search track
+ if (forcedSourceNamesArray.count)
{
[forcedSourceNamesArray sortUsingComparator:^(id obj1, id obj2)
{
@@ -154,7 +138,7 @@ NSString *keySubTrackLanguageIndex = @"keySubTrackLanguageIndex";
NSString *tempList = @"";
for (NSString *tempString in forcedSourceNamesArray)
{
- if ([tempList length])
+ if (tempList.length)
{
tempList = [tempList stringByAppendingString:@", "];
}
@@ -166,7 +150,23 @@ NSString *keySubTrackLanguageIndex = @"keySubTrackLanguageIndex";
{
self.foreignAudioSearchTrackName = @"Foreign Audio Search (Bitmap)";
}
- [forcedSourceNamesArray release];
+
+ // Note: we need to look for external subtitles so it can be added to the source array track.
+ // Remember the source container subs are already loaded with resetTitle which is already called
+ // so any external sub sources need to be added to our source subs here
+ for (NSDictionary *dict in self.subtitleArray)
+ {
+ /* We have an srt track */
+ if ([dict[keySubTrackType] intValue] == SRTSUB)
+ {
+ NSString *filePath = dict[keySubTrackSrtFilePath];
+ /* create a dictionary of source subtitle information to store in our array */
+ [self.subtitleSourceArray addObject:@{keySubTrackIndex: @(self.subtitleSourceArray.count + 1),
+ keySubTrackName: [filePath lastPathComponent],
+ keySubTrackType: @(SRTSUB),
+ keySubTrackSrtFilePath: filePath}];
+ }
+ }
// Append an empty track at the end
// to display a "None" row in the table view
@@ -186,43 +186,8 @@ NSString *keySubTrackLanguageIndex = @"keySubTrackLanguageIndex";
[self.fTableView reloadData];
}
-- (NSArray *)subtitles
-{
- NSMutableArray *ret = [self.subtitleArray mutableCopy];
- [ret removeLastObject];
- return [ret autorelease];
-}
-
-- (void)addTracksFromQueue:(NSArray *)queueSubtitleArray
-{
- /* Note: we need to look for external subtitles so it can be added to the source array track.
- * Remember the source container subs are already loaded with resetTitle which is already called
- * so any external sub sources need to be added to our source subs here
- */
- for (id tempObject in queueSubtitleArray)
- {
- /* We have an srt track */
- if ([tempObject[keySubTrackType] intValue] == SRTSUB)
- {
- NSString *filePath = tempObject[keySubTrackSrtFilePath];
- /* create a dictionary of source subtitle information to store in our array */
- [self.subtitleSourceArray addObject:@{keySubTrackIndex: @(self.subtitleSourceArray.count + 1),
- keySubTrackName: [filePath lastPathComponent],
- keySubTrackType: @(SRTSUB),
- keySubTrackSrtFilePath: filePath}];
- }
- }
-
- // Set the subtitleArray to the newSubtitleArray
- [self.subtitleArray setArray:queueSubtitleArray];
- [self.subtitleArray addObject:[self createSubtitleTrack]];
- [self.fTableView reloadData];
-}
-
- (void)applySettingsFromPreset:(NSDictionary *)preset
{
- [self.settings applySettingsFromPreset:preset];
-
[self addTracksFromDefaults:self];
}
diff --git a/macosx/HBSubtitlesDefaults.h b/macosx/HBSubtitlesDefaults.h
index b09da8127..ab65a20b3 100644
--- a/macosx/HBSubtitlesDefaults.h
+++ b/macosx/HBSubtitlesDefaults.h
@@ -5,6 +5,7 @@
It may be used under the terms of the GNU General Public License. */
#import <Foundation/Foundation.h>
+#import "HBPresetCoding.h"
typedef NS_ENUM(NSUInteger, HBSubtitleTrackSelectionBehavior) {
HBSubtitleTrackSelectionBehaviorNone,
@@ -12,7 +13,7 @@ typedef NS_ENUM(NSUInteger, HBSubtitleTrackSelectionBehavior) {
HBSubtitleTrackSelectionBehaviorAll,
};
-@interface HBSubtitlesDefaults : NSObject <NSCoding>
+@interface HBSubtitlesDefaults : NSObject <NSCoding, NSCopying, HBPresetCoding>
@property (nonatomic, readwrite) HBSubtitleTrackSelectionBehavior trackSelectionBehavior;
@property (nonatomic, readwrite, retain) NSMutableArray *trackSelectionLanguages;
@@ -21,7 +22,4 @@ typedef NS_ENUM(NSUInteger, HBSubtitleTrackSelectionBehavior) {
@property (nonatomic, readwrite) BOOL addForeignAudioSubtitle;
@property (nonatomic, readwrite) BOOL addCC;
-- (void)applySettingsFromPreset:(NSDictionary *)preset;
-- (void)prepareSubtitlesDefaultsForPreset:(NSMutableDictionary *)preset;
-
@end
diff --git a/macosx/HBSubtitlesDefaults.m b/macosx/HBSubtitlesDefaults.m
index efcd49c8d..359b19ea2 100644
--- a/macosx/HBSubtitlesDefaults.m
+++ b/macosx/HBSubtitlesDefaults.m
@@ -19,7 +19,7 @@
return self;
}
-- (void)applySettingsFromPreset:(NSDictionary *)preset
+- (void)applyPreset:(NSDictionary *)preset
{
if ([preset[@"SubtitleTrackSelectionBehavior"] isEqualToString:@"first"])
{
@@ -39,7 +39,7 @@
self.addForeignAudioSubtitle = [preset[@"SubtitleAddForeignAudioSubtitle"] boolValue];
}
-- (void)prepareSubtitlesDefaultsForPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(NSMutableDictionary *)preset
{
if (self.trackSelectionBehavior == HBSubtitleTrackSelectionBehaviorFirst)
{
@@ -60,6 +60,26 @@
preset[@"SubtitleAddForeignAudioSubtitle"] = @(self.addForeignAudioSubtitle);
}
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone
+{
+ HBSubtitlesDefaults *copy = [[[self class] alloc] init];
+
+ if (copy)
+ {
+ copy->_trackSelectionBehavior = _trackSelectionBehavior;
+ [copy->_trackSelectionLanguages release];
+ copy->_trackSelectionLanguages = [_trackSelectionLanguages mutableCopy];
+
+ copy->_addForeignAudioSearch = _addForeignAudioSearch;
+ copy->_addForeignAudioSubtitle = _addForeignAudioSubtitle;
+ copy->_addCC = _addCC;
+ }
+
+ return copy;
+}
+
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)coder
diff --git a/macosx/HBTitle.m b/macosx/HBTitle.m
index 6d179e383..c2f6dc305 100644
--- a/macosx/HBTitle.m
+++ b/macosx/HBTitle.m
@@ -74,7 +74,15 @@ extern NSString *keySubTrackSrtCharCode;
{
if (!_name)
{
- _name = [@(self.hb_title->name) retain];
+ _name = @(self.hb_title->name);
+
+ // If the name is empty use file/directory name
+ if (_name.length == 0)
+ {
+ _name = [@(self.hb_title->path) lastPathComponent];
+ }
+
+ [_name retain];
}
return _name;
@@ -146,26 +154,17 @@ extern NSString *keySubTrackSrtCharCode;
{
NSMutableArray *tracks = [NSMutableArray array];
hb_subtitle_t *subtitle;
- hb_list_t *list = self.hb_title->list_audio;
+ hb_list_t *list = self.hb_title->list_subtitle;
int count = hb_list_count(list);
- NSMutableArray *forcedSourceNamesArray = [[NSMutableArray alloc] init];
- //NSString *foreignAudioSearchTrackName = nil;
-
for (int i = 0; i < count; i++)
{
- subtitle = (hb_subtitle_t *)hb_list_item(self.hb_title->list_subtitle, i);
+ subtitle = (hb_subtitle_t *) hb_list_item(self.hb_title->list_subtitle, i);
/* Human-readable representation of subtitle->source */
NSString *bitmapOrText = subtitle->format == PICTURESUB ? @"Bitmap" : @"Text";
NSString *subSourceName = @(hb_subsource_name(subtitle->source));
- /* if the subtitle track can be forced, add its source name to the array */
- if (hb_subtitle_can_force(subtitle->source) && [forcedSourceNamesArray containsObject:subSourceName] == NO)
- {
- [forcedSourceNamesArray addObject:subSourceName];
- }
-
// Use the native language name if available
iso639_lang_t *language = lang_for_code2(subtitle->iso639_2);
NSString *nativeLanguage = strlen(language->native_name) ? @(language->native_name) : @(language->eng_name);
@@ -178,31 +177,6 @@ extern NSString *keySubTrackSrtCharCode;
keySubTrackLanguageIsoCode: @(subtitle->iso639_2)}];
}
- /* now set the name of the Foreign Audio Search track */
- if ([forcedSourceNamesArray count])
- {
- [forcedSourceNamesArray sortUsingComparator:^(id obj1, id obj2)
- {
- return [((NSString *)obj1) compare:((NSString *)obj2)];
- }];
-
- NSString *tempList = @"";
- for (NSString *tempString in forcedSourceNamesArray)
- {
- if ([tempList length])
- {
- tempList = [tempList stringByAppendingString:@", "];
- }
- tempList = [tempList stringByAppendingString:tempString];
- }
- //foreignAudioSearchTrackName = [NSString stringWithFormat:@"Foreign Audio Search (Bitmap) (%@)", tempList];
- }
- else
- {
- //foreignAudioSearchTrackName = @"Foreign Audio Search (Bitmap)";
- }
- [forcedSourceNamesArray release];
-
_subtitlesTracks = [tracks copy];
}
diff --git a/macosx/HBVideo.h b/macosx/HBVideo.h
index 5936c8803..9e7b2631e 100644
--- a/macosx/HBVideo.h
+++ b/macosx/HBVideo.h
@@ -5,24 +5,19 @@
It may be used under the terms of the GNU General Public License. */
#import <Foundation/Foundation.h>
+#import "HBPresetCoding.h"
@class HBJob;
/**
* HBVideo
*/
-@interface HBVideo : NSObject <NSCoding>
+@interface HBVideo : NSObject <NSCoding, NSCopying, HBPresetCoding>
- (instancetype)initWithJob:(HBJob *)job;
- (void)containerChanged;
-- (void)applySettingsFromPreset:(NSDictionary *)preset;
-- (void)prepareVideoForPreset:(NSMutableDictionary *)preset;
-
-- (void)applyVideoSettingsFromQueue:(NSDictionary *)queueToApply;
-- (void)prepareVideoForQueueFileJob:(NSMutableDictionary *)queueFileJob;
-
@property (nonatomic, readwrite) int encoder;
@property (nonatomic, readwrite) int qualityType;
diff --git a/macosx/HBVideo.m b/macosx/HBVideo.m
index 208ac9b17..4810fc397 100644
--- a/macosx/HBVideo.m
+++ b/macosx/HBVideo.m
@@ -244,6 +244,41 @@
return [[temp copy] autorelease];
}
+#pragma mark - NSCopying
+
+- (instancetype)copyWithZone:(NSZone *)zone
+{
+ HBVideo *copy = [[[self class] alloc] init];
+
+ if (copy)
+ {
+ copy->_encoder = _encoder;
+
+ copy->_qualityType = _qualityType;
+ copy->_avgBitrate = _avgBitrate;
+ copy->_quality = _quality;
+
+ copy->_qualityMinValue = _qualityMinValue;
+ copy->_qualityMaxValue = _qualityMaxValue;
+
+ copy->_frameRate = _frameRate;
+ copy->_frameRateMode = _frameRateMode;
+
+ copy->_twoPass = _twoPass;
+ copy->_turboTwoPass = _turboTwoPass;
+
+ copy->_advancedOptions = _advancedOptions;
+ copy->_preset = [_preset copy];
+ copy->_tune = [_tune copy];
+ copy->_profile = [_profile copy];
+ copy->_level = [_level copy];
+ copy->_videoOptionExtra = [_videoOptionExtra copy];
+ copy->_fastDecode = _fastDecode;
+ }
+
+ return copy;
+}
+
#pragma mark - NSCoding
- (void)encodeWithCoder:(NSCoder *)coder
@@ -256,6 +291,9 @@
encodeInt(_avgBitrate);
encodeDouble(_quality);
+ encodeDouble(_qualityMinValue);
+ encodeDouble(_qualityMaxValue);
+
encodeInt(_frameRate);
encodeInt(_frameRateMode);
@@ -283,6 +321,9 @@
decodeInt(_avgBitrate);
decodeDouble(_quality);
+ decodeDouble(_qualityMinValue);
+ decodeDouble(_qualityMaxValue);
+
decodeInt(_frameRate);
decodeInt(_frameRateMode);
@@ -341,7 +382,7 @@
return [string autorelease];
}
-- (void)applySettingsFromPreset:(NSDictionary *)preset
+- (void)applyPreset:(NSDictionary *)preset
{
// map legacy encoder names via libhb.
const char *strValue = hb_video_encoder_sanitize_name([preset[@"VideoEncoder"] UTF8String]);
@@ -481,7 +522,7 @@
self.turboTwoPass = [preset[@"VideoTurboTwoPass"] intValue];
}
-- (void)prepareVideoForPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(NSMutableDictionary *)preset
{
preset[@"VideoEncoder"] = @(hb_video_encoder_get_name(self.encoder));
@@ -544,137 +585,4 @@
preset[@"VideoTurboTwoPass"] = @(self.turboTwoPass);
}
-- (void)applyVideoSettingsFromQueue:(NSDictionary *)queueToApply
-{
- // Video encoder
- self.encoder = [queueToApply[@"JobVideoEncoderVcodec"] intValue];
-
- // Advanced x264 options
- if ([queueToApply[@"x264UseAdvancedOptions"] intValue])
- {
- // we are using the advanced panel
- self.preset = @"medium";
- self.tune = nil;
- self.profile = nil;
- self.level = nil;
- self.videoOptionExtra = queueToApply[@"x264Option"];
- self.advancedOptions = YES;
- }
- else if (self.encoder == HB_VCODEC_X264 || self.encoder == HB_VCODEC_X265)
- {
- // we are using the x264 preset system
- self.preset = queueToApply[@"VideoPreset"];
- self.tune = queueToApply[@"VideoTune"];
- self.videoOptionExtra = queueToApply[@"VideoOptionExtra"];
- self.profile = queueToApply[@"VideoProfile"];
- self.level = queueToApply[@"VideoLevel"];
- }
- else
- {
- self.videoOptionExtra = queueToApply[@"VideoOptionExtra"];
- }
-
- self.qualityType = [queueToApply[@"VideoQualityType"] intValue] - 1;
-
- self.avgBitrate = [queueToApply[@"VideoAvgBitrate"] intValue];
- self.quality = [queueToApply[@"VideoQualitySlider"] doubleValue];
-
- // Video framerate
- if ([queueToApply[@"JobIndexVideoFramerate"] intValue] == 0)
- {
- // Now set the Video Frame Rate Mode to either vfr or cfr according to the preset
- if ([queueToApply[@"VideoFramerateMode"] isEqualToString:@"vfr"])
- {
- self.frameRateMode = 0; // we want vfr
- }
- else
- {
- self.frameRateMode = 1; // we want cfr
- }
- }
- else
- {
- // Now set the Video Frame Rate Mode to either pfr or cfr according to the preset
- if ([queueToApply[@"VideoFramerateMode"] isEqualToString:@"pfr"])
- {
- self.frameRateMode = 0; // we want pfr
- }
- else
- {
- self.frameRateMode = 1; // we want cfr
- }
- }
-
- self.frameRate = hb_video_framerate_get_from_name([queueToApply[@"VideoFramerate"] UTF8String]);
-
- self.twoPass = [queueToApply[@"VideoTwoPass"] intValue];
- self.turboTwoPass = [queueToApply[@"VideoTurboTwoPass"] intValue];
-}
-
-- (void)prepareVideoForQueueFileJob:(NSMutableDictionary *)queueFileJob
-{
- // Video encoder.
- queueFileJob[@"VideoEncoder"] = @(hb_video_encoder_get_name(self.encoder));
- queueFileJob[@"JobVideoEncoderVcodec"] = @(self.encoder);
-
- // x264 advanced options.
- if (self.advancedOptions)
- {
- // we are using the advanced panel
- queueFileJob[@"x264UseAdvancedOptions"] = @1;
- queueFileJob[@"x264Option"] = self.videoOptionExtra;
- }
- else if (self.encoder == HB_VCODEC_X264 || self.encoder == HB_VCODEC_X265)
- {
- // we are using the x264/x265 preset system.
- queueFileJob[@"x264UseAdvancedOptions"] = @0;
- queueFileJob[@"VideoPreset"] = self.preset;
- queueFileJob[@"VideoTune"] = [self completeTune];
- queueFileJob[@"VideoOptionExtra"] = self.videoOptionExtra;
- queueFileJob[@"VideoProfile"] = self.profile;
- queueFileJob[@"VideoLevel"] = self.level;
- }
- else
- {
- // FFmpeg (lavc) Option String.
- queueFileJob[@"VideoOptionExtra"] = self.videoOptionExtra;
- }
-
- queueFileJob[@"VideoQualityType"] = @(self.qualityType + 1);
- queueFileJob[@"VideoAvgBitrate"] = @(self.avgBitrate);
- queueFileJob[@"VideoQualitySlider"] = @(self.quality);
-
- // Framerate
- if (self.frameRate)
- {
- queueFileJob[@"VideoFramerate"] = @(hb_video_framerate_get_name(self.frameRate));
- }
- else
- {
- queueFileJob[@"VideoFramerate"] = @"Same as source";
- }
- queueFileJob[@"JobIndexVideoFramerate"] = @(self.frameRate);
-
- // Frame Rate Mode
- if (self.frameRateMode == 1) // if selected we are cfr regardless of the frame rate popup
- {
- queueFileJob[@"VideoFramerateMode"] = @"cfr";
- }
- else
- {
- if (self.frameRate == 0) // Same as source frame rate
- {
- queueFileJob[@"VideoFramerateMode"] = @"vfr";
- }
- else
- {
- queueFileJob[@"VideoFramerateMode"] = @"pfr";
- }
- }
-
- // 2 Pass Encoding
- queueFileJob[@"VideoTwoPass"] = @(self.twoPass);
- queueFileJob[@"VideoTurboTwoPass"] = @(self.turboTwoPass);
-}
-
@end
diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj
index c587bde9b..809678aad 100644
--- a/macosx/HandBrake.xcodeproj/project.pbxproj
+++ b/macosx/HandBrake.xcodeproj/project.pbxproj
@@ -401,6 +401,7 @@
A98C29C21977B10600AF5DED /* HBLanguagesSelection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBLanguagesSelection.h; sourceTree = "<group>"; };
A98C29C31977B10600AF5DED /* HBLanguagesSelection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBLanguagesSelection.m; sourceTree = "<group>"; };
A9935212196F38A70069C6B7 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = ChaptersTitles.xib; sourceTree = "<group>"; };
+ A997D8EB1A4ABB0900E19B6F /* HBPresetCoding.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBPresetCoding.h; sourceTree = "<group>"; };
A9A2A77F1A4737DD006C219C /* NSCodingMacro.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSCodingMacro.h; sourceTree = "<group>"; };
A9AA44781970664A00D7DEFC /* HBUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBUtilities.h; sourceTree = "<group>"; };
A9AA44791970664A00D7DEFC /* HBUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBUtilities.m; sourceTree = "<group>"; };
@@ -911,6 +912,7 @@
273F209814ADBE670021BE6D /* HBDVDDetector.m */,
A9537BED1A48A7F900141102 /* UI Bindings Additions */,
A9A2A77F1A4737DD006C219C /* NSCodingMacro.h */,
+ A997D8EB1A4ABB0900E19B6F /* HBPresetCoding.h */,
);
name = Core;
sourceTree = "<group>";
diff --git a/macosx/NSCodingMacro.h b/macosx/NSCodingMacro.h
index 7cfbfc755..842da1121 100644
--- a/macosx/NSCodingMacro.h
+++ b/macosx/NSCodingMacro.h
@@ -18,6 +18,6 @@
#define decodeInteger(x) x = [decoder decodeIntegerForKey:OBJC_STRINGIFY(x)]
#define decodeBool(x) x = [decoder decodeBoolForKey:OBJC_STRINGIFY(x)]
#define decodeDouble(x) x = [decoder decodeDoubleForKey:OBJC_STRINGIFY(x)]
-#define decodeObject(x) x = [decoder decodeObjectForKey:OBJC_STRINGIFY(x)]
+#define decodeObject(x) x = [[decoder decodeObjectForKey:OBJC_STRINGIFY(x)] retain]
#endif