summaryrefslogtreecommitdiffstats
path: root/macosx/HBCore.m
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/HBCore.m')
-rw-r--r--macosx/HBCore.m298
1 files changed, 202 insertions, 96 deletions
diff --git a/macosx/HBCore.m b/macosx/HBCore.m
index 0702d5d8e..fb3184ba5 100644
--- a/macosx/HBCore.m
+++ b/macosx/HBCore.m
@@ -1,21 +1,14 @@
-/**
- * @file
- * Implementation of class HBCore.
- */
-
-#import "HBCore.h"
-#include "hb.h"
+/* HBCore.m $
-// These constants specify the current state of HBCore.
+ 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. */
-const NSString *HBStateIdle = @"HBStateIdle"; ///< HB is doing nothing (HB_STATE_IDLE)
-const NSString *HBStateScanning = @"HBStateScanning"; ///< HB is scanning (HB_STATE_SCANNING)
-const NSString *HBStateScanDone = @"HBStateScanDone"; ///< Scanning has been completed (HB_STATE_SCANDONE)
-const NSString *HBStateWorking = @"HBStateWorking"; ///< HB is encoding (HB_STATE_WORKING)
-const NSString *HBStatePaused = @"HBStatePaused"; ///< Encoding is paused (HB_STATE_PAUSED)
-const NSString *HBStateWorkDone = @"HBStateWorkDone"; ///< Encoding has been completed (HB_STATE_WORKDONE)
-const NSString *HBStateMuxing = @"HBStateMuxing"; ///< HB is muxing (HB_STATE_MUXING)
+#import "HBCore.h"
+#import "HBDVDDetector.h"
+#import "HBUtilities.h"
+#include <dlfcn.h>
// These constants specify various status notifications sent by HBCore
@@ -40,12 +33,25 @@ NSString *HBCoreMuxingNotification = @"HBCoreMuxingNotification";
/**
* Private methods of HBCore.
*/
-@interface HBCore (Private)
-- (NSString *)stateAsString:(int)stateValue;
+@interface HBCore ()
+
+/// Current state of HBCore.
+@property (nonatomic, readwrite) HBState state;
+
+/// Timer used to poll libhb for state changes.
+@property (nonatomic, readwrite, retain) NSTimer *updateTimer;
+
+- (void)stateUpdateTimer:(NSTimer *)timer;
+
@end
@implementation HBCore
++ (void)setDVDNav:(BOOL)enabled
+{
+ hb_dvd_set_dvdnav(enabled);
+}
+
/**
* Initializes HBCore.
*/
@@ -53,8 +59,8 @@ NSString *HBCoreMuxingNotification = @"HBCoreMuxingNotification";
{
if (self = [super init])
{
- state = HBStateIdle;
- hb_state = malloc(sizeof(struct hb_state_s));
+ _state = HBStateIdle;
+ _hb_state = malloc(sizeof(struct hb_state_s));
}
return self;
}
@@ -64,7 +70,11 @@ NSString *HBCoreMuxingNotification = @"HBCoreMuxingNotification";
*/
- (void)dealloc
{
- free(hb_state);
+ [self stopUpdateTimer];
+ hb_close(&_hb_handle);
+ _hb_handle = NULL;
+
+ free(_hb_state);
[super dealloc];
}
@@ -73,107 +83,189 @@ NSString *HBCoreMuxingNotification = @"HBCoreMuxingNotification";
* functions HBCore are used.
*
* @param debugMode If set to YES, libhb will print verbose debug output.
- * @param checkForUpdates If set to YES, libhb checks for updated versions.
*
* @return YES if libhb was opened, NO if there was an error.
*/
-- (BOOL)openInDebugMode:(BOOL)debugMode checkForUpdates:(BOOL)checkForUpdates;
+- (instancetype)initWithLoggingLevel:(int)loggingLevel
{
- NSAssert(!hb_handle, @"[HBCore openInDebugMode:checkForUpdates:] libhb is already open");
- if (hb_handle)
+ self = [self init];
+ if (self)
+ {
+ _hb_handle = hb_init(loggingLevel, 0);
+ if (!_hb_handle)
+ {
+ [self release];
+ return nil;
+ }
+ }
+
+ return self;
+}
+
+#pragma mark - Scan
+
+- (BOOL)canScan:(NSURL *)url error:(NSError **)error
+{
+ if (!_hb_handle)
+ {
+ // Libhb is not open so we cannot do anything.
return NO;
+ }
- state = HBStateIdle;
+ if (![[NSFileManager defaultManager] fileExistsAtPath:url.path]) {
+ if (*error) {
+ *error = [NSError errorWithDomain:@"HBErrorDomain"
+ code:100
+ userInfo:@{ NSLocalizedDescriptionKey: @"Unable to find the file at the specified URL" }];
+ }
- hb_handle = hb_init(debugMode ? HB_DEBUG_ALL : HB_DEBUG_NONE, checkForUpdates);
- if (!hb_handle)
return NO;
+ }
- updateTimer = [[NSTimer scheduledTimerWithTimeInterval:0.5
- target:self
- selector:@selector(stateUpdateTimer:)
- userInfo:NULL
- repeats:YES] retain];
+ HBDVDDetector *detector = [HBDVDDetector detectorForPath:url.path];
+
+ if (detector.isVideoDVD)
+ {
+ // The chosen path was actually on a DVD, so use the raw block
+ // device path instead.
+
+ [HBUtilities writeToActivityLog: "trying to open a physical dvd at: %s", [url.path UTF8String]];
+
+ // Notify the user that we don't support removal of copy protection.
+ void *dvdcss = dlopen("libdvdcss.2.dylib", RTLD_LAZY);
+ if (dvdcss)
+ {
+ // libdvdcss was found so all is well
+ [HBUtilities writeToActivityLog: "libdvdcss.2.dylib found for decrypting physical dvd"];
+ dlclose(dvdcss);
+ }
+ else
+ {
+ // compatible libdvdcss not found
+ [HBUtilities writeToActivityLog: "libdvdcss.2.dylib not found for decrypting physical dvd"];
+
+ if (*error) {
+ *error = [NSError errorWithDomain:@"HBErrorDomain" code:101 userInfo:@{ NSLocalizedDescriptionKey: @"libdvdcss.2.dylib not found for decrypting physical dvd" }];
+ }
+ }
+ }
- [[NSRunLoop currentRunLoop] addTimer:updateTimer forMode:NSModalPanelRunLoopMode];
return YES;
}
-/**
- * Closes low level HandBrake library and releases resources.
- *
- * @return YES if libhb was closed successfully, NO if there was an error.
- */
-- (BOOL)close
+- (void)scan:(NSURL *)url titleNum:(NSUInteger)titleNum previewsNum:(NSUInteger)previewsNum minTitleDuration:(NSUInteger)minTitleDuration;
{
- NSAssert(hb_handle, @"[HBCore close] libhb is not open");
- if (!hb_handle)
- return NO;
+ NSAssert(_hb_handle, @"[HBCore scan:] libhb is not open");
- [updateTimer invalidate];
- [updateTimer release];
- updateTimer = nil;
- hb_close(&hb_handle);
- hb_handle = NULL;
- return YES;
+ // Start the timer to handle libhb state changes
+ [self startUpdateTimer];
+
+ NSString *path = url.path;
+ HBDVDDetector *detector = [HBDVDDetector detectorForPath:path];
+
+ if (detector.isVideoDVD)
+ {
+ // The chosen path was actually on a DVD, so use the raw block
+ // device path instead.
+ path = detector.devicePath;
+ }
+
+ // convert minTitleDuration from seconds to the internal HB time
+ uint64_t min_title_duration_ticks = 90000LL * minTitleDuration;
+
+ // If there is no title number passed to scan, we use 0
+ // which causes the default behavior of a full source scan
+ if (titleNum > 0)
+ {
+ [HBUtilities writeToActivityLog: "scanning specifically for title: %d", titleNum];
+ }
+ else
+ {
+ // minimum title duration doesn't apply to title-specific scan
+ // it doesn't apply to batch scan either, but we can't tell it apart from DVD & BD folders here
+ [HBUtilities writeToActivityLog: "scanning titles with a duration of %d seconds or more", minTitleDuration];
+ }
+
+ hb_system_sleep_prevent(_hb_handle);
+
+ hb_scan(_hb_handle, path.fileSystemRepresentation,
+ (int)titleNum, (int)previewsNum,
+ 1, min_title_duration_ticks);
}
-/**
- * Returns libhb handle used by this HBCore instance.
- */
-- (struct hb_handle_s *)hb_handle
+#pragma mark - Encodes
+
+- (void)start
{
- return hb_handle;
+ NSAssert(_hb_handle, @"[HBCore start] libhb is not open");
+
+ // Start the timer to handle libhb state changes
+ [self startUpdateTimer];
+
+ hb_system_sleep_prevent(_hb_handle);
+ hb_start(_hb_handle);
}
+- (void)stop
+{
+ NSAssert(_hb_handle, @"[HBCore stop] libhb is not open");
+
+ hb_stop(_hb_handle);
+ hb_system_sleep_allow(_hb_handle);
+}
+
+#pragma mark - State updates
+
/**
- * Returns current state of HBCore.
- *
- * @return One of the HBState* string constants.
+ * Starts the timer used to polls libhb for state changes.
*/
-- (const NSString *)state
+- (void)startUpdateTimer
{
- return state;
+ if (!self.updateTimer)
+ {
+ self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.5
+ target:self
+ selector:@selector(stateUpdateTimer:)
+ userInfo:NULL
+ repeats:YES];
+
+ [[NSRunLoop currentRunLoop] addTimer:self.updateTimer forMode:NSEventTrackingRunLoopMode];
+ }
}
/**
- * Returns latest hb_state_s information struct returned by libhb.
- *
- * @return Pointer to a hb_state_s struct containing state information of libhb.
+ * Stops the update timer.
*/
-- (const struct hb_state_s *)hb_state
+- (void)stopUpdateTimer
{
- return hb_state;
+ [self.updateTimer invalidate];
+ self.updateTimer = nil;
}
-@end
-
-@implementation HBCore (Private)
-
/**
- * Transforms a libhb state constant to a matching HBCore state constant.
+ * Transforms a libhb state constant to a matching HBCore selector.
*/
-- (const NSString *)stateAsString:(int)stateValue
+- (const SEL)selectorForState:(HBState)stateValue
{
switch (stateValue)
{
- case HB_STATE_IDLE:
- return HBStateIdle;
- case HB_STATE_SCANNING:
- return HBStateScanning;
- case HB_STATE_SCANDONE:
- return HBStateScanDone;
case HB_STATE_WORKING:
- return HBStateWorking;
+ return @selector(handleHBStateWorking);
+ case HB_STATE_SCANNING:
+ return @selector(handleHBStateScanning);
+ case HB_STATE_MUXING:
+ return @selector(handleHBStateMuxing);
case HB_STATE_PAUSED:
- return HBStatePaused;
+ return @selector(handleHBStatePaused);
+ case HB_STATE_SEARCHING:
+ return @selector(handleHBStateSearching);
+ case HB_STATE_SCANDONE:
+ return @selector(handleHBStateScanDone);
case HB_STATE_WORKDONE:
- return HBStateWorkDone;
- case HB_STATE_MUXING:
- return HBStateMuxing;
+ return @selector(handleHBStateWorkDone);
default:
- NSAssert1(NO, @"[HBCore stateAsString:] unknown state %d", stateValue);
- return nil;
+ NSAssert1(NO, @"[HBCore selectorForState:] unknown state %lu", stateValue);
+ return NULL;
}
}
@@ -184,35 +276,40 @@ NSString *HBCoreMuxingNotification = @"HBCoreMuxingNotification";
*/
- (void)stateUpdateTimer:(NSTimer *)timer
{
- if (!hb_handle)
+ if (!_hb_handle)
{
// Libhb is not open so we cannot do anything.
return;
}
- hb_get_state(hb_handle, hb_state);
+ hb_get_state(_hb_handle, _hb_state);
- if (hb_state->state == HB_STATE_IDLE)
+ if (_hb_state->state == HB_STATE_IDLE)
{
// Libhb reported HB_STATE_IDLE, so nothing interesting has happened.
return;
}
-
+
// Update HBCore state to reflect the current state of libhb
- NSString *newState = [self stateAsString:hb_state->state];
- if (newState != state)
- {
- [self willChangeValueForKey:@"state"];
- state = newState;
- [self didChangeValueForKey:@"state"];
- }
+ self.state = _hb_state->state;
// Determine name of the method that does further processing for this state
// and call it.
- SEL sel = NSSelectorFromString([NSString stringWithFormat:@"handle%@", state]);
- if ([self respondsToSelector:sel])
- [self performSelector:sel];
+ SEL sel = [self selectorForState:self.state];
+ [self performSelector:sel];
+
+ if (_hb_state->state == HB_STATE_WORKDONE || _hb_state->state == HB_STATE_SCANDONE)
+ {
+ // Libhb reported HB_STATE_WORKDONE or HB_STATE_SCANDONE,
+ // so nothing interesting will happen after this point, stop the timer.
+ [self stopUpdateTimer];
+
+ self.state = HBStateIdle;
+ hb_system_sleep_allow(_hb_handle);
+ }
}
+#pragma mark - Notifications
+
/**
* Processes HBStateScanning state information. Current implementation just
* sends HBCoreScanningNotification.
@@ -267,4 +364,13 @@ NSString *HBCoreMuxingNotification = @"HBCoreMuxingNotification";
[[NSNotificationCenter defaultCenter] postNotificationName:HBCoreMuxingNotification object:self];
}
+/**
+ * Processes HBStateSearching state information. Current implementation just
+ * sends HBCoreSearchingNotification.
+ */
+- (void)handleHBStateSearching
+{
+ [[NSNotificationCenter defaultCenter] postNotificationName:HBCoreMuxingNotification object:self];
+}
+
@end