OSDN Git Service

Remove unneeded preview files at the beginning of a scan.
[handbrake-jp/handbrake-jp-git.git] / libhb / hb.c
1 #include "hb.h"
2 #include "hbffmpeg.h"
3
4 struct hb_handle_s
5 {
6     /* The "Check for update" thread */
7     int            build;
8     char           version[16];
9     hb_thread_t  * update_thread;
10
11     /* This thread's only purpose is to check other threads'
12        states */
13     volatile int   die;
14     hb_thread_t  * main_thread;
15     int            pid;
16
17     /* DVD/file scan thread */
18     hb_list_t    * list_title;
19     hb_thread_t  * scan_thread;
20
21     /* The thread which processes the jobs. Others threads are launched
22        from this one (see work.c) */
23     hb_list_t    * jobs;
24     hb_job_t     * current_job;
25     int            job_count;
26     int            job_count_permanent;
27     volatile int   work_die;
28     int            work_error;
29     hb_thread_t  * work_thread;
30
31     int            cpu_count;
32
33     hb_lock_t    * state_lock;
34     hb_state_t     state;
35
36     int            paused;
37     hb_lock_t    * pause_lock;
38     /* For MacGui active queue
39        increments each time the scan thread completes*/
40     int            scanCount;
41
42 };
43
44 hb_lock_t *hb_avcodec_lock;
45 hb_work_object_t * hb_objects = NULL;
46
47 static void thread_func( void * );
48
49 void hb_avcodec_init()
50 {
51     hb_avcodec_lock  = hb_lock_init();
52     av_register_all();
53 }
54
55 int hb_avcodec_open(AVCodecContext *avctx, AVCodec *codec)
56 {
57     int ret;
58     hb_lock( hb_avcodec_lock );
59     ret = avcodec_open(avctx, codec);
60     hb_unlock( hb_avcodec_lock );
61     return ret;
62 }
63
64 int hb_avcodec_close(AVCodecContext *avctx)
65 {
66     int ret;
67     hb_lock( hb_avcodec_lock );
68     ret = avcodec_close(avctx);
69     hb_unlock( hb_avcodec_lock );
70     return ret;
71 }
72
73 /**
74  * Registers work objects, by adding the work object to a liked list.
75  * @param w Handle to hb_work_object_t to register.
76  */
77 void hb_register( hb_work_object_t * w )
78 {
79     w->next    = hb_objects;
80     hb_objects = w;
81 }
82
83 /**
84  * libhb initialization routine.
85  * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
86  * @param update_check signals libhb to check for updated version from HandBrake website.
87  * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
88  */
89 hb_handle_t * hb_init_real( int verbose, int update_check )
90 {
91     hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
92     uint64_t      date;
93
94     /* See hb_deep_log() and hb_log() in common.c */
95     global_verbosity_level = verbose;
96     if( verbose )
97         putenv( "HB_DEBUG=1" );
98
99     /* Check for an update on the website if asked to */
100     h->build = -1;
101
102     if( update_check )
103     {
104         hb_log( "hb_init: checking for updates" );
105         date             = hb_get_date();
106         h->update_thread = hb_update_init( &h->build, h->version );
107
108         for( ;; )
109         {
110             if( hb_thread_has_exited( h->update_thread ) )
111             {
112                 /* Immediate success or failure */
113                 hb_thread_close( &h->update_thread );
114                 break;
115             }
116             if( hb_get_date() > date + 1000 )
117             {
118                 /* Still nothing after one second. Connection problem,
119                    let the thread die */
120                 hb_log( "hb_init: connection problem, not waiting for "
121                         "update_thread" );
122                 break;
123             }
124             hb_snooze( 500 );
125         }
126     }
127
128     /*
129      * Initialise buffer pool
130      */
131     hb_buffer_pool_init();
132
133     /* CPU count detection */
134     hb_log( "hb_init: checking cpu count" );
135     h->cpu_count = hb_get_cpu_count();
136
137     h->list_title = hb_list_init();
138     h->jobs       = hb_list_init();
139
140     h->state_lock  = hb_lock_init();
141     h->state.state = HB_STATE_IDLE;
142
143     h->pause_lock = hb_lock_init();
144
145     /* libavcodec */
146     hb_avcodec_init();
147
148     /* Start library thread */
149     hb_log( "hb_init: starting libhb thread" );
150     h->die         = 0;
151     h->main_thread = hb_thread_init( "libhb", thread_func, h,
152                                      HB_NORMAL_PRIORITY );
153
154     return h;
155
156         /* Set the scan count to start at 0 */
157         //scan_count = 0;
158 }
159
160 /**
161  * libhb initialization routine.
162  * This version is to use when calling the dylib, the macro hb_init isn't available from a dylib call!
163  * @param verbose HB_DEBUG_NONE or HB_DEBUG_ALL.
164  * @param update_check signals libhb to check for updated version from HandBrake website.
165  * @return Handle to hb_handle_t for use on all subsequent calls to libhb.
166  */
167 hb_handle_t * hb_init_dl( int verbose, int update_check )
168 {
169     hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 );
170     uint64_t      date;
171
172     /* See hb_log() in common.c */
173     if( verbose > HB_DEBUG_NONE )
174     {
175         putenv( "HB_DEBUG=1" );
176     }
177
178     /* Check for an update on the website if asked to */
179     h->build = -1;
180
181     if( update_check )
182     {
183         hb_log( "hb_init: checking for updates" );
184         date             = hb_get_date();
185         h->update_thread = hb_update_init( &h->build, h->version );
186
187         for( ;; )
188         {
189             if( hb_thread_has_exited( h->update_thread ) )
190             {
191                 /* Immediate success or failure */
192                 hb_thread_close( &h->update_thread );
193                 break;
194             }
195             if( hb_get_date() > date + 1000 )
196             {
197                 /* Still nothing after one second. Connection problem,
198                    let the thread die */
199                 hb_log( "hb_init: connection problem, not waiting for "
200                         "update_thread" );
201                 break;
202             }
203             hb_snooze( 500 );
204         }
205     }
206
207     /* CPU count detection */
208     hb_log( "hb_init: checking cpu count" );
209     h->cpu_count = hb_get_cpu_count();
210
211     h->list_title = hb_list_init();
212     h->jobs       = hb_list_init();
213     h->current_job = NULL;
214
215     h->state_lock  = hb_lock_init();
216     h->state.state = HB_STATE_IDLE;
217
218     h->pause_lock = hb_lock_init();
219
220     /* libavcodec */
221     avcodec_init();
222     avcodec_register_all();
223
224     /* Start library thread */
225     hb_log( "hb_init: starting libhb thread" );
226     h->die         = 0;
227     h->main_thread = hb_thread_init( "libhb", thread_func, h,
228                                      HB_NORMAL_PRIORITY );
229
230     hb_register( &hb_sync );
231         hb_register( &hb_decmpeg2 );
232         hb_register( &hb_decsub );
233         hb_register( &hb_render );
234         hb_register( &hb_encavcodec );
235         hb_register( &hb_encxvid );
236         hb_register( &hb_encx264 );
237     hb_register( &hb_enctheora );
238         hb_register( &hb_deca52 );
239         hb_register( &hb_decdca );
240         hb_register( &hb_decavcodec );
241         hb_register( &hb_decavcodecv );
242         hb_register( &hb_decavcodecvi );
243         hb_register( &hb_decavcodecai );
244         hb_register( &hb_declpcm );
245         hb_register( &hb_encfaac );
246         hb_register( &hb_enclame );
247         hb_register( &hb_encvorbis );
248
249         return h;
250 }
251
252
253 /**
254  * Returns current version of libhb.
255  * @param h Handle to hb_handle_t.
256  * @return character array of version number.
257  */
258 char * hb_get_version( hb_handle_t * h )
259 {
260     return HB_PROJECT_VERSION;
261 }
262
263 /**
264  * Returns current build of libhb.
265  * @param h Handle to hb_handle_t.
266  * @return character array of build number.
267  */
268 int hb_get_build( hb_handle_t * h )
269 {
270     return HB_PROJECT_BUILD;
271 }
272
273 /**
274  * Checks for needed update.
275  * @param h Handle to hb_handle_t.
276  * @param version Pointer to handle where version will be copied.
277  * @return update indicator.
278  */
279 int hb_check_update( hb_handle_t * h, char ** version )
280 {
281     *version = ( h->build < 0 ) ? NULL : h->version;
282     return h->build;
283 }
284
285 /**
286  * Sets the cpu count to the desired value.
287  * @param h Handle to hb_handle_t
288  * @param cpu_count Number of CPUs to use.
289  */
290 void hb_set_cpu_count( hb_handle_t * h, int cpu_count )
291 {
292     cpu_count    = MAX( 1, cpu_count );
293     cpu_count    = MIN( cpu_count, 8 );
294     h->cpu_count = cpu_count;
295 }
296
297 /**
298  * Deletes current previews associated with titles
299  * @param h Handle to hb_handle_t
300  */
301 void hb_remove_previews( hb_handle_t * h )
302 {
303     char            filename[1024];
304     char            dirname[1024];
305     hb_title_t    * title;
306     int             i, count, len;
307     DIR           * dir;
308     struct dirent * entry;
309
310     memset( dirname, 0, 1024 );
311     hb_get_tempory_directory( h, dirname );
312     dir = opendir( dirname );
313     if (dir == NULL) return;
314
315     count = hb_list_count( h->list_title );
316     while( ( entry = readdir( dir ) ) )
317     {
318         if( entry->d_name[0] == '.' )
319         {
320             continue;
321         }
322         for( i = 0; i < count; i++ )
323         {
324             title = hb_list_item( h->list_title, i );
325             len = snprintf( filename, 1024, "%" PRIxPTR, (intptr_t) title );
326             if (strncmp(entry->d_name, filename, len) == 0)
327             {
328                 snprintf( filename, 1024, "%s/%s", dirname, entry->d_name );
329                 unlink( filename );
330                 break;
331             }
332         }
333     }
334     closedir( dir );
335 }
336
337 /**
338  * Initializes a scan of the by calling hb_scan_init
339  * @param h Handle to hb_handle_t
340  * @param path location of VIDEO_TS folder.
341  * @param title_index Desired title to scan.  0 for all titles.
342  * @param preview_count Number of preview images to generate.
343  * @param store_previews Whether or not to write previews to disk.
344  */
345 void hb_scan( hb_handle_t * h, const char * path, int title_index,
346               int preview_count, int store_previews )
347 {
348     hb_title_t * title;
349
350     /* Clean up from previous scan */
351     hb_remove_previews( h );
352     while( ( title = hb_list_item( h->list_title, 0 ) ) )
353     {
354         hb_list_rem( h->list_title, title );
355         hb_title_close( &title );
356     }
357
358     hb_log( "hb_scan: path=%s, title_index=%d", path, title_index );
359     h->scan_thread = hb_scan_init( h, path, title_index, h->list_title,
360                                    preview_count, store_previews );
361 }
362
363 /**
364  * Returns the list of titles found.
365  * @param h Handle to hb_handle_t
366  * @return Handle to hb_list_t of the title list.
367  */
368 hb_list_t * hb_get_titles( hb_handle_t * h )
369 {
370     return h->list_title;
371 }
372
373 /**
374  * Create preview image of desired title a index of picture.
375  * @param h Handle to hb_handle_t.
376  * @param title Handle to hb_title_t of desired title.
377  * @param picture Index in title.
378  * @param buffer Handle to buufer were inage will be drawn.
379  */
380 void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture,
381                      uint8_t * buffer )
382 {
383     hb_job_t           * job = title->job;
384     char                 filename[1024];
385     FILE               * file;
386     uint8_t            * buf1, * buf2, * buf3, * buf4, * pen;
387     uint32_t           * p32, swsflags;
388     AVPicture            pic_in, pic_preview, pic_deint, pic_crop, pic_scale;
389     struct SwsContext  * context;
390     int                  i;
391     int                  rgb_width = ((job->width + 7) >> 3) << 3;
392     int                  preview_size;
393
394     swsflags = SWS_LANCZOS | SWS_ACCURATE_RND;
395
396     buf1 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
397     buf2 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height ) );
398     buf3 = av_malloc( avpicture_get_size( PIX_FMT_YUV420P, job->width, job->height ) );
399     buf4 = av_malloc( avpicture_get_size( PIX_FMT_RGBA32, rgb_width, job->height ) );
400     avpicture_fill( &pic_in, buf1, PIX_FMT_YUV420P,
401                     title->width, title->height );
402     avpicture_fill( &pic_deint, buf2, PIX_FMT_YUV420P,
403                     title->width, title->height );
404     avpicture_fill( &pic_scale, buf3, PIX_FMT_YUV420P,
405                     job->width, job->height );
406     avpicture_fill( &pic_preview, buf4, PIX_FMT_RGBA32,
407                     rgb_width, job->height );
408
409     // Allocate the AVPicture frames and fill in
410
411     memset( filename, 0, 1024 );
412
413     hb_get_tempory_filename( h, filename, "%" PRIxPTR "%d",
414                              (intptr_t) title, picture );
415
416     file = fopen( filename, "r" );
417     if( !file )
418     {
419         hb_log( "hb_get_preview: fopen failed" );
420         return;
421     }
422
423     fread( buf1, avpicture_get_size( PIX_FMT_YUV420P, title->width, title->height), 1, file );
424     fclose( file );
425
426     if( job->deinterlace )
427     {
428         // Deinterlace and crop
429         avpicture_deinterlace( &pic_deint, &pic_in, PIX_FMT_YUV420P, title->width, title->height );
430         av_picture_crop( &pic_crop, &pic_deint, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
431     }
432     else
433     {
434         // Crop
435         av_picture_crop( &pic_crop, &pic_in, PIX_FMT_YUV420P, job->crop[0], job->crop[2] );
436     }
437
438     // Get scaling context
439     context = sws_getContext(title->width  - (job->crop[2] + job->crop[3]),
440                              title->height - (job->crop[0] + job->crop[1]),
441                              PIX_FMT_YUV420P,
442                              job->width, job->height, PIX_FMT_YUV420P,
443                              swsflags, NULL, NULL, NULL);
444
445     // Scale
446     sws_scale(context,
447               pic_crop.data, pic_crop.linesize,
448               0, title->height - (job->crop[0] + job->crop[1]),
449               pic_scale.data, pic_scale.linesize);
450
451     // Free context
452     sws_freeContext( context );
453
454     // Get preview context
455     context = sws_getContext(rgb_width, job->height, PIX_FMT_YUV420P,
456                               rgb_width, job->height, PIX_FMT_RGBA32,
457                               swsflags, NULL, NULL, NULL);
458
459     // Create preview
460     sws_scale(context,
461               pic_scale.data, pic_scale.linesize,
462               0, job->height,
463               pic_preview.data, pic_preview.linesize);
464
465     // Free context
466     sws_freeContext( context );
467
468     /* Gray background */
469     p32 = (uint32_t *) buffer;
470     for( i = 0; i < ( title->width + 2 ) * ( title->height + 2 ); i++ )
471     {
472         p32[i] = 0xFF808080;
473     }
474
475     /* Draw the picture, centered, and draw the cropping zone */
476     preview_size = pic_preview.linesize[0];
477     pen = buffer + ( title->height - job->height ) *
478         ( title->width + 2 ) * 2 + ( title->width - job->width ) * 2;
479     memset( pen, 0xFF, 4 * ( job->width + 2 ) );
480     pen += 4 * ( title->width + 2 );
481     for( i = 0; i < job->height; i++ )
482     {
483         uint8_t * nextLine;
484         nextLine = pen + 4 * ( title->width + 2 );
485         memset( pen, 0xFF, 4 );
486         pen += 4;
487         memcpy( pen, buf4 + preview_size * i, 4 * job->width );
488         pen += 4 * job->width;
489         memset( pen, 0xFF, 4 );
490         pen = nextLine;
491     }
492     memset( pen, 0xFF, 4 * ( job->width + 2 ) );
493
494     // Clean up
495     avpicture_free( &pic_preview );
496     avpicture_free( &pic_scale );
497     avpicture_free( &pic_deint );
498     avpicture_free( &pic_in );
499 }
500
501  /**
502  * Analyzes a frame to detect interlacing artifacts
503  * and returns true if interlacing (combing) is found.
504  *
505  * Code taken from Thomas Oestreich's 32detect filter
506  * in the Transcode project, with minor formatting changes.
507  *
508  * @param buf         An hb_buffer structure holding valid frame data
509  * @param width       The frame's width in pixels
510  * @param height      The frame's height in pixels
511  * @param color_equal Sensitivity for detecting similar colors
512  * @param color_diff  Sensitivity for detecting different colors
513  * @param threshold   Sensitivity for flagging planes as combed
514  * @param prog_equal  Sensitivity for detecting similar colors on progressive frames
515  * @param prog_diff   Sensitivity for detecting different colors on progressive frames
516  * @param prog_threshold Sensitivity for flagging progressive frames as combed
517  */
518 int hb_detect_comb( hb_buffer_t * buf, int width, int height, int color_equal, int color_diff, int threshold, int prog_equal, int prog_diff, int prog_threshold )
519 {
520     int j, k, n, off, cc_1, cc_2, cc[3];
521         // int flag[3] ; // debugging flag
522     uint16_t s1, s2, s3, s4;
523     cc_1 = 0; cc_2 = 0;
524
525     int offset = 0;
526     
527     if ( buf->flags & 16 )
528     {
529         /* Frame is progressive, be more discerning. */
530         color_diff = prog_diff;
531         color_equal = prog_equal;
532         threshold = prog_threshold;
533     }
534
535     /* One pas for Y, one pass for Cb, one pass for Cr */    
536     for( k = 0; k < 3; k++ )
537     {
538         if( k == 1 )
539         {
540             /* Y has already been checked, now offset by Y's dimensions
541                and divide all the other values by 2, since Cr and Cb
542                are half-size compared to Y.                               */
543             offset = width * height;
544             width >>= 1;
545             height >>= 1;
546         }
547         else if ( k == 2 )
548         {
549             /* Y and Cb are done, so the offset needs to be bumped
550                so it's width*height + (width / 2) * (height / 2)  */
551             offset *= 5/4;
552         }
553
554         for( j = 0; j < width; ++j )
555         {
556             off = 0;
557
558             for( n = 0; n < ( height - 4 ); n = n + 2 )
559             {
560                 /* Look at groups of 4 sequential horizontal lines */
561                 s1 = ( ( buf->data + offset )[ off + j             ] & 0xff );
562                 s2 = ( ( buf->data + offset )[ off + j + width     ] & 0xff );
563                 s3 = ( ( buf->data + offset )[ off + j + 2 * width ] & 0xff );
564                 s4 = ( ( buf->data + offset )[ off + j + 3 * width ] & 0xff );
565
566                 /* Note if the 1st and 2nd lines are more different in
567                    color than the 1st and 3rd lines are similar in color.*/
568                 if ( ( abs( s1 - s3 ) < color_equal ) &&
569                      ( abs( s1 - s2 ) > color_diff ) )
570                         ++cc_1;
571
572                 /* Note if the 2nd and 3rd lines are more different in
573                    color than the 2nd and 4th lines are similar in color.*/
574                 if ( ( abs( s2 - s4 ) < color_equal ) &&
575                      ( abs( s2 - s3 ) > color_diff) )
576                         ++cc_2;
577
578                 /* Now move down 2 horizontal lines before starting over.*/
579                 off += 2 * width;
580             }
581         }
582
583         // compare results
584         /*  The final cc score for a plane is the percentage of combed pixels it contains.
585             Because sensitivity goes down to hundreths of a percent, multiply by 1000
586             so it will be easy to compare against the threhold value which is an integer. */
587         cc[k] = (int)( ( cc_1 + cc_2 ) * 1000.0 / ( width * height ) );
588     }
589
590
591     /* HandBrake is all yuv420, so weight the average percentage of all 3 planes accordingly.*/
592     int average_cc = ( 2 * cc[0] + ( cc[1] / 2 ) + ( cc[2] / 2 ) ) / 3;
593     
594     /* Now see if that average percentage of combed pixels surpasses the threshold percentage given by the user.*/
595     if( average_cc > threshold )
596     {
597 #if 0
598             hb_log("Average %i combed (Threshold %i) %i/%i/%i | PTS: %lld (%fs) %s", average_cc, threshold, cc[0], cc[1], cc[2], buf->start, (float)buf->start / 90000, (buf->flags & 16) ? "Film" : "Video" );
599 #endif
600         return 1;
601     }
602
603 #if 0
604     hb_log("SKIPPED Average %i combed (Threshold %i) %i/%i/%i | PTS: %lld (%fs) %s", average_cc, threshold, cc[0], cc[1], cc[2], buf->start, (float)buf->start / 90000, (buf->flags & 16) ? "Film" : "Video" );
605 #endif
606
607     /* Reaching this point means no combing detected. */
608     return 0;
609
610 }
611
612 /**
613  * Calculates job width and height for anamorphic content,
614  *
615  * @param job Handle to hb_job_t
616  * @param output_width Pointer to returned storage width
617  * @param output_height Pointer to returned storage height
618  * @param output_par_width Pointer to returned pixel width
619  @ param output_par_height Pointer to returned pixel height
620  */
621 void hb_set_anamorphic_size( hb_job_t * job,
622         int *output_width, int *output_height,
623         int *output_par_width, int *output_par_height )
624 {
625     /* Set up some variables to make the math easier to follow. */
626     hb_title_t * title = job->title;
627     int cropped_width = title->width - job->crop[2] - job->crop[3] ;
628     int cropped_height = title->height - job->crop[0] - job->crop[1] ;
629     double storage_aspect = (double)cropped_width / (double)cropped_height;
630     int mod = job->anamorphic.modulus ? job->anamorphic.modulus : 16;
631     double aspect = title->aspect;
632     
633     int pixel_aspect_width  = job->anamorphic.par_width;
634     int pixel_aspect_height = job->anamorphic.par_height;
635
636     /* If a source was really NTSC or PAL and the user specified ITU PAR
637        values, replace the standard PAR values with the ITU broadcast ones. */
638     if( title->width == 720 && job->anamorphic.itu_par )
639     {
640         // convert aspect to a scaled integer so we can test for 16:9 & 4:3
641         // aspect ratios ignoring insignificant differences in the LSBs of
642         // the floating point representation.
643         int iaspect = aspect * 9.;
644
645         /* Handle ITU PARs */
646         if (title->height == 480)
647         {
648             /* It's NTSC */
649             if (iaspect == 16)
650             {
651                 /* It's widescreen */
652                 pixel_aspect_width = 40;
653                 pixel_aspect_height = 33;
654             }
655             else if (iaspect == 12)
656             {
657                 /* It's 4:3 */
658                 pixel_aspect_width = 10;
659                 pixel_aspect_height = 11;
660             }
661         }
662         else if (title->height == 576)
663         {
664             /* It's PAL */
665             if(iaspect == 16)
666             {
667                 /* It's widescreen */
668                 pixel_aspect_width = 16;
669                 pixel_aspect_height = 11;
670             }
671             else if (iaspect == 12)
672             {
673                 /* It's 4:3 */
674                 pixel_aspect_width = 12;
675                 pixel_aspect_height = 11;
676             }
677         }
678     }
679
680     /* Figure out what width the source would display at. */
681     int source_display_width = cropped_width * (double)pixel_aspect_width /
682                                (double)pixel_aspect_height ;
683
684     /*
685        3 different ways of deciding output dimensions:
686         - 1: Strict anamorphic, preserve source dimensions
687         - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
688         - 3: Power user anamorphic, specify everything
689     */
690     int width, height;
691     switch( job->anamorphic.mode )
692     {
693         case 1:
694             /* Strict anamorphic */
695             *output_width = cropped_width;
696             *output_height = cropped_height;
697             *output_par_width = title->pixel_aspect_width;
698             *output_par_height = title->pixel_aspect_height;
699         break;
700
701         case 2:
702             /* "Loose" anamorphic.
703                 - Uses mod16-compliant dimensions,
704                 - Allows users to set the width
705             */
706             width = job->width;
707             // height: Gets set later, ignore user job->height value
708
709             /* Gotta handle bounding dimensions.
710                If the width is too big, just reset it with no rescaling.
711                Instead of using the aspect-scaled job height,
712                we need to see if the job width divided by the storage aspect
713                is bigger than the max. If so, set it to the max (this is sloppy).
714                If not, set job height to job width divided by storage aspect.
715             */
716
717             if ( job->maxWidth && (job->maxWidth < job->width) )
718                 width = job->maxWidth;
719
720             /* Time to get picture width that divide cleanly.*/
721             width  = MULTIPLE_MOD( width, mod);
722
723             /* Verify these new dimensions don't violate max height and width settings */
724             if ( job->maxWidth && (job->maxWidth < job->width) )
725                 width = job->maxWidth;
726
727             height = ((double)width / storage_aspect) + 0.5;
728             
729             if ( job->maxHeight && (job->maxHeight < height) )
730                 height = job->maxHeight;
731
732             /* Time to get picture height that divide cleanly.*/
733             height = MULTIPLE_MOD( height, mod);
734
735             /* Verify these new dimensions don't violate max height and width settings */
736             if ( job->maxHeight && (job->maxHeight < height) )
737                 height = job->maxHeight;
738
739             /* The film AR is the source's display width / cropped source height.
740                The output display width is the output height * film AR.
741                The output PAR is the output display width / output storage width. */
742             pixel_aspect_width = height * source_display_width / cropped_height;
743             pixel_aspect_height = width;
744
745             /* Pass the results back to the caller */
746             *output_width = width;
747             *output_height = height;
748         break;
749             
750         case 3:
751             /* Anamorphic 3: Power User Jamboree
752                - Set everything based on specified values */
753             
754             /* Use specified storage dimensions */
755             width = job->width;
756             height = job->height;
757             
758             /* Bind to max dimensions */
759             if( job->maxWidth && width > job->maxWidth )
760                 width = job->maxWidth;
761             if( job->maxHeight && height > job->maxHeight )
762                 height = job->maxHeight;
763             
764             /* Time to get picture dimensions that divide cleanly.*/
765             width  = MULTIPLE_MOD( width, mod);
766             height = MULTIPLE_MOD( height, mod);
767             
768             /* Verify we're still within max dimensions */
769             if( job->maxWidth && width > job->maxWidth )
770                 width = job->maxWidth - (mod/2);
771             if( job->maxHeight && height > job->maxHeight )
772                 height = job->maxHeight - (mod/2);
773                 
774             /* Re-ensure we have picture dimensions that divide cleanly. */
775             width  = MULTIPLE_MOD( width, mod );
776             height = MULTIPLE_MOD( height, mod );
777             
778             /* That finishes the storage dimensions. On to display. */            
779             if( job->anamorphic.dar_width && job->anamorphic.dar_height )
780             {
781                 /* We need to adjust the PAR to produce this aspect. */
782                 pixel_aspect_width = height * job->anamorphic.dar_width / job->anamorphic.dar_height;
783                 pixel_aspect_height = width;
784             }
785             else
786             {
787                 /* We first need the display ar.
788                    That's the source display width divided by the source height after cropping.
789                    Then we multiple the output height by that to get the pixel aspect width,
790                    and the pixel aspect height is the storage width.*/
791                 pixel_aspect_width = height * source_display_width / cropped_height;
792                 pixel_aspect_height = width;
793             }
794             
795             /* Back to caller */
796             *output_width = width;
797             *output_height = height;
798         break;
799     }
800     
801     /* While x264 is smart enough to reduce fractions on its own, libavcodec
802        needs some help with the math, so lose superfluous factors.            */
803     hb_reduce( output_par_width, output_par_height,
804                pixel_aspect_width, pixel_aspect_height );
805 }
806
807 /**
808  * Calculates job width, height, and cropping parameters.
809  * @param job Handle to hb_job_t.
810  * @param aspect Desired aspect ratio. Value of -1 uses title aspect.
811  * @param pixels Maximum desired pixel count.
812  */
813 void hb_set_size( hb_job_t * job, double aspect, int pixels )
814 {
815     hb_title_t * title = job->title;
816
817     int croppedWidth  = title->width - title->crop[2] - title->crop[3];
818     int croppedHeight = title->height - title->crop[0] - title->crop[1];
819     double croppedAspect = title->aspect * title->height * croppedWidth /
820                            croppedHeight / title->width;
821     int addCrop;
822     int i, w, h;
823
824     if( aspect <= 0 )
825     {
826         /* Keep the best possible aspect ratio */
827         aspect = croppedAspect;
828     }
829
830     /* Crop if necessary to obtain the desired ratio */
831     memcpy( job->crop, title->crop, 4 * sizeof( int ) );
832     if( aspect < croppedAspect )
833     {
834         /* Need to crop on the left and right */
835         addCrop = croppedWidth - aspect * croppedHeight * title->width /
836                     title->aspect / title->height;
837         if( addCrop & 3 )
838         {
839             addCrop = ( addCrop + 1 ) / 2;
840             job->crop[2] += addCrop;
841             job->crop[3] += addCrop;
842         }
843         else if( addCrop & 2 )
844         {
845             addCrop /= 2;
846             job->crop[2] += addCrop - 1;
847             job->crop[3] += addCrop + 1;
848         }
849         else
850         {
851             addCrop /= 2;
852             job->crop[2] += addCrop;
853             job->crop[3] += addCrop;
854         }
855     }
856     else if( aspect > croppedAspect )
857     {
858         /* Need to crop on the top and bottom */
859         addCrop = croppedHeight - croppedWidth * title->aspect *
860             title->height / aspect / title->width;
861         if( addCrop & 3 )
862         {
863             addCrop = ( addCrop + 1 ) / 2;
864             job->crop[0] += addCrop;
865             job->crop[1] += addCrop;
866         }
867         else if( addCrop & 2 )
868         {
869             addCrop /= 2;
870             job->crop[0] += addCrop - 1;
871             job->crop[1] += addCrop + 1;
872         }
873         else
874         {
875             addCrop /= 2;
876             job->crop[0] += addCrop;
877             job->crop[1] += addCrop;
878         }
879     }
880
881     /* Compute a resolution from the number of pixels and aspect */
882     for( i = 0;; i++ )
883     {
884         w = 16 * i;
885         h = MULTIPLE_16( (int)( (double)w / aspect ) );
886         if( w * h > pixels )
887         {
888             break;
889         }
890     }
891     i--;
892     job->width  = 16 * i;
893     job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
894 }
895
896 /**
897  * Returns the number of jobs in the queue.
898  * @param h Handle to hb_handle_t.
899  * @return Number of jobs.
900  */
901 int hb_count( hb_handle_t * h )
902 {
903     return hb_list_count( h->jobs );
904 }
905
906 /**
907  * Returns handle to job at index i within the job list.
908  * @param h Handle to hb_handle_t.
909  * @param i Index of job.
910  * @returns Handle to hb_job_t of desired job.
911  */
912 hb_job_t * hb_job( hb_handle_t * h, int i )
913 {
914     return hb_list_item( h->jobs, i );
915 }
916
917 hb_job_t * hb_current_job( hb_handle_t * h )
918 {
919     return( h->current_job );
920 }
921
922 /**
923  * Adds a job to the job list.
924  * @param h Handle to hb_handle_t.
925  * @param job Handle to hb_job_t.
926  */
927 void hb_add( hb_handle_t * h, hb_job_t * job )
928 {
929     hb_job_t      * job_copy;
930     hb_title_t    * title,    * title_copy;
931     hb_chapter_t  * chapter,  * chapter_copy;
932     hb_audio_t    * audio;
933     hb_subtitle_t * subtitle, * subtitle_copy;
934     int             i;
935     char            audio_lang[4];
936
937     /* Copy the title */
938     title      = job->title;
939     title_copy = malloc( sizeof( hb_title_t ) );
940     memcpy( title_copy, title, sizeof( hb_title_t ) );
941
942     title_copy->list_chapter = hb_list_init();
943     for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
944     {
945         chapter      = hb_list_item( title->list_chapter, i );
946         chapter_copy = malloc( sizeof( hb_chapter_t ) );
947         memcpy( chapter_copy, chapter, sizeof( hb_chapter_t ) );
948         hb_list_add( title_copy->list_chapter, chapter_copy );
949     }
950
951     /*
952      * Copy the metadata
953      */
954     if( title->metadata )
955     {
956         title_copy->metadata = malloc( sizeof( hb_metadata_t ) );
957         
958         if( title_copy->metadata ) 
959         {
960             memcpy( title_copy->metadata, title->metadata, sizeof( hb_metadata_t ) );
961
962             /*
963              * Need to copy the artwork seperatly (TODO).
964              */
965             if( title->metadata->coverart )
966             {
967                 title_copy->metadata->coverart = malloc( title->metadata->coverart_size );
968                 if( title_copy->metadata->coverart )
969                 {
970                     memcpy( title_copy->metadata->coverart, title->metadata->coverart,
971                             title->metadata->coverart_size );
972                 } else {
973                     title_copy->metadata->coverart_size = 0; 
974                 }
975             }
976         }
977     }
978
979     /* Copy the audio track(s) we want */
980     title_copy->list_audio = hb_list_init();
981
982     for( i = 0; i < hb_list_count(job->list_audio); i++ )
983     {
984         if( ( audio = hb_list_item( job->list_audio, i ) ) )
985         {
986             hb_list_add( title_copy->list_audio, hb_audio_copy(audio) );
987         }
988     }
989
990     title_copy->list_subtitle = hb_list_init();
991
992     /*
993      * The following code is confusing, there are three ways in which
994      * we select subtitles and it depends on whether this is single or
995      * two pass mode.
996      *
997      * subtitle_scan may be enabled, in which case the first pass
998      * scans all subtitles of that language. The second pass does not
999      * select any because they are set at the end of the first pass.
1000      *
1001      * native_language may have a preferred language, in which case we
1002      * may be switching the language we want for the subtitles in the
1003      * first pass of a single pass, or the second pass of a two pass.
1004      *
1005      * We may have manually selected a subtitle, in which case that is
1006      * selected in the first pass of a single pass, or the second of a
1007      * two pass.
1008      */
1009     memset( audio_lang, 0, sizeof( audio_lang ) );
1010
1011     if ( job->indepth_scan || job->native_language ) {
1012
1013         /*
1014          * Find the first audio language that is being encoded
1015          */
1016         for( i = 0; i < hb_list_count(job->list_audio); i++ )
1017         {
1018             if( ( audio = hb_list_item( job->list_audio, i ) ) )
1019             {
1020                 strncpy(audio_lang, audio->config.lang.iso639_2, sizeof(audio_lang));
1021                 break;
1022             }
1023         }
1024
1025         /*
1026          * In all cases switch the language if we need to to our native
1027          * language.
1028          */
1029         if( job->native_language )
1030         {
1031             if( strncasecmp( job->native_language, audio_lang,
1032                              sizeof( audio_lang ) ) != 0 )
1033             {
1034
1035                 if( job->pass != 2 )
1036                 {
1037                     hb_log( "Enabled subtitles in native language '%s', audio is in '%s'",
1038                             job->native_language, audio_lang);
1039                 }
1040                 /*
1041                  * The main audio track is not in our native language, so switch
1042                  * the subtitles to use our native language instead.
1043                  */
1044                 strncpy( audio_lang, job->native_language, sizeof( audio_lang ) );
1045             } else {
1046                 /*
1047                  * native language is irrelevent, free it.
1048                  */
1049                 free( job->native_language );
1050                 job->native_language = NULL;
1051             }
1052         }
1053     }
1054
1055     /*
1056      * If doing a subtitle scan then add all the matching subtitles for this
1057      * language.
1058      */
1059     if ( job->indepth_scan )
1060     {
1061         for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1062         {
1063             subtitle = hb_list_item( title->list_subtitle, i );
1064             if( strcmp( subtitle->iso639_2, audio_lang ) == 0 )
1065             {
1066                 /*
1067                  * Matched subtitle language with audio language, so
1068                  * add this to our list to scan.
1069                  *
1070                  * We will update the subtitle list on the second pass
1071                  * later after the first pass has completed.
1072                  */
1073                 subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1074                 memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1075                 hb_list_add( title_copy->list_subtitle, subtitle_copy );
1076                 if ( job->native_language ) {
1077                     /*
1078                      * With native language just select the
1079                      * first match in our langiage, not all of
1080                      * them. Subsequent ones are likely to be commentary
1081                      */
1082                     break;
1083                 }
1084             }
1085         }
1086     } else {
1087         /*
1088          * Not doing a subtitle scan in this pass, but maybe we are in the
1089          * first pass?
1090          */
1091         if( job->select_subtitle )
1092         {
1093             /*
1094              * Don't add subtitles here, we'll add them via select_subtitle
1095              * at the end of the subtitle_scan.
1096              */
1097         } else {
1098             /*
1099              * Definitely not doing a subtitle scan.
1100              */
1101             if( job->pass != 1 && job->native_language )
1102             {
1103                 /*
1104                  * We are not doing a subtitle scan but do want the
1105                  * native langauge subtitle selected, so select it
1106                  * for pass 0 or pass 2 of a two pass.
1107                  */
1108                 for( i=0; i < hb_list_count( title->list_subtitle ); i++ )
1109                 {
1110                     subtitle = hb_list_item( title->list_subtitle, i );
1111                     if( strcmp( subtitle->iso639_2, audio_lang ) == 0 )
1112                     {
1113                         /*
1114                          * Matched subtitle language with audio language, so
1115                          * add this to our list to scan.
1116                          */
1117                         subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1118                         memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1119                         hb_list_add( title_copy->list_subtitle, subtitle_copy );
1120                         break;
1121                     }
1122                 }
1123             } else {
1124                 /*
1125                  * Manually selected subtitle, in which case only
1126                  * bother adding them for pass 0 or pass 2 of a two
1127                  * pass.
1128                  */
1129                 if( job->pass != 1 )
1130                 {
1131                     if( ( subtitle = hb_list_item( title->list_subtitle, job->subtitle ) ) )
1132                     {
1133                         subtitle_copy = malloc( sizeof( hb_subtitle_t ) );
1134                         memcpy( subtitle_copy, subtitle, sizeof( hb_subtitle_t ) );
1135                         hb_list_add( title_copy->list_subtitle, subtitle_copy );
1136                     }
1137                 }
1138             }
1139         }
1140     }
1141
1142     /* Copy the job */
1143     job_copy        = calloc( sizeof( hb_job_t ), 1 );
1144     memcpy( job_copy, job, sizeof( hb_job_t ) );
1145     title_copy->job = job_copy;
1146     job_copy->title = title_copy;
1147     job_copy->list_audio = title_copy->list_audio;
1148     job_copy->file  = strdup( job->file );
1149     job_copy->h     = h;
1150     job_copy->pause = h->pause_lock;
1151
1152     /* Copy the job filter list */
1153     if( job->filters )
1154     {
1155         int i;
1156         int filter_count = hb_list_count( job->filters );
1157         job_copy->filters = hb_list_init();
1158         for( i = 0; i < filter_count; i++ )
1159         {
1160             /*
1161              * Copy the filters, since the MacGui reuses the global filter objects
1162              * meaning that queued up jobs overwrite the previous filter settings.
1163              * In reality, settings is probably the only field that needs duplicating
1164              * since it's the only value that is ever changed. But name is duplicated
1165              * as well for completeness. Not copying private_data since it gets
1166              * created for each job in renderInit.
1167              */
1168             hb_filter_object_t * filter = hb_list_item( job->filters, i );
1169             hb_filter_object_t * filter_copy = malloc( sizeof( hb_filter_object_t ) );
1170             memcpy( filter_copy, filter, sizeof( hb_filter_object_t ) );
1171             if( filter->name )
1172                 filter_copy->name = strdup( filter->name );
1173             if( filter->settings )
1174                 filter_copy->settings = strdup( filter->settings );
1175             hb_list_add( job_copy->filters, filter_copy );
1176         }
1177     }
1178
1179     /* Add the job to the list */
1180     hb_list_add( h->jobs, job_copy );
1181     h->job_count = hb_count(h);
1182     h->job_count_permanent++;
1183 }
1184
1185 /**
1186  * Removes a job from the job list.
1187  * @param h Handle to hb_handle_t.
1188  * @param job Handle to hb_job_t.
1189  */
1190 void hb_rem( hb_handle_t * h, hb_job_t * job )
1191 {
1192     hb_list_rem( h->jobs, job );
1193
1194     h->job_count = hb_count(h);
1195     if (h->job_count_permanent)
1196         h->job_count_permanent--;
1197
1198     /* XXX free everything XXX */
1199 }
1200
1201 /**
1202  * Starts the conversion process.
1203  * Sets state to HB_STATE_WORKING.
1204  * calls hb_work_init, to launch work thread. Stores handle to work thread.
1205  * @param h Handle to hb_handle_t.
1206  */
1207 void hb_start( hb_handle_t * h )
1208 {
1209     /* XXX Hack */
1210     h->job_count = hb_list_count( h->jobs );
1211     h->job_count_permanent = h->job_count;
1212
1213     hb_lock( h->state_lock );
1214     h->state.state = HB_STATE_WORKING;
1215 #define p h->state.param.working
1216     p.progress  = 0.0;
1217     p.job_cur   = 1;
1218     p.job_count = h->job_count;
1219     p.rate_cur  = 0.0;
1220     p.rate_avg  = 0.0;
1221     p.hours     = -1;
1222     p.minutes   = -1;
1223     p.seconds   = -1;
1224     p.sequence_id = 0;
1225 #undef p
1226     hb_unlock( h->state_lock );
1227
1228     h->paused = 0;
1229
1230     h->work_die    = 0;
1231     h->work_thread = hb_work_init( h->jobs, h->cpu_count,
1232                                    &h->work_die, &h->work_error, &h->current_job );
1233 }
1234
1235 /**
1236  * Pauses the conversion process.
1237  * @param h Handle to hb_handle_t.
1238  */
1239 void hb_pause( hb_handle_t * h )
1240 {
1241     if( !h->paused )
1242     {
1243         hb_lock( h->pause_lock );
1244         h->paused = 1;
1245
1246         hb_lock( h->state_lock );
1247         h->state.state = HB_STATE_PAUSED;
1248         hb_unlock( h->state_lock );
1249     }
1250 }
1251
1252 /**
1253  * Resumes the conversion process.
1254  * @param h Handle to hb_handle_t.
1255  */
1256 void hb_resume( hb_handle_t * h )
1257 {
1258     if( h->paused )
1259     {
1260         hb_unlock( h->pause_lock );
1261         h->paused = 0;
1262     }
1263 }
1264
1265 /**
1266  * Stops the conversion process.
1267  * @param h Handle to hb_handle_t.
1268  */
1269 void hb_stop( hb_handle_t * h )
1270 {
1271     h->work_die = 1;
1272
1273     h->job_count = hb_count(h);
1274     h->job_count_permanent = 0;
1275
1276     hb_resume( h );
1277 }
1278
1279 /**
1280  * Returns the state of the conversion process.
1281  * @param h Handle to hb_handle_t.
1282  * @param s Handle to hb_state_t which to copy the state data.
1283  */
1284 void hb_get_state( hb_handle_t * h, hb_state_t * s )
1285 {
1286     hb_lock( h->state_lock );
1287
1288     memcpy( s, &h->state, sizeof( hb_state_t ) );
1289     if ( h->state.state == HB_STATE_SCANDONE || h->state.state == HB_STATE_WORKDONE )
1290         h->state.state = HB_STATE_IDLE;
1291
1292     hb_unlock( h->state_lock );
1293 }
1294
1295 void hb_get_state2( hb_handle_t * h, hb_state_t * s )
1296 {
1297     hb_lock( h->state_lock );
1298
1299     memcpy( s, &h->state, sizeof( hb_state_t ) );
1300
1301     hb_unlock( h->state_lock );
1302 }
1303
1304 /**
1305  * Called in MacGui in UpdateUI to check
1306  *  for a new scan being completed to set a new source
1307  */
1308 int hb_get_scancount( hb_handle_t * h)
1309  {
1310      return h->scanCount;
1311  }
1312
1313 /**
1314  * Closes access to libhb by freeing the hb_handle_t handle ontained in hb_init_real.
1315  * @param _h Pointer to handle to hb_handle_t.
1316  */
1317 void hb_close( hb_handle_t ** _h )
1318 {
1319     hb_handle_t * h = *_h;
1320     hb_title_t * title;
1321
1322     h->die = 1;
1323     hb_thread_close( &h->main_thread );
1324
1325     while( ( title = hb_list_item( h->list_title, 0 ) ) )
1326     {
1327         hb_list_rem( h->list_title, title );
1328         if( title->job && title->job->filters )
1329         {
1330             hb_list_close( &title->job->filters );
1331         }
1332         free( title->job );
1333         hb_title_close( &title );
1334     }
1335     hb_list_close( &h->list_title );
1336
1337     hb_list_close( &h->jobs );
1338     hb_lock_close( &h->state_lock );
1339     hb_lock_close( &h->pause_lock );
1340     free( h );
1341     *_h = NULL;
1342
1343 }
1344
1345 /**
1346  * Monitors the state of the update, scan, and work threads.
1347  * Sets scan done state when scan thread exits.
1348  * Sets work done state when work thread exits.
1349  * @param _h Handle to hb_handle_t
1350  */
1351 static void thread_func( void * _h )
1352 {
1353     hb_handle_t * h = (hb_handle_t *) _h;
1354     char dirname[1024];
1355     DIR * dir;
1356     struct dirent * entry;
1357
1358     h->pid = getpid();
1359
1360     /* Create folder for temporary files */
1361     memset( dirname, 0, 1024 );
1362     hb_get_tempory_directory( h, dirname );
1363
1364     hb_mkdir( dirname );
1365
1366     while( !h->die )
1367     {
1368         /* In case the check_update thread hangs, it'll die sooner or
1369            later. Then, we join it here */
1370         if( h->update_thread &&
1371             hb_thread_has_exited( h->update_thread ) )
1372         {
1373             hb_thread_close( &h->update_thread );
1374         }
1375
1376         /* Check if the scan thread is done */
1377         if( h->scan_thread &&
1378             hb_thread_has_exited( h->scan_thread ) )
1379         {
1380             hb_thread_close( &h->scan_thread );
1381
1382             hb_log( "libhb: scan thread found %d valid title(s)",
1383                     hb_list_count( h->list_title ) );
1384             hb_lock( h->state_lock );
1385             h->state.state = HB_STATE_SCANDONE; //originally state.state
1386                         hb_unlock( h->state_lock );
1387                         /*we increment this sessions scan count by one for the MacGui
1388                         to trigger a new source being set */
1389             h->scanCount++;
1390         }
1391
1392         /* Check if the work thread is done */
1393         if( h->work_thread &&
1394             hb_thread_has_exited( h->work_thread ) )
1395         {
1396             hb_thread_close( &h->work_thread );
1397
1398             hb_log( "libhb: work result = %d",
1399                     h->work_error );
1400             hb_lock( h->state_lock );
1401             h->state.state                = HB_STATE_WORKDONE;
1402             h->state.param.workdone.error = h->work_error;
1403
1404             h->job_count = hb_count(h);
1405             if (h->job_count < 1)
1406                 h->job_count_permanent = 0;
1407             hb_unlock( h->state_lock );
1408         }
1409
1410         hb_snooze( 50 );
1411     }
1412
1413     if( h->work_thread )
1414     {
1415         hb_stop( h );
1416         hb_thread_close( &h->work_thread );
1417     }
1418
1419     /* Remove temp folder */
1420     dir = opendir( dirname );
1421     if (dir)
1422     {
1423         while( ( entry = readdir( dir ) ) )
1424         {
1425             char filename[1024];
1426             if( entry->d_name[0] == '.' )
1427             {
1428                 continue;
1429             }
1430             memset( filename, 0, 1024 );
1431             snprintf( filename, 1023, "%s/%s", dirname, entry->d_name );
1432             unlink( filename );
1433         }
1434         closedir( dir );
1435         rmdir( dirname );
1436     }
1437 }
1438
1439 /**
1440  * Returns the PID.
1441  * @param h Handle to hb_handle_t
1442  */
1443 int hb_get_pid( hb_handle_t * h )
1444 {
1445     return h->pid;
1446 }
1447
1448 /**
1449  * Sets the current state.
1450  * @param h Handle to hb_handle_t
1451  * @param s Handle to new hb_state_t
1452  */
1453 void hb_set_state( hb_handle_t * h, hb_state_t * s )
1454 {
1455     hb_lock( h->pause_lock );
1456     hb_lock( h->state_lock );
1457     memcpy( &h->state, s, sizeof( hb_state_t ) );
1458     if( h->state.state == HB_STATE_WORKING )
1459     {
1460         /* XXX Hack */
1461         if (h->job_count < 1)
1462             h->job_count_permanent = 1;
1463
1464         h->state.param.working.job_cur =
1465             h->job_count_permanent - hb_list_count( h->jobs );
1466         h->state.param.working.job_count = h->job_count_permanent;
1467
1468         // Set which job is being worked on
1469         if (h->current_job)
1470             h->state.param.working.sequence_id = h->current_job->sequence_id;
1471         else
1472             h->state.param.working.sequence_id = 0;
1473     }
1474     hb_unlock( h->state_lock );
1475     hb_unlock( h->pause_lock );
1476 }