summaryrefslogtreecommitdiffstats
path: root/macosx
diff options
context:
space:
mode:
authorDamiano Galassi <[email protected]>2016-01-10 08:12:21 +0100
committerDamiano Galassi <[email protected]>2016-01-10 08:12:21 +0100
commit5d7c81252a9fe042c1df2fedd7a275593760abec (patch)
tree45615328222beb54dbfa1b9a5982e5fc50140bcf /macosx
parent45c6f4b53d656e18ecfe9e00b142409e08cd3cd5 (diff)
MacGui: rework the way HBController scans, remove an ivar and move some unrelated code to HBUtilites.
Diffstat (limited to 'macosx')
-rw-r--r--macosx/HBController.m498
-rw-r--r--macosx/HBUtilities.h12
-rw-r--r--macosx/HBUtilities.m127
3 files changed, 323 insertions, 314 deletions
diff --git a/macosx/HBController.m b/macosx/HBController.m
index 7241c8126..3f0289d86 100644
--- a/macosx/HBController.m
+++ b/macosx/HBController.m
@@ -110,10 +110,7 @@
@property (nonatomic, copy) NSString *browsedSourceDisplayName;
/// The current job.
-@property (nonatomic, strong) HBJob *job;
-
-/// The job to be applied from the queue.
-@property (nonatomic, strong) HBJob *jobFromQueue;
+@property (nonatomic, strong, nullable) HBJob *job;
/// The current selected preset.
@property (nonatomic, strong) HBPreset *currentPreset;
@@ -496,13 +493,135 @@
}
}
+- (NSModalResponse)runCopyProtectionAlert
+{
+ NSAlert *alert = [[NSAlert alloc] init];
+ [alert setMessageText:NSLocalizedString(@"Copy-Protected sources are not supported.", nil)];
+ [alert setInformativeText:NSLocalizedString(@"Please note that HandBrake does not support the removal of copy-protection from DVD Discs. You can if you wish use any other 3rd party software for this function.", nil)];
+ [alert addButtonWithTitle:NSLocalizedString(@"Attempt Scan Anyway", nil)];
+ [alert addButtonWithTitle:NSLocalizedString(@"Cancel", nil)];
+
+ [NSApp requestUserAttention:NSCriticalRequest];
+
+ return [alert runModal];
+}
+
+/**
+ * Here we actually tell hb_scan to perform the source scan, using the path to source and title number
+ */
+- (void)scanURL:(NSURL *)fileURL titleIndex:(NSUInteger)index completionHandler:(void(^)(NSArray<HBTitle *> *titles))completionHandler
+{
+ // Save the current settings
+ if (self.job)
+ {
+ self.currentPreset = [self createPresetFromCurrentSettings];
+ }
+
+ self.job = nil;
+ [fSrcTitlePopUp removeAllItems];
+
+ NSError *outError = NULL;
+ BOOL suppressWarning = [[NSUserDefaults standardUserDefaults] boolForKey:@"suppressCopyProtectionAlert"];
+
+ // Check if we can scan the source and if there is any warning.
+ BOOL canScan = [self.core canScan:fileURL error:&outError];
+
+ // Notify the user that we don't support removal of copy proteciton.
+ if (canScan && [outError code] == 101 && !suppressWarning)
+ {
+ // Only show the user this warning once. They may be using a solution we don't know about. Notifying them each time is annoying.
+ [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"suppressCopyProtectionAlert"];
+
+ if ([self runCopyProtectionAlert] == NSAlertFirstButtonReturn)
+ {
+ // User chose to override our warning and scan the physical dvd anyway, at their own peril. on an encrypted dvd this produces massive log files and fails
+ [HBUtilities writeToActivityLog:"User overrode copy-protection warning - trying to open physical dvd without decryption"];
+ }
+ else
+ {
+ // User chose to cancel the scan
+ [HBUtilities writeToActivityLog:"Cannot open physical dvd, scan cancelled"];
+ canScan = NO;
+ }
+ }
+
+ if (canScan)
+ {
+ int hb_num_previews = [[[NSUserDefaults standardUserDefaults] objectForKey:@"PreviewsNumber"] intValue];
+ int min_title_duration_seconds = [[[NSUserDefaults standardUserDefaults] objectForKey:@"MinTitleScanSeconds"] intValue];
+
+ HBStateFormatter *formatter = [[HBStateFormatter alloc] init];
+
+ [self.core scanURL:fileURL
+ titleIndex:index
+ previews:hb_num_previews minDuration:min_title_duration_seconds
+ progressHandler:^(HBState state, hb_state_t hb_state)
+ {
+ fSrcDVD2Field.stringValue = [formatter stateToString:hb_state title:nil];
+ fScanIndicator.hidden = NO;
+ fScanHorizontalLine.hidden = YES;
+ fScanIndicator.doubleValue = [formatter stateToPercentComplete:hb_state];
+ }
+ completionHandler:^(HBCoreResult result)
+ {
+ fScanHorizontalLine.hidden = NO;
+ fScanIndicator.hidden = YES;
+ fScanIndicator.indeterminate = NO;
+ fScanIndicator.doubleValue = 0.0;
+
+ if (result == HBCoreResultDone)
+ {
+ for (HBTitle *title in self.core.titles)
+ {
+ // Set Source Name at top of window with the browsedSourceDisplayName grokked right before -performScan
+ fSrcDVD2Field.stringValue = self.browsedSourceDisplayName;
+
+ [fSrcTitlePopUp addItemWithTitle:title.description];
+
+ // See if this is the main feature according
+ if (title.isFeatured)
+ {
+ [fSrcTitlePopUp selectItemWithTitle:title.description];
+ }
+ }
+
+ // Select the first item is nothing is selected
+ if (!fSrcTitlePopUp.selectedItem)
+ {
+ [fSrcTitlePopUp selectItemAtIndex:0];
+ }
+
+ completionHandler(self.core.titles);
+ }
+ else
+ {
+ // We display a message if a valid source was not chosen
+ fSrcDVD2Field.stringValue = NSLocalizedString(@"No Valid Source Found", @"");
+ }
+ [self.window.toolbar validateVisibleItems];
+ }];
+ }
+}
+
+- (void)openURL:(NSURL *)fileURL titleIndex:(NSUInteger)index
+{
+ NSURL *mediaURL = [HBUtilities mediaURLFromURL:fileURL];
+
+ self.browsedSourceDisplayName = fileURL.lastPathComponent;
+ [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:fileURL];
+
+ [self scanURL:mediaURL titleIndex:index completionHandler:^(NSArray<HBTitle *> *titles)
+ {
+ HBJob *job = [self jobFromTitle:titles.firstObject];
+ self.job = job;
+ }];
+}
+
- (BOOL)openURL:(NSURL *)fileURL
{
if (self.core.state != HBStateScanning)
{
- self.browsedSourceDisplayName = fileURL.lastPathComponent;
- [self performScan:fileURL scanTitleNum:0];
-
+ [self openURL:fileURL titleIndex:0];
return YES;
}
return NO;
@@ -515,17 +634,34 @@
{
if (self.core.state != HBStateScanning)
{
- self.jobFromQueue = job;
-
// Set the browsedSourceDisplayName for showNewScan
- self.browsedSourceDisplayName = self.jobFromQueue.fileURL.lastPathComponent;
+ self.browsedSourceDisplayName = job.fileURL.lastPathComponent;
+
+ [self scanURL:job.fileURL titleIndex:job.titleIdx completionHandler:^(NSArray<HBTitle *> *titles)
+ {
+ job.title = titles.firstObject;
+ self.job = job;
+ }];
- [self performScan:self.jobFromQueue.fileURL scanTitleNum:self.jobFromQueue.titleIdx];
return YES;
}
return NO;
}
+- (HBJob *)jobFromTitle:(HBTitle *)title
+{
+ // If there is already a title load, save the current settings to a preset
+ if (self.job)
+ {
+ self.currentPreset = [self createPresetFromCurrentSettings];
+ }
+
+ HBJob *job = [[HBJob alloc] initWithTitle:title andPreset:self.currentPreset];
+ job.destURL = [HBUtilities destURLForJob:job];
+
+ return job;
+}
+
- (void)removeJobObservers
{
if (self.job)
@@ -583,6 +719,15 @@
if (job)
{
fPreviewController.generator = [[HBPreviewGenerator alloc] initWithCore:self.core job:job];
+
+ HBTitle *title = job.title;
+
+ // If we are a stream type and a batch scan, grok the output file name from title->name upon title change
+ if (title.isStream && self.core.titles.count > 1)
+ {
+ // Change the source to read out the parent folder also
+ fSrcDVD2Field.stringValue = [NSString stringWithFormat:@"%@/%@", self.browsedSourceDisplayName, title.name];
+ }
}
else
{
@@ -626,214 +771,28 @@
[panel beginSheetModalForWindow:self.window completionHandler: ^(NSInteger result)
{
- if (result == NSOKButton)
+ if (result == NSFileHandlingPanelOKButton)
{
- NSURL *url = panel.URL;
-
// Check if we selected a folder or not
id outValue = nil;
- [url getResourceValue:&outValue forKey:NSURLIsDirectoryKey error:NULL];
+ [panel.URL getResourceValue:&outValue forKey:NSURLIsDirectoryKey error:NULL];
// we set the last searched source directory in the prefs here
if ([outValue boolValue])
{
- [[NSUserDefaults standardUserDefaults] setURL:url forKey:@"HBLastSourceDirectoryURL"];
+ [[NSUserDefaults standardUserDefaults] setURL:panel.URL forKey:@"HBLastSourceDirectoryURL"];
}
else
{
- [[NSUserDefaults standardUserDefaults] setURL:url.URLByDeletingLastPathComponent forKey:@"HBLastSourceDirectoryURL"];
+ [[NSUserDefaults standardUserDefaults] setURL:panel.URL.URLByDeletingLastPathComponent forKey:@"HBLastSourceDirectoryURL"];
}
- // We check to see if the chosen file at path is a package
- if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:url.path])
- {
- [HBUtilities writeToActivityLog:"trying to open a package at: %s", url.path.UTF8String];
- // We check to see if this is an .eyetv package
- if ([url.pathExtension isEqualToString:@"eyetv"])
- {
- [HBUtilities writeToActivityLog:"trying to open eyetv package"];
- // We're looking at an EyeTV package - try to open its enclosed .mpg media file
- self.browsedSourceDisplayName = url.URLByDeletingPathExtension.lastPathComponent;
- NSString *mpgname;
- NSUInteger n = [[url.path stringByAppendingString: @"/"]
- completePathIntoString: &mpgname caseSensitive: YES
- matchesIntoArray: nil
- filterTypes: @[@"mpg"]];
- if (n > 0)
- {
- // Found an mpeg inside the eyetv package, make it our scan path
- [HBUtilities writeToActivityLog:"found mpeg in eyetv package"];
- url = [NSURL fileURLWithPath:mpgname];
- }
- else
- {
- // We did not find an mpeg file in our package, so we do not call performScan
- [HBUtilities writeToActivityLog:"no valid mpeg in eyetv package"];
- }
- }
- // We check to see if this is a .dvdmedia package
- else if ([url.pathExtension isEqualToString:@"dvdmedia"])
- {
- // path IS a package - but dvdmedia packages can be treaded like normal directories
- self.browsedSourceDisplayName = url.URLByDeletingPathExtension.lastPathComponent;
- [HBUtilities writeToActivityLog:"trying to open dvdmedia package"];
- }
- else
- {
- // The package is not an eyetv package, try to open it anyway
- self.browsedSourceDisplayName = url.lastPathComponent;
- [HBUtilities writeToActivityLog:"not a known to package"];
- }
- }
- else
- {
- // path is not a package, so we call perform scan directly on our file
- if ([url.lastPathComponent isEqualToString:@"VIDEO_TS"])
- {
- [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
- url = url.URLByDeletingLastPathComponent;
- self.browsedSourceDisplayName = url.lastPathComponent;
- }
- else
- {
- [HBUtilities writeToActivityLog:"trying to open a folder or file"];
- // if not the VIDEO_TS Folder, we can assume the chosen folder is the source name
- // make sure we remove any path extension
- self.browsedSourceDisplayName = url.lastPathComponent;
- }
- }
-
- // Add the url to the Open Recent menu.
- [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:url];
-
- NSInteger titleIdx = 0;
- if (self.scanSpecificTitle)
- {
- titleIdx = self.scanSpecificTitleIdx;
- }
- [self performScan:url scanTitleNum:titleIdx];
+ NSInteger titleIdx = self.scanSpecificTitle ? self.scanSpecificTitle : 0;
+ [self openURL:panel.URL titleIndex:titleIdx];
}
}];
}
-/**
- * Here we actually tell hb_scan to perform the source scan, using the path to source and title number
- */
-- (void)performScan:(NSURL *)scanURL scanTitleNum:(NSInteger)scanTitleNum
-{
- // Save the current settings
- if (self.job)
- {
- self.currentPreset = [self createPresetFromCurrentSettings];
- }
-
- self.job = nil;
- [fSrcTitlePopUp removeAllItems];
-
- NSError *outError = NULL;
- BOOL suppressWarning = [[NSUserDefaults standardUserDefaults] boolForKey:@"suppressCopyProtectionAlert"];
-
- // Check if we can scan the source and if there is any warning.
- BOOL canScan = [self.core canScan:scanURL error:&outError];
-
- // Notify the user that we don't support removal of copy proteciton.
- if (canScan && [outError code] == 101 && !suppressWarning)
- {
- // Only show the user this warning once. They may be using a solution we don't know about. Notifying them each time is annoying.
- [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"suppressCopyProtectionAlert"];
-
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Copy-Protected sources are not supported.", nil)];
- [alert setInformativeText:NSLocalizedString(@"Please note that HandBrake does not support the removal of copy-protection from DVD Discs. You can if you wish use any other 3rd party software for this function.", nil)];
- [alert addButtonWithTitle:NSLocalizedString(@"Attempt Scan Anyway", nil)];
- [alert addButtonWithTitle:NSLocalizedString(@"Cancel", nil)];
-
- [NSApp requestUserAttention:NSCriticalRequest];
- NSInteger status = [alert runModal];
-
- if (status == NSAlertFirstButtonReturn)
- {
- // User chose to override our warning and scan the physical dvd anyway, at their own peril. on an encrypted dvd this produces massive log files and fails
- [HBUtilities writeToActivityLog:"User overrode copy-protection warning - trying to open physical dvd without decryption"];
- }
- else
- {
- // User chose to cancel the scan
- [HBUtilities writeToActivityLog:"Cannot open physical dvd, scan cancelled"];
- canScan = NO;
- }
- }
-
- if (canScan)
- {
- int hb_num_previews = [[[NSUserDefaults standardUserDefaults] objectForKey:@"PreviewsNumber"] intValue];
- int min_title_duration_seconds = [[[NSUserDefaults standardUserDefaults] objectForKey:@"MinTitleScanSeconds"] intValue];
-
- HBStateFormatter *formatter = [[HBStateFormatter alloc] init];
-
- [self.core scanURL:scanURL
- titleIndex:scanTitleNum
- previews:hb_num_previews minDuration:min_title_duration_seconds
- progressHandler:^(HBState state, hb_state_t hb_state)
- {
- fSrcDVD2Field.stringValue = [formatter stateToString:hb_state title:nil];
- fScanIndicator.hidden = NO;
- fScanHorizontalLine.hidden = YES;
- fScanIndicator.doubleValue = [formatter stateToPercentComplete:hb_state];
- }
- completionHandler:^(HBCoreResult result)
- {
- fScanHorizontalLine.hidden = NO;
- fScanIndicator.hidden = YES;
- fScanIndicator.indeterminate = NO;
- fScanIndicator.doubleValue = 0.0;
-
- if (result == HBCoreResultDone)
- {
- [self showNewScan];
- }
- else
- {
- // We display a message if a valid source was not chosen
- fSrcDVD2Field.stringValue = NSLocalizedString(@"No Valid Source Found", @"");
- }
- [self.window.toolbar validateVisibleItems];
- }];
- }
-}
-
-- (void)showNewScan
-{
- for (HBTitle *title in self.core.titles)
- {
- // Set Source Name at top of window with the browsedSourceDisplayName grokked right before -performScan
- fSrcDVD2Field.stringValue = self.browsedSourceDisplayName;
-
- [fSrcTitlePopUp addItemWithTitle:title.description];
-
- // See if this is the main feature according
- if (title.isFeatured)
- {
- [fSrcTitlePopUp selectItemWithTitle:title.description];
- }
- }
-
- // Select the first item is nothing is selected
- if (!fSrcTitlePopUp.selectedItem)
- {
- [fSrcTitlePopUp selectItemAtIndex:0];
- }
-
- [self titlePopUpChanged:nil];
-
- if (self.jobFromQueue)
- {
- [fPresetsView deselect];
- self.jobFromQueue = nil;
- }
-}
-
#pragma mark - GUI Controls Changed Methods
- (IBAction)browseDestination:(id)sender
@@ -860,98 +819,11 @@
}];
}
-- (NSString *)automaticNameForJob:(HBJob *)job
-{
- HBTitle *title = job.title;
-
- // Generate a new file name
- NSString *fileName = [HBUtilities automaticNameForSource:title.name
- title:title.index
- chapters:NSMakeRange(job.range.chapterStart + 1, job.range.chapterStop + 1)
- quality:job.video.qualityType ? job.video.quality : 0
- bitrate:!job.video.qualityType ? job.video.avgBitrate : 0
- videoCodec:job.video.encoder];
- return fileName;
-}
-
-- (NSString *)automaticExtForJob:(HBJob *)job
+- (IBAction)titlePopUpChanged:(NSPopUpButton *)sender
{
- NSString *extension = @(hb_container_get_default_extension(job.container));
-
- if (job.container & HB_MUX_MASK_MP4)
- {
- BOOL anyCodecAC3 = [job.audio anyCodecMatches:HB_ACODEC_AC3] || [job.audio anyCodecMatches:HB_ACODEC_AC3_PASS];
- // Chapter markers are enabled if the checkbox is ticked and we are doing p2p or we have > 1 chapter
- BOOL chapterMarkers = (job.chaptersEnabled) &&
- (job.range.type != HBRangeTypeChapters || job.range.chapterStart < job.range.chapterStop);
-
- if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"] isEqualToString:@".m4v"] ||
- ((YES == anyCodecAC3 || YES == chapterMarkers) &&
- [[[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"] isEqualToString:@"Auto"]))
- {
- extension = @"m4v";
- }
- }
-
- return extension;
-}
-
-- (NSURL *)destURLForJob:(HBJob *)job
-{
- // Check to see if the last destination has been set,use if so, if not, use Desktop
- NSURL *destURL = [[NSUserDefaults standardUserDefaults] URLForKey:@"HBLastDestinationDirectory"];
- if (!destURL || ![[NSFileManager defaultManager] fileExistsAtPath:destURL.path])
- {
- destURL = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES) firstObject]
- isDirectory:YES];
- }
-
- // Generate a new file name
- NSString *fileName = job.title.name;
-
- // If Auto Naming is on. We create an output filename of dvd name - title number
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"])
- {
- fileName = [self automaticNameForJob:job];
- }
-
- destURL = [destURL URLByAppendingPathComponent:fileName];
- // use the correct extension based on the container
- NSString *ext = [self automaticExtForJob:job];
- destURL = [destURL URLByAppendingPathExtension:ext];
-
- return destURL;
-}
-
-- (IBAction)titlePopUpChanged:(id)sender
-{
- // If there is already a title load, save the current settings to a preset
- if (self.job)
- {
- self.currentPreset = [self createPresetFromCurrentSettings];
- }
-
- HBTitle *title = self.core.titles[fSrcTitlePopUp.indexOfSelectedItem];
-
- // 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
- {
- HBJob *job = [[HBJob alloc] initWithTitle:title andPreset:self.currentPreset];
- job.destURL = [self destURLForJob:job];
- self.job = job;
- }
-
- // If we are a stream type and a batch scan, grok the output file name from title->name upon title change
- if (title.isStream && self.core.titles.count > 1)
- {
- // Change the source to read out the parent folder also
- fSrcDVD2Field.stringValue = [NSString stringWithFormat:@"%@/%@", self.browsedSourceDisplayName, title.name];
- }
+ HBTitle *title = self.core.titles[sender.indexOfSelectedItem];
+ HBJob *job = [self jobFromTitle:title];
+ self.job = job;
}
- (void)chapterPopUpChanged:(NSNotification *)notification
@@ -979,7 +851,7 @@
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"])
{
// Generate a new file name
- NSString *fileName = [self automaticNameForJob:self.job];
+ NSString *fileName = [HBUtilities automaticNameForJob:self.job];
// Swap the old one with the new one
self.job.destURL = [[self.job.destURL URLByDeletingLastPathComponent] URLByAppendingPathComponent:
@@ -989,7 +861,7 @@
- (void)updateFileExtension:(NSNotification *)notification
{
- NSString *extension = [self automaticExtForJob:self.job];
+ NSString *extension = [HBUtilities automaticExtForJob:self.job];
if (![extension isEqualTo:self.job.destURL.pathExtension])
{
self.job.destURL = [[self.job.destURL URLByDeletingPathExtension] URLByAppendingPathExtension:extension];
@@ -1246,7 +1118,7 @@
- (void)doAddTitlesAtIndexesToQueue:(NSIndexSet *)indexes;
{
- NSMutableArray *jobs = [[NSMutableArray alloc] init];
+ NSMutableArray<HBJob *> *jobs = [[NSMutableArray alloc] init];
BOOL fileExists = NO;
// Get the preset from the loaded job.
@@ -1257,13 +1129,13 @@
if ([indexes containsIndex:title.index])
{
HBJob *job = [[HBJob alloc] initWithTitle:title andPreset:preset];
- job.destURL = [self destURLForJob:job];
+ job.destURL = [HBUtilities destURLForJob:job];
job.title = nil;
[jobs addObject:job];
}
}
- NSMutableSet *destinations = [[NSMutableSet alloc] init];
+ NSMutableSet<NSURL *> *destinations = [[NSMutableSet alloc] init];
for (HBJob *job in jobs)
{
if ([destinations containsObject:job.destURL])
@@ -1324,20 +1196,6 @@
#pragma mark - Picture
-- (IBAction)toggleDrawer:(id)sender
-{
- if (fPresetDrawer.state == NSDrawerClosedState)
- {
- [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"HBDefaultPresetsDrawerShow"];
- }
- else
- {
- [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"HBDefaultPresetsDrawerShow"];
- }
-
- [fPresetDrawer toggle:self];
-}
-
- (IBAction)showPreviewWindow:(id)sender
{
[fPreviewController showWindow:sender];
@@ -1358,6 +1216,20 @@
#pragma mark - Presets
+- (IBAction)toggleDrawer:(id)sender
+{
+ if (fPresetDrawer.state == NSDrawerClosedState)
+ {
+ [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"HBDefaultPresetsDrawerShow"];
+ }
+ else
+ {
+ [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"HBDefaultPresetsDrawerShow"];
+ }
+
+ [fPresetDrawer toggle:self];
+}
+
- (void)setCurrentPreset:(HBPreset *)currentPreset
{
NSParameterAssert(currentPreset);
diff --git a/macosx/HBUtilities.h b/macosx/HBUtilities.h
index de4fe2036..362e32012 100644
--- a/macosx/HBUtilities.h
+++ b/macosx/HBUtilities.h
@@ -4,10 +4,12 @@
Homepage: <http://handbrake.fr/>.
It may be used under the terms of the GNU General Public License. */
-#import <Foundation/Foundation.h>
+#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
+@class HBJob;
+
@interface HBUtilities : NSObject
/**
@@ -19,6 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
* Returns the url of the current <user>/Library/Application Support/HandBrake folder.
*/
+ (nullable NSURL *)appSupportURL;
+
/**
* Writes a message to standard error.
* The message will show up in the output panel and in the activity log.
@@ -27,6 +30,12 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (void)writeToActivityLog:(const char *)format, ...;
++ (NSURL *)mediaURLFromURL:(NSURL *)URL;
+
++ (NSString *)automaticNameForJob:(HBJob *)job;
++ (NSString *)automaticExtForJob:(HBJob *)job;
++ (NSURL *)destURLForJob:(HBJob *)job;
+
/**
* Generates a file name automatically based on the inputs,
* it can be configured with NSUserDefaults.
@@ -49,5 +58,6 @@ NS_ASSUME_NONNULL_BEGIN
@end
+
NS_ASSUME_NONNULL_END
diff --git a/macosx/HBUtilities.m b/macosx/HBUtilities.m
index eab00968e..cbec14384 100644
--- a/macosx/HBUtilities.m
+++ b/macosx/HBUtilities.m
@@ -5,6 +5,10 @@
It may be used under the terms of the GNU General Public License. */
#import "HBUtilities.h"
+
+#import "HBTitle.h"
+#import "HBJob.h"
+
#include "common.h"
@implementation HBUtilities
@@ -47,6 +51,129 @@
va_end(args);
}
++ (NSURL *)mediaURLFromURL:(NSURL *)URL
+{
+ NSURL *mediaURL = URL;
+
+ // We check to see if the chosen file at path is a package
+ if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:URL.path])
+ {
+ [HBUtilities writeToActivityLog:"trying to open a package at: %s", URL.path.UTF8String];
+ // We check to see if this is an .eyetv package
+ if ([URL.pathExtension isEqualToString:@"eyetv"])
+ {
+ [HBUtilities writeToActivityLog:"trying to open eyetv package"];
+ // We're looking at an EyeTV package - try to open its enclosed .mpg media file
+ NSString *mpgname;
+ NSUInteger n = [[URL.path stringByAppendingString: @"/"]
+ completePathIntoString: &mpgname caseSensitive: YES
+ matchesIntoArray: nil
+ filterTypes: @[@"mpg"]];
+ if (n > 0)
+ {
+ // Found an mpeg inside the eyetv package, make it our scan path
+ [HBUtilities writeToActivityLog:"found mpeg in eyetv package"];
+ mediaURL = [NSURL fileURLWithPath:mpgname];
+ }
+ else
+ {
+ // We did not find an mpeg file in our package, so we do not call performScan
+ [HBUtilities writeToActivityLog:"no valid mpeg in eyetv package"];
+ }
+ }
+ // We check to see if this is a .dvdmedia package
+ else if ([URL.pathExtension isEqualToString:@"dvdmedia"])
+ {
+ // path IS a package - but dvdmedia packages can be treaded like normal directories
+ [HBUtilities writeToActivityLog:"trying to open dvdmedia package"];
+ }
+ else
+ {
+ // The package is not an eyetv package, try to open it anyway
+ [HBUtilities writeToActivityLog:"not a known to package"];
+ }
+ }
+ else
+ {
+ // path is not a package, so we call perform scan directly on our file
+ if ([URL.lastPathComponent isEqualToString:@"VIDEO_TS"])
+ {
+ [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
+ mediaURL = URL.URLByDeletingLastPathComponent;
+ }
+ else
+ {
+ [HBUtilities writeToActivityLog:"trying to open a folder or file"];
+ }
+ }
+
+ return mediaURL;
+}
+
++ (NSString *)automaticNameForJob:(HBJob *)job
+{
+ HBTitle *title = job.title;
+
+ // Generate a new file name
+ NSString *fileName = [HBUtilities automaticNameForSource:title.name
+ title:title.index
+ chapters:NSMakeRange(job.range.chapterStart + 1, job.range.chapterStop + 1)
+ quality:job.video.qualityType ? job.video.quality : 0
+ bitrate:!job.video.qualityType ? job.video.avgBitrate : 0
+ videoCodec:job.video.encoder];
+ return fileName;
+}
+
++ (NSString *)automaticExtForJob:(HBJob *)job
+{
+ NSString *extension = @(hb_container_get_default_extension(job.container));
+
+ if (job.container & HB_MUX_MASK_MP4)
+ {
+ BOOL anyCodecAC3 = [job.audio anyCodecMatches:HB_ACODEC_AC3] || [job.audio anyCodecMatches:HB_ACODEC_AC3_PASS];
+ // Chapter markers are enabled if the checkbox is ticked and we are doing p2p or we have > 1 chapter
+ BOOL chapterMarkers = (job.chaptersEnabled) &&
+ (job.range.type != HBRangeTypeChapters || job.range.chapterStart < job.range.chapterStop);
+
+ if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"] isEqualToString:@".m4v"] ||
+ ((YES == anyCodecAC3 || YES == chapterMarkers) &&
+ [[[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"] isEqualToString:@"Auto"]))
+ {
+ extension = @"m4v";
+ }
+ }
+
+ return extension;
+}
+
++ (NSURL *)destURLForJob:(HBJob *)job
+{
+ // Check to see if the last destination has been set,use if so, if not, use Desktop
+ NSURL *destURL = [[NSUserDefaults standardUserDefaults] URLForKey:@"HBLastDestinationDirectory"];
+ if (!destURL || ![[NSFileManager defaultManager] fileExistsAtPath:destURL.path])
+ {
+ destURL = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES) firstObject]
+ isDirectory:YES];
+ }
+
+ // Generate a new file name
+ NSString *fileName = job.title.name;
+
+ // If Auto Naming is on. We create an output filename of dvd name - title number
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"])
+ {
+ fileName = [self automaticNameForJob:job];
+ }
+
+ destURL = [destURL URLByAppendingPathComponent:fileName];
+ // use the correct extension based on the container
+ NSString *ext = [self automaticExtForJob:job];
+ destURL = [destURL URLByAppendingPathExtension:ext];
+
+ return destURL;
+}
+
+ (NSString *)automaticNameForSource:(NSString *)sourceName
title:(NSUInteger)title
chapters:(NSRange)chaptersRange