Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add preference for keeping duplicate blu ray titles #5985

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

samhutchins
Copy link
Contributor

@samhutchins samhutchins commented Apr 21, 2024

Description of Change:

Currently HandBrake filters out duplicate titles when opening a Blu Ray, which has a couple of issues for more advanced usage:

  1. The order that libbluray discovers titles seems to depend on something outside of HandBrake. For a particular source I have, title indexes change depending on if I open the source from an internal drive or an external drive, which means I can't reliably open a specific title by index. Keeping duplicate titles makes the indexes consistent.
  2. Filtering out duplicate titles can make it impossible to locate a specific playlist (.mpls) in HandBrake.

I've had a crack at implementing this for all the user interfaces, but I'm far from an expert in any of them. I'm keen to learn though :-)

CLI: --keep-duplicate-titles
Mac: Settings -> Advanced
Linux: Preferences -> General
Windows: Preferences -> Advanced

I've tried to put the new setting near the "min duration" config in all cases.

I've also deleted a method in the Linux GUI in hb-backend.c: ghb_backend_queue_scan. I couldn't find anywhere this method was actually called, so I just removed it

Tested on:

  • Windows 10+ (via MinGW)
  • macOS 10.13+
  • Debian Linux

@sr55 sr55 requested a review from jstebbins April 21, 2024 18:37
@jstebbins
Copy link
Contributor

jstebbins commented Apr 21, 2024

This patch is rather invasive due to the number of function APIs that it touches. So I would like to make a suggestion.

@sr55 @galad87 what would you think of adding keep_duplicate_titles variable to hb_handle_t and adding a function hb_keep_duplicate_titles(hb_handle_t * h, int enable) to hb.c to set this value. hb_bd_init() can then just pull the value out of hb_handle_t without requiring an API change. This patch would just need to ensure that the value gets set for each hb_handle_t the frontend uses.

This would eliminate almost all the changes to libhb in this patch. And it simplifies the frontends some as well. I.e. the LinGui creates all the handles it uses on startup. The value can be changed in the handle immediately when the preference option changes.

@samhutchins
Copy link
Contributor Author

That seems like it would be much neater

@jstebbins
Copy link
Contributor

The order that libbluray discovers titles seems to depend on something outside of HandBrake. For a particular source I have, title indexes change depending on if I open the source from an internal drive or an external drive, which means I can't reliably open a specific title by index. Keeping duplicate titles makes the indexes consistent.

This is very strange. I'm wondering if different drives can result in reading directory entries in a different order. This is the only mechanism by which I can see the lists being different. The playlist is processed in the order that they are read from the PLAYLIST directory.

@jstebbins
Copy link
Contributor

jstebbins commented Apr 21, 2024

If I'm correct about the order of reading playlists differing depending on drive, then filtering titles with duplicate clips will result in similar problems.

Edit: Oh, I take that back. Titles with duplicate clips will all be filtered. There's no dependency on which it sees first because it is not comparing to another title.

@galad87
Copy link
Contributor

galad87 commented Apr 21, 2024

I'm not sure which way would be better, it's something that will be used only in hb_scan(), so having some hb_handle options and some doesn't look ideal, but then again hb_scan has got so many parameters, and the dvdnav option is already a hb_handle option.

What happens if a job with one of those duplicate titles is added to the queue, then the duplicated option is disabled and the queue started? Will the queue scan find the title?

@samhutchins
Copy link
Contributor Author

This is very strange. I'm wondering if different drives can result in reading directory entries in a different order. This is the only mechanism by which I can see the lists being different. The playlist is processed in the order that they are read from the PLAYLIST directory.

Agreed. The 2 drives are a different filesystems (exFAT vs EXT4), which may be the key difference. Very reproducible for me though (and super annoying)

@samhutchins
Copy link
Contributor Author

I'm not sure which way would be better, it's something that will be used only in hb_scan(), so having some hb_handle options and some doesn't look ideal, but then again hb_scan has got so many parameters, and the dvdnav option is already a hb_handle option.

