diff options
-rw-r--r-- | macosx/Controller.m | 408 | ||||
-rw-r--r-- | macosx/English.lproj/Subtitles.xib | 131 | ||||
-rw-r--r-- | macosx/English.lproj/SubtitlesDefaults.xib | 192 | ||||
-rw-r--r-- | macosx/HBLanguagesSelection.h | 50 | ||||
-rw-r--r-- | macosx/HBLanguagesSelection.m | 123 | ||||
-rw-r--r-- | macosx/HBQueueController.mm | 38 | ||||
-rw-r--r-- | macosx/HBSubtitlesController.h | 19 | ||||
-rw-r--r-- | macosx/HBSubtitlesController.m | 1341 | ||||
-rw-r--r-- | macosx/HBSubtitlesDefaultsController.h | 17 | ||||
-rw-r--r-- | macosx/HBSubtitlesDefaultsController.m | 68 | ||||
-rw-r--r-- | macosx/HBSubtitlesSettings.h | 27 | ||||
-rw-r--r-- | macosx/HBSubtitlesSettings.m | 61 | ||||
-rw-r--r-- | macosx/HandBrake.xcodeproj/project.pbxproj | 58 |
13 files changed, 1584 insertions, 949 deletions
diff --git a/macosx/Controller.m b/macosx/Controller.m index f7a30d903..195911615 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -2613,7 +2613,7 @@ fWorkingCount = 0; [fAudioController prepareAudioForQueueFileJob: queueFileJob]; /* Subtitles */ - NSMutableArray *subtitlesArray = [[NSMutableArray alloc] initWithArray:[fSubtitlesViewController subtitleArray] copyItems:YES]; + NSMutableArray *subtitlesArray = [[NSMutableArray alloc] initWithArray:[fSubtitlesViewController subtitles] copyItems:YES]; [queueFileJob setObject:[NSArray arrayWithArray: subtitlesArray] forKey:@"SubtitleList"]; [subtitlesArray autorelease]; @@ -3097,131 +3097,95 @@ fWorkingCount = 0; [fVideoController prepareVideoForJobPreview:job andTitle:title]; /* Subtitle settings */ - NSMutableArray *subtitlesArray = [[NSMutableArray alloc] initWithArray:fSubtitlesViewController.subtitleArray copyItems:YES]; - -int subtitle; -int force; -int burned; -int def; -bool one_burned = FALSE; - + BOOL one_burned = NO; int i = 0; - NSEnumerator *enumerator = [subtitlesArray objectEnumerator]; - id tempObject; - while (tempObject = [enumerator nextObject]) + + for (id subtitleDict in fSubtitlesViewController.subtitles) { - - subtitle = [[tempObject objectForKey:@"subtitleSourceTrackNum"] intValue]; - force = [[tempObject objectForKey:@"subtitleTrackForced"] intValue]; - burned = [[tempObject objectForKey:@"subtitleTrackBurned"] intValue]; - def = [[tempObject objectForKey:@"subtitleTrackDefault"] intValue]; - - /* since the subtitleSourceTrackNum 0 is "None" in our array of the subtitle popups, - * we want to ignore it for display as well as encoding. - */ - if (subtitle > 0) + int subtitle = [subtitleDict[keySubTrackIndex] intValue]; + int force = [subtitleDict[keySubTrackForced] intValue]; + int burned = [subtitleDict[keySubTrackBurned] intValue]; + int def = [subtitleDict[keySubTrackDefault] intValue]; + + // if i is 0, then we are in the first item of the subtitles which we need to + // check for the "Foreign Audio Search" which would be keySubTrackIndex of -1 + + /* if we are on the first track and using "Foreign Audio Search" */ + if (i == 0 && subtitle == -1) { - /* if i is 0, then we are in the first item of the subtitles which we need to - * check for the "Foreign Audio Search" which would be subtitleSourceTrackNum of 1 - * bearing in mind that for all tracks subtitleSourceTrackNum of 0 is None. - */ - - /* if we are on the first track and using "Foreign Audio Search" */ - if (i == 0 && subtitle == 1) + [HBUtilities writeToActivityLog: "Foreign Language Search: %d", 1]; + + job->indepth_scan = 1; + + if (burned != 1) { - /* NOTE: Currently foreign language search is borked for preview. - * Commented out but left in for initial commit. */ - - - [HBUtilities writeToActivityLog: "Foreign Language Search: %d", 1]; - - job->indepth_scan = 1; - - if (burned != 1) - { - job->select_subtitle_config.dest = PASSTHRUSUB; - } - else - { - job->select_subtitle_config.dest = RENDERSUB; - } - - job->select_subtitle_config.force = force; - job->select_subtitle_config.default_track = def; + job->select_subtitle_config.dest = PASSTHRUSUB; } else { - /* if we are getting the subtitles from an external srt file */ - if ([[tempObject objectForKey:@"subtitleSourceTrackType"] intValue] == SRTSUB) - { - hb_subtitle_config_t sub_config; - - sub_config.offset = [[tempObject objectForKey:@"subtitleTrackSrtOffset"] intValue]; - - /* we need to srncpy file path and char code */ - strncpy(sub_config.src_filename, [[tempObject objectForKey:@"subtitleSourceSrtFilePath"] UTF8String], 255); - sub_config.src_filename[255] = 0; - strncpy(sub_config.src_codeset, [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String], 39); - sub_config.src_codeset[39] = 0; - - if( !burned && hb_subtitle_can_pass( SRTSUB, job->mux ) ) - { - sub_config.dest = PASSTHRUSUB; - } - else if( hb_subtitle_can_burn( SRTSUB ) ) - { - // Only allow one subtitle to be burned into the video - if( one_burned ) - continue; - one_burned = TRUE; - sub_config.dest = RENDERSUB; - } + job->select_subtitle_config.dest = RENDERSUB; + } - sub_config.force = 0; - sub_config.default_track = def; - hb_srt_add( job, &sub_config, [[tempObject objectForKey:@"subtitleTrackSrtLanguageIso3"] UTF8String]); - continue; + job->select_subtitle_config.force = force; + job->select_subtitle_config.default_track = def; + } + else + { + /* if we are getting the subtitles from an external srt file */ + if ([subtitleDict[keySubTrackType] intValue] == SRTSUB) + { + hb_subtitle_config_t sub_config; + + sub_config.offset = [subtitleDict[keySubTrackSrtOffset] intValue]; + + /* we need to srncpy file name and codeset */ + strncpy(sub_config.src_filename, [subtitleDict[keySubTrackSrtFilePath] UTF8String], 255); + sub_config.src_filename[255] = 0; + strncpy(sub_config.src_codeset, [subtitleDict[keySubTrackSrtCharCode] UTF8String], 39); + sub_config.src_codeset[39] = 0; + + if( !burned && hb_subtitle_can_pass( SRTSUB, job->mux ) ) + { + sub_config.dest = PASSTHRUSUB; } - - /* for the actual source tracks, we must subtract the non source entries so - * that the menu index matches the source subtitle_list index for convenience */ - if( i == 0 ) + else if( hb_subtitle_can_burn( SRTSUB ) ) { - /* for the first track, the source tracks start at menu index 2 ( None is 0, - * Foreign Language Search is 1) so subtract 2 */ - subtitle = subtitle - 2; + // Only allow one subtitle to be burned into the video + if( one_burned ) + continue; + one_burned = TRUE; + sub_config.dest = RENDERSUB; } - else + + sub_config.force = 0; + sub_config.default_track = def; + hb_srt_add( job, &sub_config, [subtitleDict[keySubTrackLanguageIsoCode] UTF8String]); + continue; + } + + /* We are setting a source subtitle so access the source subtitle info */ + hb_subtitle_t * subt = (hb_subtitle_t *) hb_list_item( title->list_subtitle, subtitle ); + + if( subt != NULL ) + { + hb_subtitle_config_t sub_config = subt->config; + + if( !burned && hb_subtitle_can_pass( subt->source, job->mux ) ) { - /* for all other tracks, the source tracks start at menu index 1 (None is 0) - * so subtract 1. */ - subtitle = subtitle - 1; + sub_config.dest = PASSTHRUSUB; } - - /* We are setting a source subtitle so access the source subtitle info */ - hb_subtitle_t * subt = (hb_subtitle_t *) hb_list_item( title->list_subtitle, subtitle ); - - if( subt != NULL ) + else if( hb_subtitle_can_burn( subt->source ) ) { - hb_subtitle_config_t sub_config = subt->config; - - if( !burned && hb_subtitle_can_pass( subt->source, job->mux ) ) - { - sub_config.dest = PASSTHRUSUB; - } - else if( hb_subtitle_can_burn( subt->source ) ) - { - // Only allow one subtitle to be burned into the video - if( one_burned ) - continue; - one_burned = TRUE; - sub_config.dest = RENDERSUB; - } - - sub_config.force = force; - sub_config.default_track = def; - hb_subtitle_add( job, &sub_config, subtitle ); + // Only allow one subtitle to be burned into the video + if( one_burned ) + continue; + one_burned = TRUE; + sub_config.dest = RENDERSUB; } + + sub_config.force = force; + sub_config.default_track = def; + hb_subtitle_add( job, &sub_config, subtitle ); } } i++; @@ -3230,15 +3194,10 @@ bool one_burned = FALSE; { filter = hb_filter_init( HB_FILTER_RENDER_SUB ); hb_add_filter( job, filter, [[NSString stringWithFormat:@"%d:%d:%d:%d", - job->crop[0], job->crop[1], - job->crop[2], job->crop[3]] UTF8String] ); + job->crop[0], job->crop[1], + job->crop[2], job->crop[3]] UTF8String] ); } - - - -[subtitlesArray autorelease]; - - + /* Auto Passthru */ job->acodec_copy_mask = 0; if (fAudioController.allowAACPassCheck) @@ -3641,141 +3600,100 @@ bool one_burned = FALSE; job->vbitrate = 0; } - + job->grayscale = [[queueToApply objectForKey:@"VideoGrayScale"] intValue]; - + // Map the settings in the dictionaries for the SubtitleList array to match title->list_subtitle + BOOL one_burned = NO; + int i = 0; -#pragma mark - -#pragma mark Process Subtitles to libhb - -/* Map the settings in the dictionaries for the SubtitleList array to match title->list_subtitle - * which means that we need to account for the offset of non source language settings in from - * the NSPopUpCell menu. For all of the objects in the SubtitleList array this means 0 is "None" - * from the popup menu, additionally the first track has "Foreign Audio Search" at 1. So we use - * an int to offset the index number for the objectForKey:@"subtitleSourceTrackNum" to map that - * to the source tracks position in title->list_subtitle. - */ + NSArray *subtitles = [queueToApply objectForKey:@"SubtitleList"]; + for (id subtitleDict in subtitles) + { + int subtitle = [subtitleDict[keySubTrackIndex] intValue]; + int force = [subtitleDict[keySubTrackForced] intValue]; + int burned = [subtitleDict[keySubTrackBurned] intValue]; + int def = [subtitleDict[keySubTrackDefault] intValue]; -int subtitle; -int force; -int burned; -int def; -bool one_burned = FALSE; + // if i is 0, then we are in the first item of the subtitles which we need to + // check for the "Foreign Audio Search" which would be keySubTrackIndex of -1 - int i = 0; - NSEnumerator *enumerator = [[queueToApply objectForKey:@"SubtitleList"] objectEnumerator]; - id tempObject; - while (tempObject = [enumerator nextObject]) - { - - subtitle = [[tempObject objectForKey:@"subtitleSourceTrackNum"] intValue]; - force = [[tempObject objectForKey:@"subtitleTrackForced"] intValue]; - burned = [[tempObject objectForKey:@"subtitleTrackBurned"] intValue]; - def = [[tempObject objectForKey:@"subtitleTrackDefault"] intValue]; - - /* since the subtitleSourceTrackNum 0 is "None" in our array of the subtitle popups, - * we want to ignore it for display as well as encoding. - */ - if (subtitle > 0) + // if we are on the first track and using "Foreign Audio Search" + if (i == 0 && subtitle == -1) { - /* if i is 0, then we are in the first item of the subtitles which we need to - * check for the "Foreign Audio Search" which would be subtitleSourceTrackNum of 1 - * bearing in mind that for all tracks subtitleSourceTrackNum of 0 is None. - */ - - /* if we are on the first track and using "Foreign Audio Search" */ - if (i == 0 && subtitle == 1) + [HBUtilities writeToActivityLog: "Foreign Language Search: %d", 1]; + + job->indepth_scan = 1; + + if (burned != 1) { - [HBUtilities writeToActivityLog: "Foreign Language Search: %d", 1]; - - job->indepth_scan = 1; - - if (burned != 1) - { - job->select_subtitle_config.dest = PASSTHRUSUB; - } - else - { - job->select_subtitle_config.dest = RENDERSUB; - } - - job->select_subtitle_config.force = force; - job->select_subtitle_config.default_track = def; + job->select_subtitle_config.dest = PASSTHRUSUB; } else { - /* if we are getting the subtitles from an external srt file */ - if ([[tempObject objectForKey:@"subtitleSourceTrackType"] intValue] == SRTSUB) - { - hb_subtitle_config_t sub_config; - - sub_config.offset = [[tempObject objectForKey:@"subtitleTrackSrtOffset"] intValue]; - - /* we need to srncpy file name and codeset */ - strncpy(sub_config.src_filename, [[tempObject objectForKey:@"subtitleSourceSrtFilePath"] UTF8String], 255); - sub_config.src_filename[255] = 0; - strncpy(sub_config.src_codeset, [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String], 39); - sub_config.src_codeset[39] = 0; - - if( !burned && hb_subtitle_can_pass( SRTSUB, job->mux ) ) - { - sub_config.dest = PASSTHRUSUB; - } - else if( hb_subtitle_can_burn( SRTSUB ) ) - { - // Only allow one subtitle to be burned into the video - if( one_burned ) - continue; - one_burned = TRUE; - sub_config.dest = RENDERSUB; - } + job->select_subtitle_config.dest = RENDERSUB; + } + + job->select_subtitle_config.force = force; + job->select_subtitle_config.default_track = def; + } + else + { + // if we are getting the subtitles from an external srt file + if ([subtitleDict[keySubTrackType] intValue] == SRTSUB) + { + hb_subtitle_config_t sub_config; + + sub_config.offset = [subtitleDict[keySubTrackSrtOffset] intValue]; + + // we need to srncpy file name and codeset + strncpy(sub_config.src_filename, [subtitleDict[keySubTrackSrtFilePath] UTF8String], 255); + sub_config.src_filename[255] = 0; + strncpy(sub_config.src_codeset, [subtitleDict[keySubTrackSrtCharCode] UTF8String], 39); + sub_config.src_codeset[39] = 0; - sub_config.force = 0; - sub_config.default_track = def; - hb_srt_add( job, &sub_config, [[tempObject objectForKey:@"subtitleTrackSrtLanguageIso3"] UTF8String]); - continue; + if( !burned && hb_subtitle_can_pass( SRTSUB, job->mux ) ) + { + sub_config.dest = PASSTHRUSUB; } - - /* for the actual source tracks, we must subtract the non source entries so - * that the menu index matches the source subtitle_list index for convenience */ - if( i == 0 ) + else if( hb_subtitle_can_burn( SRTSUB ) ) { - /* for the first track, the source tracks start at menu index 2 ( None is 0, - * Foreign Language Search is 1) so subtract 2 */ - subtitle = subtitle - 2; + // Only allow one subtitle to be burned into the video + if( one_burned ) + continue; + one_burned = TRUE; + sub_config.dest = RENDERSUB; } - else + + sub_config.force = 0; + sub_config.default_track = def; + hb_srt_add( job, &sub_config, [subtitleDict[keySubTrackLanguageIsoCode] UTF8String]); + continue; + } + + /* We are setting a source subtitle so access the source subtitle info */ + hb_subtitle_t * subt = (hb_subtitle_t *) hb_list_item( title->list_subtitle, subtitle ); + + if( subt != NULL ) + { + hb_subtitle_config_t sub_config = subt->config; + + if( !burned && hb_subtitle_can_pass( subt->source, job->mux ) ) { - /* for all other tracks, the source tracks start at menu index 1 (None is 0) - * so subtract 1. */ - subtitle = subtitle - 1; + sub_config.dest = PASSTHRUSUB; } - - /* We are setting a source subtitle so access the source subtitle info */ - hb_subtitle_t * subt = (hb_subtitle_t *) hb_list_item( title->list_subtitle, subtitle ); - - if( subt != NULL ) + else if( hb_subtitle_can_burn( subt->source ) ) { - hb_subtitle_config_t sub_config = subt->config; - - if( !burned && hb_subtitle_can_pass( subt->source, job->mux ) ) - { - sub_config.dest = PASSTHRUSUB; - } - else if( hb_subtitle_can_burn( subt->source ) ) - { - // Only allow one subtitle to be burned into the video - if( one_burned ) - continue; - one_burned = TRUE; - sub_config.dest = RENDERSUB; - } - - sub_config.force = force; - sub_config.default_track = def; - hb_subtitle_add( job, &sub_config, subtitle ); + // Only allow one subtitle to be burned into the video + if( one_burned ) + continue; + one_burned = TRUE; + sub_config.dest = RENDERSUB; } + + sub_config.force = force; + sub_config.default_track = def; + hb_subtitle_add( job, &sub_config, subtitle ); } } i++; @@ -3788,8 +3706,6 @@ bool one_burned = FALSE; job->crop[2], job->crop[3]] UTF8String] ); } -#pragma mark - - /* Auto Passthru */ job->acodec_copy_mask = 0; if( [[queueToApply objectForKey: @"AudioAllowAACPass"] intValue] == 1 ) @@ -5410,11 +5326,8 @@ return YES; [fAudioController addTracksFromPreset: chosenPreset]; /*Subtitles*/ - // To be fixed in the automatic subtitles changes - //[fSubPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Subtitles"]]; - /* Forced Subtitles */ - //[fSubForcedCheck setState:[[chosenPreset objectForKey:@"SubtitlesForced"] intValue]]; - + [fSubtitlesViewController applySettingsFromPreset:chosenPreset]; + /* Picture Settings */ /* Note: objectForKey:@"UsesPictureSettings" refers to picture size, which encompasses: * height, width, keep ar, anamorphic and crop settings. @@ -5901,13 +5814,8 @@ return YES; [preset setObject:[NSMutableArray arrayWithArray: audioListArray] forKey:@"AudioList"]; [audioListArray release]; - - /* Temporarily remove subtitles from creating a new preset as it has to be converted over to use the new - * subititle array code. */ - /* Subtitles*/ - //[preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"]; - /* Forced Subtitles */ - //[preset setObject:[NSNumber numberWithInt:[fSubForcedCheck state]] forKey:@"SubtitlesForced"]; + /* Subtitles */ + [fSubtitlesViewController prepareSubtitlesForPreset:preset]; } [preset autorelease]; return preset; diff --git a/macosx/English.lproj/Subtitles.xib b/macosx/English.lproj/Subtitles.xib index 924881f80..d9662e04c 100644 --- a/macosx/English.lproj/Subtitles.xib +++ b/macosx/English.lproj/Subtitles.xib @@ -7,7 +7,7 @@ <objects> <customObject id="-2" userLabel="File's Owner" customClass="HBSubtitlesController"> <connections> - <outlet property="fBrowseSrtFileButton" destination="Q4r-2h-9cA" id="wSH-Hb-eot"/> + <outlet property="actionsPopUp" destination="2Tb-KC-Ugi" id="VMz-bu-7bQ"/> <outlet property="fTableView" destination="0yM-wE-D2x" id="0vq-y5-Ubi"/> <outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/> </connections> @@ -19,79 +19,76 @@ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <subviews> <scrollView autohidesScrollers="YES" horizontalLineScroll="27" horizontalPageScroll="10" verticalLineScroll="27" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" id="Syo-rH-vof"> - <rect key="frame" x="20" y="20" width="886" height="258"/> + <rect key="frame" x="20" y="20" width="886" height="266"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <clipView key="contentView" id="ljc-nW-Cnc"> - <rect key="frame" x="1" y="17" width="884" height="240"/> + <rect key="frame" x="1" y="17" width="884" height="248"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" multipleSelection="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="25" headerView="IiW-3a-Drv" id="0yM-wE-D2x"> - <rect key="frame" x="0.0" y="0.0" width="884" height="240"/> + <rect key="frame" x="0.0" y="0.0" width="884" height="248"/> <autoresizingMask key="autoresizingMask"/> <size key="intercellSpacing" width="3" height="2"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/> <tableColumns> - <tableColumn identifier="track" editable="NO" width="323" minWidth="40" maxWidth="1000" id="N3S-st-yGv"> + <tableColumn identifier="track" editable="NO" width="322" minWidth="40" maxWidth="1000" id="N3S-st-yGv"> <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Track"> <font key="font" metaFont="smallSystem"/> <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" white="0.33333299" alpha="1" colorSpace="calibratedWhite"/> </tableHeaderCell> - <popUpButtonCell key="dataCell" type="bevel" title="Pop Up" bezelStyle="rounded" alignment="left" controlSize="mini" lineBreakMode="truncatingTail" state="on" borderStyle="bezel" imageScaling="proportionallyDown" inset="2" preferredEdge="minX" selectedItem="T2a-d2-cIn" id="I4m-dX-JtL"> - <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="miniSystem"/> - <menu key="menu" title="OtherViews" id="aJW-QB-1Tq"> + <popUpButtonCell key="dataCell" type="push" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" borderStyle="border" imageScaling="proportionallyDown" inset="2" arrowPosition="arrowAtCenter" preferredEdge="maxY" id="kzn-6s-3Ka"> + <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="smallSystem"/> + <menu key="menu" title="OtherViews" id="Umu-1b-U1Z"> <items> - <menuItem title="Pop Up" state="on" id="T2a-d2-cIn"/> + <menuItem title="Pop Up" id="cSW-OC-qKA"/> </items> </menu> </popUpButtonCell> <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> </tableColumn> - <tableColumn identifier="forced" width="75" minWidth="10" maxWidth="3.4028229999999999e+38" id="klV-Gy-igk"> + <tableColumn identifier="forced" width="76" minWidth="10" maxWidth="3.4028229999999999e+38" id="klV-Gy-igk"> <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="center" title="Forced Only"> <font key="font" metaFont="smallSystem"/> <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/> </tableHeaderCell> - <buttonCell key="dataCell" type="check" title="Check" bezelStyle="regularSquare" imagePosition="only" alignment="left" controlSize="small" inset="2" id="JLr-Qi-X0X"> + <buttonCell key="dataCell" type="check" title="Check" bezelStyle="regularSquare" imagePosition="only" alignment="left" controlSize="small" continuous="YES" inset="2" id="JLr-Qi-X0X"> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <font key="font" metaFont="smallSystem"/> </buttonCell> - <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> </tableColumn> - <tableColumn identifier="burned" width="65" minWidth="10" maxWidth="3.4028229999999999e+38" id="fIe-Fg-ufj"> + <tableColumn identifier="burned" width="64" minWidth="10" maxWidth="3.4028229999999999e+38" id="fIe-Fg-ufj"> <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="center" title="Burned In"> <font key="font" metaFont="smallSystem"/> <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/> </tableHeaderCell> - <buttonCell key="dataCell" type="check" title="Check" bezelStyle="regularSquare" imagePosition="only" alignment="left" controlSize="small" inset="2" id="R9w-Bn-CCt"> + <buttonCell key="dataCell" type="check" title="Check" bezelStyle="regularSquare" imagePosition="only" alignment="left" controlSize="small" continuous="YES" inset="2" id="R9w-Bn-CCt"> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <font key="font" metaFont="smallSystem"/> </buttonCell> - <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> </tableColumn> - <tableColumn identifier="default" width="77" minWidth="10" maxWidth="3.4028229999999999e+38" id="fvq-pE-sOC"> + <tableColumn identifier="default" width="51" minWidth="10" maxWidth="3.4028229999999999e+38" id="fvq-pE-sOC"> <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="center" title="Default"> <font key="font" metaFont="smallSystem"/> <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/> </tableHeaderCell> - <buttonCell key="dataCell" type="check" title="Check" bezelStyle="regularSquare" imagePosition="only" alignment="left" controlSize="small" inset="2" id="ooy-Sh-Edm"> + <buttonCell key="dataCell" type="check" title="Check" bezelStyle="regularSquare" imagePosition="only" alignment="left" controlSize="small" continuous="YES" inset="2" id="ooy-Sh-Edm"> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <font key="font" metaFont="smallSystem"/> </buttonCell> - <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> </tableColumn> - <tableColumn identifier="srt_lang" width="148" minWidth="10" maxWidth="3.4028229999999999e+38" id="9ka-9O-WDj"> + <tableColumn identifier="srt_lang" width="173" minWidth="10" maxWidth="3.4028229999999999e+38" id="9ka-9O-WDj"> <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Srt Language"> <font key="font" metaFont="smallSystem"/> <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/> </tableHeaderCell> - <popUpButtonCell key="dataCell" type="bevel" title="Pop Up" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" state="on" borderStyle="bezel" imageScaling="proportionallyDown" inset="2" arrowPosition="arrowAtCenter" preferredEdge="maxY" selectedItem="vHW-fn-RSG" id="2Qz-Lh-O8g"> + <popUpButtonCell key="dataCell" type="bevel" title="Pop Up" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" continuous="YES" state="on" borderStyle="bezel" imageScaling="proportionallyDown" inset="2" arrowPosition="arrowAtCenter" preferredEdge="maxY" selectedItem="vHW-fn-RSG" id="2Qz-Lh-O8g"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="smallSystem"/> <menu key="menu" title="OtherViews" id="UOP-xa-WpP"> @@ -102,13 +99,13 @@ </popUpButtonCell> <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> </tableColumn> - <tableColumn identifier="srt_charcode" width="104" minWidth="10" maxWidth="3.4028229999999999e+38" id="1Qg-We-ltR"> + <tableColumn identifier="srt_charcode" width="113" minWidth="10" maxWidth="3.4028229999999999e+38" id="1Qg-We-ltR"> <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Srt Char Code"> <font key="font" metaFont="smallSystem"/> <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/> </tableHeaderCell> - <popUpButtonCell key="dataCell" type="bevel" title="Pop Up" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" state="on" borderStyle="bezel" imageScaling="proportionallyDown" inset="2" arrowPosition="arrowAtCenter" preferredEdge="maxY" selectedItem="xt1-a1-JhF" id="AdJ-Mv-JI2"> + <popUpButtonCell key="dataCell" type="bevel" title="Pop Up" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" continuous="YES" state="on" borderStyle="bezel" imageScaling="proportionallyDown" inset="2" arrowPosition="arrowAtCenter" preferredEdge="maxY" selectedItem="xt1-a1-JhF" id="AdJ-Mv-JI2"> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="smallSystem"/> <menu key="menu" title="OtherViews" id="ABd-Ec-K2L"> @@ -119,14 +116,14 @@ </popUpButtonCell> <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> </tableColumn> - <tableColumn identifier="srt_offset" width="71" minWidth="10" maxWidth="3.4028229999999999e+38" id="Fgh-pZ-6uu"> + <tableColumn identifier="srt_offset" width="64" minWidth="10" maxWidth="3.4028229999999999e+38" id="Fgh-pZ-6uu"> <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Srt Offset"> <font key="font" metaFont="smallSystem"/> <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/> </tableHeaderCell> - <textFieldCell key="dataCell" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" title="Text" id="QRj-KI-a03"> - <font key="font" metaFont="system"/> + <textFieldCell key="dataCell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" continuous="YES" sendsActionOnEndEditing="YES" alignment="center" title="Text" id="QRj-KI-a03"> + <font key="font" metaFont="smallSystem"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> </textFieldCell> @@ -136,6 +133,7 @@ <connections> <outlet property="dataSource" destination="-2" id="DH5-v0-2ba"/> <outlet property="delegate" destination="-2" id="Dfm-tw-89m"/> + <outlet property="menu" destination="KgC-dn-Hq2" id="Iff-7t-kdg"/> </connections> </tableView> </subviews> @@ -154,18 +152,79 @@ <autoresizingMask key="autoresizingMask"/> </tableHeaderView> </scrollView> - <button verticalHuggingPriority="750" id="Q4r-2h-9cA"> - <rect key="frame" x="19" y="286" width="116" height="16"/> + <popUpButton verticalHuggingPriority="750" id="2Tb-KC-Ugi"> + <rect key="frame" x="17" y="291" width="89" height="22"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> - <buttonCell key="cell" type="push" title="Add External SRT ..." bezelStyle="rounded" alignment="center" controlSize="mini" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="iXi-me-brz"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="miniSystem"/> - </buttonCell> - <connections> - <action selector="browseImportSrtFile:" target="-2" id="kM6-n3-W2N"/> - </connections> - </button> + <popUpButtonCell key="cell" type="push" title="Actions" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" pullsDown="YES" id="8ZD-D6-TLA"> + <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="smallSystem"/> + <menu key="menu" title="OtherViews" id="Fr7-eG-NuL"> + <items> + <menuItem title="Actions" state="on" hidden="YES" id="TJO-RZ-jgb"/> + <menuItem title="Add All" id="4PX-In-DpF"> + <connections> + <action selector="addAll:" target="-2" id="tuS-uF-dje"/> + </connections> + </menuItem> + <menuItem title="Add External SRT…" id="HW0-PS-t0U"> + <connections> + <action selector="browseImportSrtFile:" target="-2" id="dog-BP-my4"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="2hO-bG-5qB"/> + <menuItem title="Remove All" id="mVi-zH-KUq"> + <connections> + <action selector="removeAll:" target="-2" id="QsA-lb-0rD"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="ndj-S4-hj5"/> + <menuItem title="Reload Defaults" id="Zlj-4G-jKI"> + <connections> + <action selector="addTracksFromDefaults:" target="-2" id="7WM-Xh-1NG"/> + </connections> + </menuItem> + <menuItem title="Configure Defaults…" id="1LC-qX-pjQ"> + <connections> + <action selector="showSettingsSheet:" target="-2" id="jqh-lz-3rr"/> + </connections> + </menuItem> + </items> + </menu> + </popUpButtonCell> + </popUpButton> </subviews> </customView> + <menu id="KgC-dn-Hq2"> + <items> + <menuItem title="Add All" id="S2I-Jd-Lyg"> + <attributedString key="attributedTitle"/> + <connections> + <action selector="addAll:" target="-2" id="ojh-vi-2gX"/> + </connections> + </menuItem> + <menuItem title="Add External SRT…" id="fXD-7h-jMl"> + <connections> + <action selector="browseImportSrtFile:" target="-2" id="tEu-2l-wjN"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="Pr7-iM-rgd"/> + <menuItem title="Remove All" id="R8a-qg-ASg"> + <connections> + <action selector="removeAll:" target="-2" id="8yF-Gu-7bi"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="eER-z8-aB9"/> + <menuItem title="Reload Defaults" id="jcM-HL-QJ6"> + <connections> + <action selector="addTracksFromDefaults:" target="-2" id="IQq-bX-u1t"/> + </connections> + </menuItem> + <menuItem title="Configure Defaults…" id="pwm-PV-1x4"> + <connections> + <action selector="showSettingsSheet:" target="-2" id="aQq-Fi-0Ro"/> + </connections> + </menuItem> + </items> + </menu> </objects> </document> diff --git a/macosx/English.lproj/SubtitlesDefaults.xib b/macosx/English.lproj/SubtitlesDefaults.xib new file mode 100644 index 000000000..4cf0471a4 --- /dev/null +++ b/macosx/English.lproj/SubtitlesDefaults.xib @@ -0,0 +1,192 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13E28" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none"> + <dependencies> + <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/> + </dependencies> + <objects> + <customObject id="-2" userLabel="File's Owner" customClass="HBSubtitlesDefaultsController"> + <connections> + <outlet property="showAllButton" destination="QAt-5X-NBT" id="3IW-6r-piX"/> + <outlet property="tableController" destination="ZBe-aP-wvq" id="HBN-Z2-bbo"/> + <outlet property="window" destination="kwM-lz-5lG" id="rob-Fo-JhL"/> + </connections> + </customObject> + <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> + <customObject id="-3" userLabel="Application"/> + <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="kwM-lz-5lG"> + <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/> + <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> + <rect key="contentRect" x="283" y="305" width="427" height="304"/> + <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1418"/> + <view key="contentView" id="ZP2-Cp-K5w"> + <rect key="frame" x="0.0" y="0.0" width="427" height="304"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="fPg-3n-1TN"> + <rect key="frame" x="18" y="268" width="137" height="14"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Track Selection Behavior:" id="GbM-vm-RC2"> + <font key="font" metaFont="smallSystem"/> + <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> + </textFieldCell> + </textField> + <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="Jsz-Er-bsF"> + <rect key="frame" x="90" y="244" width="65" height="14"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Languages:" id="mAT-Jp-SG1"> + <font key="font" metaFont="smallSystem"/> + <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> + </textFieldCell> + </textField> + <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="Hqz-Lw-gAu"> + <rect key="frame" x="106" y="66" width="49" height="14"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Options:" id="NJl-q3-zXL"> + <font key="font" metaFont="smallSystem"/> + <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> + </textFieldCell> + </textField> + <popUpButton verticalHuggingPriority="750" id="oiD-QI-wly"> + <rect key="frame" x="158" y="263" width="252" height="22"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <popUpButtonCell key="cell" type="push" title="None" bezelStyle="rounded" alignment="left" controlSize="small" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="mvw-Hg-JFM" id="21e-KY-8TR"> + <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="smallSystem"/> + <menu key="menu" title="OtherViews" id="Kwy-lU-VuU"> + <items> + <menuItem title="None" state="on" id="mvw-Hg-JFM"/> + <menuItem title="First Matching Selected Languages" id="jDd-Ji-7Sm"/> + <menuItem title="All Matching Selected Languages" id="GZP-q7-SYy"/> + </items> + </menu> + </popUpButtonCell> + <connections> + <binding destination="-2" name="selectedIndex" keyPath="self.settings.trackSelectionBehavior" id="sKn-Mr-Hce"/> + </connections> + </popUpButton> + <button id="uF5-6E-EIe"> + <rect key="frame" x="158" y="63" width="215" height="18"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <buttonCell key="cell" type="check" title="Add Closed Captions when available" bezelStyle="regularSquare" imagePosition="left" controlSize="small" state="on" inset="2" id="66v-2g-DHn"> + <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> + <font key="font" metaFont="smallSystem"/> + </buttonCell> + <connections> + <binding destination="-2" name="value" keyPath="self.settings.addCC" id="JNz-WE-LD3"/> + </connections> + </button> + <button id="OOC-GZ-OFA"> + <rect key="frame" x="158" y="45" width="169" height="18"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <buttonCell key="cell" type="check" title="Add "Foreign Audio Search"" bezelStyle="regularSquare" imagePosition="left" controlSize="small" state="on" inset="2" id="vNY-OC-hTJ"> + <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> + <font key="font" metaFont="smallSystem"/> + </buttonCell> + <connections> + <binding destination="-2" name="value" keyPath="self.settings.addForeignAudioSearch" id="UZC-m0-Mco"/> + </connections> + </button> + <scrollView autohidesScrollers="YES" horizontalLineScroll="16" horizontalPageScroll="10" verticalLineScroll="16" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="aTC-39-h6S"> + <rect key="frame" x="161" y="123" width="246" height="135"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" heightSizable="YES"/> + <clipView key="contentView" id="TdE-Sh-NcS"> + <rect key="frame" x="1" y="1" width="244" height="133"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="14" id="Of7-71-Ci6"> + <rect key="frame" x="0.0" y="0.0" width="244" height="133"/> + <autoresizingMask key="autoresizingMask"/> + <size key="intercellSpacing" width="3" height="2"/> + <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> + <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/> + <tableColumns> + <tableColumn width="20" minWidth="20" maxWidth="20" id="G44-XP-6xE"> + <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left"> + <font key="font" metaFont="smallSystem"/> + <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/> + </tableHeaderCell> + <buttonCell key="dataCell" type="check" bezelStyle="regularSquare" imagePosition="left" controlSize="small" lineBreakMode="truncatingMiddle" inset="2" id="6by-yL-8VC"> + <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> + <font key="font" metaFont="smallSystem"/> + </buttonCell> + <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> + <connections> + <binding destination="ZBe-aP-wvq" name="value" keyPath="arrangedObjects.isSelected" id="fRp-oC-H6C"/> + </connections> + </tableColumn> + <tableColumn width="210" minWidth="10" maxWidth="2000" id="IJ6-jx-Nba"> + <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left"> + <font key="font" metaFont="smallSystem"/> + <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/> + </tableHeaderCell> + <textFieldCell key="dataCell" controlSize="small" lineBreakMode="truncatingMiddle" alignment="left" title="Text Cell" id="lY3-CN-AmZ"> + <font key="font" metaFont="smallSystem"/> + <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> + </textFieldCell> + <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> + <connections> + <binding destination="ZBe-aP-wvq" name="value" keyPath="arrangedObjects.language" id="y6d-Rn-DIv"/> + </connections> + </tableColumn> + </tableColumns> + <connections> + <binding destination="ZBe-aP-wvq" name="content" keyPath="arrangedObjects" id="ak7-UG-Fqe"/> + </connections> + </tableView> + </subviews> + <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> + </clipView> + <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="bXf-U5-ogz"> + <rect key="frame" x="1" y="118" width="244" height="16"/> + <autoresizingMask key="autoresizingMask"/> + </scroller> + <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="BWM-rq-VTg"> + <rect key="frame" x="-15" y="1" width="16" height="0.0"/> + <autoresizingMask key="autoresizingMask"/> + </scroller> + </scrollView> + <button verticalHuggingPriority="750" id="QAt-5X-NBT"> + <rect key="frame" x="161" y="93" width="71" height="23"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <buttonCell key="cell" type="smallSquare" title="Show All" bezelStyle="smallSquare" imagePosition="overlaps" alignment="center" controlSize="small" state="on" borderStyle="border" inset="3" id="PiQ-bA-7P1"> + <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/> + <font key="font" metaFont="smallSystem"/> + </buttonCell> + <connections> + <action selector="edit:" target="-2" id="13y-nD-hEj"/> + </connections> + </button> + <button verticalHuggingPriority="750" id="sC2-52-liU"> + <rect key="frame" x="358" y="14" width="54" height="28"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <buttonCell key="cell" type="push" title="Done" bezelStyle="rounded" alignment="center" controlSize="small" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="kDe-1L-VkD"> + <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="smallSystem"/> + <string key="keyEquivalent" base64-UTF8="YES"> +DQ +</string> + </buttonCell> + <connections> + <action selector="done:" target="-2" id="Rdg-PN-7l6"/> + </connections> + </button> + </subviews> + </view> + </window> + <arrayController objectClassName="HBLang" id="ZBe-aP-wvq" userLabel="Table Controller" customClass="HBLanguageArrayController"> + <declaredKeys> + <string>language</string> + <string>isSelected</string> + </declaredKeys> + <connections> + <binding destination="-2" name="contentArray" keyPath="languagesList.languagesArray" id="vKV-y3-Zbg"/> + </connections> + </arrayController> + </objects> +</document> diff --git a/macosx/HBLanguagesSelection.h b/macosx/HBLanguagesSelection.h new file mode 100644 index 000000000..725fdf9d9 --- /dev/null +++ b/macosx/HBLanguagesSelection.h @@ -0,0 +1,50 @@ +/* HBLanguagesSelection.h $ + + 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. */ + +#import <Foundation/Foundation.h> +#import <Cocoa/Cocoa.h> + +/** + * A collection of KVO enabled model and controllers class + * used to populate the languages selection table view + */ + +/** + * HBLang + */ +@interface HBLang : NSObject + +@property (nonatomic, readwrite) BOOL isSelected; +@property (nonatomic, readonly) NSString *language; +@property (nonatomic, readonly) NSString *iso639_2; + +- (instancetype)initWithLanguage:(NSString *)value iso639_2code:(NSString *)code; + +@end; + +/** + * HBLanguagesSelection + */ +@interface HBLanguagesSelection : NSObject + +@property (nonatomic, readonly) NSMutableArray *languagesArray; +@property (nonatomic, readonly) NSArray *selectedLanguages; + +- (instancetype)initWithLanguages:(NSArray *)languages; + +@end + +/** + * HBLanguageArrayController + */ +@interface HBLanguageArrayController : NSArrayController + +/** + * Set whether to show only the selected languages or all languages + */ +@property (nonatomic, readwrite) BOOL showSelectedOnly; + +@end diff --git a/macosx/HBLanguagesSelection.m b/macosx/HBLanguagesSelection.m new file mode 100644 index 000000000..8a27ad9c1 --- /dev/null +++ b/macosx/HBLanguagesSelection.m @@ -0,0 +1,123 @@ +/* HBLanguagesSelection.m $ + + 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. */ + +#import "HBLanguagesSelection.h" +#include "lang.h" + +@implementation HBLang + +- (instancetype)initWithLanguage:(NSString *)value iso639_2code:(NSString *)code +{ + self = [super init]; + if (self) + { + _language = [value retain]; + _iso639_2 = [code retain]; + } + return self; +} + +- (void)dealloc +{ + [super dealloc]; + [_language release]; +} + +@end + +@implementation HBLanguagesSelection + +- (instancetype)initWithLanguages:(NSArray *)languages +{ + self = [super init]; + if (self) + { + NSMutableArray *internal = [[NSMutableArray alloc] init]; + + int insertedItems = 0; + const iso639_lang_t *lang = lang_get_next(NULL); + for (lang = lang_get_next(lang); lang != NULL; lang = lang_get_next(lang)) + { + HBLang *item = [[[HBLang alloc] initWithLanguage:@(lang->eng_name) + iso639_2code:@(lang->iso639_2)] autorelease]; + if ([languages containsObject:item.iso639_2]) + { + item.isSelected = YES; + [internal insertObject:item atIndex:insertedItems++]; + } + else + { + [internal addObject:item]; + } + } + + // Add the (Any) item. + HBLang *item = [[[HBLang alloc] initWithLanguage:@"(Any)" + iso639_2code:@"und"] autorelease]; + if ([languages containsObject:item.iso639_2]) + { + item.isSelected = YES; + } + [internal insertObject:item atIndex:0]; + + _languagesArray = internal; + } + + return self; +} + +- (NSArray *)selectedLanguages +{ + NSMutableArray *selected = [[[NSMutableArray alloc] init] autorelease]; + for (HBLang *lang in self.languagesArray) + { + if (lang.isSelected) + { + [selected addObject:lang.iso639_2]; + } + } + + return [[selected copy] autorelease]; +} + +- (void)dealloc +{ + [super dealloc]; + [_languagesArray release]; +} + +@end + +NSString *kHBLanguagesDragRowsType = @"kHBLanguagesDragRowsType"; + +@implementation HBLanguageArrayController + +- (void)setShowSelectedOnly:(BOOL)showSelectedOnly +{ + _showSelectedOnly = showSelectedOnly; + [self rearrangeObjects]; +} + +- (NSArray *)arrangeObjects:(NSArray *)objects +{ + if (!self.showSelectedOnly) { + return [super arrangeObjects:objects]; + } + + // Returns a filtered array with only the selected items + NSMutableArray *filteredObjects = [NSMutableArray arrayWithCapacity:[objects count]]; + for (id item in objects) + { + if ([[item valueForKeyPath:@"isSelected"] boolValue]) + { + [filteredObjects addObject:item]; + } + } + + return [super arrangeObjects:filteredObjects]; +} + +@end diff --git a/macosx/HBQueueController.mm b/macosx/HBQueueController.mm index 120afbda6..5bb1d9a1d 100644 --- a/macosx/HBQueueController.mm +++ b/macosx/HBQueueController.mm @@ -896,7 +896,7 @@ return ![(HBQueueOutlineView*)outlineView isDragging]; NSString * passesString = @""; /* check to see if our first subtitle track is Foreign Language Search, in which case there is an in depth scan */ - if ([item objectForKey:@"SubtitleList"] && [[[[item objectForKey:@"SubtitleList"] objectAtIndex:0] objectForKey:@"subtitleSourceTrackNum"] intValue] == 1) + if ([[item objectForKey:@"SubtitleList"] count] && [[[[item objectForKey:@"SubtitleList"] objectAtIndex:0] objectForKey:@"keySubTrackIndex"] intValue] == -1) { passesString = [passesString stringByAppendingString:@"1 Foreign Language Search Pass - "]; } @@ -1204,28 +1204,22 @@ return ![(HBQueueOutlineView*)outlineView isDragging]; id tempObject; while (tempObject = [enumerator nextObject]) { - /* since the subtitleSourceTrackNum 0 is "None" in our array of the subtitle popups, - * we want to ignore it for display as well as encoding. - */ - if ([[tempObject objectForKey:@"subtitleSourceTrackNum"] intValue] > 0) - { - /* remember that index 0 of Subtitles can contain "Foreign Audio Search*/ - [finalString appendString: @"Subtitle: " withAttributes:detailBoldAttr]; - [finalString appendString: [tempObject objectForKey:@"subtitleSourceTrackName"] withAttributes:detailAttr]; - if ([[tempObject objectForKey:@"subtitleTrackForced"] intValue] == 1) - { - [finalString appendString: @" - Forced Only" withAttributes:detailAttr]; - } - if ([[tempObject objectForKey:@"subtitleTrackBurned"] intValue] == 1) - { - [finalString appendString: @" - Burned In" withAttributes:detailAttr]; - } - if ([[tempObject objectForKey:@"subtitleTrackDefault"] intValue] == 1) - { - [finalString appendString: @" - Default" withAttributes:detailAttr]; - } - [finalString appendString:@"\n" withAttributes:detailAttr]; + /* remember that index 0 of Subtitles can contain "Foreign Audio Search*/ + [finalString appendString: @"Subtitle: " withAttributes:detailBoldAttr]; + [finalString appendString: [tempObject objectForKey:@"keySubTrackName"] withAttributes:detailAttr]; + if ([[tempObject objectForKey:@"keySubTrackForced"] intValue] == 1) + { + [finalString appendString: @" - Forced Only" withAttributes:detailAttr]; + } + if ([[tempObject objectForKey:@"keySubTrackBurned"] intValue] == 1) + { + [finalString appendString: @" - Burned In" withAttributes:detailAttr]; } + if ([[tempObject objectForKey:@"keySubTrackDefault"] intValue] == 1) + { + [finalString appendString: @" - Default" withAttributes:detailAttr]; + } + [finalString appendString:@"\n" withAttributes:detailAttr]; i++; } diff --git a/macosx/HBSubtitlesController.h b/macosx/HBSubtitlesController.h index 66428bf39..71bafe868 100644 --- a/macosx/HBSubtitlesController.h +++ b/macosx/HBSubtitlesController.h @@ -6,6 +6,20 @@ #import <Cocoa/Cocoa.h> +extern NSString *keySubTrackName; +extern NSString *keySubTrackIndex; +extern NSString *keySubTrackLanguage; +extern NSString *keySubTrackLanguageIsoCode; +extern NSString *keySubTrackType; + +extern NSString *keySubTrackForced; +extern NSString *keySubTrackBurned; +extern NSString *keySubTrackDefault; + +extern NSString *keySubTrackSrtOffset; +extern NSString *keySubTrackSrtFilePath; +extern NSString *keySubTrackSrtCharCode; + /** * HBSubtitlesController * Responds to HBContainerChangedNotification and HBTitleChangedNotification notifications. @@ -15,7 +29,10 @@ - (void)enableUI:(BOOL)b; - (void)addTracksFromQueue:(NSMutableArray *)newSubtitleArray; +- (void)applySettingsFromPreset:(NSDictionary *)preset; +- (void)prepareSubtitlesForPreset:(NSMutableDictionary *)preset; + // Get the list of subtitles tracks -@property (readonly, nonatomic) NSArray *subtitleArray; +@property (readonly, nonatomic, copy) NSArray *subtitles; @end diff --git a/macosx/HBSubtitlesController.m b/macosx/HBSubtitlesController.m index 43bed5034..a804de748 100644 --- a/macosx/HBSubtitlesController.m +++ b/macosx/HBSubtitlesController.m @@ -5,24 +5,60 @@ It may be used under the terms of the GNU General Public License. */ #import "HBSubtitlesController.h" +#import "HBSubtitlesDefaultsController.h" +#import "HBSubtitlesSettings.h" + #import "Controller.h" #include "hb.h" #include "lang.h" +NSString *keySubTrackSelectionIndex = @"keySubTrackSelectionIndex"; +NSString *keySubTrackName = @"keySubTrackName"; +NSString *keySubTrackIndex = @"keySubTrackIndex"; +NSString *keySubTrackLanguage = @"keySubTrackLanguage"; +NSString *keySubTrackLanguageIsoCode = @"keySubTrackLanguageIsoCode"; +NSString *keySubTrackType = @"keySubTrackType"; + +NSString *keySubTrackForced = @"keySubTrackForced"; +NSString *keySubTrackBurned = @"keySubTrackBurned"; +NSString *keySubTrackDefault = @"keySubTrackDefault"; + +NSString *keySubTrackSrtOffset = @"keySubTrackSrtOffset"; +NSString *keySubTrackSrtFilePath = @"keySubTrackSrtFilePath"; +NSString *keySubTrackSrtCharCode = @"keySubTrackSrtCharCode"; +NSString *keySubTrackSrtCharCodeIndex = @"keySubTrackSrtCharCodeIndex"; +NSString *keySubTrackLanguageIndex = @"keySubTrackLanguageIndex"; + +#define CHAR_CODE_DEFAULT_INDEX 11 + @interface HBSubtitlesController () <NSTableViewDataSource, NSTableViewDelegate> -{ - NSMutableArray *subtitleArray; // contains the output subtitle track info - NSMutableArray *subtitleSourceArray;// contains the source subtitle track info - NSString *foreignAudioSearchTrackName; - NSMutableArray *languagesArray; // array of languages taken from lang.c - NSInteger languagesArrayDefIndex; - NSMutableArray *charCodeArray; // array of character codes - int charCodeArrayDefIndex; - int container; -} -@property (assign) IBOutlet NSButton *fBrowseSrtFileButton; +// IBOutles +@property (assign) IBOutlet NSPopUpButton *actionsPopUp; @property (assign) IBOutlet NSTableView *fTableView; +@property (nonatomic, readwrite) BOOL enabled; + +// Subtitles arrays +@property (nonatomic, readonly) NSMutableArray *subtitleArray; +@property (nonatomic, readonly) NSMutableArray *subtitleSourceArray; + +@property (nonatomic, readwrite, retain) NSString *foreignAudioSearchTrackName; +@property (nonatomic, readwrite) int container; + +// Defaults +@property (nonatomic, readwrite, retain) HBSubtitlesDefaultsController *defaultsController; +@property (nonatomic, readwrite, retain) HBSubtitlesSettings *settings; + +// Table view cells models +@property (nonatomic, readonly) NSArray *charCodeArray; +@property (nonatomic, readwrite) BOOL foreignAudioSearchSelected; + +@property (nonatomic, readonly) NSArray *languagesArray; +@property (nonatomic, readonly) NSInteger languagesArrayDefIndex; + +// Cached table view's cells +@property (nonatomic, readonly) NSPopUpButtonCell *languagesCell; +@property (nonatomic, readonly) NSPopUpButtonCell *encodingsCell; @end @@ -33,127 +69,79 @@ self = [super initWithNibName:@"Subtitles" bundle:nil]; if (self) { - /* setup our array of languages */ - const iso639_lang_t *lang; - languagesArray = [[NSMutableArray alloc] init]; - for (lang = lang_get_next(NULL); lang != NULL; lang = lang_get_next(lang)) - { - [languagesArray addObject:[NSArray arrayWithObjects: - [NSString stringWithUTF8String:lang->eng_name], - [NSString stringWithUTF8String:lang->iso639_2], - nil]]; - if (!strcasecmp(lang->eng_name, "English")) - { - languagesArrayDefIndex = [languagesArray count] - 1; - } - } - - /* populate the charCodeArray */ - charCodeArray = [[NSMutableArray alloc] init]; - [charCodeArray addObject:@"ANSI_X3.4-1968"]; - [charCodeArray addObject:@"ANSI_X3.4-1986"]; - [charCodeArray addObject:@"ANSI_X3.4"]; - [charCodeArray addObject:@"ANSI_X3.110-1983"]; - [charCodeArray addObject:@"ANSI_X3.110"]; - [charCodeArray addObject:@"ASCII"]; - [charCodeArray addObject:@"ECMA-114"]; - [charCodeArray addObject:@"ECMA-118"]; - [charCodeArray addObject:@"ECMA-128"]; - [charCodeArray addObject:@"ECMA-CYRILLIC"]; - [charCodeArray addObject:@"IEC_P27-1"]; - [charCodeArray addObject:@"ISO-8859-1"]; - [charCodeArray addObject:@"ISO-8859-2"]; - [charCodeArray addObject:@"ISO-8859-3"]; - [charCodeArray addObject:@"ISO-8859-4"]; - [charCodeArray addObject:@"ISO-8859-5"]; - [charCodeArray addObject:@"ISO-8859-6"]; - [charCodeArray addObject:@"ISO-8859-7"]; - [charCodeArray addObject:@"ISO-8859-8"]; - [charCodeArray addObject:@"ISO-8859-9"]; - [charCodeArray addObject:@"ISO-8859-9E"]; - [charCodeArray addObject:@"ISO-8859-10"]; - [charCodeArray addObject:@"ISO-8859-11"]; - [charCodeArray addObject:@"ISO-8859-13"]; - [charCodeArray addObject:@"ISO-8859-14"]; - [charCodeArray addObject:@"ISO-8859-15"]; - [charCodeArray addObject:@"ISO-8859-16"]; - [charCodeArray addObject:@"UTF-7"]; - [charCodeArray addObject:@"UTF-8"]; - [charCodeArray addObject:@"UTF-16"]; - [charCodeArray addObject:@"UTF-16LE"]; - [charCodeArray addObject:@"UTF-16BE"]; - [charCodeArray addObject:@"UTF-32"]; - [charCodeArray addObject:@"UTF-32LE"]; - [charCodeArray addObject:@"UTF-32BE"]; - - charCodeArrayDefIndex = 11; - + _subtitleSourceArray = [[NSMutableArray alloc] init]; + _subtitleArray = [[NSMutableArray alloc] init]; + _languagesArray = [[self populateLanguageArray] retain]; + + // populate the charCodeArray. + _charCodeArray = [@[@"ANSI_X3.4-1968", @"ANSI_X3.4-1986", @"ANSI_X3.4", @"ANSI_X3.110-1983", @"ANSI_X3.110", @"ASCII", + @"ECMA-114", @"ECMA-118", @"ECMA-128", @"ECMA-CYRILLIC", @"IEC_P27-1", @"ISO-8859-1", @"ISO-8859-2", + @"ISO-8859-3", @"ISO-8859-4", @"ISO-8859-5", @"ISO-8859-6", @"ISO-8859-7", @"ISO-8859-8", @"ISO-8859-9", + @"ISO-8859-9E", @"ISO-8859-10", @"ISO-8859-11", @"ISO-8859-13", @"ISO-8859-14", @"ISO-8859-15", @"ISO-8859-16", + @"UTF-7", @"UTF-8", @"UTF-16", @"UTF-16LE", @"UTF-16BE", @"UTF-32", @"UTF-32LE", @"UTF-32BE"] retain]; + + // Register as observer for the HBController notifications. [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(containerChanged:) name: HBContainerChangedNotification object: nil]; - [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(titleChanged:) name: HBTitleChangedNotification object: nil]; + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(titleChanged:) name: HBTitleChangedNotification object: nil]; } return self; } +- (void)enableUI:(BOOL)b +{ + [self.actionsPopUp setEnabled:b]; + [self.fTableView setEnabled:b]; + self.enabled = b; +} + - (void)titleChanged:(NSNotification *)aNotification { NSDictionary *notDict = [aNotification userInfo]; - NSData *theData = [notDict objectForKey: keyTitleTag]; + NSData *theData = notDict[keyTitleTag]; hb_title_t *title = NULL; - [theData getBytes: &title length: sizeof(title)]; + + /* reset the subtitles arrays */ + [self.subtitleArray removeAllObjects]; + [self.subtitleSourceArray removeAllObjects]; + if (title) { - /* reset the subtitle source array */ - if (subtitleSourceArray) - { - [subtitleSourceArray release]; - } - subtitleSourceArray = [[NSMutableArray alloc] init]; - /* now populate the array with the source subtitle track info */ - int i; - hb_subtitle_t *subtitle; NSMutableArray *forcedSourceNamesArray = [[NSMutableArray alloc] init]; - for (i = 0; i < hb_list_count(title->list_subtitle); i++) + for (int i = 0; i < hb_list_count(title->list_subtitle); i++) { - subtitle = (hb_subtitle_t*)hb_list_item(title->list_subtitle, i); + hb_subtitle_t *subtitle = (hb_subtitle_t *)hb_list_item(title->list_subtitle, i); /* Human-readable representation of subtitle->source */ NSString *bitmapOrText = subtitle->format == PICTURESUB ? @"Bitmap" : @"Text"; - NSString *subSourceName = [NSString stringWithUTF8String:hb_subsource_name(subtitle->source)]; + NSString *subSourceName = @(hb_subsource_name(subtitle->source)); + /* if the subtitle track can be forced, add its source name to the array */ - if (hb_subtitle_can_force(subtitle->source) && - [forcedSourceNamesArray containsObject:subSourceName] == NO) + if (hb_subtitle_can_force(subtitle->source) && [forcedSourceNamesArray containsObject:subSourceName] == NO) { [forcedSourceNamesArray addObject:subSourceName]; } /* create a dictionary of source subtitle information to store in our array */ - NSMutableDictionary *newSubtitleSourceTrack = [[NSMutableDictionary alloc] init]; - /* Subtitle Source track name */ - [newSubtitleSourceTrack setObject:[NSString stringWithFormat:@"%d - %@ - (%@) (%@)", - i, [NSString stringWithUTF8String:subtitle->lang], - bitmapOrText,subSourceName] - forKey:@"sourceTrackName"]; - /* Subtitle Source track number, type and features */ - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:i] forKey:@"sourceTrackNum"]; - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:subtitle->source] forKey:@"sourceTrackType"]; - [subtitleSourceArray addObject:newSubtitleSourceTrack]; - [newSubtitleSourceTrack autorelease]; + [self.subtitleSourceArray addObject:@{keySubTrackName: [NSString stringWithFormat:@"%d: %@ (%@) (%@)", i, @(subtitle->lang), bitmapOrText, subSourceName], + keySubTrackIndex: @(i), + keySubTrackType: @(subtitle->source), + keySubTrackLanguage: @(subtitle->lang), + keySubTrackLanguageIsoCode: @(subtitle->iso639_2)}]; } /* now set the name of the Foreign Audio Search track */ if ([forcedSourceNamesArray count]) { [forcedSourceNamesArray sortUsingComparator:^(id obj1, id obj2) - { - return [((NSString*)obj1) compare:((NSString*)obj2)]; - }]; - NSString *tempString; - NSString *tempList = @""; - NSEnumerator *enumerator = [forcedSourceNamesArray objectEnumerator]; - while (tempString = (NSString*)[enumerator nextObject]) + { + return [((NSString *)obj1) compare:((NSString *)obj2)]; + }]; + + NSString *tempList = @""; + for (NSString *tempString in forcedSourceNamesArray) { if ([tempList length]) { @@ -161,521 +149,542 @@ } tempList = [tempList stringByAppendingString:tempString]; } - [foreignAudioSearchTrackName release]; - foreignAudioSearchTrackName = [[NSString stringWithFormat:@"Foreign Audio Search - (Bitmap) (%@)", tempList] - retain]; + self.foreignAudioSearchTrackName = [NSString stringWithFormat:@"Foreign Audio Search (Bitmap) (%@)", tempList]; } else { - [foreignAudioSearchTrackName release]; - foreignAudioSearchTrackName = @"Foreign Audio Search - (Bitmap)"; + self.foreignAudioSearchTrackName = @"Foreign Audio Search (Bitmap)"; } [forcedSourceNamesArray release]; - - /* reset the subtitle output array */ - if (subtitleArray) - { - [subtitleArray release]; - } - subtitleArray = [[NSMutableArray alloc] init]; - [self addSubtitleTrack]; - } - else - { - [subtitleArray removeAllObjects]; - [subtitleSourceArray removeAllObjects]; + + // Append an empty track at the end + // to display a "None" row in the table view + [self.subtitleArray addObject:[self createSubtitleTrack]]; } [self.fTableView reloadData]; } -- (void)enableUI:(BOOL)b +- (void)containerChanged:(NSNotification *)aNotification { - [self.fBrowseSrtFileButton setEnabled:b]; - [self.fTableView setEnabled:b]; -} + NSDictionary *notDict = [aNotification userInfo]; + self.container = [notDict[keyContainerTag] intValue]; -#pragma mark - -#pragma mark Create new Subtitles + [self validatePassthru]; -- (void)addSubtitleTrack -{ - [subtitleArray addObject:[self createSubtitleTrack]]; + [self.fTableView reloadData]; } -/* Creates a new subtitle track and stores it in an NSMutableDictionary */ -- (NSDictionary *)createSubtitleTrack +- (NSArray *)subtitles { - NSMutableDictionary *newSubtitleTrack = [[NSMutableDictionary alloc] init]; - /* Subtitle Source track popup index */ - [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackNum"]; - /* Subtitle Source track popup language */ - [newSubtitleTrack setObject:@"None" forKey:@"subtitleSourceTrackName"]; - /* Subtitle track forced state */ - [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackForced"]; - /* Subtitle track burned state */ - [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"]; - /* Subtitle track default state */ - [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"]; - - [newSubtitleTrack autorelease]; - return newSubtitleTrack; + NSMutableArray *ret = [self.subtitleArray mutableCopy]; + [ret removeLastObject]; + return [ret autorelease]; } -- (void)createSubtitleSrtTrack:(NSURL *)fileURL +- (void)addTracksFromQueue:(NSMutableArray *)newSubtitleArray { - /* Create a new entry for the subtitle source array so it shows up in our subtitle source list */ - NSString *displayname = [fileURL lastPathComponent];// grok an appropriate display name from the srt subtitle */ - /* create a dictionary of source subtitle information to store in our array */ - NSMutableDictionary *newSubtitleSourceTrack = [[NSMutableDictionary alloc] init]; - /* Subtitle Source track popup index */ - [newSubtitleSourceTrack setObject:[NSNumber numberWithInteger:[subtitleSourceArray count]+1] forKey:@"sourceTrackNum"]; - /* Subtitle Source track name */ - [newSubtitleSourceTrack setObject:displayname forKey:@"sourceTrackName"]; - /* Subtitle Source track type (VobSub, Srt, etc.) */ - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"sourceTrackType"]; - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"subtitleSourceTrackType"]; - /* Subtitle Source file path */ - [newSubtitleSourceTrack setObject:[fileURL path] forKey:@"sourceSrtFilePath"]; - - [subtitleSourceArray addObject:newSubtitleSourceTrack]; - [newSubtitleSourceTrack autorelease]; - - /* Now create a new srt subtitle dictionary assuming the user wants to add it to their list - * Note: the subtitle array always has last entry for "None", so we need to replace its - * position in the array and tack a "None" track back on the end of the list */ - [subtitleArray removeObjectAtIndex:[subtitleArray count] - 1]; - - - NSMutableDictionary *newSubtitleSrtTrack = [[NSMutableDictionary alloc] init]; - /* Subtitle Source track popup index */ - if ([subtitleArray count] == 0) // we now have an empty array so this will be our first track - { - [newSubtitleSrtTrack setObject:[NSNumber numberWithInteger:[subtitleSourceArray count] + 1] forKey:@"subtitleSourceTrackNum"]; - } - else + /* Note: we need to look for external subtitles so it can be added to the source array track. + * Remember the source container subs are already loaded with resetTitle which is already called + * so any external sub sources need to be added to our source subs here + */ + for (id tempObject in newSubtitleArray) { - [newSubtitleSrtTrack setObject:[NSNumber numberWithInteger:[subtitleSourceArray count]] forKey:@"subtitleSourceTrackNum"]; + /* We have an srt track */ + if ([tempObject[keySubTrackType] intValue] == SRTSUB) + { + NSString *filePath = tempObject[keySubTrackSrtFilePath]; + /* create a dictionary of source subtitle information to store in our array */ + [self.subtitleSourceArray addObject:@{keySubTrackIndex: @(self.subtitleSourceArray.count + 1), + keySubTrackName: [filePath lastPathComponent], + keySubTrackType: @(SRTSUB), + keySubTrackSrtFilePath: filePath}]; + } } - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"sourceTrackType"]; - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"subtitleSourceTrackType"]; - /* Subtitle Source track popup language */ - [newSubtitleSrtTrack setObject:displayname forKey:@"subtitleSourceTrackName"]; - /* Subtitle track forced state */ - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackForced"]; - /* Subtitle track burned state */ - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"]; - /* Subtitle track default state */ - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"]; - - /* now the srt only info, Language, Chart Code and offset */ - [newSubtitleSrtTrack setObject:[fileURL path] forKey:@"subtitleSourceSrtFilePath"]; - [newSubtitleSrtTrack setObject:[NSNumber numberWithInteger:languagesArrayDefIndex] forKey:@"subtitleTrackSrtLanguageIndex"]; - [newSubtitleSrtTrack setObject:[[languagesArray objectAtIndex:languagesArrayDefIndex] objectAtIndex:0] forKey:@"subtitleTrackSrtLanguageLong"]; - [newSubtitleSrtTrack setObject:[[languagesArray objectAtIndex:languagesArrayDefIndex] objectAtIndex:1] forKey:@"subtitleTrackSrtLanguageIso3"]; - - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:charCodeArrayDefIndex] forKey:@"subtitleTrackSrtCharCodeIndex"]; - [newSubtitleSrtTrack setObject:[charCodeArray objectAtIndex:charCodeArrayDefIndex] forKey:@"subtitleTrackSrtCharCode"]; - - [newSubtitleSrtTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackSrtOffset"]; + [newSubtitleArray addObject:[self createSubtitleTrack]]; + // Set the subtitleArray to the newSubtitleArray + [self.subtitleArray setArray:newSubtitleArray]; + [self.fTableView reloadData]; +} - [subtitleArray addObject:newSubtitleSrtTrack]; - [newSubtitleSrtTrack release]; +- (void)applySettingsFromPreset:(NSDictionary *)preset +{ + self.settings = [[[HBSubtitlesSettings alloc] init] autorelease]; + [self.settings applySettingsFromPreset:preset]; - /* now add back the none track to the end of the array */ - [self addSubtitleTrack]; + [self addTracksFromDefaults:self]; } -/* used to return the current subtitleArray to controller.m */ -- (NSMutableArray *) subtitleArray +- (void)prepareSubtitlesForPreset:(NSMutableDictionary *)preset { - return subtitleArray; + [self.settings prepareSubtitlesForPreset:preset]; } -// This gets called whenever the video container changes. -- (void) containerChanged: (NSNotification *) aNotification +#pragma mark - Actions +- (BOOL)validateUserInterfaceItem:(id < NSValidatedUserInterfaceItem >)anItem { - NSDictionary *notDict = [aNotification userInfo]; - - container = [[notDict objectForKey: keyContainerTag] intValue]; - [self.fTableView reloadData]; + return self.enabled; } -- (void)addTracksFromQueue:(NSMutableArray *)newSubtitleArray +/** + * Add every subtitles track that still isn't in the subtitles array. + */ +- (IBAction)addAll:(id)sender { - /* Note: we need to look for external subtitles so it can be added to the source array track. - * Remember the source container subs are already loaded with resetTitle which is already called - * so any external sub sources need to be added to our source subs here - */ + [self.subtitleArray removeAllObjects]; + + // Add the foreign audio search pass + [self addTrack:[self trackFromSourceTrackIndex:-1]]; - int i = 0; - for ( id tempObject in newSubtitleArray ) + // Add the remainings tracks + for (NSDictionary *track in self.subtitleSourceArray) { - /* We have an srt track */ - if ([[tempObject objectForKey:@"subtitleSourceTrackType"] intValue] == SRTSUB) - { - NSString *filePath = [tempObject objectForKey:@"subtitleSourceSrtFilePath"]; - /* Start replicate the add new srt code above */ - /* Create a new entry for the subtitle source array so it shows up in our subtitle source list */ - NSString *displayname = [filePath lastPathComponent];// grok an appropriate display name from the srt subtitle */ - /* create a dictionary of source subtitle information to store in our array */ - NSMutableDictionary *newSubtitleSourceTrack = [[NSMutableDictionary alloc] init]; - /* Subtitle Source track popup index */ - [newSubtitleSourceTrack setObject:[NSNumber numberWithInteger:[subtitleSourceArray count]+1] forKey:@"sourceTrackNum"]; - /* Subtitle Source track name */ - [newSubtitleSourceTrack setObject:displayname forKey:@"sourceTrackName"]; - /* Subtitle Source track type (VobSub, Srt, etc.) */ - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"sourceTrackType"]; - [newSubtitleSourceTrack setObject:[NSNumber numberWithInt:SRTSUB] forKey:@"subtitleSourceTrackType"]; - /* Subtitle Source file path */ - [newSubtitleSourceTrack setObject:filePath forKey:@"sourceSrtFilePath"]; - - [subtitleSourceArray addObject:newSubtitleSourceTrack]; - [newSubtitleSourceTrack autorelease]; - /* END replicate the add new srt code above */ - } - i++; - } - - /*Set the subtitleArray to the newSubtitleArray */ - [subtitleArray setArray:newSubtitleArray]; + NSInteger sourceIndex = [track[keySubTrackIndex] integerValue]; + [self addTrack:[self trackFromSourceTrackIndex:sourceIndex]]; + } + + [self.subtitleArray addObject:[self createSubtitleTrack]]; + [self validatePassthru]; [self.fTableView reloadData]; } -#pragma mark - Srt import +/** + * Remove all the subtitles tracks. + */ +- (IBAction)removeAll:(id)sender +{ + [self.subtitleArray removeAllObjects]; + [self.subtitleArray addObject:[self createSubtitleTrack]]; + [self.fTableView reloadData]; +} -- (IBAction)browseImportSrtFile:(id)sender +/** + * Remove all the subtitles tracks and + * add new ones based on the defaults settings + */ +- (IBAction)addTracksFromDefaults:(id)sender { - NSOpenPanel *panel = [NSOpenPanel openPanel]; - [panel setAllowsMultipleSelection:NO]; - [panel setCanChooseFiles:YES]; - [panel setCanChooseDirectories:NO]; + [self.subtitleArray removeAllObjects]; - NSURL *sourceDirectory; - if ([[NSUserDefaults standardUserDefaults] URLForKey:@"LastSrtImportDirectoryURL"]) - { - sourceDirectory = [[NSUserDefaults standardUserDefaults] URLForKey:@"LastSrtImportDirectoryURL"]; - } - else - { - sourceDirectory = [[NSURL fileURLWithPath:NSHomeDirectory()] URLByAppendingPathComponent:@"Desktop"]; - } + // Add the foreign audio search pass + if (self.settings.addForeignAudioSearch) + { + [self addTrack:[self trackFromSourceTrackIndex:-1]]; + } - /* we open up the browse srt sheet here and call for browseImportSrtFileDone after the sheet is closed */ - NSArray *fileTypes = [NSArray arrayWithObjects:@"plist", @"srt", nil]; - [panel setDirectoryURL:sourceDirectory]; - [panel setAllowedFileTypes:fileTypes]; - [panel beginSheetModalForWindow:[[self view] window] completionHandler:^(NSInteger result) { - if (result == NSOKButton) + // If the languages list contains the "(Any)" language, remove all the others + NSArray *languages = nil; + if ([self.settings.trackSelectionLanguages containsObject:@"und"]) + { + languages = @[@"und"]; + } + else + { + languages = self.settings.trackSelectionLanguages; + } + + // Add the tracks for the selected languages + if (self.settings.trackSelectionBehavior != HBSubtitleTrackSelectionBehaviorNone) + { + for (NSString *lang in languages) { - NSURL *importSrtFileURL = [panel URL]; - NSURL *importSrtDirectory = [importSrtFileURL URLByDeletingLastPathComponent]; - [[NSUserDefaults standardUserDefaults] setURL:importSrtDirectory forKey:@"LastSrtImportDirectoryURL"]; + NSInteger sourceIndex = 0; + for (NSDictionary *track in self.subtitleSourceArray) + { + if ([lang isEqualToString:@"und"] || [track[keySubTrackLanguageIsoCode] isEqualToString:lang]) + { + [self addTrack:[self trackFromSourceTrackIndex:sourceIndex]]; - /* now pass the string off to fSubtitlesDelegate to add the srt file to the dropdown */ - [self createSubtitleSrtTrack:importSrtFileURL]; + if (self.settings.trackSelectionBehavior == HBSubtitleTrackSelectionBehaviorFirst) + { + break; + } + } + sourceIndex++; + } + } + } - [self.fTableView reloadData]; + // Add the closed captions track if there is one. + if (self.settings.addCC) + { + NSInteger sourceIndex = 0; + for (NSDictionary *track in self.subtitleSourceArray) + { + if ([track[keySubTrackType] intValue] == CC608SUB) + { + [self addTrack:[self trackFromSourceTrackIndex:sourceIndex]]; + break; + } + sourceIndex++; } - }]; + } + + [self.subtitleArray addObject:[self createSubtitleTrack]]; + [self validatePassthru]; + [self.fTableView reloadData]; } -#pragma mark - -#pragma mark Subtitle Table Delegate Methods -/* Table View delegate methods */ -/* Returns the number of tracks displayed - * NOTE: we return one more than the actual number of tracks - * specified as we always keep one track set to "None" which is ignored - * for setting up tracks, but is used to add tracks. +- (IBAction)showSettingsSheet:(id)sender +{ + self.defaultsController = [[[HBSubtitlesDefaultsController alloc] initWithSettings:self.settings] autorelease]; + self.defaultsController.delegate = self; + + [NSApp beginSheet:[self.defaultsController window] + modalForWindow:[[self view] window] + modalDelegate:self + didEndSelector:NULL + contextInfo:NULL]; +} + +- (void)sheetDidEnd +{ + self.defaultsController = nil; +} + +#pragma mark - Subtitles tracks creation and validation + +/** + * Convenience method to add a track to subtitlesArray. + * It calculates the keySubTrackSelectionIndex. + * + * @param track the track to add. */ -- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView +- (void)addTrack:(NSMutableDictionary *)newTrack { - return [subtitleArray count]; + newTrack[keySubTrackSelectionIndex] = @([newTrack[keySubTrackIndex] integerValue] + 1 + (self.subtitleArray.count == 0)); + [self.subtitleArray addObject:newTrack]; } -/* Used to tell the Table view which information is to be displayed per item */ -- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex +/** + * Creates a new subtitle track. + */ +- (NSMutableDictionary *)createSubtitleTrack { - NSString *cellEntry = @"__DATA ERROR__"; + NSMutableDictionary *newSubtitleTrack = [[NSMutableDictionary alloc] init]; + newSubtitleTrack[keySubTrackIndex] = @0; + newSubtitleTrack[keySubTrackSelectionIndex] = @0; + newSubtitleTrack[keySubTrackName] = @"None"; + newSubtitleTrack[keySubTrackForced] = @0; + newSubtitleTrack[keySubTrackBurned] = @0; + newSubtitleTrack[keySubTrackDefault] = @0; + + return [newSubtitleTrack autorelease]; +} - /* we setup whats displayed given the column identifier */ - if ([[aTableColumn identifier] isEqualToString:@"track"]) +/** + * Creates a new track dictionary from a source track. + * + * @param index the index of the source track in the subtitlesSourceArray, + * -1 means a Foreign Audio Search pass. + * + * @return a new mutable track dictionary. + */ +- (NSMutableDictionary *)trackFromSourceTrackIndex:(NSInteger)index +{ + NSMutableDictionary *track = [self createSubtitleTrack]; + + if (index == -1) { - /* 'track' is a popup of all available source subtitle tracks for the given title */ - NSPopUpButtonCell *cellTrackPopup = [[NSPopUpButtonCell alloc] init]; - [cellTrackPopup autorelease]; - /* Set the Popups properties */ - [cellTrackPopup setControlSize:NSSmallControlSize]; - [cellTrackPopup setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]]; + /* + * we are foreign lang search, which is inherently bitmap + * + * since it can be either VOBSUB or PGS and the latter can't be + * passed through to MP4, we need to know whether there are any + * PGS tracks in the source - otherwise we can just set the + * source track type to VOBSUB + */ + int subtitleTrackType = VOBSUB; + if ([self.foreignAudioSearchTrackName rangeOfString:@(hb_subsource_name(PGSSUB))].location != NSNotFound) + { + subtitleTrackType = PGSSUB; + } + // Use -1 to indicate the foreign lang search + track[keySubTrackIndex] = @(-1); + track[keySubTrackName] = self.foreignAudioSearchTrackName; + track[keySubTrackType] = @(subtitleTrackType); + // foreign lang search is most useful when combined w/Forced Only - make it default + track[keySubTrackForced] = @1; + } + else + { + NSDictionary *sourceTrack = self.subtitleSourceArray[index]; + track[keySubTrackIndex] = @(index); + track[keySubTrackName] = sourceTrack[keySubTrackName]; - /* 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: @""]; + /* check to see if we are an srt, in which case set our file path and source track type kvp's*/ + if ([self.subtitleSourceArray[index][keySubTrackType] intValue] == SRTSUB) + { + track[keySubTrackType] = @(SRTSUB); + track[keySubTrackSrtFilePath] = sourceTrack[keySubTrackSrtFilePath]; - /* Foreign Audio Search (index 1 in the popup) is only available for the first track */ - if (rowIndex == 0) + track[keySubTrackLanguageIndex] = @(self.languagesArrayDefIndex); + track[keySubTrackLanguageIsoCode] = self.languagesArray[self.languagesArrayDefIndex][1]; + + track[keySubTrackSrtCharCodeIndex] = @(CHAR_CODE_DEFAULT_INDEX); + track[keySubTrackSrtCharCode] = self.charCodeArray[CHAR_CODE_DEFAULT_INDEX]; + } + else + { + track[keySubTrackType] = sourceTrack[keySubTrackType]; + } + } + + if (!hb_subtitle_can_burn([track[keySubTrackType] intValue])) + { + /* the source track cannot be burned in, so uncheck the widget */ + track[keySubTrackBurned] = @0; + } + + if (!hb_subtitle_can_force([track[keySubTrackType] intValue])) + { + /* the source track does not support forced flags, so uncheck the widget */ + track[keySubTrackForced] = @0; + } + + return track; +} + +/** + * 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 +{ + int subtitleTrackType; + BOOL convertToBurnInUsed = NO; + NSMutableArray *tracksToDelete = [[NSMutableArray alloc] init]; + + // convert any non-None incompatible tracks to burn-in or remove them + for (id tempObject in self.subtitleArray) + { + if (tempObject[keySubTrackType] == nil) { - // TODO: hide the track when no force-able subtitles are present in the source - [[cellTrackPopup menu] addItemWithTitle:foreignAudioSearchTrackName - action:NULL - keyEquivalent:@""]; + continue; } - int i; - for(i = 0; i < [subtitleSourceArray count]; i++ ) + subtitleTrackType = [tempObject[keySubTrackType] intValue]; + if (!hb_subtitle_can_pass(subtitleTrackType, self.container)) { - [[cellTrackPopup menu] addItemWithTitle: [[subtitleSourceArray objectAtIndex:i] objectForKey: @"sourceTrackName"] action: NULL keyEquivalent: @""]; + if (convertToBurnInUsed == NO) + { + //we haven't set any track to burned-in yet, so we can + tempObject[keySubTrackBurned] = @1; + convertToBurnInUsed = YES; //remove any additional tracks + } + else + { + //we already have a burned-in track, we must remove others + [tracksToDelete addObject:tempObject]; + } } + } + //if we converted a track to burned-in, unset it for tracks that support passthru + if (convertToBurnInUsed == YES) + { + for (id tempObject in self.subtitleArray) + { + if (tempObject[keySubTrackType] == nil) + { + continue; + } + subtitleTrackType = [tempObject[keySubTrackType] intValue]; + if (hb_subtitle_can_pass(subtitleTrackType, self.container)) + { + tempObject[keySubTrackBurned] = @0; + } + } + } - [aTableColumn setDataCell:cellTrackPopup]; + if (tracksToDelete.count) + { + [self.subtitleArray removeObjectsInArray:tracksToDelete]; + [self.fTableView reloadData]; + } + [tracksToDelete release]; +} + +- (void)validateBurned:(NSInteger)index +{ + [self.subtitleArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) + { + if (idx != index) + { + obj[keySubTrackBurned] = @0; + } + }]; + [self validatePassthru]; +} + +- (void)validateDefault:(NSInteger)index +{ + [self.subtitleArray 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.subtitleArray.count; +} + +- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex +{ + NSDictionary *track = self.subtitleArray[rowIndex]; + + if ([[aTableColumn identifier] isEqualToString:@"track"]) + { + NSNumber *index = track[keySubTrackSelectionIndex]; + if (index) + return index; + else + return @0; } else if ([[aTableColumn identifier] isEqualToString:@"forced"]) { - /* 'forced' is a checkbox to determine if a given source track is only to be forced */ - NSButtonCell *cellForcedCheckBox = [[NSButtonCell alloc] init]; - [cellForcedCheckBox autorelease]; - [cellForcedCheckBox setButtonType:NSSwitchButton]; - [cellForcedCheckBox setImagePosition:NSImageOnly]; - [cellForcedCheckBox setAllowsMixedState:NO]; - [aTableColumn setDataCell:cellForcedCheckBox]; - + return track[keySubTrackForced]; } else if ([[aTableColumn identifier] isEqualToString:@"burned"]) { - /* 'burned' is a checkbox to determine if a given source track is only to be burned */ - NSButtonCell *cellBurnedCheckBox = [[NSButtonCell alloc] init]; - [cellBurnedCheckBox autorelease]; - [cellBurnedCheckBox setButtonType:NSSwitchButton]; - [cellBurnedCheckBox setImagePosition:NSImageOnly]; - [cellBurnedCheckBox setAllowsMixedState:NO]; - [aTableColumn setDataCell:cellBurnedCheckBox]; + return track[keySubTrackBurned]; } else if ([[aTableColumn identifier] isEqualToString:@"default"]) { - NSButtonCell *cellDefaultCheckBox = [[NSButtonCell alloc] init]; - [cellDefaultCheckBox autorelease]; - [cellDefaultCheckBox setButtonType:NSSwitchButton]; - [cellDefaultCheckBox setImagePosition:NSImageOnly]; - [cellDefaultCheckBox setAllowsMixedState:NO]; - [aTableColumn setDataCell:cellDefaultCheckBox]; + 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"]) { - /* 'srt_lang' is a popup of commonly used languages to be matched to the source srt file */ - NSPopUpButtonCell *cellSrtLangPopup = [[NSPopUpButtonCell alloc] init]; - [cellSrtLangPopup autorelease]; - /* Set the Popups properties */ - [cellSrtLangPopup setControlSize:NSSmallControlSize]; - [cellSrtLangPopup setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]]; - /* list our languages as per the languagesArray */ - int i; - for(i = 0; i < [languagesArray count]; i++ ) + if ([track[keySubTrackType] intValue] == SRTSUB) + { + return track[keySubTrackLanguageIndex]; + } + else { - [[cellSrtLangPopup menu] addItemWithTitle: [[languagesArray objectAtIndex:i] objectAtIndex:0] action: NULL keyEquivalent: @""]; + return @0; } - [aTableColumn setDataCell:cellSrtLangPopup]; } else if ([[aTableColumn identifier] isEqualToString:@"srt_charcode"]) { - /* 'srt_charcode' is a popup of commonly used character codes to be matched to the source srt file */ - NSPopUpButtonCell *cellSrtCharCodePopup = [[NSPopUpButtonCell alloc] init]; - [cellSrtCharCodePopup autorelease]; - /* Set the Popups properties */ - [cellSrtCharCodePopup setControlSize:NSSmallControlSize]; - [cellSrtCharCodePopup setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]]; - /* list our character codes, as per charCodeArray */ - - int i; - for(i = 0; i < [charCodeArray count]; i++ ) + if ([track[keySubTrackType] intValue] == SRTSUB) { - [[cellSrtCharCodePopup menu] addItemWithTitle: [charCodeArray objectAtIndex:i] action: NULL keyEquivalent: @""]; + return track[keySubTrackSrtCharCodeIndex]; + } + else + { + return @0; } - [aTableColumn setDataCell:cellSrtCharCodePopup]; - } else if ([[aTableColumn identifier] isEqualToString:@"srt_offset"]) { - if ([[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackSrtOffset"]) + if (track[keySubTrackSrtOffset]) { - cellEntry = [NSString stringWithFormat:@"%d",[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackSrtOffset"] intValue]]; + return [track[keySubTrackSrtOffset] stringValue]; } else { - cellEntry = [NSString stringWithFormat:@"%d",0]; + return @"0"; } } - else - { - cellEntry = nil; - } - return cellEntry; + 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) */ +/** + * 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"]) { - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:[anObject intValue]] forKey:@"subtitleSourceTrackNum"]; /* Set the array to track if we are vobsub (picture sub) */ - if ([anObject intValue] != 0) + if ([anObject intValue] > 0) { - /* The first row has an additional track (Foreign Audio Search) */ - int sourceSubtitleIndex = [anObject intValue] - 1 - (rowIndex == 0); - - if(rowIndex == 0 && [anObject intValue] == 1) - { - /* - * we are foreign lang search, which is inherently bitmap - * - * since it can be either VOBSUB or PGS and the latter can't be - * passed through to MP4, we need to know whether there are any - * PGS tracks in the source - otherwise we can just set the - * source track type to VOBSUB - */ - int subtitleTrackType = VOBSUB; - if ([foreignAudioSearchTrackName rangeOfString: - [NSString stringWithUTF8String: - hb_subsource_name(PGSSUB)]].location != NSNotFound) - { - subtitleTrackType = PGSSUB; - } - // now set the track type - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:subtitleTrackType] forKey:@"subtitleSourceTrackType"]; - // foreign lang search is most useful when combined w/Forced Only - make it default - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:1] forKey:@"subtitleTrackForced"]; - } - /* check to see if we are an srt, in which case set our file path and source track type kvp's*/ - else if ([[[subtitleSourceArray objectAtIndex:sourceSubtitleIndex] objectForKey:@"sourceTrackType"] intValue] == SRTSUB) - { - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:SRTSUB] - forKey:@"subtitleSourceTrackType"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[[subtitleSourceArray objectAtIndex:sourceSubtitleIndex] objectForKey:@"sourceSrtFilePath"] - forKey:@"subtitleSourceSrtFilePath"]; - } - else - { - [[subtitleArray objectAtIndex:rowIndex] setObject:[[subtitleSourceArray objectAtIndex:sourceSubtitleIndex] objectForKey:@"sourceTrackType"] - forKey:@"subtitleSourceTrackType"]; - } - - if (!hb_subtitle_can_burn([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue])) - { - /* the source track cannot be burned in, so uncheck the widget */ - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"]; - } - - if (!hb_subtitle_can_force([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue])) - { - /* the source track does not support forced flags, so uncheck the widget */ - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackForced"]; - } + NSMutableDictionary *newTrack = [self trackFromSourceTrackIndex:[anObject integerValue] - 1 - (rowIndex == 0)]; + // Selection index calculation + newTrack[keySubTrackSelectionIndex] = @([anObject integerValue]); + self.subtitleArray[rowIndex] = newTrack; } } else if ([[aTableColumn identifier] isEqualToString:@"forced"]) { - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:[anObject intValue]] forKey:@"subtitleTrackForced"]; + self.subtitleArray[rowIndex][keySubTrackForced] = @([anObject intValue]); } else if ([[aTableColumn identifier] isEqualToString:@"burned"]) { - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:[anObject intValue]] forKey:@"subtitleTrackBurned"]; + self.subtitleArray[rowIndex][keySubTrackBurned] = @([anObject intValue]); if([anObject intValue] == 1) { /* Burned In and Default are mutually exclusive */ - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"]; + self.subtitleArray[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) { - int i = 0; - NSEnumerator *enumerator = [subtitleArray objectEnumerator]; - id tempObject; - while ( tempObject = [enumerator nextObject] ) - { - if (i != rowIndex ) - { - [tempObject setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"]; - } - i++; - } + [self validateBurned:rowIndex]; } } else if ([[aTableColumn identifier] isEqualToString:@"default"]) { - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:[anObject intValue]] forKey:@"subtitleTrackDefault"]; + self.subtitleArray[rowIndex][keySubTrackDefault] = @([anObject intValue]); if([anObject intValue] == 1) { /* Burned In and Default are mutually exclusive */ - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"]; + self.subtitleArray[rowIndex][keySubTrackBurned] = @0; } /* now we need to make sure no other tracks are set to default */ if ([anObject intValue] == 1) { - int i = 0; - NSEnumerator *enumerator = [subtitleArray objectEnumerator]; - id tempObject; - while ( tempObject = [enumerator nextObject] ) - { - if (i != rowIndex) - { - [tempObject setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"]; - } - i++; - } + [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"]) { - - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:[anObject intValue]] forKey:@"subtitleTrackSrtLanguageIndex"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[[languagesArray objectAtIndex:[anObject intValue]] objectAtIndex:0] forKey:@"subtitleTrackSrtLanguageLong"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[[languagesArray objectAtIndex:[anObject intValue]] objectAtIndex:1] forKey:@"subtitleTrackSrtLanguageIso3"]; - + self.subtitleArray[rowIndex][keySubTrackLanguageIndex] = @([anObject intValue]); + self.subtitleArray[rowIndex][keySubTrackLanguageIsoCode] = self.languagesArray[[anObject intValue]][1]; } else if ([[aTableColumn identifier] isEqualToString:@"srt_charcode"]) { /* charCodeArray */ - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:[anObject intValue]] forKey:@"subtitleTrackSrtCharCodeIndex"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[charCodeArray objectAtIndex:[anObject intValue]] forKey:@"subtitleTrackSrtCharCode"]; + self.subtitleArray[rowIndex][keySubTrackSrtCharCodeIndex] = @([anObject intValue]); + self.subtitleArray[rowIndex][keySubTrackSrtCharCode] = self.charCodeArray[[anObject intValue]]; } else if ([[aTableColumn identifier] isEqualToString:@"srt_offset"]) { - [[subtitleArray objectAtIndex:rowIndex] setObject:anObject forKey:@"subtitleTrackSrtOffset"]; + self.subtitleArray[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 ((container & HB_MUX_MASK_MP4) && ([anObject intValue] != 0)) + if ((self.container & HB_MUX_MASK_MP4) && ([anObject intValue] != 0)) { - if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue] == VOBSUB) + if ([self.subtitleArray[rowIndex][keySubTrackType] intValue] == VOBSUB) { /* lets see if there are currently any burned in subs specified */ - NSEnumerator *enumerator = [subtitleArray objectEnumerator]; - id tempObject; BOOL subtrackBurnedInFound = NO; - while ( tempObject = [enumerator nextObject] ) + for (id tempObject in self.subtitleArray) { - if ([[tempObject objectForKey:@"subtitleTrackBurned"] intValue] == 1) + if ([tempObject[keySubTrackBurned] intValue] == 1) { subtrackBurnedInFound = YES; } @@ -683,9 +692,9 @@ /* if we have no current vobsub set to burn it in ... burn it in by default */ if (!subtrackBurnedInFound) { - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:1] forKey:@"subtitleTrackBurned"]; + self.subtitleArray[rowIndex][keySubTrackBurned] = @1; /* Burned In and Default are mutually exclusive */ - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"]; + self.subtitleArray[rowIndex][keySubTrackDefault] = @0; } } } @@ -694,235 +703,295 @@ * 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 == [subtitleArray count] - 1) // if we have a last track which != "None" + if ([anObject intValue] != 0 && rowIndex == [self.subtitleArray count] - 1) // if we have a last track which != "None" { /* add a new empty None track */ - [self addSubtitleTrack]; - + [self.subtitleArray addObject:[self createSubtitleTrack]]; } - else if ([anObject intValue] == 0 && rowIndex != ([subtitleArray count] -1))// if this track is set to "None" and not the last track displayed + else if ([anObject intValue] == 0 && rowIndex != ([self.subtitleArray 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 && [[[subtitleArray objectAtIndex: 1] objectForKey: @"subtitleSourceTrackNum"] intValue] != 0) + if (rowIndex == 0 && [self.subtitleArray[1][keySubTrackSelectionIndex] intValue] != 0) { /* get the index of the selection in row one (which is track two) */ - int trackOneSelectedIndex = [[[subtitleArray objectAtIndex: 1] objectForKey: @"subtitleSourceTrackNum"] intValue]; + int trackOneSelectedIndex = [self.subtitleArray[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 */ - [[subtitleArray objectAtIndex: 1] setObject:[NSNumber numberWithInt:trackOneSelectedIndex + 1] forKey:@"subtitleSourceTrackNum"]; + self.subtitleArray[1][keySubTrackSelectionIndex] = @(trackOneSelectedIndex + 1); } /* now that we have made the adjustment for track one (index 0) go ahead and delete the track */ - [subtitleArray removeObjectAtIndex: rowIndex]; + [self.subtitleArray 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.foreignAudioSearchTrackName action:NULL keyEquivalent:@""]; + } + + for (NSDictionary *track in self.subtitleSourceArray) + { + [[cellTrackPopup menu] addItemWithTitle:track[keySubTrackName] action:NULL keyEquivalent:@""]; + } + + return [cellTrackPopup autorelease]; + } + else if ([[tableColumn identifier] isEqualToString:@"srt_lang"]) + { + return self.languagesCell; + } + else if ([[tableColumn identifier] isEqualToString:@"srt_charcode"]) + { + return self.encodingsCell; + } -/* Gives fine grained control over the final drawing of the widget, including widget status via the controlling array */ + return nil; +} + +/** + * Enables/Disables the table view cells. + */ - (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex { - /* we setup whats displayed given the column identifier */ if ([[aTableColumn identifier] isEqualToString:@"track"]) { - /* Set the index of the recorded source track here */ - [aCell selectItemAtIndex:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue]]; - /* now that we have actually selected our track, we can grok the titleOfSelectedItem for that track */ - [[subtitleArray objectAtIndex:rowIndex] setObject:[[aTableColumn dataCellForRow:rowIndex] titleOfSelectedItem] forKey:@"subtitleSourceTrackName"]; + return; + } + // If the Track is None, we disable the other cells as None is an empty track + if ([self.subtitleArray[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]; + } - [aCell setAlignment:NSCenterTextAlignment]; - /* If the Track is None, we disable the other cells as None is an empty track */ - if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] == 0) + 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.subtitleArray[rowIndex][keySubTrackSelectionIndex] intValue] || + !hb_subtitle_can_force([self.subtitleArray[rowIndex][keySubTrackType] intValue])) { - [aCell setState: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"]) + } + 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.subtitleArray[rowIndex][keySubTrackType] intValue]; + if (![self.subtitleArray[rowIndex][keySubTrackSelectionIndex] intValue] || + !hb_subtitle_can_burn(subtitleTrackType) || !hb_subtitle_can_pass(subtitleTrackType, self.container)) { - [aCell setState:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackForced"] intValue]]; - /* Disable the "Forced Only" checkbox if a) the track is "None" or b) the subtitle track doesn't support forced flags */ - if (![[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] || - !hb_subtitle_can_force([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue])) - { - [aCell setEnabled:NO]; - } - else - { - [aCell setEnabled:YES]; - } + [aCell setEnabled:NO]; } - else if ([[aTableColumn identifier] isEqualToString:@"burned"]) - { - [aCell setState:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackBurned"] intValue]]; - /* - * 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 = [[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue]; - if (![[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] || - !hb_subtitle_can_burn(subtitleTrackType) || !hb_subtitle_can_pass(subtitleTrackType, container)) - { - [aCell setEnabled:NO]; - } - else - { - [aCell setEnabled:YES]; - } + else + { + [aCell setEnabled:YES]; } - else if ([[aTableColumn identifier] isEqualToString:@"default"]) + } + 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.subtitleArray[rowIndex][keySubTrackSelectionIndex] intValue] || + !hb_subtitle_can_pass([self.subtitleArray[rowIndex][keySubTrackType] intValue], self.container)) { - /* - * 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 (![[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] || - !hb_subtitle_can_pass([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue], container)) - { - [aCell setState:NSOffState]; - [aCell setEnabled:NO]; - } - else - { - [aCell setState:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackDefault"] intValue]]; - [aCell setEnabled:YES]; - } + [aCell setEnabled:NO]; } - /* These next three columns only apply to srt's. they are disabled for source subs */ - else if ([[aTableColumn identifier] isEqualToString:@"srt_lang"]) + else { - /* We have an srt file so set the track type (Source or SRT, and the srt file path ) kvp's*/ - if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue] == SRTSUB) - { - [aCell setEnabled:YES]; - if([[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackSrtLanguageIndex"]) - { - [aCell selectItemAtIndex:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackSrtLanguageIndex"] intValue]]; - } - else - { - [aCell selectItemAtIndex:languagesArrayDefIndex]; // English - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInteger:languagesArrayDefIndex] forKey:@"subtitleTrackSrtLanguageIndex"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[[languagesArray objectAtIndex:languagesArrayDefIndex] objectAtIndex:0] forKey:@"subtitleTrackSrtLanguageLong"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[[languagesArray objectAtIndex:languagesArrayDefIndex] objectAtIndex:1] forKey:@"subtitleTrackSrtLanguageIso3"]; - - } - } - else - { - [aCell setEnabled:NO]; - } + [aCell setEnabled:YES]; } - else if ([[aTableColumn identifier] isEqualToString:@"srt_charcode"]) + } + /* 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.subtitleArray[rowIndex][keySubTrackType] intValue] == SRTSUB) { - /* We have an srt file so set the track type (Source or SRT, and the srt file path ) kvp's*/ - if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue] == SRTSUB) - { - [aCell setEnabled:YES]; - if ([[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackSrtCharCodeIndex"]) - { - [aCell selectItemAtIndex:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackSrtCharCodeIndex"] intValue]]; - } - else - { - [aCell selectItemAtIndex:charCodeArrayDefIndex]; // ISO-8859-1 - [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:charCodeArrayDefIndex] forKey:@"subtitleTrackSrtCharCodeIndex"]; - [[subtitleArray objectAtIndex:rowIndex] setObject:[charCodeArray objectAtIndex:charCodeArrayDefIndex] forKey:@"subtitleTrackSrtCharCode"]; - } - } - else - { - [aCell setEnabled:NO]; - } + [aCell setEnabled:YES]; } - else if ([[aTableColumn identifier] isEqualToString:@"srt_offset"]) + else { - if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue] == SRTSUB) - { - [aCell setEnabled:YES]; - } - else - { - [aCell setEnabled:NO]; - } + [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.subtitleArray[rowIndex][keySubTrackType] intValue] == SRTSUB) + { + [aCell setEnabled:YES]; } + else + { + [aCell setEnabled:NO]; + } + } + else if ([[aTableColumn identifier] isEqualToString:@"srt_offset"]) + { + if ([self.subtitleArray[rowIndex][keySubTrackType] intValue] == SRTSUB) + { + [aCell setEnabled:YES]; + } + else + { + [aCell setEnabled:NO]; + } + } +} - /* - * Let's check whether any subtitles in the list cannot be passed through. - * Set the first of any such subtitles to burned-in, remove the others. - */ - id tempObject; - int subtitleTrackType; - BOOL convertToBurnInUsed = NO; - NSMutableArray *tracksToDelete = [[NSMutableArray alloc] init]; - NSEnumerator *enumerator = [subtitleArray objectEnumerator]; - /* convert any non-None incompatible tracks to burn-in or remove them */ - while ((tempObject = [enumerator nextObject]) && - [tempObject objectForKey:@"subtitleSourceTrackType"]) - { - subtitleTrackType = [[tempObject objectForKey:@"subtitleSourceTrackType"] intValue]; - if (!hb_subtitle_can_pass(subtitleTrackType, container)) - { - if (convertToBurnInUsed == NO) - { - /* we haven't set any track to burned-in yet, so we can */ - [tempObject setObject:[NSNumber numberWithInt:1] forKey:@"subtitleTrackBurned"]; - convertToBurnInUsed = YES; //remove any additional tracks - } - else - { - /* we already have a burned-in track, we must remove others */ - [tracksToDelete addObject:tempObject]; - } - } +#pragma mark - Srt import + +/** + * Imports a srt file. + * + * @param sender + */ +- (IBAction)browseImportSrtFile:(id)sender +{ + NSOpenPanel *panel = [NSOpenPanel openPanel]; + [panel setAllowsMultipleSelection:NO]; + [panel setCanChooseFiles:YES]; + [panel setCanChooseDirectories: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.subtitleSourceArray addObject:@{keySubTrackIndex: @(self.subtitleSourceArray.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 trackFromSourceTrackIndex:self.subtitleSourceArray.count - 1]; + // Calculate the pop up selection index + newSubtitleSrtTrack[keySubTrackSelectionIndex] = @(self.subtitleSourceArray.count + (self.subtitleArray.count == 1)); + [self.subtitleArray insertObject:newSubtitleSrtTrack atIndex:self.subtitleArray.count - 1]; + + [self.fTableView reloadData]; } - /* if we converted a track to burned-in, unset it for tracks that support passthru */ - if (convertToBurnInUsed == YES) + }]; +} + +#pragma mark - UI cells + +- (NSArray *)populateLanguageArray +{ + NSMutableArray *languages = [[[NSMutableArray alloc] init] autorelease]; + + for (const iso639_lang_t * lang = lang_get_next(NULL); lang != NULL; lang = lang_get_next(lang)) + { + [languages addObject:@[@(lang->eng_name), + @(lang->iso639_2)]]; + if (!strcasecmp(lang->eng_name, "English")) { - enumerator = [subtitleArray objectEnumerator]; - while ((tempObject = [enumerator nextObject]) && - [tempObject objectForKey:@"subtitleSourceTrackType"]) - { - subtitleTrackType = [[tempObject objectForKey:@"subtitleSourceTrackType"] intValue]; - if (hb_subtitle_can_pass(subtitleTrackType, container)) - { - [tempObject setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"]; - } - } + _languagesArrayDefIndex = [languages count] - 1; + } + } + return [[languages copy] autorelease]; +} + +@synthesize languagesCell = _languagesCell; + +- (NSPopUpButtonCell *)languagesCell +{ + if (!_languagesCell) + { + // '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.languagesArray) + { + [[_languagesCell menu] addItemWithTitle:lang[0] action:NULL keyEquivalent:@""]; } - /* this is where the actual removal takes place */ - if ([tracksToDelete count] > 0) + } + 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]]]; + + // list our character codes, as per charCodeArray + for (NSString *charCode in self.charCodeArray) { - [subtitleArray removeObjectsInArray:tracksToDelete]; - [aTableView reloadData]; - /* this must be called after reloadData so as to not block the UI */ - [[NSAlert alertWithMessageText:@"Subtitle tack(s) removed" - defaultButton:@"OK" - alternateButton:nil - otherButton:nil - informativeTextWithFormat:@"%lu subtitle %@ could neither be converted to burn-in nor passed through", - (unsigned long)[tracksToDelete count], - [tracksToDelete count] > 1 ? @"tracks" : @"track"] runModal]; + [[_encodingsCell menu] addItemWithTitle:charCode action: NULL keyEquivalent: @""]; } - [tracksToDelete release]; } + return _encodingsCell; } @end diff --git a/macosx/HBSubtitlesDefaultsController.h b/macosx/HBSubtitlesDefaultsController.h new file mode 100644 index 000000000..12056a021 --- /dev/null +++ b/macosx/HBSubtitlesDefaultsController.h @@ -0,0 +1,17 @@ +/* HBSubtitlesDefaultsController.h $ + + 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. */ + +#import <Cocoa/Cocoa.h> + +@class HBSubtitlesSettings; + +@interface HBSubtitlesDefaultsController : NSWindowController + +- (instancetype)initWithSettings:(HBSubtitlesSettings *)settings; + +@property (nonatomic, readwrite, assign) id delegate; + +@end diff --git a/macosx/HBSubtitlesDefaultsController.m b/macosx/HBSubtitlesDefaultsController.m new file mode 100644 index 000000000..f529798d4 --- /dev/null +++ b/macosx/HBSubtitlesDefaultsController.m @@ -0,0 +1,68 @@ +/* HBSubtitlesDefaultsController.m $ + + 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. */ + +#import "HBSubtitlesDefaultsController.h" +#import "HBSubtitlesSettings.h" +#import "HBLanguagesSelection.h" + +@interface HBSubtitlesDefaultsController () + +@property (nonatomic, readonly) HBSubtitlesSettings *settings; + +@property (nonatomic, readonly) HBLanguagesSelection *languagesList; +@property (assign) IBOutlet HBLanguageArrayController *tableController; +@property (assign) IBOutlet NSButton *showAllButton; + +@end + +@implementation HBSubtitlesDefaultsController + +- (instancetype)initWithSettings:(HBSubtitlesSettings *)settings +{ + self = [super initWithWindowNibName:@"SubtitlesDefaults"]; + if (self) + { + _settings = [settings retain]; + _languagesList = [[HBLanguagesSelection alloc] initWithLanguages:_settings.trackSelectionLanguages]; + } + return self; +} + +- (void)windowDidLoad +{ + if (self.settings.trackSelectionLanguages.count) + { + self.tableController.showSelectedOnly = YES; + [self.showAllButton setState:NSOffState]; + } +} + +- (IBAction)edit:(id)sender +{ + self.tableController.showSelectedOnly = !self.tableController.showSelectedOnly; +} + +- (IBAction)done:(id)sender +{ + [[self window] orderOut:nil]; + [NSApp endSheet:[self window]]; + + [self.settings.trackSelectionLanguages removeAllObjects]; + [self.settings.trackSelectionLanguages addObjectsFromArray:self.languagesList.selectedLanguages]; + + if ([self.delegate respondsToSelector:@selector(sheetDidEnd)]) + { + [self.delegate performSelector:@selector(sheetDidEnd)]; + } +} + +- (void)dealloc +{ + [super dealloc]; + [_settings release]; +} + +@end diff --git a/macosx/HBSubtitlesSettings.h b/macosx/HBSubtitlesSettings.h new file mode 100644 index 000000000..a2cda1fb8 --- /dev/null +++ b/macosx/HBSubtitlesSettings.h @@ -0,0 +1,27 @@ +/* HBSubtitlesSettings.h $ + + 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. */ + +#import <Foundation/Foundation.h> + +typedef NS_ENUM(NSUInteger, HBSubtitleTrackSelectionBehavior) { + HBSubtitleTrackSelectionBehaviorNone, + HBSubtitleTrackSelectionBehaviorFirst, + HBSubtitleTrackSelectionBehaviorAll, +}; + +@interface HBSubtitlesSettings : NSObject + +@property (nonatomic, readwrite) HBSubtitleTrackSelectionBehavior trackSelectionBehavior; +@property (nonatomic, readwrite, retain) NSMutableArray *trackSelectionLanguages; + +@property (nonatomic, readwrite) BOOL addForeignAudioSearch; +@property (nonatomic, readwrite) BOOL addForeignAudioSubtitle; +@property (nonatomic, readwrite) BOOL addCC; + +- (void)applySettingsFromPreset:(NSDictionary *)preset; +- (void)prepareSubtitlesForPreset:(NSMutableDictionary *)preset; + +@end diff --git a/macosx/HBSubtitlesSettings.m b/macosx/HBSubtitlesSettings.m new file mode 100644 index 000000000..fd85dcfcb --- /dev/null +++ b/macosx/HBSubtitlesSettings.m @@ -0,0 +1,61 @@ +/* HBSubtitlesSettings.m $ + + 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. */ + +#import "HBSubtitlesSettings.h" + +@implementation HBSubtitlesSettings + +- (instancetype)init +{ + self = [super init]; + if (self) + { + _trackSelectionLanguages = [[NSMutableArray alloc] init]; + } + return self; +} + +- (void)applySettingsFromPreset:(NSDictionary *)preset +{ + if ([preset[@"SubtitleTrackSelectionBehavior"] isEqualToString:@"first"]) + { + self.trackSelectionBehavior = HBSubtitleTrackSelectionBehaviorFirst; + } + else if ([preset[@"SubtitleTrackSelectionBehavior"] isEqualToString:@"all"]) + { + self.trackSelectionBehavior = HBSubtitleTrackSelectionBehaviorAll; + } + else + { + self.trackSelectionBehavior = HBSubtitleTrackSelectionBehaviorNone; + } + self.trackSelectionLanguages = [NSMutableArray arrayWithArray:preset[@"SubtitleLanguageList"]]; + self.addCC = [preset[@"SubtitleAddCC"] boolValue]; + self.addForeignAudioSearch = [preset[@"SubtitleAddForeignAudioSearch"] boolValue]; + self.addForeignAudioSubtitle = [preset[@"SubtitleAddForeignAudioSubtitle"] boolValue]; +} + +- (void)prepareSubtitlesForPreset:(NSMutableDictionary *)preset +{ + if (self.trackSelectionBehavior == HBSubtitleTrackSelectionBehaviorFirst) + { + preset[@"SubtitleTrackSelectionBehavior"] = @"first"; + } + else if (self.trackSelectionBehavior == HBSubtitleTrackSelectionBehaviorAll) + { + preset[@"SubtitleTrackSelectionBehavior"] = @"all"; + } + else + { + preset[@"SubtitleTrackSelectionBehavior"] = @"none"; + } + preset[@"SubtitleLanguageList"] = self.trackSelectionLanguages; + preset[@"SubtitleAddCC"] = @(self.addCC); + preset[@"SubtitleAddForeignAudioSearch"] = @(self.addForeignAudioSearch); + preset[@"SubtitleAddForeignAudioSubtitle"] = @(self.addForeignAudioSubtitle); +} + +@end diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj index ae8038976..c229f3f94 100644 --- a/macosx/HandBrake.xcodeproj/project.pbxproj +++ b/macosx/HandBrake.xcodeproj/project.pbxproj @@ -119,9 +119,11 @@ A91726E7197291BC00D1AFEF /* HBChapterTitlesController.m in Sources */ = {isa = PBXBuildFile; fileRef = A91726E6197291BC00D1AFEF /* HBChapterTitlesController.m */; }; A93E0ED31972957000FD67FB /* HBVideoController.m in Sources */ = {isa = PBXBuildFile; fileRef = A93E0ED11972957000FD67FB /* HBVideoController.m */; }; A93E0ED71972958C00FD67FB /* Video.xib in Resources */ = {isa = PBXBuildFile; fileRef = A93E0ED51972958C00FD67FB /* Video.xib */; }; + A98C29C41977B10600AF5DED /* HBLanguagesSelection.m in Sources */ = {isa = PBXBuildFile; fileRef = A98C29C31977B10600AF5DED /* HBLanguagesSelection.m */; }; A9935213196F38A70069C6B7 /* ChaptersTitles.xib in Resources */ = {isa = PBXBuildFile; fileRef = A9935211196F38A70069C6B7 /* ChaptersTitles.xib */; }; A9AA447A1970664A00D7DEFC /* HBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = A9AA44791970664A00D7DEFC /* HBUtilities.m */; }; A9B34D75197696FE00871B7D /* DiskArbitration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9B34D74197696FE00871B7D /* DiskArbitration.framework */; }; + A9C0DB85197E7B0000DF55B3 /* SubtitlesDefaults.xib in Resources */ = {isa = PBXBuildFile; fileRef = A9C0DB83197E7B0000DF55B3 /* SubtitlesDefaults.xib */; }; A9D1E41718262364002F6424 /* HBPreviewGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = A9D1E41618262364002F6424 /* HBPreviewGenerator.m */; }; A9DC6C52196F04F6002AE6B4 /* HBSubtitlesController.m in Sources */ = {isa = PBXBuildFile; fileRef = A9DC6C50196F04F6002AE6B4 /* HBSubtitlesController.m */; }; A9DC6C56196F0517002AE6B4 /* Subtitles.xib in Resources */ = {isa = PBXBuildFile; fileRef = A9DC6C54196F0517002AE6B4 /* Subtitles.xib */; }; @@ -131,6 +133,8 @@ A9E1468216BC2AD800C307BC /* play-p.pdf in Resources */ = {isa = PBXBuildFile; fileRef = A9E1467E16BC2AD800C307BC /* play-p.pdf */; }; A9E1468316BC2AD800C307BC /* prev-p.pdf in Resources */ = {isa = PBXBuildFile; fileRef = A9E1467F16BC2AD800C307BC /* prev-p.pdf */; }; A9F2EB6F196F12C800066546 /* Audio.xib in Resources */ = {isa = PBXBuildFile; fileRef = A9F2EB6D196F12C800066546 /* Audio.xib */; }; + A9F472891976B7F30009EC65 /* HBSubtitlesDefaultsController.m in Sources */ = {isa = PBXBuildFile; fileRef = A9F472871976B7F30009EC65 /* HBSubtitlesDefaultsController.m */; }; + A9F4728D1976BAA70009EC65 /* HBSubtitlesSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = A9F4728C1976BAA70009EC65 /* HBSubtitlesSettings.m */; }; D2BCB10916F5152C0084604C /* activity.png in Resources */ = {isa = PBXBuildFile; fileRef = D2BCB0F616F515230084604C /* activity.png */; }; D2BCB10A16F5152C0084604C /* activity@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D2BCB0F716F515230084604C /* activity@2x.png */; }; D2BCB10B16F5152C0084604C /* addqueue.png in Resources */ = {isa = PBXBuildFile; fileRef = D2BCB0F816F515240084604C /* addqueue.png */; }; @@ -318,6 +322,8 @@ A93E0ED01972957000FD67FB /* HBVideoController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBVideoController.h; sourceTree = "<group>"; }; A93E0ED11972957000FD67FB /* HBVideoController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBVideoController.m; sourceTree = "<group>"; }; A93E0ED61972958C00FD67FB /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = Video.xib; sourceTree = "<group>"; }; + A98C29C21977B10600AF5DED /* HBLanguagesSelection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBLanguagesSelection.h; sourceTree = "<group>"; }; + A98C29C31977B10600AF5DED /* HBLanguagesSelection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBLanguagesSelection.m; sourceTree = "<group>"; }; A9935212196F38A70069C6B7 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = ChaptersTitles.xib; sourceTree = "<group>"; }; A9AA44781970664A00D7DEFC /* HBUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBUtilities.h; sourceTree = "<group>"; }; A9AA44791970664A00D7DEFC /* HBUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBUtilities.m; sourceTree = "<group>"; }; @@ -325,6 +331,7 @@ A9AA447C1970726500D7DEFC /* HBQueueController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBQueueController.h; sourceTree = "<group>"; }; A9AA447D1970729300D7DEFC /* HBPreviewGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBPreviewGenerator.h; sourceTree = "<group>"; }; A9B34D74197696FE00871B7D /* DiskArbitration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DiskArbitration.framework; path = System/Library/Frameworks/DiskArbitration.framework; sourceTree = SDKROOT; }; + A9C0DB84197E7B0000DF55B3 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = SubtitlesDefaults.xib; sourceTree = "<group>"; }; A9D1E41618262364002F6424 /* HBPreviewGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBPreviewGenerator.m; sourceTree = "<group>"; }; A9DC6C4F196F04F6002AE6B4 /* HBSubtitlesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBSubtitlesController.h; sourceTree = SOURCE_ROOT; }; A9DC6C50196F04F6002AE6B4 /* HBSubtitlesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBSubtitlesController.m; sourceTree = SOURCE_ROOT; }; @@ -335,6 +342,10 @@ A9E1467E16BC2AD800C307BC /* play-p.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "play-p.pdf"; sourceTree = "<group>"; }; A9E1467F16BC2AD800C307BC /* prev-p.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "prev-p.pdf"; sourceTree = "<group>"; }; A9F2EB6E196F12C800066546 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = Audio.xib; sourceTree = "<group>"; }; + A9F472861976B7F30009EC65 /* HBSubtitlesDefaultsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBSubtitlesDefaultsController.h; sourceTree = "<group>"; }; + A9F472871976B7F30009EC65 /* HBSubtitlesDefaultsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBSubtitlesDefaultsController.m; sourceTree = "<group>"; }; + A9F4728B1976BAA70009EC65 /* HBSubtitlesSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBSubtitlesSettings.h; sourceTree = "<group>"; }; + A9F4728C1976BAA70009EC65 /* HBSubtitlesSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBSubtitlesSettings.m; sourceTree = "<group>"; }; D2BCB0F616F515230084604C /* activity.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = activity.png; sourceTree = "<group>"; }; D2BCB0F716F515230084604C /* activity@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "activity@2x.png"; sourceTree = "<group>"; }; D2BCB0F816F515240084604C /* addqueue.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = addqueue.png; sourceTree = "<group>"; }; @@ -547,10 +558,9 @@ isa = PBXGroup; children = ( A9B34D6F197683FE00871B7D /* Controllers */, + A98C29C51977C00000AF5DED /* Model */, A9AA447D1970729300D7DEFC /* HBPreviewGenerator.h */, A9D1E41618262364002F6424 /* HBPreviewGenerator.m */, - 273F20A114ADBE670021BE6D /* HBPresets.h */, - 273F20A214ADBE670021BE6D /* HBPresets.m */, A9AA44781970664A00D7DEFC /* HBUtilities.h */, A9AA44791970664A00D7DEFC /* HBUtilities.m */, 273F209714ADBE670021BE6D /* HBDVDDetector.h */, @@ -648,6 +658,7 @@ A93E0ED51972958C00FD67FB /* Video.xib */, A9F2EB6D196F12C800066546 /* Audio.xib */, A9DC6C54196F0517002AE6B4 /* Subtitles.xib */, + A9C0DB83197E7B0000DF55B3 /* SubtitlesDefaults.xib */, 273F217A14ADDDA10021BE6D /* AdvancedView.xib */, A9935211196F38A70069C6B7 /* ChaptersTitles.xib */, 273F218014ADDDA10021BE6D /* OutputPanel.xib */, @@ -712,6 +723,19 @@ name = "Products (external)"; sourceTree = "<group>"; }; + A98C29C51977C00000AF5DED /* Model */ = { + isa = PBXGroup; + children = ( + 273F20A114ADBE670021BE6D /* HBPresets.h */, + 273F20A214ADBE670021BE6D /* HBPresets.m */, + A9F4728B1976BAA70009EC65 /* HBSubtitlesSettings.h */, + A9F4728C1976BAA70009EC65 /* HBSubtitlesSettings.m */, + A98C29C21977B10600AF5DED /* HBLanguagesSelection.h */, + A98C29C31977B10600AF5DED /* HBLanguagesSelection.m */, + ); + name = Model; + sourceTree = "<group>"; + }; A9B34D6F197683FE00871B7D /* Controllers */ = { isa = PBXGroup; children = ( @@ -737,14 +761,15 @@ children = ( A93E0ED01972957000FD67FB /* HBVideoController.h */, A93E0ED11972957000FD67FB /* HBVideoController.m */, - 273F209114ADBE670021BE6D /* HBAudio.h */, - 273F209214ADBE670021BE6D /* HBAudio.m */, A9AA447B1970724D00D7DEFC /* HBAdvancedController.h */, 273F209014ADBE670021BE6D /* HBAdvancedController.m */, + 273F209114ADBE670021BE6D /* HBAudio.h */, + 273F209214ADBE670021BE6D /* HBAudio.m */, 273F209314ADBE670021BE6D /* HBAudioController.h */, 273F209414ADBE670021BE6D /* HBAudioController.m */, A9DC6C4F196F04F6002AE6B4 /* HBSubtitlesController.h */, A9DC6C50196F04F6002AE6B4 /* HBSubtitlesController.m */, + A9F472851976B7AA0009EC65 /* Subtitles Defaults */, A91726E5197291BC00D1AFEF /* HBChapterTitlesController.h */, A91726E6197291BC00D1AFEF /* HBChapterTitlesController.m */, ); @@ -762,6 +787,15 @@ name = "UI Views"; sourceTree = "<group>"; }; + A9F472851976B7AA0009EC65 /* Subtitles Defaults */ = { + isa = PBXGroup; + children = ( + A9F472861976B7F30009EC65 /* HBSubtitlesDefaultsController.h */, + A9F472871976B7F30009EC65 /* HBSubtitlesDefaultsController.m */, + ); + name = "Subtitles Defaults"; + sourceTree = "<group>"; + }; /* End PBXGroup section */ /* Begin PBXLegacyTarget section */ @@ -892,6 +926,7 @@ D2BCB10B16F5152C0084604C /* addqueue.png in Resources */, D2BCB10C16F5152C0084604C /* addqueue@2x.png in Resources */, D2BCB10D16F5152C0084604C /* advanced.png in Resources */, + A9C0DB85197E7B0000DF55B3 /* SubtitlesDefaults.xib in Resources */, D2BCB10E16F5152C0084604C /* advanced@2x.png in Resources */, D2BCB10F16F5152C0084604C /* audio.png in Resources */, D2BCB11016F5152C0084604C /* audio@2x.png in Resources */, @@ -936,6 +971,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + A98C29C41977B10600AF5DED /* HBLanguagesSelection.m in Sources */, A9AA447A1970664A00D7DEFC /* HBUtilities.m in Sources */, 273F20AC14ADBE670021BE6D /* Controller.m in Sources */, 273F20AD14ADBE670021BE6D /* HBAdvancedController.m in Sources */, @@ -947,6 +983,8 @@ 273F20B414ADBE670021BE6D /* HBOutputRedirect.m in Sources */, 273F20B514ADBE670021BE6D /* HBPreferencesController.m in Sources */, A9DC6C52196F04F6002AE6B4 /* HBSubtitlesController.m in Sources */, + A9F472891976B7F30009EC65 /* HBSubtitlesDefaultsController.m in Sources */, + A9F4728D1976BAA70009EC65 /* HBSubtitlesSettings.m in Sources */, A93E0ED31972957000FD67FB /* HBVideoController.m in Sources */, 273F20B614ADBE670021BE6D /* HBPresets.m in Sources */, 273F20B714ADBE670021BE6D /* HBPreviewController.m in Sources */, @@ -1055,6 +1093,14 @@ name = ChaptersTitles.xib; sourceTree = "<group>"; }; + A9C0DB83197E7B0000DF55B3 /* SubtitlesDefaults.xib */ = { + isa = PBXVariantGroup; + children = ( + A9C0DB84197E7B0000DF55B3 /* English */, + ); + name = SubtitlesDefaults.xib; + sourceTree = "<group>"; + }; A9DC6C54196F0517002AE6B4 /* Subtitles.xib */ = { isa = PBXVariantGroup; children = ( @@ -1096,10 +1142,12 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; OTHER_LDFLAGS = ( "-filelist", "$(EXTERNAL_BUILD)/macosx/osl.filelist.txt", ); + SDKROOT = macosx; SHARED_PRECOMPS_DIR = "$(CONFIGURATION_TEMP_DIR)/PrecompiledHeaders"; STRIP_INSTALLED_PRODUCT = NO; }; @@ -1123,10 +1171,12 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; OTHER_LDFLAGS = ( "-filelist", "$(EXTERNAL_BUILD)/macosx/osl.filelist.txt", ); + SDKROOT = macosx; SHARED_PRECOMPS_DIR = "$(CONFIGURATION_TEMP_DIR)/PrecompiledHeaders"; STRIP_INSTALLED_PRODUCT = YES; }; |