This is absolutely insane... but why?
krackers opened this issue · comments
This is some great RE work, and +1 for using objc_setAssociatedObject
which is something I didn't know existed, obj-c runtime always surprises me. But honestly curious, why do this over using mpv? Video player is one app where ui doesn't matter, and quicktime is too limited anyway.
Also in terms of implementation, question: why explicitly declare needsCheckWindowButtons
and needsSetHasAutoCanDrawSubviewsIntoLayer
instead of using zkhookivar here? Would think that's cleaner since you don't need to match the ivar layout.
But honestly curious, why do this over using mpv? Video player is one app where ui doesn't matter
Oh, but the UI does matter to me! If I'm sitting down to watch a movie, I want it to be a pleasant experience.
IMO, QuickTime X's interface is without equal. It looks good—keeping me in a movie-watching mood—and it has just the options I need without a bunch of knobs and dials I don't want. It also has excellent Applescript support, which I use with my Harmony remote.
QuickTime is probably the second-most used app on my computer after Chromium. My mac is connected to my projector, and I have a script ("Media Subscriptions Preference Pane" on my website) which automatically downloads Youtube videos and podcast episodes overnight. I rip BluRays with MakeMKV and I play those with QuickTime as well.
The Applescript I built into the my modified QuickTime 10.2, which saves my current position when a file is closed, has also been fantastic. I can close any file I'm in the middle of watching, and it'll always remember the spot where I left off and re-open there.
and quicktime is too limited anyway.
But not QuickTime 10.2, because it supports custom video codecs! I updated FFusion to support HEVC and VP9. and I have a small helper utility ("QuickTime Helper" on my website) to automatically remux MKV files into MOVs.
The latter is a bit more finicky than I would like, but it works 99% of the time and it's better than using mpv. FFusion is seamless to the point where unless I explicitly check, I can't tell what codec is in use. CPU usage isn't great, but my 4790K is strong enough to brute force it.
Also in terms of implementation, question: why explicitly declare needsCheckWindowButtons and needsSetHasAutoCanDrawSubviewsIntoLayer instead of using zkhookivar here?
Can zkhookivar
add new ivars? If so, I didn't know that. needsCheckWindowButtons
and needsSetHasAutoCanDrawSubviewsIntoLayer
do not normally exist in QuickTime; they are original variables which I need for my code.
I really should be using objc_setAssociatedObject
to track these. I don't totally understand what's going on with swizzled memory mapping, but the fact that I need unsigned int doNotUse1
is not comforting. However, I wrote this specific code before I knew about objc_setAssociatedObject
, and since needsCheckWindowButtons
and needsSetHasAutoCanDrawSubviewsIntoLayer
are primitives, I'd have to store them as NSNumber
's or something, which would be messier.
Fwiw, most of this code was written during December 2020, when there was nothing happening at work due to the holidays and I was stuck inside due to the pandemic. I think it was only my second or third time writing Objective-C and using swizzling.
So I just kept looking through the headers from class dump and trying anything with an interesting name. More than anything else I've made, there's a lot of code in here that I don't understand why it works. The code I added to MGCinematicFrameView
's displayIfNeeded
, for example, is still mostly a gigantic WTF.
Interesting... To me the limitation of quicktime was that even with perian its support for typesetting subtitles was not as good as implementations using libass. And even if that were fixed, it doesn't offer any on-the-fly finetuning like sub sync, external subs/audio (without remuxing), font scale as well as features like screenshot and configurable seek duration. But I guess those might be considered niche features (though I wish every application exposed its internals via a scriptable api like mpv, it's lot better than swizzling).
Can you expand more on quicktime X interface? Are you referring to the on-screen control overlay (play button, etc.)? Or something else particular about the UX?
They are original variables which I need for my code.
Oh I see. I don't think you can add new ivars at runtime after the class has been created. In fact, are you sure that your existing approach doesn't overwrite any existing ivar? The way I understand it, ivar access will essentially be compiled down to
int *ivar_val_ptr = object_ptr + ivarAreaOffset + ivarValOffsetFromArea
but when you're swizzling, the implementation of your swizzled method will reference the ivaroffset for the object it's part of (myCoolNSView
), which is out-of-bounds in the ivars for the original object (NSView
). I.e. the fact that you declare some ivars in myCoolNSView
doesn't really matter because all the objects are of type NSView
(and swizzling only exchanges method implementations).
I think objc_setAssociatedObject
is the best solution.