What happens if a job with one of those duplicate titles is added to the queue, then the duplicated option is disabled and the queue started? Will the queue scan find the title?

It's used in the scan and by the reader for the job (which is part of what makes it a far-reaching change), so the keep_duplicate_titles bool is in the job struct/dict as well.

I'm not sure what happens in the situation you've described on all platforms, I'll do further testing

@jstebbins
Copy link
Contributor

it's something that will be used only in hb_scan()

I wish that were the case. But when we open a particular title to encode, the index must match what was previously scanned. So the setting must be the same for both scan and encode.

@samhutchins
Copy link
Contributor Author

What happens if a job with one of those duplicate titles is added to the queue, then the duplicated option is disabled and the queue started? Will the queue scan find the title?

If I changed it to the approach suggested by @jstebbins, I think it wouldn't work in any UI

With the patch as I currently have it:

Case 1: Open title, add to queue, change setting, start queue
Case 2: Open title, change setting, add to queue/start

Linux

  1. works (the linux GUI stamps the config option into the job when it's added to the queue)
  2. doesn't work (it tries to encode a different title because the title indexes changed between scan and encode)

Windows

Both cases don't work

Mac

Both cases don't work

I'm not immediately sure how to deal with that, I guess each GUI would need some piece of state that remembers what the setting was at the moment the title was initially scanned.

A simpler solution, if you're willing to forgo configurability, would be not do anything I've done with this patch and just change TITLES_RELEVANT to TITLES_FILTER_DUP_CLIP in bd.c ;-)

@samhutchins
Copy link
Contributor Author

I was just thinking about why the same problem doesn't exist for the minimum title length setting, but I think that's because the filtering of titles based on length is done by HandBrake rather than libbluray. Would it be possible to have libbluray always give HandBrake all the titles, then do the removal (or not) of duplicate titles within HandBrake? I think this would make the indexes stable regardless of that setting, but I'm not sure how to go about detecting duplicate titles after the call to bd_get_titles

@jstebbins
Copy link
Contributor

jstebbins commented Apr 21, 2024

Hmm, there is a twist when you consider allowing changing the value between scans and between scanning and encoding. Glad we are hashing this out. There's some interesting corner cases.

We will need to record what value was used during scan in the hb_title_t because the same setting must be used when scanning the title again prior to encoding. When creating the job, we will need to copy that value from the title to the job.

Summary:

  • either add a flag to hb_handle_t and set this value in the scan handle whenever the preference changes. Or modify a number of APIs to pass this flag down through an hb_scan() parameter. I'm not too concerned about which.
  • In hb_bd_title_scan() record the flag in hb_title_t.
  • Update hb_title_to_dict_internal() to encode the flag to a title dict
  • Update hb_job_to_dict() and hb_dict_to_job() to add the flag to the Source part of that dict
  • Modify the Win UI to recognize the new flag in titles and jobs
  • Modify hb_preset_job_init() to copy the flag from the title to the job
  • Modify Win UI to copy the flag from the title to the job
  • Modify hb_json_job_scan() to read the flag from the job and use it

Edit: I should mention hb_preset_job_init() is only used by mac and linux UI. This is why there is extra work in the Win UI to copy the flag. It would simplify things if the Win UI used hb_preset_job_init_json() (hint, hint @sr55 😜 )

@jstebbins
Copy link
Contributor

I'm not sure how to go about detecting duplicate titles after the call to bd_get_titles

The information necessary is not available. The function that does this in libblueray basically parses the entire playlist structure and checks that they are completely identical in every detail.

@samhutchins
Copy link
Contributor Author

The information necessary is not available. The function that does this in libblueray basically parses the entire playlist structure and checks that they are completely identical in every detail.

Shame. Oh well

I'll have a look at what you've suggested in the next couple of days, thanks!

@sr55
Copy link
Contributor

sr55 commented Apr 22, 2024

@jstebbins The WinUI is pretty decoupled from libhb these days, by design. It's pretty much POCO + JSON for most of the work so it's been susceptible to scan -> encode setting changes for years. Don't really see it as much of an issue to be honest. I just throw a "Requires Restart" label after anything that it applies to.

