summaryrefslogtreecommitdiffstats
path: root/macosx/HBSubtitlesController.m
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/HBSubtitlesController.m')
-rw-r--r--macosx/HBSubtitlesController.m533
1 files changed, 24 insertions, 509 deletions
diff --git a/macosx/HBSubtitlesController.m b/macosx/HBSubtitlesController.m
index 509ab0de5..3fb0b7f50 100644
--- a/macosx/HBSubtitlesController.m
+++ b/macosx/HBSubtitlesController.m
@@ -10,23 +10,11 @@
#import "HBSubtitles.h"
#import "HBSubtitlesDefaults.h"
-#include "hb.h"
-#include "lang.h"
-
-static void *HBSubtitlesControllerContext = &HBSubtitlesControllerContext;
-
-@interface HBSubtitlesController () <NSTableViewDataSource, NSTableViewDelegate>
-
-// IBOutles
-@property (unsafe_unretained) IBOutlet NSTableView *fTableView;
+@interface HBSubtitlesController ()
// Defaults
@property (nonatomic, readwrite, strong) HBSubtitlesDefaultsController *defaultsController;
-// Cached table view's cells
-@property (nonatomic, readonly) NSPopUpButtonCell *languagesCell;
-@property (nonatomic, readonly) NSPopUpButtonCell *encodingsCell;
-
@end
@implementation HBSubtitlesController
@@ -34,41 +22,12 @@ static void *HBSubtitlesControllerContext = &HBSubtitlesControllerContext;
- (instancetype)init
{
self = [super initWithNibName:@"Subtitles" bundle:nil];
-
- [self addObserver:self forKeyPath:@"self.subtitles.tracks" options:NSKeyValueObservingOptionInitial context:HBSubtitlesControllerContext];
-
return self;
}
-#pragma mark - KVO
-
-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
-{
- if (context == HBSubtitlesControllerContext)
- {
- // We use KVO to update the table manually
- // because this table isn't using bindings
- if ([keyPath isEqualToString:@"self.subtitles.tracks"])
- {
- [self.fTableView reloadData];
- }
- }
- else
- {
- [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
- }
-}
-
-- (void)setSubtitles:(HBSubtitles *)subtitles
-{
- _subtitles = subtitles;
-
- [self.fTableView reloadData];
-}
-
#pragma mark - Actions
-- (BOOL)validateUserInterfaceItem:(id < NSValidatedUserInterfaceItem >)anItem
+- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)anItem
{
return (self.subtitles != nil);
}
@@ -79,7 +38,6 @@ static void *HBSubtitlesControllerContext = &HBSubtitlesControllerContext;
- (IBAction)addAll:(id)sender
{
[self.subtitles addAllTracks];
- [self.fTableView reloadData];
}
/**
@@ -88,7 +46,6 @@ static void *HBSubtitlesControllerContext = &HBSubtitlesControllerContext;
- (IBAction)removeAll:(id)sender
{
[self.subtitles removeAll];
- [self.fTableView reloadData];
}
/**
@@ -98,15 +55,14 @@ static void *HBSubtitlesControllerContext = &HBSubtitlesControllerContext;
- (IBAction)addTracksFromDefaults:(id)sender
{
[self.subtitles reloadDefaults];
- [self.fTableView reloadData];
}
- (IBAction)showSettingsSheet:(id)sender
{
self.defaultsController = [[HBSubtitlesDefaultsController alloc] initWithSettings:self.subtitles.defaults];
- [NSApp beginSheet:[self.defaultsController window]
- modalForWindow:[[self view] window]
+ [NSApp beginSheet:self.defaultsController.window
+ modalForWindow:self.view.window
modalDelegate:self
didEndSelector:@selector(sheetDidEnd)
contextInfo:NULL];
@@ -117,388 +73,6 @@ static void *HBSubtitlesControllerContext = &HBSubtitlesControllerContext;
self.defaultsController = nil;
}
-#pragma mark - Subtitles tracks creation and validation
-
-/**
- * Checks whether any subtitles in the list cannot be passed through.
- * Set the first of any such subtitles to burned-in, remove the others.
- */
-- (void)validatePassthru
-{
- [self.subtitles validatePassthru];
- [self.fTableView reloadData];
-}
-
-- (void)validateBurned:(NSInteger)index
-{
- [self.subtitles.tracks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
- {
- if (idx != index)
- {
- obj[keySubTrackBurned] = @0;
- }
- }];
- [self validatePassthru];
-}
-
-- (void)validateDefault:(NSInteger)index
-{
- [self.subtitles.tracks enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
- {
- if (idx != index)
- {
- obj[keySubTrackDefault] = @0;
- }
- }];
-}
-
-#pragma mark -
-#pragma mark Subtitle Table Data Source Methods
-
-- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
-{
- return self.subtitles.tracks.count;
-}
-
-- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
-{
- NSDictionary *track = self.subtitles.tracks[rowIndex];
-
- if ([[aTableColumn identifier] isEqualToString:@"track"])
- {
- NSNumber *index = track[keySubTrackSelectionIndex];
- if (index)
- return index;
- else
- return @0;
- }
- else if ([[aTableColumn identifier] isEqualToString:@"forced"])
- {
- return track[keySubTrackForced];
- }
- else if ([[aTableColumn identifier] isEqualToString:@"burned"])
- {
- return track[keySubTrackBurned];
- }
- else if ([[aTableColumn identifier] isEqualToString:@"default"])
- {
- return track[keySubTrackDefault];
- }
- /* These next three columns only apply to srt's. they are disabled for source subs */
- else if ([[aTableColumn identifier] isEqualToString:@"srt_lang"])
- {
- if ([track[keySubTrackType] intValue] == SRTSUB)
- {
- return track[keySubTrackLanguageIndex];
- }
- else
- {
- return @0;
- }
- }
- else if ([[aTableColumn identifier] isEqualToString:@"srt_charcode"])
- {
- if ([track[keySubTrackType] intValue] == SRTSUB)
- {
- return track[keySubTrackSrtCharCodeIndex];
- }
- else
- {
- return @0;
- }
- }
- else if ([[aTableColumn identifier] isEqualToString:@"srt_offset"])
- {
- if (track[keySubTrackSrtOffset])
- {
- return [track[keySubTrackSrtOffset] stringValue];
- }
- else
- {
- return @"0";
- }
- }
-
- return nil;
-}
-
-/**
- * Called whenever a widget in the table is edited or changed, we use it to record the change in the controlling array
- * including removing and adding new tracks via the "None" ("track" index of 0)
- */
-- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
-{
- if ([[aTableColumn identifier] isEqualToString:@"track"])
- {
- /* Set the array to track if we are vobsub (picture sub) */
- if ([anObject intValue] > 0)
- {
- NSMutableDictionary *newTrack = [self.subtitles trackFromSourceTrackIndex:[anObject integerValue] - 1 - (rowIndex == 0)];
- // Selection index calculation
- newTrack[keySubTrackSelectionIndex] = @([anObject integerValue]);
- self.subtitles.tracks[rowIndex] = newTrack;
- }
- }
- else if ([[aTableColumn identifier] isEqualToString:@"forced"])
- {
- self.subtitles.tracks[rowIndex][keySubTrackForced] = @([anObject intValue]);
- }
- else if ([[aTableColumn identifier] isEqualToString:@"burned"])
- {
- self.subtitles.tracks[rowIndex][keySubTrackBurned] = @([anObject intValue]);
- if([anObject intValue] == 1)
- {
- /* Burned In and Default are mutually exclusive */
- self.subtitles.tracks[rowIndex][keySubTrackDefault] = @0;
- }
- /* now we need to make sure no other tracks are set to burned if we have set burned */
- if ([anObject intValue] == 1)
- {
- [self validateBurned:rowIndex];
- }
- }
- else if ([[aTableColumn identifier] isEqualToString:@"default"])
- {
- self.subtitles.tracks[rowIndex][keySubTrackDefault] = @([anObject intValue]);
- if([anObject intValue] == 1)
- {
- /* Burned In and Default are mutually exclusive */
- self.subtitles.tracks[rowIndex][keySubTrackBurned] = @0;
- }
- /* now we need to make sure no other tracks are set to default */
- if ([anObject intValue] == 1)
- {
- [self validateDefault:rowIndex];
- }
- }
- /* These next three columns only apply to srt's. they are disabled for source subs */
- else if ([[aTableColumn identifier] isEqualToString:@"srt_lang"])
- {
- self.subtitles.tracks[rowIndex][keySubTrackLanguageIndex] = @([anObject intValue]);
- self.subtitles.tracks[rowIndex][keySubTrackLanguageIsoCode] = self.subtitles.languagesArray[[anObject intValue]][1];
- }
- else if ([[aTableColumn identifier] isEqualToString:@"srt_charcode"])
- {
- /* charCodeArray */
- self.subtitles.tracks[rowIndex][keySubTrackSrtCharCodeIndex] = @([anObject intValue]);
- self.subtitles.tracks[rowIndex][keySubTrackSrtCharCode] = self.subtitles.charCodeArray[[anObject intValue]];
- }
- else if ([[aTableColumn identifier] isEqualToString:@"srt_offset"])
- {
- self.subtitles.tracks[rowIndex][keySubTrackSrtOffset] = @([anObject integerValue]);
- }
-
- /* now lets do a bit of logic to add / remove tracks as necessary via the "None" track (index 0) */
- if ([[aTableColumn identifier] isEqualToString:@"track"])
- {
- /* Since currently no quicktime based playback devices support soft vobsubs in mp4, we make sure "burned in" is specified
- * by default to avoid massive confusion and anarchy. However we also want to guard against multiple burned in subtitle tracks
- * as libhb would ignore all but the first one anyway. Plus it would probably be stupid.
- */
- if ((self.subtitles.container & HB_MUX_MASK_MP4) && ([anObject intValue] != 0))
- {
- if ([self.subtitles.tracks[rowIndex][keySubTrackType] intValue] == VOBSUB)
- {
- /* lets see if there are currently any burned in subs specified */
- BOOL subtrackBurnedInFound = NO;
- for (id tempObject in self.subtitles.tracks)
- {
- if ([tempObject[keySubTrackBurned] intValue] == 1)
- {
- subtrackBurnedInFound = YES;
- }
- }
- /* if we have no current vobsub set to burn it in ... burn it in by default */
- if (!subtrackBurnedInFound)
- {
- self.subtitles.tracks[rowIndex][keySubTrackBurned] = @1;
- /* Burned In and Default are mutually exclusive */
- self.subtitles.tracks[rowIndex][keySubTrackDefault] = @0;
- }
- }
- }
-
- /* We use the track popup index number (presumes index 0 is "None" which is ignored and only used to remove tracks if need be)
- * to determine whether to 1 modify an existing track, 2. add a new empty "None" track or 3. remove an existing track.
- */
-
- if ([anObject intValue] != 0 && rowIndex == [self.subtitles.tracks count] - 1) // if we have a last track which != "None"
- {
- /* add a new empty None track */
- [self.subtitles.tracks addObject:[self.subtitles createSubtitleTrack]];
- }
- else if ([anObject intValue] == 0 && rowIndex != ([self.subtitles.tracks count] -1))// if this track is set to "None" and not the last track displayed
- {
- /* we know the user chose to remove this track by setting it to None, so remove it from the array */
- /* However,if this is the first track we have to reset the selected index of the next track by + 1, since it will now become
- * the first track, which has to account for the extra "Foreign Language Search" index. */
- if (rowIndex == 0 && [self.subtitles.tracks[1][keySubTrackSelectionIndex] intValue] != 0)
- {
- /* get the index of the selection in row one (which is track two) */
- int trackOneSelectedIndex = [self.subtitles.tracks[1][keySubTrackSelectionIndex] intValue];
- /* increment the index of the subtitle menu item by one, to account for Foreign Language Search which is unique to the first track */
- self.subtitles.tracks[1][keySubTrackSelectionIndex] = @(trackOneSelectedIndex + 1);
- }
- /* now that we have made the adjustment for track one (index 0) go ahead and delete the track */
- [self.subtitles.tracks removeObjectAtIndex: rowIndex];
- }
-
- // Validate the current passthru tracks.
- [self validatePassthru];
- }
-
- [aTableView reloadData];
-}
-
-#pragma mark -
-#pragma mark Subtitle Table Delegate Methods
-
-- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex
-{
- if ([[tableColumn identifier] isEqualToString:@"track"])
- {
- // 'track' is a popup of all available source subtitle tracks for the given title
- NSPopUpButtonCell *cellTrackPopup = [[NSPopUpButtonCell alloc] init];
- [cellTrackPopup setControlSize:NSSmallControlSize];
- [cellTrackPopup setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
-
- // Add our initial "None" track which we use to add source tracks or remove tracks.
- // "None" is always index 0.
- [[cellTrackPopup menu] addItemWithTitle:@"None" action:NULL keyEquivalent:@""];
-
- // Foreign Audio Search (index 1 in the popup) is only available for the first track
- if (rowIndex == 0)
- {
- [[cellTrackPopup menu] addItemWithTitle:self.subtitles.foreignAudioSearchTrackName action:NULL keyEquivalent:@""];
- }
-
- for (NSDictionary *track in self.subtitles.masterTrackArray)
- {
- [[cellTrackPopup menu] addItemWithTitle:track[keySubTrackName] action:NULL keyEquivalent:@""];
- }
-
- return cellTrackPopup;
- }
- else if ([[tableColumn identifier] isEqualToString:@"srt_lang"])
- {
- return self.languagesCell;
- }
- else if ([[tableColumn identifier] isEqualToString:@"srt_charcode"])
- {
- return self.encodingsCell;
- }
-
- return nil;
-}
-
-/**
- * Enables/Disables the table view cells.
- */
-- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
-{
- if ([[aTableColumn identifier] isEqualToString:@"track"])
- {
- return;
- }
-
- // If the Track is None, we disable the other cells as None is an empty track
- if ([self.subtitles.tracks[rowIndex][keySubTrackSelectionIndex] intValue] == 0)
- {
- [aCell setEnabled:NO];
- }
- else
- {
- // Since we have a valid track, we go ahead and enable the rest of the widgets and set them according to the controlling array */
- [aCell setEnabled:YES];
- }
-
- if ([[aTableColumn identifier] isEqualToString:@"forced"])
- {
- // Disable the "Forced Only" checkbox if a) the track is "None" or b) the subtitle track doesn't support forced flags
- if (![self.subtitles.tracks[rowIndex][keySubTrackSelectionIndex] intValue] ||
- !hb_subtitle_can_force([self.subtitles.tracks[rowIndex][keySubTrackType] intValue]))
- {
- [aCell setEnabled:NO];
- }
- else
- {
- [aCell setEnabled:YES];
- }
- }
- else if ([[aTableColumn identifier] isEqualToString:@"burned"])
- {
- /*
- * Disable the "Burned In" checkbox if:
- * a) the track is "None" OR
- * b) the subtitle track can't be burned in OR
- * c) the subtitle track can't be passed through (e.g. PGS w/MP4)
- */
- int subtitleTrackType = [self.subtitles.tracks[rowIndex][keySubTrackType] intValue];
- if (![self.subtitles.tracks[rowIndex][keySubTrackSelectionIndex] intValue] ||
- !hb_subtitle_can_burn(subtitleTrackType) || !hb_subtitle_can_pass(subtitleTrackType, self.subtitles.container))
- {
- [aCell setEnabled:NO];
- }
- else
- {
- [aCell setEnabled:YES];
- }
- }
- else if ([[aTableColumn identifier] isEqualToString:@"default"])
- {
- /*
- * Disable the "Default" checkbox if:
- * a) the track is "None" OR
- * b) the subtitle track can't be passed through (e.g. PGS w/MP4)
- */
- if (![self.subtitles.tracks[rowIndex][keySubTrackSelectionIndex] intValue] ||
- !hb_subtitle_can_pass([self.subtitles.tracks[rowIndex][keySubTrackType] intValue], self.subtitles.container))
- {
- [aCell setEnabled:NO];
- }
- else
- {
- [aCell setEnabled:YES];
- }
- }
- /* These next three columns only apply to srt's. they are disabled for source subs */
- else if ([[aTableColumn identifier] isEqualToString:@"srt_lang"])
- {
- /* We have an srt file so set the track type (Source or SRT, and the srt file path ) kvp's*/
- if ([self.subtitles.tracks[rowIndex][keySubTrackType] intValue] == SRTSUB)
- {
- [aCell setEnabled:YES];
- }
- else
- {
- [aCell setEnabled:NO];
- }
- }
- else if ([[aTableColumn identifier] isEqualToString:@"srt_charcode"])
- {
- /* We have an srt file so set the track type (Source or SRT, and the srt file path ) kvp's*/
- if ([self.subtitles.tracks[rowIndex][keySubTrackType] intValue] == SRTSUB)
- {
- [aCell setEnabled:YES];
- }
- else
- {
- [aCell setEnabled:NO];
- }
- }
- else if ([[aTableColumn identifier] isEqualToString:@"srt_offset"])
- {
- if ([self.subtitles.tracks[rowIndex][keySubTrackType] intValue] == SRTSUB)
- {
- [aCell setEnabled:YES];
- }
- else
- {
- [aCell setEnabled:NO];
- }
- }
-}
-
#pragma mark - Srt import
/**
@@ -509,92 +83,33 @@ static void *HBSubtitlesControllerContext = &HBSubtitlesControllerContext;
- (IBAction)browseImportSrtFile:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
- [panel setAllowsMultipleSelection:NO];
- [panel setCanChooseFiles:YES];
- [panel setCanChooseDirectories:NO];
+ panel.allowsMultipleSelection = NO;
+ panel.canChooseFiles = YES;
+ panel.canChooseDirectories = NO;
NSURL *sourceDirectory;
- if ([[NSUserDefaults standardUserDefaults] URLForKey:@"LastSrtImportDirectoryURL"])
- {
- sourceDirectory = [[NSUserDefaults standardUserDefaults] URLForKey:@"LastSrtImportDirectoryURL"];
- }
- else
- {
- sourceDirectory = [[NSURL fileURLWithPath:NSHomeDirectory()] URLByAppendingPathComponent:@"Desktop"];
- }
-
- /* we open up the browse srt sheet here and call for browseImportSrtFileDone after the sheet is closed */
- NSArray *fileTypes = @[@"plist", @"srt"];
- [panel setDirectoryURL:sourceDirectory];
- [panel setAllowedFileTypes:fileTypes];
- [panel beginSheetModalForWindow:[[self view] window] completionHandler:^(NSInteger result) {
- if (result == NSOKButton)
- {
- NSURL *importSrtFileURL = [panel URL];
- NSURL *importSrtDirectory = [importSrtFileURL URLByDeletingLastPathComponent];
- [[NSUserDefaults standardUserDefaults] setURL:importSrtDirectory forKey:@"LastSrtImportDirectoryURL"];
-
- /* Create a new entry for the subtitle source array so it shows up in our subtitle source list */
- NSString *displayname = [importSrtFileURL lastPathComponent];// grok an appropriate display name from the srt subtitle */
-
- /* create a dictionary of source subtitle information to store in our array */
- [self.subtitles.masterTrackArray addObject:@{keySubTrackIndex: @(self.subtitles.masterTrackArray.count),
- keySubTrackName: displayname,
- keySubTrackType: @(SRTSUB),
- keySubTrackSrtFilePath: importSrtFileURL.path}];
-
- // Now create a new srt subtitle dictionary assuming the user wants to add it to their list
- NSMutableDictionary *newSubtitleSrtTrack = [self.subtitles trackFromSourceTrackIndex:self.subtitles.masterTrackArray.count - 1];
- // Calculate the pop up selection index
- newSubtitleSrtTrack[keySubTrackSelectionIndex] = @(self.subtitles.masterTrackArray.count + (self.subtitles.tracks.count == 1));
- [self.subtitles.tracks insertObject:newSubtitleSrtTrack atIndex:self.subtitles.tracks.count - 1];
-
- [self.fTableView reloadData];
- }
- }];
-}
-
-#pragma mark - UI cells
-
-@synthesize languagesCell = _languagesCell;
-
-- (NSPopUpButtonCell *)languagesCell
-{
- if (!_languagesCell)
+ if ([[NSUserDefaults standardUserDefaults] URLForKey:@"LastSrtImportDirectoryURL"])
{
- // 'srt_lang' is a popup of commonly used languages to be matched to the source srt file
- _languagesCell = [[NSPopUpButtonCell alloc] init];
- // Set the Popups properties
- [_languagesCell setControlSize:NSSmallControlSize];
- [_languagesCell setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
-
- // list our languages as per the languagesArray
- for (NSArray *lang in self.subtitles.languagesArray)
- {
- [[_languagesCell menu] addItemWithTitle:lang[0] action:NULL keyEquivalent:@""];
- }
+ sourceDirectory = [[NSUserDefaults standardUserDefaults] URLForKey:@"LastSrtImportDirectoryURL"];
+ }
+ else
+ {
+ sourceDirectory = [[NSURL fileURLWithPath:NSHomeDirectory()] URLByAppendingPathComponent:@"Desktop"];
}
- return _languagesCell;
-}
-
-@synthesize encodingsCell = _encodingsCell;
-- (NSPopUpButtonCell *)encodingsCell
-{
- if (!_encodingsCell) {
- // 'srt_charcode' is a popup of commonly used character codes to be matched to the source srt file
- _encodingsCell = [[NSPopUpButtonCell alloc] init];
- // Set the Popups properties
- [_encodingsCell setControlSize:NSSmallControlSize];
- [_encodingsCell setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
+ panel.directoryURL = sourceDirectory;
+ panel.allowedFileTypes = @[@"srt"];
- // list our character codes, as per charCodeArray
- for (NSString *charCode in self.subtitles.charCodeArray)
+ [panel beginSheetModalForWindow:self.view.window completionHandler:^(NSInteger result)
+ {
+ if (result == NSFileHandlingPanelOKButton)
{
- [[_encodingsCell menu] addItemWithTitle:charCode action: NULL keyEquivalent: @""];
+ NSURL *importSrtFileURL = panel.URL;
+ NSURL *importSrtDirectory = importSrtFileURL.URLByDeletingLastPathComponent;
+ [[NSUserDefaults standardUserDefaults] setURL:importSrtDirectory forKey:@"LastSrtImportDirectoryURL"];
+
+ [self.subtitles addSrtTrackFromURL:importSrtFileURL];
}
- }
- return _encodingsCell;
+ }];
}
-
@end