OSDN Git Service

MacGui: remove deprecated headers from the previous Sparkle framework
[handbrake-jp/handbrake-jp-git.git] / macosx / HBSubtitles.m
1 /* $Id: HBSubtitles.m,v 1.35 2005/08/01 14:29:50 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.fr/>.
5    It may be used under the terms of the GNU General Public License. */
6 //
7
8 #import "HBSubtitles.h"
9 #include "hb.h"
10
11 @implementation HBSubtitles
12 - (id)init 
13 {
14     self = [super init];
15     if( self != nil )
16     {
17         fTitle = NULL;
18     }
19     
20     return self;
21 }
22
23
24 - (void)resetWithTitle:(hb_title_t *)title
25 {
26     fTitle = title;
27     
28     if (!title)
29     {
30         return;
31     }
32     
33     if (subtitleArray)
34     {
35         [subtitleArray release];
36     }
37     subtitleArray = [[NSMutableArray alloc] init];
38     [self addSubtitleTrack];
39 }
40
41 #pragma mark -
42 #pragma mark Create new Subtitles
43
44 - (void)addSubtitleTrack
45 {
46     [subtitleArray addObject:[self createSubtitleTrack]];
47 }
48
49 /* Creates a new subtitle track and stores it in an NSMutableDictionary */
50 - (NSDictionary *)createSubtitleTrack
51 {
52     NSMutableDictionary *newSubtitleTrack = [[NSMutableDictionary alloc] init];
53     /* Subtitle Source track popup index */
54     [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackNum"];
55     /* Subtitle Source track popup language */
56     [newSubtitleTrack setObject:@"None" forKey:@"subtitleSourceTrackName"];
57     /* Subtitle Source track popup isPictureSub */
58     [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackisPictureSub"];
59     /* Subtitle track forced state */
60     [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackForced"];
61     /* Subtitle track burned state */
62     [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"];
63     /* Subtitle track default state */
64     [newSubtitleTrack setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"];
65
66     [newSubtitleTrack autorelease];
67     return newSubtitleTrack;
68 }
69
70 - (NSMutableArray*) getSubtitleArray: (NSMutableArray *) subtitlesArray 
71 {
72     //NSMutableArray *returnSubtitlesArray = [[NSMutableArray alloc] init];
73     //[returnSubtitlesArray initWithArray:subtitleArray];
74     //[returnSubtitlesArray autorelease];
75     return subtitleArray;
76 }
77
78 - (void)containerChanged:(int) newContainer
79 {
80 container = newContainer;
81 }
82    
83 #pragma mark -
84 #pragma mark Subtitle Table Delegate Methods
85 /* Table View delegate methods */
86 /* Returns the number of tracks displayed
87  * NOTE: we return one more than the actual number of tracks
88  * specified as we always keep one track set to "None" which is ignored
89  * for setting up tracks, but is used to add tracks.
90  */
91 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
92 {
93     if( fTitle == NULL || ![subtitleArray count])
94     {
95         return 0;
96     }
97     else
98     {
99         return [subtitleArray count];
100     }
101 }
102
103 /* Used to tell the Table view which information is to be displayed per item */
104 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
105 {
106     NSString *cellEntry = @"__DATA ERROR__";
107     
108     /* we setup whats displayed given the column identifier */
109     if ([[aTableColumn identifier] isEqualToString:@"track"])
110     {
111         /* 'track' is a popup of all available source subtitle tracks for the given title */
112         
113         
114         NSPopUpButtonCell *cellTrackPopup = [[NSPopUpButtonCell alloc] init];
115         [cellTrackPopup autorelease];
116         /* Set the Popups properties */
117         /* Following two lines can be used to show kind of a text field with indicator arrows which
118          * will popup when clicked on. Comment out for a standard style popup */
119         //[cellTrackPopup setShowsBorderOnlyWhileMouseInside:YES];
120         //[cellTrackPopup setBordered:NO];
121         
122         [cellTrackPopup setControlSize:NSSmallControlSize];
123         [cellTrackPopup setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
124         
125         
126         /* Add our initial "None" track which we use to add source tracks or remove tracks.
127          * "None" is always index 0.
128          */
129         [[cellTrackPopup menu] addItemWithTitle: @"None" action: NULL keyEquivalent: @""];
130         
131         /* Foreign Audio Search (index 1 in the popup) is only available for the first track */
132         if (rowIndex == 0)
133         {
134             [[cellTrackPopup menu] addItemWithTitle: @"Foreign Audio Search - (Bitmap)" action: NULL keyEquivalent: @""];
135         }
136         
137         if (fTitle)
138         {
139             hb_subtitle_t *subtitle;
140             hb_subtitle_config_t sub_config;
141             int i;
142             for(i = 0; i < hb_list_count( fTitle->list_subtitle ); i++ )
143             {
144                 NSString * trackTypeString = @"";
145                 subtitle = (hb_subtitle_t *) hb_list_item( fTitle->list_subtitle, i );
146                 sub_config = subtitle->config;
147                 
148                 if (subtitle->format == PICTURESUB)
149                 {
150                     trackTypeString = @"- (Bitmap)";
151                 }
152                 else
153                 {
154                     trackTypeString = @"- (Text)";
155                 }
156                 
157                 
158                 NSString *popupMenuItemDescription = [NSString stringWithFormat:@"%d - %@ %@",i,[NSString stringWithUTF8String:subtitle->lang],trackTypeString];
159                 
160                 [[cellTrackPopup menu] addItemWithTitle: popupMenuItemDescription action: NULL keyEquivalent: @""];
161             }
162         }
163         
164         [aTableColumn setDataCell:cellTrackPopup];
165         
166     }
167     else if ([[aTableColumn identifier] isEqualToString:@"forced"])
168     {
169     /* 'forced' is a checkbox to determine if a given source track is only to be forced */
170     NSButtonCell *cellForcedCheckBox = [[NSButtonCell alloc] init];
171     [cellForcedCheckBox autorelease];
172     [cellForcedCheckBox setButtonType:NSSwitchButton];
173     [cellForcedCheckBox setImagePosition:NSImageOnly];
174     [cellForcedCheckBox setAllowsMixedState:NO];
175     [aTableColumn setDataCell:cellForcedCheckBox];
176
177     }
178     else if ([[aTableColumn identifier] isEqualToString:@"burned"])
179     {
180     /* 'burned' is a checkbox to determine if a given source track is only to be burned */
181     NSButtonCell *cellBurnedCheckBox = [[NSButtonCell alloc] init];
182     [cellBurnedCheckBox autorelease];
183     [cellBurnedCheckBox setButtonType:NSSwitchButton];
184     [cellBurnedCheckBox setImagePosition:NSImageOnly];
185     [cellBurnedCheckBox setAllowsMixedState:NO];
186     [aTableColumn setDataCell:cellBurnedCheckBox];
187     }
188     else if ([[aTableColumn identifier] isEqualToString:@"default"])
189     {
190     NSButtonCell *cellDefaultCheckBox = [[NSButtonCell alloc] init];
191     [cellDefaultCheckBox autorelease];
192     [cellDefaultCheckBox setButtonType:NSSwitchButton];
193     [cellDefaultCheckBox setImagePosition:NSImageOnly];
194     [cellDefaultCheckBox setAllowsMixedState:NO];
195     [aTableColumn setDataCell:cellDefaultCheckBox];
196     }
197     else
198     {
199     cellEntry = nil;    
200     }
201
202     return cellEntry;
203 }
204
205 /* Called whenever a widget in the table is edited or changed, we use it to record the change in the controlling array 
206  * including removing and adding new tracks via the "None" ("track" index of 0) */
207 - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
208 {
209     
210     if ([[aTableColumn identifier] isEqualToString:@"track"])
211     {
212         [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:[anObject intValue]] forKey:@"subtitleSourceTrackNum"];
213         /* Set the array to track if we are vobsub (picture sub) */
214         if ([anObject intValue] != 0)
215         {
216             int sourceSubtitleIndex;
217             bool isPictureSub = FALSE;
218             if (rowIndex == 0)
219             {
220                 sourceSubtitleIndex = [anObject intValue] - 2;
221             }
222             else
223             {
224                 sourceSubtitleIndex = [anObject intValue] - 1;
225             }
226             
227             if (rowIndex == 0 && [anObject intValue] == 1)// we are Foreign Launguage Search, which is inherently bitmap
228             {
229                 isPictureSub = TRUE;
230             }
231             else
232             {
233                 hb_subtitle_t        * subtitle;
234                 hb_subtitle_config_t   sub_config;
235                 subtitle = (hb_subtitle_t *) hb_list_item( fTitle->list_subtitle, sourceSubtitleIndex );
236                 sub_config = subtitle->config;
237                 if (subtitle->format == PICTURESUB)
238                 {
239                     isPictureSub = TRUE;
240                 }
241             }
242             if (isPictureSub == TRUE)
243             {
244                 [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:1] forKey:@"subtitleSourceTrackisPictureSub"];
245             }
246             else
247             {
248                 [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleSourceTrackisPictureSub"];
249                 /* if we are not picture sub, then we must be a text sub, handbrake does not support burning in text subs */
250                 [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"];
251             }
252         }
253      }
254     else if ([[aTableColumn identifier] isEqualToString:@"forced"])
255     {
256         [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:[anObject intValue]] forKey:@"subtitleTrackForced"];   
257     }
258     else if ([[aTableColumn identifier] isEqualToString:@"burned"])
259     {
260         [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:[anObject intValue]] forKey:@"subtitleTrackBurned"];   
261         /* now we need to make sure no other tracks are set to burned if we have set burned*/
262         if ([anObject intValue] == 1)
263         {
264             int i = 0;
265             NSEnumerator *enumerator = [subtitleArray objectEnumerator];
266             id tempObject;
267             while ( tempObject = [enumerator nextObject] )  
268             {
269                 if (i != rowIndex )
270                 {
271                     [tempObject setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackBurned"];
272                 }
273             i++;
274             }
275         }
276     }
277     else if ([[aTableColumn identifier] isEqualToString:@"default"])
278     {
279         [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:[anObject intValue]] forKey:@"subtitleTrackDefault"];   
280         /* now we need to make sure no other tracks are set to default */
281         if ([anObject intValue] == 1)
282         {
283             int i = 0;
284             NSEnumerator *enumerator = [subtitleArray objectEnumerator];
285             id tempObject;
286             while ( tempObject = [enumerator nextObject] )  
287             {
288                 if (i != rowIndex)
289                 {
290                     [tempObject setObject:[NSNumber numberWithInt:0] forKey:@"subtitleTrackDefault"];
291                 }
292             i++;
293             }
294         }
295         
296     }
297     
298     
299     /* now lets do a bit of logic to add / remove tracks as necessary via the "None" track (index 0) */
300     if ([[aTableColumn identifier] isEqualToString:@"track"])
301     {
302  
303         /* since mp4 only supports burned in vobsubs (bitmap) we need to make sure burned in is specified */
304         if (container == HB_MUX_MP4 && [anObject intValue] != 0)
305         {
306             /* so, if isPictureSub = TRUE and we are mp4, we now have to A) set burned-in to 1 and b) remove any other
307              * tracks specified that are burned in */
308             if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackisPictureSub"] intValue] == 1)
309             {
310                 [[subtitleArray objectAtIndex:rowIndex] setObject:[NSNumber numberWithInt:1] forKey:@"subtitleTrackBurned"];
311             }
312         }
313         
314          
315          /* We use the track popup index number (presumes index 0 is "None" which is ignored and only used to remove tracks if need be)
316          * to determine whether to 1 modify an existing track, 2. add a new empty "None" track or 3. remove an existing track.
317          */
318
319         if ([anObject intValue] != 0 && rowIndex == [subtitleArray count] - 1) // if we have a last track which != "None"
320         {
321             /* add a new empty None track */
322             [self addSubtitleTrack];
323         }
324         else if ([anObject intValue] == 0 && rowIndex != ([subtitleArray count] -1))// if this track is set to "None" and not the last track displayed
325         {
326             /* we know the user chose to remove this track by setting it to None, so remove it from the array */
327             /* 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
328              * the first track, which has to account for the extra "Foreign Language Search" index. */
329             if (rowIndex == 0 && [[[subtitleArray objectAtIndex: 1] objectForKey: @"subtitleSourceTrackNum"] intValue] != 0)
330             {
331                 /* get the index of the selection in row one (which is track two) */
332                 int trackOneSelectedIndex = [[[subtitleArray objectAtIndex: 1] objectForKey: @"subtitleSourceTrackNum"] intValue];
333                 /* increment the index of the subtitle menu item by one, to account for Foreign Language Search which is unique to the first track */
334                 [[subtitleArray objectAtIndex: 1] setObject:[NSNumber numberWithInt:trackOneSelectedIndex + 1] forKey:@"subtitleSourceTrackNum"];
335             }
336            /* now that we have made the adjustment for track one (index 0) go ahead and delete the track */
337            [subtitleArray removeObjectAtIndex: rowIndex]; 
338         }
339         
340         
341         
342     }
343     
344     [aTableView reloadData];
345 }
346
347
348 /* Gives fine grained control over the final drawing of the widget, including widget status via the controlling array */
349 - (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
350 {
351     /* we setup whats displayed given the column identifier */
352     if ([[aTableColumn identifier] isEqualToString:@"track"])
353     {
354         /* Set the index of the recorded source track here */
355         [aCell selectItemAtIndex:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue]];
356         /* now that we have actually selected our track, we can grok the titleOfSelectedItem for that track */
357         [[subtitleArray objectAtIndex:rowIndex] setObject:[[aTableColumn dataCellForRow:rowIndex] titleOfSelectedItem] forKey:@"subtitleSourceTrackName"];
358         
359     }
360     else
361     {
362         
363         [aCell setAlignment:NSCenterTextAlignment];
364         /* If the Track is None, we disable the other cells as None is an empty track */
365         if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] == 0)
366         {
367             [aCell setState:0];
368             [aCell setEnabled:NO];
369         }
370         else
371         {
372             /* Since we have a valid track, we go ahead and enable the rest of the widgets and set them according to the controlling array */
373             [aCell setEnabled:YES];
374         }
375         
376         if ([[aTableColumn identifier] isEqualToString:@"forced"])
377         {
378             [aCell setState:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackForced"] intValue]];
379         }
380         else if ([[aTableColumn identifier] isEqualToString:@"burned"])
381         {
382             [aCell setState:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackBurned"] intValue]];
383             /* Disable the "Burned-In" checkbox if a) the track is "None", b) the subtitle track is text (we do not support burning in
384              * text subs, or c) we are mp4 and the track is a vobsub (picture sub) */
385             if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackNum"] intValue] == 0 ||
386                 [[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackisPictureSub"] intValue] == 0 ||
387                 (container == HB_MUX_MP4 && [[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackisPictureSub"] intValue] == 1))
388             {
389                 [aCell setEnabled:NO];
390             }
391             else
392             {
393                 [aCell setEnabled:YES];
394             }
395         }
396         else if ([[aTableColumn identifier] isEqualToString:@"default"])
397         {
398             [aCell setState:[[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleTrackDefault"] intValue]];   
399         }
400         
401     }
402     
403     
404     if (container == HB_MUX_MP4)
405     {
406         /* now remove any other tracks that are set as burned and are picturesubs */
407         int i = 0;
408         int removedTracks = 0;
409         NSEnumerator *enumerator = [subtitleArray objectEnumerator];
410         id tempObject;
411         NSMutableArray *tempArrayToDelete = [NSMutableArray array];
412         BOOL removeTrack = NO; 
413         while ( tempObject = [enumerator nextObject] )  
414         {
415             
416             if ([[tempObject objectForKey:@"subtitleSourceTrackisPictureSub"] intValue] == 1)
417             {
418                 /* if this is the first vobsub mark it. if not, remove it */
419                 if (removeTrack == NO)
420                 {
421                     /* make sure that this is set to be burned in */
422                     [tempObject setObject:[NSNumber numberWithInt:1] forKey:@"subtitleTrackBurned"];
423                     removeTrack = YES;
424                 }
425                 else
426                 {
427                     [tempArrayToDelete addObject:tempObject];
428                     removedTracks ++;
429                 }
430             }
431             
432             i++;
433         }
434         /* check to see if there are tracks to remove from the array */
435         if ([tempArrayToDelete count] > 0)
436         {
437             /* Popup a warning that hb only support one pic sub being burned in with mp4 */
438             int status;
439             status = NSRunAlertPanel(@"More than one vobsub is not supported in an mp4...",@"Your first vobsub track will now be used.", @"OK", nil, nil);
440             [NSApp requestUserAttention:NSCriticalRequest];
441             
442             [subtitleArray removeObjectsInArray:tempArrayToDelete];
443             [aTableView reloadData];
444         }
445     }
446 }
447
448
449 @end