#import "HBAddPresetController.h"
#import "HBPreset.h"
-
-#include "hb.h"
+#import "HBMutablePreset.h"
@interface HBAddPresetController ()
[self.picSettingsPopUp addItemWithTitle:NSLocalizedString(@"None", @"")];
[[self.picSettingsPopUp lastItem] setTag: 0];
- if ([self.preset.content[@"PicturePAR"] integerValue] != HB_ANAMORPHIC_STRICT)
+ if (![self.preset[@"PicturePAR"] isEqualToString:@"strict"])
{
// not Strict, Custom is applicable
[self.picSettingsPopUp addItemWithTitle:NSLocalizedString(@"Custom", @"")];
}
else
{
- self.preset.name = self.name.stringValue;
- self.preset.presetDescription = self.desc.stringValue;
-
- NSMutableDictionary *dict = [self.preset.content mutableCopy];
+ HBMutablePreset *newPreset = [self.preset mutableCopy];
- dict[@"PresetName"] = self.name.stringValue;
- dict[@"PresetDescription"] = self.desc.stringValue;
+ newPreset.name = self.name.stringValue;
+ newPreset.presetDescription = self.desc.stringValue;
// Get the picture size
- dict[@"PictureWidth"] = @(self.picWidth.integerValue);
- dict[@"PictureHeight"] = @(self.picHeight.integerValue);
+ newPreset[@"PictureWidth"] = @(self.picWidth.integerValue);
+ newPreset[@"PictureHeight"] = @(self.picHeight.integerValue);
//Get the whether or not to apply pic Size and Cropping (includes Anamorphic)
- dict[@"UsesPictureSettings"] = @(self.picSettingsPopUp.selectedItem.tag);
+ newPreset[@"UsesPictureSettings"] = @(self.picSettingsPopUp.selectedItem.tag);
// Always use Picture Filter settings for the preset
- dict[@"UsesPictureFilters"] = @YES;
+ newPreset[@"UsesPictureFilters"] = @YES;
- self.preset.content = [dict copy];
+ [newPreset cleanUp];
- [self.preset cleanUp];
+ self.preset = [newPreset copy];
[[self window] orderOut:nil];
[NSApp endSheet:[self window] returnCode:NSModalResponseContinue];
#pragma mark - Presets
-- (void)writeToPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(HBMutablePreset *)preset
{
[self.defaults writeToPreset:preset];
}
-- (void)applyPreset:(NSDictionary *)preset
+- (void)applyPreset:(HBPreset *)preset
{
[self.defaults applyPreset:preset];
[self addTracksFromDefaults:NO];
return nil;
}
-- (void)applyPreset:(NSDictionary *)preset
+- (void)applyPreset:(HBPreset *)preset
{
// Track selection behavior
if ([preset[@"AudioTrackSelectionBehavior"] isEqualToString:@"first"])
}
}
-- (void)writeToPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(HBMutablePreset *)preset
{
// Track selection behavior
if (self.trackSelectionBehavior == HBAudioTrackSelectionBehaviorFirst)
#import "HBPresetsManager.h"
#import "HBPreset.h"
+#import "HBMutablePreset.h"
#import "HBUtilities.h"
#import "HBPictureViewController.h"
- (HBPreset *)createPresetFromCurrentSettings
{
- NSMutableDictionary *preset = [NSMutableDictionary dictionary];
- NSDictionary *currentPreset = self.currentPreset.content;
-
- preset[@"PresetBuildNumber"] = [NSString stringWithFormat: @"%d", [[[NSBundle mainBundle] infoDictionary][@"CFBundleVersion"] intValue]];
- preset[@"PresetName"] = self.job.presetName;
- preset[@"Folder"] = @NO;
+ HBMutablePreset *preset = [self.currentPreset mutableCopy];
// Set whether or not this is a user preset or factory 0 is factory, 1 is user
preset[@"Type"] = @1;
preset[@"Default"] = @NO;
- // Get the whether or not to apply pic Size and Cropping (includes Anamorphic)
- preset[@"UsesPictureSettings"] = currentPreset[@"UsesPictureSettings"];
- // Get whether or not to use the current Picture Filter settings for the preset
- preset[@"UsesPictureFilters"] = currentPreset[@"UsesPictureFilters"];
-
- preset[@"PictureWidth"] = currentPreset[@"PictureWidth"];
- preset[@"PictureHeight"] = currentPreset[@"PictureHeight"];
-
- preset[@"PresetDescription"] = currentPreset[@"PresetDescription"];
-
- [self.job applyCurrentSettingsToPreset:preset];
+ [self.job writeToPreset:preset];
- return [[HBPreset alloc] initWithName:preset[@"PresetName"] content:preset builtIn:NO];
+ return [preset copy];
}
#pragma mark -
#pragma mark - Presets and queue
-- (void)writeToPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(HBMutablePreset *)preset
{
preset[@"PictureDeinterlaceFilter"] = self.deinterlace;
preset[@"PictureDeinterlacePreset"] = self.deinterlacePreset;
preset[@"VideoGrayScale"] = @(self.grayscale);
}
-- (void)applyPreset:(NSDictionary *)preset
+- (void)applyPreset:(HBPreset *)preset
{
self.notificationsEnabled = NO;
#import <Foundation/Foundation.h>
@class HBPreset;
+@class HBMutablePreset;
@class HBTitle;
#import "HBRange.h"
/**
* HBJob
*/
-@interface HBJob : NSObject <NSSecureCoding, NSCopying, HBUniqueObject>
+@interface HBJob : NSObject <NSSecureCoding, NSCopying, HBPresetCoding, HBUniqueObject>
- (instancetype)initWithTitle:(HBTitle *)title andPreset:(HBPreset *)preset;
-- (void)applyPreset:(HBPreset *)preset;
-- (void)applyCurrentSettingsToPreset:(NSMutableDictionary *)dict;
-
/// Current state of the job.
@property (nonatomic, readwrite) HBJobState state;
#import "HBJob.h"
#import "HBTitle.h"
-#import "HBPreset.h"
#import "HBAudioDefaults.h"
#import "HBSubtitlesDefaults.h"
return self;
}
+#pragma mark - HBPresetCoding
+
- (void)applyPreset:(HBPreset *)preset
{
self.presetName = preset.name;
- NSDictionary *content = preset.content;
-
- self.container = hb_container_get_from_name([content[@"FileFormat"] UTF8String]);
+ self.container = hb_container_get_from_name([preset[@"FileFormat"] UTF8String]);
// MP4 specifics options.
- self.mp4HttpOptimize = [content[@"Mp4HttpOptimize"] boolValue];
- self.mp4iPodCompatible = [content[@"Mp4iPodCompatible"] boolValue];
+ self.mp4HttpOptimize = [preset[@"Mp4HttpOptimize"] boolValue];
+ self.mp4iPodCompatible = [preset[@"Mp4iPodCompatible"] boolValue];
// Chapter Markers
- self.chaptersEnabled = [content[@"ChapterMarkers"] boolValue];
+ self.chaptersEnabled = [preset[@"ChapterMarkers"] boolValue];
[@[self.audio, self.subtitles, self.filters, self.picture, self.video] makeObjectsPerformSelector:@selector(applyPreset:)
- withObject:content];
+ withObject:preset];
}
-- (void)applyCurrentSettingsToPreset:(NSMutableDictionary *)dict
+- (void)writeToPreset:(HBMutablePreset *)preset
{
- dict[@"FileFormat"] = @(hb_container_get_short_name(self.container));
- dict[@"ChapterMarkers"] = @(self.chaptersEnabled);
+ preset.name = self.presetName;
+
+ preset[@"FileFormat"] = @(hb_container_get_short_name(self.container));
+ preset[@"ChapterMarkers"] = @(self.chaptersEnabled);
// MP4 specifics options.
- dict[@"Mp4HttpOptimize"] = @(self.mp4HttpOptimize);
- dict[@"Mp4iPodCompatible"] = @(self.mp4iPodCompatible);
+ preset[@"Mp4HttpOptimize"] = @(self.mp4HttpOptimize);
+ preset[@"Mp4iPodCompatible"] = @(self.mp4iPodCompatible);
[@[self.video, self.filters, self.picture, self.audio, self.subtitles] makeObjectsPerformSelector:@selector(writeToPreset:)
- withObject:dict];
+ withObject:preset];
}
- (void)setContainer:(int)container
--- /dev/null
+//
+// HBMutablePreset.h
+// HandBrake
+//
+// Created by Damiano Galassi on 12/10/15.
+//
+//
+
+#import <Foundation/Foundation.h>
+#import "HBPreset.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * A mutable subclass of HBPreset.
+ */
+@interface HBMutablePreset : HBPreset
+
+/**
+ * Removes unknown keys and normalizes values.
+ */
+- (void)cleanUp;
+
+- (void)setObject:(id)obj forKey:(NSString *)key;
+- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key;
+
+@end
+
+NS_ASSUME_NONNULL_END
--- /dev/null
+//
+// HBMutablePreset.m
+// HandBrake
+//
+// Created by Damiano Galassi on 12/10/15.
+//
+//
+
+#import "HBMutablePreset.h"
+
+@interface HBPreset (HBMutablePreset)
+
+@property (nonatomic, strong, nullable) NSMutableDictionary *content;
+- (void)cleanUp;
+
+@end
+
+@implementation HBMutablePreset
+
+- (void)setObject:(id)obj forKey:(NSString *)key;
+{
+ self.content[key] = obj;
+}
+
+- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key
+{
+ self.content[key] = obj;
+}
+
+- (void)cleanUp
+{
+ [super cleanUp];
+}
+
+@end
#pragma mark - Presets
-- (void)writeToPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(HBMutablePreset *)preset
{
preset[@"PictureKeepRatio"] = @(self.keepDisplayAspect);
preset[@"PictureRightCrop"] = @(self.cropRight);
}
-- (void)applyPreset:(NSDictionary *)preset
+- (void)applyPreset:(HBPreset *)preset
{
self.validating = YES;
self.notificationsEnabled = NO;
*
* An instance of HBPreset can be an actual preset or a folder.
*/
-@interface HBPreset : HBTreeNode <NSCopying>
+@interface HBPreset : HBTreeNode <NSCopying, NSMutableCopying>
- (instancetype)initWithFolderName:(NSString *)title builtIn:(BOOL)builtIn;
*/
- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)atomically format:(HBPresetFormat)format removeRoot:(BOOL)removeRoot;
-/**
- * Removes unknown keys and normalizes values.
- */
-- (void)cleanUp;
-
/**
* The name of the preset.
*/
@property (nonatomic) BOOL isDefault;
/**
- * The actual content of the preset.
- */
-@property (nonatomic, strong, nullable) NSDictionary *content;
-
-/**
- * A dictionary representation of the preset.
+ * Returns the value associated with a given key.
+ *
+ * @param key The key for which to return the corresponding value.
+ *
+ * @return The value associated with key, or nil if no value is associated with key
*/
-@property (readonly, copy) NSDictionary *dictionary;
+- (nullable id)objectForKey:(NSString *)key;
+- (nullable id)objectForKeyedSubscript:(NSString *)key;
@end
It may be used under the terms of the GNU General Public License. */
#import "HBPreset.h"
+#import "HBMutablePreset.h"
+
#include "preset.h"
#import "NSJSONSerialization+HBAdditions.h"
+@interface HBPreset ()
+
+/**
+ * The actual content of the preset.
+ */
+@property (nonatomic, strong, nullable) NSMutableDictionary *content;
+
+@end
+
@implementation HBPreset
- (instancetype)init
{
_name = [title copy];
_isBuiltIn = builtIn;
- _content = [content copy];
+ _content = [content mutableCopy];
if ([content[@"PresetDescription"] isKindOfClass:[NSString class]])
{
_presetDescription = [content[@"PresetDescription"] copy];
}
+/**
+ * A dictionary representation of the preset.
+ */
- (NSDictionary *)dictionary
{
NSMutableDictionary *output = [[NSMutableDictionary alloc] init];
return success;
}
+#pragma mark - NSCopying
+
- (id)copyWithZone:(NSZone *)zone
{
HBPreset *node = [super copyWithZone:zone];
node->_name = [self.name copy];
- node->_content = [self.content copy];
+ node->_content = [self.content mutableCopy];
node->_presetDescription = [self.presetDescription copy];
return node;
}
-- (NSUInteger)hash
+- (id)mutableCopyWithZone:(NSZone *)zone
{
- return self.name.hash + self.isBuiltIn + self.isLeaf;
+ return [[HBMutablePreset allocWithZone:zone] initWithDictionary:_content];
}
-- (void)cleanUp
+- (NSUInteger)hash
{
- // Run the libhb clean function
- NSString *presetJson = [NSJSONSerialization HB_StringWithJSONObject:self.dictionary options:0 error:NULL];
-
- if (presetJson.length)
- {
- char *cleanedJson = hb_presets_clean_json(presetJson.UTF8String);
- NSDictionary *cleanedDict = [NSJSONSerialization HB_JSONObjectWithUTF8String:cleanedJson options:0 error:NULL];
- free(cleanedJson);
-
- if ([cleanedDict isKindOfClass:[NSDictionary class]])
- {
- self.content = cleanedDict;
- }
- }
+ return self.name.hash + self.isBuiltIn + self.isLeaf;
}
+#pragma mark - Properties
+
- (void)setName:(NSString *)name
{
_name = [name copy];
[self.delegate nodeDidChange:self];
}
+#pragma mark - Keys
+
+- (id)objectForKey:(NSString *)key
+{
+ return [_content objectForKey:key];
+}
+
+- (nullable id)objectForKeyedSubscript:(NSString *)key
+{
+ return _content[key];
+}
+
#pragma mark - KVC
- (BOOL)validateName:(id *)ioValue error:(NSError * __autoreleasing *)outError
#import <Foundation/Foundation.h>
-@protocol HBPresetCoding <NSObject>
+#import "HBPreset.h"
+#import "HBMutablePreset.h"
-- (void)applyPreset:(NSDictionary *)preset;
-- (void)writeToPreset:(NSMutableDictionary *)preset;
+@protocol HBPresetCoding <NSObject>
+- (void)applyPreset:(HBPreset *)preset;
+- (void)writeToPreset:(HBMutablePreset *)preset;
@end
\ No newline at end of file
#pragma mark - Presets
-- (void)writeToPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(HBMutablePreset *)preset
{
[self.defaults writeToPreset:preset];
}
-- (void)applyPreset:(NSDictionary *)preset
+- (void)applyPreset:(HBPreset *)preset
{
[self.defaults applyPreset:preset];
[self addTracksFromDefaults];
return self;
}
-- (void)applyPreset:(NSDictionary *)preset
+- (void)applyPreset:(HBPreset *)preset
{
if ([preset[@"SubtitleTrackSelectionBehavior"] isEqualToString:@"first"])
{
self.burnInBluraySubtitles = [preset[@"SubtitleBurnBDSub"] boolValue];
}
-- (void)writeToPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(HBMutablePreset *)preset
{
if (self.trackSelectionBehavior == HBSubtitleTrackSelectionBehaviorFirst)
{
return string;
}
-- (void)applyPreset:(NSDictionary *)preset
+- (void)applyPreset:(HBPreset *)preset
{
self.notificationsEnabled = NO;
self.notificationsEnabled = YES;
}
-- (void)writeToPreset:(NSMutableDictionary *)preset
+- (void)writeToPreset:(HBMutablePreset *)preset
{
preset[@"VideoEncoder"] = @(hb_video_encoder_get_short_name(self.encoder));
- (void)testAutoCrop
{
- XCTAssertEqual([self.preset.content[@"PictureAutoCrop"] boolValue], self.job.picture.autocrop);
+ XCTAssertEqual([self.preset[@"PictureAutoCrop"] boolValue], self.job.picture.autocrop);
}
- (void)testAutoCropValues
A955128B1A320B02001BFC6F /* libjansson.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A95512881A320A12001BFC6F /* libjansson.a */; };
A9597A2A1A49749D00007771 /* HBRange+UIAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A9597A291A49749D00007771 /* HBRange+UIAdditions.m */; };
A967E4BA1A16768200DF1DFC /* EncodeCanceled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A967E4B91A16768200DF1DFC /* EncodeCanceled@2x.png */; };
+ A96CD1761BCC5F9100F372F1 /* HBMutablePreset.m in Sources */ = {isa = PBXBuildFile; fileRef = A96CD1751BCC5F9100F372F1 /* HBMutablePreset.m */; };
A9706CB41AC1436F00BAEAA8 /* HBApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = A9706CB31AC1436F00BAEAA8 /* HBApplication.m */; };
A9706CB71AC1437800BAEAA8 /* HBExceptionAlertController.m in Sources */ = {isa = PBXBuildFile; fileRef = A9706CB61AC1437800BAEAA8 /* HBExceptionAlertController.m */; };
A9706CBA1AC1452800BAEAA8 /* ExceptionAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = A9706CB81AC1452800BAEAA8 /* ExceptionAlert.xib */; };
A95B8D931B09F16700F2F152 /* HandBrake Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "HandBrake Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
A95B8D961B09F16700F2F152 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A967E4B91A16768200DF1DFC /* EncodeCanceled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "EncodeCanceled@2x.png"; sourceTree = "<group>"; };
+ A96CD1741BCC5F9100F372F1 /* HBMutablePreset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBMutablePreset.h; sourceTree = "<group>"; };
+ A96CD1751BCC5F9100F372F1 /* HBMutablePreset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBMutablePreset.m; sourceTree = "<group>"; };
A9706CB21AC1436F00BAEAA8 /* HBApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBApplication.h; sourceTree = "<group>"; };
A9706CB31AC1436F00BAEAA8 /* HBApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBApplication.m; sourceTree = "<group>"; };
A9706CB51AC1437800BAEAA8 /* HBExceptionAlertController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBExceptionAlertController.h; sourceTree = "<group>"; };
273F20A214ADBE670021BE6D /* HBPresetsManager.m */,
A9CF25F21990D64E0023F727 /* HBPreset.h */,
A9CF25F31990D64E0023F727 /* HBPreset.m */,
+ A96CD1741BCC5F9100F372F1 /* HBMutablePreset.h */,
+ A96CD1751BCC5F9100F372F1 /* HBMutablePreset.m */,
A9D488A31996270300E9B1BA /* HBTreeNode.h */,
A9D488A41996270300E9B1BA /* HBTreeNode.m */,
);
273F20AD14ADBE670021BE6D /* HBAdvancedController.m in Sources */,
273F20AE14ADBE670021BE6D /* HBAudioTrack.m in Sources */,
A9DEC87A1A23C89E00C79B48 /* HBPicture.m in Sources */,
+ A96CD1761BCC5F9100F372F1 /* HBMutablePreset.m in Sources */,
273F20AF14ADBE670021BE6D /* HBAudioController.m in Sources */,
A9537BF31A48A99500141102 /* HBVideo+UIAdditions.m in Sources */,
273F20B114ADBE670021BE6D /* HBDVDDetector.m in Sources */,