I also don't use much of the libhb preset system. Only fetch / upgrade the JSON and handle everything else natively. It's a little extra work but it's cleaner from a code perspective.

If you need help with the WinUI changes, just let me know and I'm happy to do them. Just let me know what's needed.

@jstebbins
Copy link
Contributor

@sr55 does the Win UI represent presets or jobs with significantly different json than libhb? Because hb_preset_job_init_json() is pretty straight forward. Just seems like it would save you quite a lot of synchronization work.

@sr55
Copy link
Contributor

sr55 commented Apr 23, 2024

Presets is standard JSON but is converted to an internal representation which isn't the same.

I've never used the job model. The UI has it's own modelling which again gets converted to the JSON.

It's not a lot of code to convert back/forth really so was never worth changing and it allows me to extend the model for some UI specific stuff.

It would be major work to try change it at this point.

@samhutchins
Copy link
Contributor Author

I got the Linux GUI working with the suggested changes, you can change that setting all you like after the initial scan, and it still works just fine. You can even add to the queue, change the setting, then restart the application and the queued item still does what it should.

I'm struggling with the Mac GUI though, I was expecting it to work similarly to the linux ui.

Here's my WIP, on top of 7be4117, just removing the changes I made to make the GUI override keep_duplicate_titles in the job. I was expecting that this would mean the job inherits the keep_duplicate_titles setting from the title, but it doesn't. I don't (yet) understand the data flow in the Mac gui well enough to understand why this isn't enough. I added some logging in job_setup, and I can see that gets called a number of times after I click "start". It's only the last call to it that has the wrong value for keep_duplicate_titles in the title, and I'm not sure where it got it from. I'll keep noodling as I have time

diff --git a/macosx/HBJob+HBJobConversion.m b/macosx/HBJob+HBJobConversion.m
index d6ee08699..8d6d52718 100644
--- a/macosx/HBJob+HBJobConversion.m
+++ b/macosx/HBJob+HBJobConversion.m
@@ -58,8 +58,6 @@ - (hb_job_t *)hb_job
     {
         job->hw_decode = HB_DECODE_SUPPORT_VIDEOTOOLBOX | HB_DECODE_SUPPORT_FORCE_HW;
     }
-    
-    job->keep_duplicate_titles = self.keepDuplicateTitles;
 
     // Title Angle for dvdnav
     job->angle = self.angle;
diff --git a/macosx/HBJob.h b/macosx/HBJob.h
index 03bb5c69f..e44c65525 100644
--- a/macosx/HBJob.h
+++ b/macosx/HBJob.h
@@ -80,7 +80,6 @@ typedef NS_ENUM(NSUInteger, HBJobHardwareDecoderUsage) {
 
 @property (nonatomic, readwrite) BOOL metadataPassthru;
 @property (nonatomic, readwrite) HBJobHardwareDecoderUsage hwDecodeUsage;
-@property (nonatomic, readwrite) BOOL keepDuplicateTitles;
 
 @property (nonatomic, readwrite, weak, nullable) NSUndoManager *undo;
 
diff --git a/macosx/HBJob.m b/macosx/HBJob.m
index 35cb99205..39ea40f3e 100644
--- a/macosx/HBJob.m
+++ b/macosx/HBJob.m
@@ -425,7 +425,6 @@ - (instancetype)copyWithZone:(NSZone *)zone
 
         copy->_metadataPassthru = _metadataPassthru;
         copy->_hwDecodeUsage = _hwDecodeUsage;
-        copy->_keepDuplicateTitles = _keepDuplicateTitles;
     }
 
     return copy;
@@ -491,7 +490,6 @@ - (void)encodeWithCoder:(NSCoder *)coder
 
     encodeBool(_metadataPassthru);
     encodeInteger(_hwDecodeUsage);
-    encodeBool(_keepDuplicateTitles);
 }
 
 - (instancetype)initWithCoder:(NSCoder *)decoder
