NCrusher74 / SwiftTaggerID3

A Swift library for reading and editing ID3 tags
Apache License 2.0
5 stars 2 forks source link

added NSImage extension here since this library is the only one that uses it. Need to determine how to proceed when not working strictly with Mac apps, however. #16

Closed NCrusher74 closed 3 years ago

NCrusher74 commented 3 years ago

So, I just encountered an issue that I probably should have anticipated earlier.

A bit of background: I'm a little stuck on Audiobook Liberator for the moment, because I honestly can't remember why I thought it was needful or even a good idea to do things like caching metadata from that app when it's supposed to be a straightforward conversion/DRM-decryption tool.

Also, if I were to make that app a Ipad app with Mac Catalyst instead of a straight-up Mac App, I could use MobileFFmpeg instead of bundling FFmpeg in the app, and if I can ever get anyone to reply to me, it's possible that CryptoSwift might be an alternative to RCrack, which means that I wouldn't have to bundle ANYTHING in with the app, it could all be done using libraries, which seems much cleaner but would require a bit of walking things back and redoing them using tools that either didn't exist, or that I didn't understand how to use, back when I started.

I get that a year ago, when I was making these decisions, I didn't know as much as I do now, but still that's kind of a bitter pill to swallow and I'm still trying to figure out how I feel about it all and how I want to proceed.

In the meantime, though, it's been a year, and I really should probably create something that I can actually put up on the App store or request donations on or...something. Because bills.

So, the issue I encountered. Today I started poking at SwiftUI and MacCatalyst with the idea of moving ahead with my library management app (AudiobookLibrarian), while I'm figuring out how I want to handle things with Audiobook Liberator, and I discoverted that the way I handle converting images to data isn't going to work if I try to work with Mac Catalyst.

    /// Converts an `NSImage` to png data
    var pngData: Data {
        if let tiff = tiffRepresentation,
           let bitmap = NSBitmapImageRep(data: tiff),
           let data = bitmap.representation(using: .png, properties: [.compressionFactor: 1.0]) {
            return data
        } else {
            // Not sure if this situation can ever happen anyway.
            // If it does turn out to be possible, this should be turned into a thrown error instead.
            fatalError("Unable to convert image to PNG.")
        }
    }

// and also a corresponding jpgData property 

Because it looks like tiffRepresentation/NSBitmapImageRep isn't available for Mac Catalyst. I could just go ahead and mac it a pure Mac app, but sooner or later, I'm going to want to create an iOS version of my library management app and I'm going to have to deal with the fact that my image handling here is Cocoa-based and not compatible with iOS.

But this is the first time since doing the early "build your first app" tutorials over a year ago that I've even looked at iOS and frankly I don't remember much, and I don't believe any of those tutorials ever covered how to make an app cross-platform compatible.

SDGGiesbrecht commented 3 years ago

I don’t know CryptoSwift any better than you do, but encryption libraries are a dime a dozen and encryption breaking libraries tend to be few and far between. I would first check that it actually supplies a metaphorical lock pick, and not just locks and keys.


NSImage (on macOS) and UIImage on iOS are nearly identical. Writing cross‐platform code is just a matter of splitting the implementation wherever necessary with #if:

#if os(macOS)
  typealias NativeImage = NSImage
#elseif os(iOS)
  typealias NativeImage = UIImage
#endif

let x: NativeImage = // ...
NCrusher74 commented 3 years ago

I would first check that it actually supplies a metaphorical lock pick, and not just locks and keys.

Yeah, that's what I've been trying to figure out, but I can't seem to get anyone to answer. I emailed days ago, then posted in the issues a couple days later, asking if this was an alternative, and no one has responded. I'm not sure how else to go about finding out.

NSImage (on macOS) and UIImage on iOS are nearly identical.

I knew that much (and I believe UIImage has an inherent pngData property or method already?) but I wasn't sure about the syntax for switching between the two. I was trying a bunch of combinations of things similar to #if os(macOS) but I wasn't getting it right.

Is there anything I should add in the manifest for my libraries for multi-platform support? I have seen a platform specified in the manifest on occasion, if it isn't specified, is complete cross-platform support assumed?

SDGGiesbrecht commented 3 years ago

Platforms do not need to be “enabled”. They simply successfully compile or not.

What you saw in the manifest was a declaration that the minimum version of a particular platform to compile for. Without that, the compiler will aim for compatibility with the oldest version it knows about. You don’t need to add such a declaration until the compiler yelps at you that something isn’t doesn’t exist far enough back. (And even then, libraries are better off using an individual @available(macOS 10.11, *) on the symbol itself, so as to impose as few restrictions on clients as possible.

NCrusher74 commented 3 years ago

vis a vis the rCrack/CryptoSwift thing, I don't hold out much hope that I could reverse engineer RCrack into Swift (even though it's in C/C++, except for the Rainbow Tables) but maybe I could do it with this, which is by the same guy who created the inAudible-NG tool. I'm frankly not sure why he recommends using the RCrack option instead, since this seems a much more...legitimate?...way of getting one's own activation bytes.

Python is close enough to Swift in syntax that I can largely figure out what it's doing, and even if I couldn't, ultimately I know that what it's doing is logging using the users own username/email and password to get the activation bytes from the Audible servers, which shouldn't be that difficult to replicate.

NCrusher74 commented 3 years ago

Okay, here's another question which I'll just add here since it's a variation on the theme, just in the MP4 library. I think it's possible I might run into it in this library as well, I just haven't yet.

When I have a methods to create an image atom/frame from the URL of an image file, but apparently that works differently in iOS than it does in macOS and you can't initialize UIImage using .init(contentsOf: URL).

But I'm not sure which of the UIImage initializers would be the closest analog if someone were using the library management app on, say, an iPad or whatever. I'm not even sure someone who already has an audiobook loaded on their device will be altering the cover art, but who knows?

At any rate, I need to come up with an iOS analog for this method:

    init(imageLocation: URL) throws {
        if imageLocation.pathExtension == "jpg" ||
            imageLocation.pathExtension == "jpeg" {
            self.dataType = .jpeg
        } else if imageLocation.pathExtension == "png" {
            self.dataType = .png
        } else {
            throw MetadataAtomError.UnsupportedImageFormat
        }

        self.data = try Data(contentsOf: imageLocation)
//
    }
SDGGiesbrecht commented 3 years ago

The equivalent of init(contentsOf: x) would be init(contentsOfFile: x.path). Or there is init?(data: Data). The whole list is here: https://developer.apple.com/documentation/uikit/uiimage. AppKit (macOS) and UIKit (iOS) are usually very similar, but often have minor differences in spelling.

NCrusher74 commented 3 years ago

Ah okay, I didn't realize init(contentsOfFile:) was looking for a path. I thought it was looking for some sort of file object I hadn't dealt with before. I'm not sure why I assumed that now. Possibly my brain took a break.