1 /* This file is part of the HandBrake source code.
2 Homepage: <http://handbrake.fr/>.
3 It may be used under the terms of the GNU General Public License. */
5 #import "ExpressController.h"
7 #define INSERT_STRING @"Insert a DVD"
8 #define TOOLBAR_START @"TOOLBAR_START"
9 #define TOOLBAR_PAUSE @"TOOLBAR_PAUSE"
10 #define TOOLBAR_OPEN @"TOOLBAR_OPEN"
11 #define TOOLBAR_ADVANCED @"TOOLBAR_ADVANCED"
13 #define p fState->param
17 @interface ExpressController (Private)
19 - (void) openUpdateDrives: (NSDictionary *) drives;
20 - (void) openBrowseDidEnd: (NSOpenPanel *) sheet returnCode: (int)
21 returnCode contextInfo: (void *) contextInfo;
22 - (void) openEnable: (BOOL) b;
24 - (id) updatePopUpIcon: (id) value;
26 - (void) convertEnable: (BOOL) b;
30 @implementation ExpressController
32 /***********************************************************************
33 * Application delegate methods
34 **********************************************************************/
37 NSEnumerator * enumerator;
39 /* NSToolbar initializations */
40 fToolbar = [[NSToolbar alloc] initWithIdentifier: @"InstantHandBrake Toolbar"];
41 [fToolbar setDelegate: self];
42 [fToolbar setAllowsUserCustomization: NO];
43 [fToolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
44 [fToolbar setVisible:NO];
45 [fWindow setShowsToolbarButton:NO];
46 [fWindow setToolbar: fToolbar];
48 /* Show the "Open DVD" interface */
49 fDriveDetector = [[DriveDetector alloc] initWithCallback: self
50 selector: @selector( openUpdateDrives: )];
52 [self openEnable: YES];
53 [fWindow setContentSize: [fOpenView frame].size];
54 [fWindow setContentView: fOpenView];
56 [fWindow makeKeyAndOrderFront: nil];
58 /* NSTableView initializations */
59 NSButtonCell * buttonCell;
60 NSTableColumn * tableColumn;
61 enumerator = [[fConvertTableView tableColumns] objectEnumerator];
62 while( ( tableColumn = [enumerator nextObject] ) )
64 [tableColumn setEditable: NO];
66 tableColumn = [fConvertTableView tableColumnWithIdentifier: @"Check"];
67 buttonCell = [[[NSButtonCell alloc] initTextCell: @""] autorelease];
68 [buttonCell setEditable: YES];
69 [buttonCell setButtonType: NSSwitchButton];
70 [tableColumn setDataCell: buttonCell];
73 fConvertFolderString = [NSHomeDirectory() stringByAppendingPathComponent:@"Desktop"];
74 [fConvertFolderString retain];
77 - (void) applicationWillFinishLaunching: (NSNotification *) n
79 fCore = [[HBCore alloc] init];
80 [fCore openInDebugMode:NO checkForUpdates:NO];
81 fHandle = [fCore hb_handle];
82 fState = [fCore hb_state];
83 fList = hb_get_titles( fHandle );
85 fDevice = [[DeviceController alloc] init];
87 [[NSNotificationCenter defaultCenter] addObserver:self
88 selector:@selector(scanningSource:)
89 name:@"HBCoreScanningNotification" object:nil];
91 [[NSNotificationCenter defaultCenter] addObserver:self
92 selector:@selector(scanDone:)
93 name:@"HBCoreScanDoneNotification" object:nil];
95 [[NSNotificationCenter defaultCenter] addObserver:self
96 selector:@selector(muxing:)
97 name:@"HBCoreMuxingNotification" object:nil];
99 [[NSNotificationCenter defaultCenter] addObserver:self
100 selector:@selector(working:)
101 name:@"HBCoreWorkingNotification" object:nil];
103 [[NSNotificationCenter defaultCenter] addObserver:self
104 selector:@selector(workDone:)
105 name:@"HBCoreWorkDoneNotification" object:nil];
107 [GrowlApplicationBridge setGrowlDelegate: self];
110 - (void) applicationWillTerminate: (NSNotification *) n
115 - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
118 [fWindow makeKeyAndOrderFront:nil];
124 - (NSToolbarItem *) toolbar: (NSToolbar *) toolbar itemForItemIdentifier: (NSString *) ident
125 willBeInsertedIntoToolbar: (BOOL) flag
127 NSToolbarItem * item;
128 item = [[NSToolbarItem alloc] initWithItemIdentifier: ident];
130 if ([ident isEqualToString: TOOLBAR_START])
132 [item setLabel: NSLocalizedString(@"Convert", "Convert")];
133 [item setPaletteLabel: NSLocalizedString(@"Convert/Cancel", @"Convert/Cancel")];
134 [item setImage: [NSImage imageNamed: @"Play"]];
135 [item setTarget: self];
136 [item setAction: @selector(convertGo:)];
138 else if ([ident isEqualToString: TOOLBAR_PAUSE])
140 [item setLabel: NSLocalizedString(@"Pause", "Pause")];
141 [item setPaletteLabel: NSLocalizedString(@"Pause/Resume", @"Pause/Resume")];
142 [item setImage: [NSImage imageNamed: @"Pause"]];
143 [item setTarget: self];
144 [item setAction: @selector(pauseGo:)];
146 else if ([ident isEqualToString: TOOLBAR_OPEN])
148 [item setLabel: NSLocalizedString(@"Open...", "Open...")];
149 [item setPaletteLabel: NSLocalizedString(@"Open Another Source", "Open Another Source")];
150 [item setImage: [NSImage imageNamed: @"Open"]];
151 [item setTarget: self];
152 [item setAction: @selector(openShow:)];
163 - (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
165 return [NSArray arrayWithObjects: TOOLBAR_START, TOOLBAR_PAUSE,
166 NSToolbarFlexibleSpaceItemIdentifier, TOOLBAR_OPEN, nil];
169 - (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
171 return [NSArray arrayWithObjects: TOOLBAR_START, TOOLBAR_PAUSE,
172 TOOLBAR_OPEN, NSToolbarFlexibleSpaceItemIdentifier, nil];
175 /***********************************************************************
176 * Tableview datasource methods
177 **********************************************************************/
178 - (int) numberOfRowsInTableView: (NSTableView *) t
183 return hb_list_count( fList );
186 - (id) tableView:(NSTableView *) t objectValueForTableColumn:
187 (NSTableColumn *) col row: (int) row
189 if( [[col identifier] isEqualToString: @"Check"] )
191 return [fConvertCheckArray objectAtIndex: row];
195 hb_title_t * title = hb_list_item( fList, row );
196 if( [[col identifier] isEqualToString: @"Title"] )
198 return [@"Title " stringByAppendingFormat: @"%d",
201 else if( [[col identifier] isEqualToString: @"Duration"] )
203 if( title->hours > 0 )
205 return [NSString stringWithFormat:
206 @"%d hour%s %d min%s", title->hours,
207 title->hours > 1 ? "s" : "", title->minutes,
208 title->minutes > 1 ? "s": ""];
210 else if( title->minutes > 0 )
212 return [NSString stringWithFormat:
213 @"%d min%s %d sec%s", title->minutes,
214 title->minutes > 1 ? "s" : "", title->seconds,
215 title->seconds > 1 ? "s": ""];
219 return [NSString stringWithFormat: @"%d seconds",
223 else if( [[col identifier] isEqualToString: @"Size"] )
225 return [NSString stringWithFormat:@"-"];
231 - (void) tableView: (NSTableView *) t setObjectValue: (id) object
232 forTableColumn: (NSTableColumn *) col row: (int) row
234 if( [[col identifier] isEqualToString: @"Check"] )
236 [fConvertCheckArray replaceObjectAtIndex: row withObject: object];
240 /***********************************************************************
241 * User events methods
242 **********************************************************************/
243 - (void) openShow: (id) sender
245 NSRect frame = [fWindow frame];
246 float offset = ( [fConvertView frame].size.height -
247 [fOpenView frame].size.height ) * [fWindow userSpaceScaleFactor];
249 frame.origin.y += offset;
250 frame.size.height -= offset;
251 [fWindow setContentView: fEmptyView];
252 [fWindow setFrame: frame display: YES animate: YES];
253 [fToolbar setVisible:NO];
254 [fOpenProgressField setStringValue: @""];
255 [fWindow setContentView: fOpenView];
257 [fDriveDetector run];
260 - (void) openMatrixChanged: (id) sender
262 [self openEnable: YES];
263 if( [fOpenMatrix selectedRow] )
265 [self openBrowse: self];
269 - (void) openBrowse: (id) sender
271 NSOpenPanel * panel = [NSOpenPanel openPanel];
272 [panel setAllowsMultipleSelection: NO];
273 [panel setCanChooseFiles: YES];
274 [panel setCanChooseDirectories: YES ];
275 [panel beginSheetForDirectory: nil file: nil types: nil
276 modalForWindow: fWindow modalDelegate: self
277 didEndSelector: @selector( openBrowseDidEnd:returnCode:contextInfo: )
281 - (void) openGo: (id) sender
283 [self openEnable: NO];
284 [fOpenIndicator setIndeterminate: YES];
285 [fOpenIndicator startAnimation: nil];
286 [fOpenProgressField setStringValue: NSLocalizedString( @"Opening...", @"Opening...") ];
287 [fDriveDetector stop];
289 if( [fOpenMatrix selectedRow] )
291 hb_scan( fHandle, [fOpenFolderString UTF8String], 0 );
295 hb_scan( fHandle, [[fDrives objectForKey: [fOpenPopUp
296 titleOfSelectedItem]] UTF8String], 0 );
300 - (void) selectFolderSheetShow: (id) sender
302 NSOpenPanel * panel = [NSOpenPanel openPanel];
304 [panel setPrompt: NSLocalizedString(@"Select", @"Convert -> Save panel prompt")];
305 [panel setAllowsMultipleSelection: NO];
306 [panel setCanChooseFiles: NO];
307 [panel setCanChooseDirectories: YES];
308 [panel setCanCreateDirectories: YES];
310 [panel beginSheetForDirectory: nil file: nil types: nil
311 modalForWindow: fWindow modalDelegate: self didEndSelector:
312 @selector(selectFolderSheetClosed:returnCode:contextInfo:) contextInfo: nil];
315 - (void) selectFolderSheetClosed: (NSOpenPanel *) sheet returnCode: (int)
316 returnCode contextInfo: (void *) contextInfo
318 if( returnCode != NSOKButton )
321 if( fConvertFolderString )
322 [fConvertFolderString release];
323 fConvertFolderString = [[[sheet filenames] objectAtIndex: 0] retain];
324 [[fConvertFolderPopUp itemAtIndex: 0] setTitle: [fConvertFolderString lastPathComponent]];
325 [fConvertFolderPopUp selectItemAtIndex:0];
327 NSMenuItem * item = [fConvertFolderPopUp itemAtIndex: 0];
328 [item setImage: [self updatePopUpIcon:fConvertFolderString]];
332 - (void) convertGo: (id) sender
335 Preset * currentPreset = [[[fDevice devicesList] objectAtIndex:[fConvertFormatPopUp indexOfSelectedItem]] firstPreset];
337 for( i = 0; i < hb_list_count( fList ); i++ )
339 if( ![[fConvertCheckArray objectAtIndex: i] boolValue] )
342 hb_title_t * title = hb_list_item( fList, i );
343 hb_job_t * job = title->job;
345 int maxwidth = [currentPreset maxWidth];
346 int maxheight = [currentPreset maxHeight];
347 int pixels = maxwidth * maxheight;
348 int aspect = title->aspect;
350 if( [fConvertAspectPopUp indexOfSelectedItem] == 1 )
352 aspect = 4 * HB_ASPECT_BASE / 3;
354 else if ( [fConvertAspectPopUp indexOfSelectedItem] == 2 )
356 aspect = 16 * HB_ASPECT_BASE / 9;
359 job->vbitrate = [currentPreset videoBitRate];
361 if( [fConvertMaxWidthPopUp indexOfSelectedItem] == 2 )
364 job->vbitrate /= 1.5;
366 else if ( [fConvertMaxWidthPopUp indexOfSelectedItem] == 3 )
372 if ( [fConvertAspectPopUp indexOfSelectedItem] > 0 )
376 hb_set_size( job, aspect, pixels );
378 } while(job->width > maxwidth || job->height > maxheight);
382 /* Reset job->crop values */
383 memcpy( job->crop, job->title->crop, 4 * sizeof( int ) );
384 job->width = maxwidth;
385 hb_fix_aspect( job, HB_KEEP_WIDTH );
388 job->mux = [currentPreset muxer];
389 job->vcodec = [currentPreset videoCodec];
390 job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
391 strcpy(job->x264opts, [[currentPreset videoCodecOptions] UTF8String]);
392 job->chapter_markers = 1;
393 job->vquality = -1.0;
397 /* Audio selection */
399 lang = [[fConvertAudioPopUp titleOfSelectedItem] UTF8String];
401 for( j = 0; j < hb_list_count( title->list_audio ); j++ )
403 /* Choose the first track that matches the language */
404 audio = hb_list_item( title->list_audio, j );
405 if( !strcmp( lang, audio->lang_simple ) )
411 if( job->audios[0] == -1 )
413 /* If the language isn't available in this title, choose
419 job->audio_mixdowns[0] = HB_AMIXDOWN_DOLBYPLII;
421 /* Subtitle selection */
422 hb_subtitle_t * subtitle;
423 lang = [[fConvertSubtitlePopUp titleOfSelectedItem] UTF8String];
425 for( j = 0; j < hb_list_count( title->list_subtitle ); j++ )
427 /* Choose the first track that matches the language */
428 subtitle = hb_list_item( title->list_subtitle, j );
429 if( !strcmp( lang, subtitle->lang ) )
436 job->file = strdup( [[NSString stringWithFormat:
437 @"%@/%s - Title %d.m4v", fConvertFolderString,
438 title->name, title->index] UTF8String] );
439 hb_add( fHandle, job );
444 [self convertEnable: NO];
447 - (void) convertCancel: (id) sender
450 [self convertEnable: YES];
455 /***********************************************************************
457 **********************************************************************/
459 @implementation ExpressController (Private)
461 - (void) openUpdateDrives: (NSDictionary *) drives
467 fDrives = [[NSDictionary alloc] initWithDictionary: drives];
470 NSEnumerator * enumerator = [fDrives keyEnumerator];
471 [fOpenPopUp removeAllItems];
472 while( ( device = [enumerator nextObject] ) )
474 [fOpenPopUp addItemWithTitle: device];
477 if( ![fOpenPopUp numberOfItems] )
479 [fOpenPopUp addItemWithTitle: INSERT_STRING];
481 [fOpenPopUp selectItemAtIndex: 0];
482 if( [fOpenMatrix isEnabled] )
484 [self openEnable: YES];
488 - (void) openBrowseDidEnd: (NSOpenPanel *) sheet returnCode: (int)
489 returnCode contextInfo: (void *) contextInfo
491 if( returnCode != NSOKButton )
494 if( fOpenFolderString )
495 [fOpenFolderString release];
496 fOpenFolderString = [[[sheet filenames] objectAtIndex: 0] retain];
497 [fOpenFolderField setStringValue: [fOpenFolderString lastPathComponent]];
501 - (BOOL)validateToolbarItem: (NSToolbarItem *) toolbarItem
503 NSString * ident = [toolbarItem itemIdentifier];
505 if ([ident isEqualToString: TOOLBAR_START] && [HBStateWorking isEqualToString:[fCore state]])
507 [toolbarItem setAction: @selector(convertCancel:)];
508 [toolbarItem setLabel:NSLocalizedString(@"Cancel", @"Cancel")];
511 else if ([ident isEqualToString: TOOLBAR_START] && [HBStateWorkDone isEqualToString:[fCore state]])
513 [toolbarItem setAction: @selector(convertGo:)];
514 [toolbarItem setLabel:NSLocalizedString(@"Convert", @"Convert")];
517 else if ([ident isEqualToString: TOOLBAR_OPEN] && [HBStateWorking isEqualToString:[fCore state]])
525 - (void) openEnable: (BOOL) b
527 [fOpenMatrix setEnabled: b];
528 [fOpenPopUp setEnabled: b];
529 [fOpenFolderField setEnabled: b];
530 [fOpenBrowseButton setEnabled: b];
531 [fOpenGoButton setEnabled: b];
535 if( [fOpenMatrix selectedRow] )
537 [fOpenPopUp setEnabled: NO];
541 [fOpenFolderField setEnabled: NO];
542 [fOpenBrowseButton setEnabled: NO];
543 if( [[fOpenPopUp titleOfSelectedItem]
544 isEqualToString: INSERT_STRING] )
546 [fOpenGoButton setEnabled: NO];
552 - (void) scanningSource: (NSNotification *) n
554 [fOpenIndicator setIndeterminate: NO];
555 [fOpenIndicator setDoubleValue: 100.0 *
556 ( (float) p.scanning.title_cur - 0.5 ) / p.scanning.title_count];
557 [fOpenProgressField setStringValue: [NSString
558 stringWithFormat: @"Scanning title %d of %d...",
559 p.scanning.title_cur, p.scanning.title_count]];
562 - (void) scanDone: (NSNotification *) n
564 [fOpenIndicator setIndeterminate: NO];
565 [fOpenIndicator setDoubleValue: 0.0];
567 [self openEnable: YES];
569 if( hb_list_count( fList ) )
575 [fDriveDetector run];
576 [fOpenProgressField setStringValue: NSLocalizedString(@"No Title Found...",@"No Title Found...")];
584 fConvertCheckArray = [[NSMutableArray alloc] initWithCapacity:
585 hb_list_count( fList )];
586 [fConvertAudioPopUp removeAllItems];
587 [fConvertSubtitlePopUp removeAllItems];
588 [fConvertSubtitlePopUp addItemWithTitle: @"None"];
589 for( i = 0; i < hb_list_count( fList ); i++ )
591 /* Default is to convert titles longer than 30 minutes. */
592 hb_title_t * title = hb_list_item( fList, i );
593 [fConvertCheckArray addObject: [NSNumber numberWithBool:
594 ( 60 * title->hours + title->minutes > 30 )]];
596 /* Update audio popup */
598 for( j = 0; j < hb_list_count( title->list_audio ); j++ )
600 audio = hb_list_item( title->list_audio, j );
601 [fConvertAudioPopUp addItemWithTitle:
602 [NSString stringWithUTF8String: audio->lang_simple]];
604 [fConvertAudioPopUp selectItemWithTitle: @"English"];
606 if ( [fConvertAudioPopUp selectedItem] == nil )
607 [fConvertAudioPopUp selectItemAtIndex:0];
609 /* Update subtitle popup */
610 hb_subtitle_t * subtitle;
611 for( j = 0; j < hb_list_count( title->list_subtitle ); j++ )
613 subtitle = hb_list_item( title->list_subtitle, j );
614 [fConvertSubtitlePopUp addItemWithTitle:
615 [NSString stringWithUTF8String: subtitle->lang]];
618 [fConvertTableView reloadData];
620 NSEnumerator * enumerator;
622 enumerator = [[fDevice devicesList] objectEnumerator];
624 while( ( device = [enumerator nextObject] ) )
625 [fConvertFormatPopUp addItemWithTitle:[device name]];
627 NSRect frame = [fWindow frame];
628 float offset = ( [fConvertView frame].size.height -
629 [fOpenView frame].size.height ) * [fWindow userSpaceScaleFactor];;
630 frame.origin.y -= offset;
631 frame.size.height += offset;
632 [fWindow setContentView: fEmptyView];
633 [fWindow setFrame: frame display: YES animate: YES];
634 [fToolbar setVisible:YES];
635 [fWindow setContentView: fConvertView];
637 NSMenuItem * item = [fConvertFolderPopUp itemAtIndex: 0];
638 [item setTitle: [fConvertFolderString lastPathComponent]];
639 [item setImage: [self updatePopUpIcon:fConvertFolderString]];
641 [self convertEnable: YES];
644 - (void) convertEnable: (BOOL) b
646 [fConvertTableView setEnabled: b];
647 [fConvertFolderPopUp setEnabled: b];
648 [fConvertFormatPopUp setEnabled: b];
649 [fConvertAspectPopUp setEnabled: b];
650 [fConvertMaxWidthPopUp setEnabled: b];
651 [fConvertAudioPopUp setEnabled: b];
652 [fConvertSubtitlePopUp setEnabled: b];
655 /***********************************************************************
657 ***********************************************************************
658 * Shows a progression bar on the dock icon, filled according to
659 * 'progress' (0.0 <= progress <= 1.0).
660 * Called with progress < 0.0 or progress > 1.0, restores the original
662 **********************************************************************/
663 - (void) UpdateDockIcon: (float) progress
667 NSBitmapImageRep * bmp;
669 uint32_t black = htonl( 0x000000FF );
670 uint32_t red = htonl( 0xFF0000FF );
671 uint32_t white = htonl( 0xFFFFFFFF );
672 int row_start, row_end;
675 /* Get application original icon */
676 icon = [NSImage imageNamed: @"NSApplicationIcon"];
678 if( progress < 0.0 || progress > 1.0 )
680 [NSApp setApplicationIconImage: icon];
684 /* Get it in a raw bitmap form */
685 tiff = [icon TIFFRepresentationUsingCompression:
686 NSTIFFCompressionNone factor: 1.0];
687 bmp = [NSBitmapImageRep imageRepWithData: tiff];
689 /* Draw the progression bar */
690 /* It's pretty simple (ugly?) now, but I'm no designer */
692 row_start = 3 * (int) [bmp size].height / 4;
693 row_end = 7 * (int) [bmp size].height / 8;
695 for( i = row_start; i < row_start + 2; i++ )
697 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
698 for( j = 0; j < (int) [bmp size].width; j++ )
703 for( i = row_start + 2; i < row_end - 2; i++ )
705 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
708 for( j = 2; j < (int) [bmp size].width - 2; j++ )
710 if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
722 for( i = row_end - 2; i < row_end; i++ )
724 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
725 for( j = 0; j < (int) [bmp size].width; j++ )
731 /* Now update the dock icon */
732 tiff = [bmp TIFFRepresentationUsingCompression:
733 NSTIFFCompressionNone factor: 1.0];
734 icon = [[NSImage alloc] initWithData: tiff];
735 [NSApp setApplicationIconImage: icon];
739 - (id) updatePopUpIcon: (id) value
746 icon = [[NSWorkspace sharedWorkspace] iconForFile: value];
748 [icon setScalesWhenResized: YES];
749 [icon setSize: NSMakeSize(16.0 , 16.0)];
754 - (void) working: (NSNotification *) n
756 float progress_total = ( p.working.progress + p.working.job_cur - 1 ) / p.working.job_count;
757 NSMutableString * string = [NSMutableString stringWithFormat: @"Converting: %.1f %%", 100.0 * progress_total];
759 if( p.working.seconds > -1 )
761 [string appendFormat: @" (%.1f fps, ", p.working.rate_avg];
762 if( p.working.hours > 0 )
764 [string appendFormat: @"%d hour%s %d min%s",
765 p.working.hours, p.working.hours == 1 ? "" : "s",
766 p.working.minutes, p.working.minutes == 1 ? "" : "s"];
768 else if( p.working.minutes > 0 )
770 [string appendFormat: @"%d min%s %d sec%s",
771 p.working.minutes, p.working.minutes == 1 ? "" : "s",
772 p.working.seconds, p.working.seconds == 1 ? "" : "s"];
776 [string appendFormat: @"%d second%s",
777 p.working.seconds, p.working.seconds == 1 ? "" : "s"];
779 [string appendString: @" left)"];
782 [fConvertInfoString setStringValue: string];
783 [fConvertIndicator setIndeterminate: NO];
784 [fConvertIndicator setDoubleValue: 100.0 * progress_total];
785 [self UpdateDockIcon: progress_total];
788 - (void) muxing: (NSNotification *) n
790 [fConvertInfoString setStringValue: NSLocalizedString(@"Muxing...",@"Muxing...")];
791 [fConvertIndicator setIndeterminate: YES];
792 [fConvertIndicator startAnimation: nil];
793 [self UpdateDockIcon: 1.0];
796 - (void) workDone: (NSNotification *) n
798 [fConvertIndicator setIndeterminate: NO];
799 [fConvertIndicator setDoubleValue: 0.0];
800 [self UpdateDockIcon: -1.0];
801 [self convertEnable: YES];
803 [fConvertInfoString setStringValue: NSLocalizedString(@"Done.",@"Done.")];
805 [fCore removeAllJobs];