@@ -537,7 +535,6 @@ - (instancetype)initWithCoder:(NSCoder *)decoder
 
         decodeBool(_metadataPassthru);
         decodeInteger(_hwDecodeUsage); if (_hwDecodeUsage != HBJobHardwareDecoderUsageNone && _hwDecodeUsage != HBJobHardwareDecoderUsageAlways && _hwDecodeUsage != HBJobHardwareDecoderUsageFullPathOnly) { goto fail; }
-        decodeBool(_keepDuplicateTitles);
 
         return self;
     }
diff --git a/macosx/HBPreviewGenerator.m b/macosx/HBPreviewGenerator.m
index a161e908f..5d8bbd8b7 100644
--- a/macosx/HBPreviewGenerator.m
+++ b/macosx/HBPreviewGenerator.m
@@ -273,8 +273,6 @@ - (BOOL) createMovieAsyncWithImageAtIndex: (NSUInteger) index duration: (NSUInte
     {
         job.hwDecodeUsage = HBJobHardwareDecoderUsageNone;
     }
-    
-    job.keepDuplicateTitles = [NSUserDefaults.standardUserDefaults boolForKey:HBKeepDuplicateTitles];
 
     // Init the libhb core
     NSInteger level = [NSUserDefaults.standardUserDefaults integerForKey:HBLoggingLevel];
diff --git a/macosx/HBQueueWorker.m b/macosx/HBQueueWorker.m
index e557ced99..fc9cb7364 100644
--- a/macosx/HBQueueWorker.m
+++ b/macosx/HBQueueWorker.m
@@ -224,8 +224,6 @@ - (void)realEncodeItem:(HBQueueJobItem *)item
     {
         job.hwDecodeUsage = HBJobHardwareDecoderUsageNone;
     }
-    
-    job.keepDuplicateTitles = [NSUserDefaults.standardUserDefaults boolForKey:HBKeepDuplicateTitles];
 
     // Progress handler
     void (^progressHandler)(HBState state, HBProgress progress, NSString *info) = ^(HBState state, HBProgress progress, NSString *info)

@galad87
Copy link
Contributor

galad87 commented Apr 25, 2024

The Mac UI doesn't use the json API, so it's a bit different. However you were missing only one thing: reading the title keep_duplicate_titles and setting it in the job:

diff --git a/macosx/HBJob+HBJobConversion.m b/macosx/HBJob+HBJobConversion.m
index d6ee08699..8d6d52718 100644
--- a/macosx/HBJob+HBJobConversion.m
+++ b/macosx/HBJob+HBJobConversion.m
@@ -58,8 +58,6 @@ - (hb_job_t *)hb_job
     {
         job->hw_decode = HB_DECODE_SUPPORT_VIDEOTOOLBOX | HB_DECODE_SUPPORT_FORCE_HW;
     }
-    
-    job->keep_duplicate_titles = self.keepDuplicateTitles;
 
     // Title Angle for dvdnav
     job->angle = self.angle;
diff --git a/macosx/HBJob.m b/macosx/HBJob.m
index 35cb99205..9707f91df 100644
--- a/macosx/HBJob.m
+++ b/macosx/HBJob.m
@@ -52,6 +52,8 @@ - (nullable instancetype)initWithTitle:(HBTitle *)title preset:(HBPreset *)prese
         NSParameterAssert(title);
         NSParameterAssert(preset);
 
+        _keepDuplicateTitles = title.keepDuplicateTitles;
+
         _title = title;
         _titleIdx = title.index;
         _stream = title.isStream;
diff --git a/macosx/HBPreviewGenerator.m b/macosx/HBPreviewGenerator.m
index a161e908f..5d8bbd8b7 100644
--- a/macosx/HBPreviewGenerator.m
+++ b/macosx/HBPreviewGenerator.m
@@ -273,8 +273,6 @@ - (BOOL) createMovieAsyncWithImageAtIndex: (NSUInteger) index duration: (NSUInte
     {
         job.hwDecodeUsage = HBJobHardwareDecoderUsageNone;
     }
-    
-    job.keepDuplicateTitles = [NSUserDefaults.standardUserDefaults boolForKey:HBKeepDuplicateTitles];
 
     // Init the libhb core
     NSInteger level = [NSUserDefaults.standardUserDefaults integerForKey:HBLoggingLevel];
diff --git a/macosx/HBQueueWorker.m b/macosx/HBQueueWorker.m
index e557ced99..68c37d0d9 100644
--- a/macosx/HBQueueWorker.m
+++ b/macosx/HBQueueWorker.m
@@ -199,7 +199,7 @@ - (void)encodeItem:(HBQueueJobItem *)item
            minDuration:0
           keepPreviews:NO
        hardwareDecoder:[NSUserDefaults.standardUserDefaults boolForKey:HBUseHardwareDecoder]
-       keepDuplicateTitles:[NSUserDefaults.standardUserDefaults boolForKey:HBKeepDuplicateTitles]
+       keepDuplicateTitles:item.job.keepDuplicateTitles
        progressHandler:progressHandler
      completionHandler:completionHandler];
 }
