summaryrefslogtreecommitdiffstats
path: root/macosx/HBCore.m
blob: 40377605166bf6f064a43d6ec7d842075c2dc89c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/**
 * @file
 * Implementation of class HBCore.
 */

#import "HBCore.h"
#include "hb.h"

// These constants specify the current state of HBCore.

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)


// These constants specify various status notifications sent by HBCore

/// Notification sent to update status while scanning. Matches HB_STATE_SCANNING constant in libhb.
NSString *HBCoreScanningNotification = @"HBCoreScanningNotification";

/// Notification sent after scanning is complete. Matches HB_STATE_SCANDONE constant in libhb.
NSString *HBCoreScanDoneNotification = @"HBCoreScanDoneNotification";

/// Notification sent to update status while encoding. Matches HB_STATE_WORKING constant in libhb.
NSString *HBCoreWorkingNotification = @"HBCoreWorkingNotification";

/// Notification sent when encoding is paused. Matches HB_STATE_PAUSED constant in libhb.
NSString *HBCorePausedNotification = @"HBCorePausedNotification";

/// Notification sent after encoding is complete. Matches HB_STATE_WORKDONE constant in libhb.
NSString *HBCoreWorkDoneNotification = @"HBCoreWorkDoneNotification";

/// Notification sent to update status while muxing. Matches HB_STATE_MUXING constant in libhb.
NSString *HBCoreMuxingNotification = @"HBCoreMuxingNotification";

/**
 * Private methods of HBCore.
 */
@interface HBCore (Private)
- (NSString *)stateAsString:(int)stateValue;
@end

@implementation HBCore

/**
 * Initializes HBCore.
 */
- (id)init
{
    if (self = [super init])
    {
        state = HBStateIdle;    
        hb_state = malloc(sizeof(struct hb_state_s));   
    }
    return self;
}

/**
 * Releases resources.
 */
- (void)dealloc
{
    free(hb_state);    
    [super dealloc];
}

/**
 * Opens low level HandBrake library. This should be called once before other
 * 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;
{
    NSAssert(!hb_handle, @"[HBCore openInDebugMode:checkForUpdates:] libhb is already open");
    if (hb_handle)
        return NO;

    state = HBStateIdle;    

    hb_handle = hb_init(debugMode ? HB_DEBUG_ALL : HB_DEBUG_NONE, checkForUpdates);
    if (!hb_handle)
        return NO;

    updateTimer = [[NSTimer scheduledTimerWithTimeInterval:0.2
                                                    target:self
                                                  selector:@selector(stateUpdateTimer:) 
                                                  userInfo:NULL 
                                                   repeats:YES] retain];

    [[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
{
    NSAssert(hb_handle, @"[HBCore close] libhb is not open");
    if (!hb_handle)
        return NO;
        
    [updateTimer invalidate];
    [updateTimer release];
    updateTimer = nil;
    hb_close(&hb_handle);
    hb_handle = NULL;
    return YES;
}

/**
 * Returns libhb handle used by this HBCore instance.
 */ 
- (struct hb_handle_s *)hb_handle
{
    return hb_handle;
}

/**
 * Returns current state of HBCore.
 *
 * @return One of the HBState* string constants.
 */
- (const NSString *)state
{
    return state;
}

/**
 * Returns latest hb_state_s information struct returned by libhb.
 *
 * @return Pointer to a hb_state_s struct containing state information of libhb.
 */
- (const struct hb_state_s *)hb_state
{
    return hb_state;
}

@end 

@implementation HBCore (Private)

/**
 * Transforms a libhb state constant to a matching HBCore state constant.
 */
- (const NSString *)stateAsString:(int)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;
        case HB_STATE_PAUSED:
            return HBStatePaused;
        case HB_STATE_WORKDONE:
            return HBStateWorkDone;
        case HB_STATE_MUXING:
            return HBStateMuxing;        
        default:
            NSAssert1(NO, @"[HBCore stateAsString:] unknown state %d", stateValue);
            return nil;
    }
}

/**
 * This method polls libhb continuously for state changes and processes them.
 * Additional processing for each state is performed in methods that start
 * with 'handle' (e.g. handleHBStateScanning).
 */
- (void)stateUpdateTimer:(NSTimer *)timer
{
    if (!hb_handle)
    {
        // Libhb is not open so we cannot do anything.
        return;
    }
    hb_get_state(hb_handle, hb_state);

    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"];
    }

    // 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];
}

/**
 * Processes HBStateScanning state information. Current implementation just
 * sends HBCoreScanningNotification.
 */
- (void)handleHBStateScanning
{
    [[NSNotificationCenter defaultCenter] postNotificationName:HBCoreScanningNotification object:self];    
}

/**
 * Processes HBStateScanDone state information. Current implementation just
 * sends HBCoreScanDoneNotification.
 */
- (void)handleHBStateScanDone
{
    [[NSNotificationCenter defaultCenter] postNotificationName:HBCoreScanDoneNotification object:self];    
}

/**
 * Processes HBStateWorking state information. Current implementation just
 * sends HBCoreWorkingNotification.
 */
- (void)handleHBStateWorking
{
    [[NSNotificationCenter defaultCenter] postNotificationName:HBCoreWorkingNotification object:self];    
}

/**
 * Processes HBStatePaused state information. Current implementation just
 * sends HBCorePausedNotification.
 */
- (void)handleHBStatePaused
{
    [[NSNotificationCenter defaultCenter] postNotificationName:HBCorePausedNotification object:self];    
}

/**
 * Processes HBStateWorkDone state information. Current implementation just
 * sends HBCoreWorkDoneNotification.
 */
- (void)handleHBStateWorkDone
{
    [[NSNotificationCenter defaultCenter] postNotificationName:HBCoreWorkDoneNotification object:self];    
}

/**
 * Processes HBStateMuxing state information. Current implementation just
 * sends HBCoreMuxingNotification.
 */
- (void)handleHBStateMuxing
{
    [[NSNotificationCenter defaultCenter] postNotificationName:HBCoreMuxingNotification object:self];    
}

@end