在Node.js / Electron应用中使用iTunes Library框架吗? [英] Use iTunes Library framework in Node.js/Electron app?

查看:92
本文介绍了在Node.js / Electron应用中使用iTunes Library框架吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个访问iTunes数据库的Electron(Node.js)应用程序。在Catalina之前,可以使用导出的XML版本的数据库 iTunes Music Music.xml 。此邮件已在Catalina中删除,应使用iTunes库框架代替 https://developer.apple.com/文档/ ituneslibrary

I am developing an Electron (Node.js) app that accesses the iTunes database. Before Catalina one could use an exported XML version of the database iTunes Music Library.xml. This was removed in Catalina where the iTunes library framework should be used instead https://developer.apple.com/documentation/ituneslibrary.

是否可以在我的Electron或通常在Node.js项目中包含此框架并与之交互,如果可以,怎么做?

Is it possible to include this framework in my Electron or generally in a Node.js project and interact with it and if yes — how?

我在GitHub上扫描了模块或可能的解决方案,但它们都依赖于旧的XML文件。

I scanned GitHub for modules or possible solutions but all of them rely on the old XML file.

推荐答案

<我看到的唯一方法是使用节点本机模块。苹果使用Objectiv-C,其他所有语言(javascript,python等)都使用C或C ++绑定。幸运的是,clang支持Objective-C ++,它允许将C ++和Objective-C混合使用。一个有效的基本代码段如下所示(将其命名为 readMusic.mm mm 是Objectiv-C ++的扩展名)

The only way I see is using a node native module. Apple uses Objectiv-C and every other language (javascript, python, etc) uses C or C++ bindings. Luckly, clang supports Objective-C++, which allows to mix C++ and Objective-C. A basic snippet that works looks like this (name it readMusic.mm. mm is the extension für Objectiv-C++)

#import <Foundation/Foundation.h>
#import <iTunesLibrary/ITLibrary.h>
#import <iTunesLibrary/ITLibMediaItem.h>
#import <iTunesLibrary/ITLibArtist.h>
#include <node.h>
 

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Array;
using v8::Object;
using v8::String;
using v8::Value;
using v8::Integer;

char const *emptyString = "";

void Method(const FunctionCallbackInfo<Value>& args) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Set this up so Cocoa works

    Isolate* isolate = args.GetIsolate(); // Setup for Javascript Connection
    Local<v8::Context> context = isolate->GetCurrentContext();
    Local<String> keyTitle = String::NewFromUtf8(isolate, "title").ToLocalChecked();
    Local<String> keyArtist = String::NewFromUtf8(isolate, "artist").ToLocalChecked();
    Local<String> keyFilePath = String::NewFromUtf8(isolate, "filePath").ToLocalChecked();
    Local<String> keyBpm = String::NewFromUtf8(isolate, "bpm").ToLocalChecked();


    NSError *error = nil;
    ITLibrary *library = [ITLibrary libraryWithAPIVersion:@"1.0" error:&error]; // Connect to iTunes / Music Library
    if (library)
    {
        NSArray *tracks = library.allMediaItems; // Load all Songs with Cocoa / Objective-C
        int size = [tracks count];

        Local<Array> jsSongsArr = Array::New(isolate, size); // Create Array for Javascript v8 engine

        for (int i = 0; i < size; i++) { // Copy elements
            // Reading Data from Cocoa
            ITLibMediaItem *song = tracks[i];
            NSString *title = [song title];
            ITLibArtist *artist = [song artist];
            NSURL *location = [song location];

            // Convert it to c
            const char *titleInC = emptyString;
            const char *artistInC = emptyString;
            const char *filePathInC = emptyString;
            const long bpmInC = [song beatsPerMinute];

            if (title) {
                titleInC = [title UTF8String];
            }
            if (artist) {
                NSString *artistNSString = [artist name];
                if (artistNSString) {
                    artistInC = [artistNSString UTF8String];
                }
            }
            if (location) {
                NSString *locationNSString = [location absoluteString];
                if (locationNSString) {
                    filePathInC = [locationNSString UTF8String];
                }
            }

            Local<Object> jsSong = Object::New(isolate); // Create Javascript Object
            jsSong->Set(context, keyTitle, String::NewFromUtf8(isolate, titleInC).ToLocalChecked()).FromJust(); // Copy data in Javascript Object
            jsSong->Set(context, keyArtist, String::NewFromUtf8(isolate, artistInC).ToLocalChecked()).FromJust();
            jsSong->Set(context, keyFilePath, String::NewFromUtf8(isolate, filePathInC).ToLocalChecked()).FromJust();
            jsSong->Set(context, keyBpm, Integer::New(isolate, bpmInC)).FromJust();
            
            jsSongsArr->Set(context, i, jsSong).FromJust(); // Add the Object to Javascript Array
        }
        args.GetReturnValue().Set(jsSongsArr); // Set the return value of the function
    } else { // If error occurs
        args.GetReturnValue().Set(String::NewFromUtf8(isolate, [[error localizedDescription] UTF8String]).ToLocalChecked());
    }
}

void Initialize(Local<Object> exports) {
  NODE_SET_METHOD(exports, "readMusic", Method); // Tells node which function to use
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize) // Inits a native node module

}

这样做时,请不要忘记NSAutoReleasePool。对于绑定,您需要在 binding.gyp 中设置-ObjC ++标志。

Don't forget the NSAutoReleasePool when doing stuff like that. For the binding you need to set the -ObjC++ flags in your binding.gyp.

{
  "targets": [
    {
      "target_name": "addon",
      "sources": [ "readMusic.mm" ],
      "cflags!": [ "-ObjC++" ],
      "cflags_cc!": [ "-ObjC++" ],
      "libraries": [
          "/System/Library/Frameworks/iTunesLibrary.framework/Versions/Current/iTunesLibrary"
      ]
    }
  ]
}

然后编译并对其进行代码签名(对于分发非常重要),通过

Then compile and codesign it (very important for distribution) via

HOME=~/.electron-gyp node-gyp rebuild --target=10.1.0 --arch=x64 --dist-url=https://electronjs.org/headers
codesign -s "YOUR DEVELOPER ID" build/Release/addon.node

并通过

require("./build/Release/addon.node").readMusic();

由于依赖本机模块,因此只能在Mac上编译( https://www.electron.build/multi-platform-b​​uild )。确保在Windows平台上排除该代码。

Because of the dependence on native modules this is only compilable on Mac (https://www.electron.build/multi-platform-build). Make sure to exclude that code on windows platforms.

这篇关于在Node.js / Electron应用中使用iTunes Library框架吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