@@ -224,8 +224,6 @@ - (void)realEncodeItem:(HBQueueJobItem *)item
     {
         job.hwDecodeUsage = HBJobHardwareDecoderUsageNone;
     }
-    
-    job.keepDuplicateTitles = [NSUserDefaults.standardUserDefaults boolForKey:HBKeepDuplicateTitles];
 
     // Progress handler
     void (^progressHandler)(HBState state, HBProgress progress, NSString *info) = ^(HBState state, HBProgress progress, NSString *info)
diff --git a/macosx/HBTitle.h b/macosx/HBTitle.h
index 46c71f71f..3227b43dc 100644
--- a/macosx/HBTitle.h
+++ b/macosx/HBTitle.h
@@ -70,6 +70,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, readonly) NSURL *url;
 
+@property (nonatomic, readonly) BOOL keepDuplicateTitles;
+
 @property (nonatomic, readonly) int index;
 @property (nonatomic, readonly) int angles;
 @property (nonatomic, readonly) int duration;
diff --git a/macosx/HBTitle.m b/macosx/HBTitle.m
index c41a8de54..daa4262b5 100644
--- a/macosx/HBTitle.m
+++ b/macosx/HBTitle.m
@@ -424,6 +424,11 @@ - (NSURL *)url
     return [NSURL fileURLWithPath:@(_hb_title->path)];
 }
 
+- (BOOL)keepDuplicateTitles
+{
+    return self.hb_title->keep_duplicate_titles;
+}
+
 - (int)index
 {
     return self.hb_title->index;

@jstebbins
Copy link
Contributor

@galad87 mac UI appears to call hb_preset_job_init() which would copy keep_duplicate_titles from the title to the job it creates. Is the flag getting lost somewhere after this happens?

@jstebbins
Copy link
Contributor

@samhutchins Linux and libhb changes look good to me on an initial reading. I'll read everything through a second time once the rest is working 😄

@galad87
Copy link
Contributor

galad87 commented Apr 25, 2024

Only parts of the result of hb_preset_job_init() are copied back to the objective-c HBJob instance. Yes we could copy keep_duplicate_titles from that too, it would save only 4 or 5 lines of code.

@galad87
Copy link
Contributor

galad87 commented Apr 25, 2024

When reloading a job from the queue it needs to use the keepDuplicateTitles value from the job, instead of the one from the preferences, here's the updated changes for the Mac GUI:

diff --git a/macosx/HBController.m b/macosx/HBController.m
index f92a96161..2211f6dfa 100644
--- a/macosx/HBController.m
+++ b/macosx/HBController.m
@@ -648,7 +648,7 @@ - (NSModalResponse)runCopyProtectionAlert
 /**
  * Here we actually tell hb_scan to perform the source scan, using the path to source and title number
  */
-- (void)scanURLs:(NSArray<NSURL *> *)fileURLs titleIndex:(NSUInteger)index completionHandler:(void(^)(NSArray<HBTitle *> *titles))completionHandler
+- (void)scanURLs:(NSArray<NSURL *> *)fileURLs titleIndex:(NSUInteger)index keepDuplicateTitles:(BOOL)keepDuplicateTitles completionHandler:(void(^)(NSArray<HBTitle *> *titles))completionHandler
 {
     [self showWindow:self];
 
@@ -682,13 +682,14 @@ - (void)scanURLs:(NSArray<NSURL *> *)fileURLs titleIndex:(NSUInteger)index compl
     {
         NSUInteger hb_num_previews = [NSUserDefaults.standardUserDefaults integerForKey:HBPreviewsNumber];
         NSUInteger min_title_duration_seconds = [NSUserDefaults.standardUserDefaults integerForKey:HBMinTitleScanSeconds];
+        BOOL hardwareDecoder = [NSUserDefaults.standardUserDefaults boolForKey:HBUseHardwareDecoder];
 
         [self.core scanURLs:fileURLs
                  titleIndex:index
                    previews:hb_num_previews minDuration:min_title_duration_seconds
                keepPreviews:YES
-            hardwareDecoder:[NSUserDefaults.standardUserDefaults boolForKey:HBUseHardwareDecoder]
-            keepDuplicateTitles:[NSUserDefaults.standardUserDefaults boolForKey:HBKeepDuplicateTitles]
+            hardwareDecoder:hardwareDecoder
+            keepDuplicateTitles:keepDuplicateTitles
             progressHandler:^(HBState state, HBProgress progress, NSString *info)
          {
              self.sourceLabel.stringValue = info;
@@ -810,7 +811,7 @@ - (void)openURLs:(NSArray<NSURL *> *)fileURLs recursive:(BOOL)recursive titleInd
     NSArray<NSURL *> *subtitlesFileURLs = [HBUtilities extractURLs:expandedFileURLs withExtension:HBUtilities.supportedExtensions];
     NSArray<NSURL *> *trimmedFileURLs   = [HBUtilities trimURLs:expandedFileURLs withExtension:excludedExtensions];
 
-    [self scanURLs:trimmedFileURLs titleIndex:index completionHandler:^(NSArray<HBTitle *> *titles)
+    [self scanURLs:trimmedFileURLs titleIndex:index keepDuplicateTitles:[NSUserDefaults.standardUserDefaults boolForKey:HBKeepDuplicateTitles] completionHandler:^(NSArray<HBTitle *> *titles)
     {
         NSArray<NSURL *> *baseURLs = [HBUtilities baseURLs:trimmedFileURLs];
 
@@ -872,7 +873,7 @@ - (void)openJob:(HBJob *)job completionHandler:(void (^)(BOOL result))handler
         [job refreshSecurityScopedResources];
         self.fileTokens = @[[HBSecurityAccessToken tokenWithObject:job.fileURL]];
 
-        [self scanURLs:@[job.fileURL] titleIndex:job.titleIdx completionHandler:^(NSArray<HBTitle *> *titles)
+        [self scanURLs:@[job.fileURL] titleIndex:job.titleIdx keepDuplicateTitles:job.keepDuplicateTitles completionHandler:^(NSArray<HBTitle *> *titles)
         {
             if (titles.count)
             {
diff --git a/macosx/HBJob+HBJobConversion.m b/macosx/HBJob+HBJobConversion.m
index d6ee08699..8d6d52718 100644
--- a/macosx/HBJob+HBJobConversion.m
+++ b/macosx/HBJob+HBJobConversion.m
@@ -58,8 +58,6 @@ - (hb_job_t *)hb_job
     {
         job->hw_decode = HB_DECODE_SUPPORT_VIDEOTOOLBOX | HB_DECODE_SUPPORT_FORCE_HW;
     }
-    
-    job->keep_duplicate_titles = self.keepDuplicateTitles;
 
     // Title Angle for dvdnav
     job->angle = self.angle;
diff --git a/macosx/HBJob.m b/macosx/HBJob.m
index 35cb99205..9707f91df 100644
--- a/macosx/HBJob.m
+++ b/macosx/HBJob.m
@@ -52,6 +52,8 @@ - (nullable instancetype)initWithTitle:(HBTitle *)title preset:(HBPreset *)prese
         NSParameterAssert(title);
         NSParameterAssert(preset);
 
+        _keepDuplicateTitles = title.keepDuplicateTitles;
+
         _title = title;
         _titleIdx = title.index;
         _stream = title.isStream;
diff --git a/macosx/HBPreviewGenerator.m b/macosx/HBPreviewGenerator.m
index a161e908f..5d8bbd8b7 100644
--- a/macosx/HBPreviewGenerator.m
+++ b/macosx/HBPreviewGenerator.m
@@ -273,8 +273,6 @@ - (BOOL) createMovieAsyncWithImageAtIndex: (NSUInteger) index duration: (NSUInte
     {
         job.hwDecodeUsage = HBJobHardwareDecoderUsageNone;
     }
-    
-    job.keepDuplicateTitles = [NSUserDefaults.standardUserDefaults boolForKey:HBKeepDuplicateTitles];
 
     // Init the libhb core
     NSInteger level = [NSUserDefaults.standardUserDefaults integerForKey:HBLoggingLevel];
diff --git a/macosx/HBQueueWorker.m b/macosx/HBQueueWorker.m
index e557ced99..68c37d0d9 100644
--- a/macosx/HBQueueWorker.m
+++ b/macosx/HBQueueWorker.m
@@ -199,7 +199,7 @@ - (void)encodeItem:(HBQueueJobItem *)item
            minDuration:0
           keepPreviews:NO
        hardwareDecoder:[NSUserDefaults.standardUserDefaults boolForKey:HBUseHardwareDecoder]
-       keepDuplicateTitles:[NSUserDefaults.standardUserDefaults boolForKey:HBKeepDuplicateTitles]
+       keepDuplicateTitles:item.job.keepDuplicateTitles
        progressHandler:progressHandler
      completionHandler:completionHandler];
 }
@@ -224,8 +224,6 @@ - (void)realEncodeItem:(HBQueueJobItem *)item
     {
         job.hwDecodeUsage = HBJobHardwareDecoderUsageNone;
     }
-    
-    job.keepDuplicateTitles = [NSUserDefaults.standardUserDefaults boolForKey:HBKeepDuplicateTitles];
 
     // Progress handler
     void (^progressHandler)(HBState state, HBProgress progress, NSString *info) = ^(HBState state, HBProgress progress, NSString *info)
diff --git a/macosx/HBTitle.h b/macosx/HBTitle.h
index 46c71f71f..3227b43dc 100644
--- a/macosx/HBTitle.h
+++ b/macosx/HBTitle.h
@@ -70,6 +70,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @property (nonatomic, readonly) NSURL *url;
 
+@property (nonatomic, readonly) BOOL keepDuplicateTitles;
+
 @property (nonatomic, readonly) int index;
 @property (nonatomic, readonly) int angles;
 @property (nonatomic, readonly) int duration;
diff --git a/macosx/HBTitle.m b/macosx/HBTitle.m
index c41a8de54..daa4262b5 100644
--- a/macosx/HBTitle.m
+++ b/macosx/HBTitle.m
@@ -424,6 +424,11 @@ - (NSURL *)url
     return [NSURL fileURLWithPath:@(_hb_title->path)];
 }
 
+- (BOOL)keepDuplicateTitles
+{
+    return self.hb_title->keep_duplicate_titles;
+}
+
 - (int)index
 {
     return self.hb_title->index;

@samhutchins
Copy link
Contributor Author

@galad87 Thanks! I think I've got everything now

@sr55 I think I've got the windows UI working, but I feel pretty shaky about it.

@jstebbins Thanks! Once everyone's happy I'll probably force-push a squashed commit if that's OK

@sr55 sr55 added this to the 1.9.0 milestone May 7, 2024
@sr55
Copy link
Contributor

sr55 commented May 7, 2024

I'll do a review / test on the Windows side when I get a moment. Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

4 participants