@sequencemedia/music-library 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -0
- package/app.mjs +133 -0
- package/babel.config.cjs +24 -0
- package/package.json +77 -0
- package/src/common/normalise.mjs +9 -0
- package/src/index.mjs +1 -0
- package/src/library/index.js +37 -0
- package/src/library/playlists/index.js +37 -0
- package/src/library/playlists/transform/index.js +67 -0
- package/src/library/tracks/index.js +37 -0
- package/src/library/tracks/transform/index.js +67 -0
- package/src/library/transform/index.js +65 -0
- package/src/watch/index.mjs +1 -0
- package/src/watch/library/index.mjs +42 -0
- package/src/watch/library/playlists/index.mjs +42 -0
- package/src/watch/library/playlists/transform/index.mjs +102 -0
- package/src/watch/library/tracks/index.mjs +42 -0
- package/src/watch/library/tracks/transform/index.mjs +102 -0
- package/src/watch/library/transform/index.mjs +100 -0
package/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# @sequencemedia/itunes-library
|
|
2
|
+
|
|
3
|
+
Parses an `iTunes Library.xml` file and transforms it to [`m3u`](https://en.wikipedia.org/wiki/M3U) files, JSON, or JavaScript.
|
|
4
|
+
|
|
5
|
+
The command line app can watch for changes to an `iTunes Library.xml` file and write `m3u` files to a destination directory.
|
|
6
|
+
|
|
7
|
+
Or, the component functions can be imported into your own application.
|
|
8
|
+
|
|
9
|
+
This packages implements [`@sequencemedia/itunes-library-parser`](https://github.com/sequencemedia/itunes-library-parser).
|
|
10
|
+
|
|
11
|
+
Requires [Java](https://www.oracle.com/java/technologies/javase-downloads.html) and [Saxon PE](https://www.saxonica.com/welcome/welcome.xml).
|
|
12
|
+
|
|
13
|
+
## Command line app
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
npm run start -- --jar "/usr/local/bin/saxon/SaxonPE10-0J/saxon-pe-10.0.jar" --xml "~/Music/iTunes/iTunes Library.xml" --destination "~/Documents/iTunes Library"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Paths will differ on your device.
|
|
20
|
+
|
|
21
|
+
## Library
|
|
22
|
+
|
|
23
|
+
Transforms the entire library.
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
const { toM3U } = require('./lib/library')
|
|
27
|
+
const {
|
|
28
|
+
toJSON,
|
|
29
|
+
toJS,
|
|
30
|
+
toES
|
|
31
|
+
} = require('./lib/library/transform')
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### `toM3U`
|
|
35
|
+
|
|
36
|
+
Requires the arguments `jar`, `xml`, and `destination`.
|
|
37
|
+
|
|
38
|
+
- `jar` - the path to the Saxon binary on your device
|
|
39
|
+
- `xml` - the path to the `iTunes Library.xml` file
|
|
40
|
+
- `destination` - the path for the `m3u` files to be written
|
|
41
|
+
|
|
42
|
+
Returns a `Promise` resolving when all `m3u` files are written.
|
|
43
|
+
|
|
44
|
+
### `toJSON`
|
|
45
|
+
|
|
46
|
+
Requires the arguments `jar`, and `xml`.
|
|
47
|
+
|
|
48
|
+
- `jar` - the path to the Saxon binary on your device
|
|
49
|
+
- `xml` - the path to the `iTunes Library.xml` file
|
|
50
|
+
|
|
51
|
+
Returns a `Promise` resolving to a `JSON` string.
|
|
52
|
+
|
|
53
|
+
### `toJS`
|
|
54
|
+
|
|
55
|
+
Requires the arguments `jar`, and `xml`.
|
|
56
|
+
|
|
57
|
+
- `jar` - the path to the Saxon binary on your device
|
|
58
|
+
- `xml` - the path to the `iTunes Library.xml` file
|
|
59
|
+
|
|
60
|
+
Returns a `Promise` resolving to a JavaScript object.
|
|
61
|
+
|
|
62
|
+
### `toES`
|
|
63
|
+
|
|
64
|
+
Requires the arguments `jar`, and `xml`.
|
|
65
|
+
|
|
66
|
+
- `jar` - the path to the Saxon binary on your device
|
|
67
|
+
- `xml` - the path to the `iTunes Library.xml` file
|
|
68
|
+
|
|
69
|
+
Returns a `Promise` resolving to a collection of JavaScript `Map` and `Set` instances.
|
|
70
|
+
|
|
71
|
+
## Playlists
|
|
72
|
+
|
|
73
|
+
Transforms the playlists.
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
const { toM3U } = require('./lib/library/playlists')
|
|
77
|
+
const {
|
|
78
|
+
toJSON,
|
|
79
|
+
toJS,
|
|
80
|
+
toES
|
|
81
|
+
} = require('./lib/library/playlists/transform')
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
See **Library**.
|
|
85
|
+
|
|
86
|
+
## Tracks
|
|
87
|
+
|
|
88
|
+
Transforms the tracks.
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
const { toM3U } = require('./lib/library/tracks')
|
|
92
|
+
const {
|
|
93
|
+
toJSON,
|
|
94
|
+
toJS,
|
|
95
|
+
toES
|
|
96
|
+
} = require('./lib/library/tracks/transform')
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
See **Library**.
|
package/app.mjs
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import 'dotenv/config'
|
|
4
|
+
|
|
5
|
+
import debug from 'debug'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
readFile
|
|
9
|
+
} from 'fs/promises'
|
|
10
|
+
|
|
11
|
+
import psList from 'ps-list'
|
|
12
|
+
|
|
13
|
+
import commander from 'commander'
|
|
14
|
+
|
|
15
|
+
import * as watch from '#music-library/watch'
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
library,
|
|
19
|
+
library: {
|
|
20
|
+
tracks,
|
|
21
|
+
playlists
|
|
22
|
+
}
|
|
23
|
+
} = watch
|
|
24
|
+
|
|
25
|
+
const NAME = 'ml.App'
|
|
26
|
+
process.title = NAME
|
|
27
|
+
|
|
28
|
+
async function app () {
|
|
29
|
+
const PACKAGE = JSON.parse(await readFile('./package.json'))
|
|
30
|
+
|
|
31
|
+
const {
|
|
32
|
+
name
|
|
33
|
+
} = PACKAGE
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Permit only one instance of the application
|
|
37
|
+
*/
|
|
38
|
+
try {
|
|
39
|
+
const a = (await psList())
|
|
40
|
+
.filter(({ name }) => name === NAME)
|
|
41
|
+
|
|
42
|
+
if (a.length > 1) {
|
|
43
|
+
const {
|
|
44
|
+
pid: PID
|
|
45
|
+
} = process
|
|
46
|
+
|
|
47
|
+
const {
|
|
48
|
+
pid
|
|
49
|
+
} = a.find(({ pid }) => pid !== PID)
|
|
50
|
+
|
|
51
|
+
const log = debug('music-library:process:log')
|
|
52
|
+
|
|
53
|
+
log(`Killing application "${name}" in process ${pid}.`)
|
|
54
|
+
|
|
55
|
+
process.kill(pid)
|
|
56
|
+
}
|
|
57
|
+
} catch ({ message }) {
|
|
58
|
+
const error = debug('music-library:process:error')
|
|
59
|
+
|
|
60
|
+
error(message)
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const log = debug('@sequencemedia/music-library')
|
|
65
|
+
|
|
66
|
+
const {
|
|
67
|
+
pid,
|
|
68
|
+
argv,
|
|
69
|
+
env: {
|
|
70
|
+
JAR,
|
|
71
|
+
XML,
|
|
72
|
+
DESTINATION
|
|
73
|
+
}
|
|
74
|
+
} = process
|
|
75
|
+
|
|
76
|
+
log(`Starting application "${name}" in process ${pid}.`)
|
|
77
|
+
|
|
78
|
+
const {
|
|
79
|
+
version
|
|
80
|
+
} = PACKAGE
|
|
81
|
+
|
|
82
|
+
commander
|
|
83
|
+
.version(version)
|
|
84
|
+
.option('-j, --jar [jar]', 'Path to Saxon PE/EE JAR')
|
|
85
|
+
.option('-x, --xml [xml]', 'Path to iTunes Library XML')
|
|
86
|
+
.option('-d, --destination [destination]', 'Destination path for M3Us')
|
|
87
|
+
.option('-t, --tracks', 'Parse all tracks')
|
|
88
|
+
.option('-p, --playlists', 'Parse all playlists')
|
|
89
|
+
.parse(argv)
|
|
90
|
+
|
|
91
|
+
const {
|
|
92
|
+
jar = JAR,
|
|
93
|
+
xml = XML,
|
|
94
|
+
destination = DESTINATION,
|
|
95
|
+
tracks: t = false,
|
|
96
|
+
playlists: p = false
|
|
97
|
+
} = commander.opts()
|
|
98
|
+
|
|
99
|
+
const l = (
|
|
100
|
+
(t && p) || (!t && !p)
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
if (l) {
|
|
104
|
+
log(`Application "${name}" in process ${pid} watching Library.`)
|
|
105
|
+
|
|
106
|
+
log({ jar, xml, destination })
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
library
|
|
110
|
+
.toM3U(jar, xml, destination)
|
|
111
|
+
)
|
|
112
|
+
} else {
|
|
113
|
+
if (t) {
|
|
114
|
+
log(`Application "${name}" in process ${pid} watching Tracks.`)
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
tracks
|
|
118
|
+
.toM3U(jar, xml, destination)
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (p) {
|
|
123
|
+
log(`Application "${name}" in process ${pid} watching Playlists.`)
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
playlists
|
|
127
|
+
.toM3U(jar, xml, destination)
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export default app()
|
package/babel.config.cjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const presets = [
|
|
2
|
+
[
|
|
3
|
+
'@babel/env',
|
|
4
|
+
{
|
|
5
|
+
targets: {
|
|
6
|
+
node: 'current'
|
|
7
|
+
},
|
|
8
|
+
useBuiltIns: 'usage',
|
|
9
|
+
corejs: 3
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
const plugins = [
|
|
15
|
+
'@babel/proposal-export-default-from',
|
|
16
|
+
'@babel/proposal-export-namespace-from'
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
compact: true,
|
|
21
|
+
comments: false,
|
|
22
|
+
presets,
|
|
23
|
+
plugins
|
|
24
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sequencemedia/music-library",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Watch Apple Music Library XML and parse to JSON, JS, ES, or M3U",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"music",
|
|
7
|
+
"library",
|
|
8
|
+
"xml",
|
|
9
|
+
"parser",
|
|
10
|
+
"music",
|
|
11
|
+
"audio",
|
|
12
|
+
"video",
|
|
13
|
+
"track",
|
|
14
|
+
"playlist",
|
|
15
|
+
"json",
|
|
16
|
+
"m3u",
|
|
17
|
+
"m3u8"
|
|
18
|
+
],
|
|
19
|
+
"main": "./app.mjs",
|
|
20
|
+
"type": "module",
|
|
21
|
+
"author": "Jonathan Perry for Sequence Media Limited <sequencemedia@sequencemedia.net>",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=16.13.0"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git://github.com/sequencemedia/music-library"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/sequencemedia/music-library",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/sequencemedia/music-library/issues"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"lint": "eslint . --ext .mjs --ext .cjs",
|
|
36
|
+
"lint:fix": "npm run lint -- --fix",
|
|
37
|
+
"start": "cross-env DEBUG=@sequencemedia/music-library* NODE_ENV=production node .",
|
|
38
|
+
"start:dev": "cross-env DEBUG=@sequencemedia/music-library* NODE_ENV=development node ."
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@sequencemedia/music-library-parser": "1.0.0",
|
|
42
|
+
"chokidar": "^3.5.2",
|
|
43
|
+
"commander": "^8.3.0",
|
|
44
|
+
"cross-env": "^7.0.3",
|
|
45
|
+
"debug": "^4.3.3",
|
|
46
|
+
"dotenv": "^10.0.0",
|
|
47
|
+
"ps-list": "7.2.0",
|
|
48
|
+
"supports-color": "^9.2.1"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@babel/cli": "^7.16.0",
|
|
52
|
+
"@babel/core": "^7.16.5",
|
|
53
|
+
"@babel/eslint-parser": "^7.16.5",
|
|
54
|
+
"@babel/plugin-proposal-export-default-from": "^7.16.5",
|
|
55
|
+
"@babel/plugin-proposal-export-namespace-from": "^7.16.5",
|
|
56
|
+
"@babel/preset-env": "^7.16.5",
|
|
57
|
+
"core-js": "^3.20.1",
|
|
58
|
+
"eslint": "7.32.0",
|
|
59
|
+
"eslint-config-standard": "^16.0.3",
|
|
60
|
+
"eslint-import-resolver-babel-module": "^5.3.1",
|
|
61
|
+
"eslint-plugin-import": "^2.25.3",
|
|
62
|
+
"eslint-plugin-node": "^11.1.0",
|
|
63
|
+
"eslint-plugin-promise": "5.2.0",
|
|
64
|
+
"rimraf": "^3.0.2"
|
|
65
|
+
},
|
|
66
|
+
"imports": {
|
|
67
|
+
"#music-library/common/normalise": "./src/common/normalise.mjs",
|
|
68
|
+
"#music-library/library": "./src/library/index.mjs",
|
|
69
|
+
"#music-library/watch": "./src/watch/index.mjs",
|
|
70
|
+
"#music-library/watch/library": "./src/watch/library/index.mjs",
|
|
71
|
+
"#music-library/watch/library/transform": "./src/watch/library/transform/index.mjs",
|
|
72
|
+
"#music-library/watch/library/playlists": "./src/watch/library/playlists/index.mjs",
|
|
73
|
+
"#music-library/watch/library/playlists/transform": "./src/watch/library/playlists/transform/index.mjs",
|
|
74
|
+
"#music-library/watch/library/tracks": "./src/watch/library/tracks/index.mjs",
|
|
75
|
+
"#music-library/watch/library/tracks/transform": "./src/watch/library/tracks/transform/index.mjs"
|
|
76
|
+
}
|
|
77
|
+
}
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as library from '#music-library/library'
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import debug from 'debug'
|
|
2
|
+
|
|
3
|
+
import * as musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
4
|
+
|
|
5
|
+
import normalise from '#music-library/common/normalise'
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
library: {
|
|
9
|
+
toM3U: parseToM3U
|
|
10
|
+
}
|
|
11
|
+
} = musicLibraryParser
|
|
12
|
+
|
|
13
|
+
const error = debug('@sequencemedia/music-library:error')
|
|
14
|
+
|
|
15
|
+
export async function toM3U (jar, xml, destination) {
|
|
16
|
+
try {
|
|
17
|
+
const j = jar
|
|
18
|
+
? normalise(jar)
|
|
19
|
+
: jar
|
|
20
|
+
|
|
21
|
+
const x = xml
|
|
22
|
+
? normalise(xml)
|
|
23
|
+
: xml
|
|
24
|
+
|
|
25
|
+
const d = destination
|
|
26
|
+
? normalise(destination)
|
|
27
|
+
: destination
|
|
28
|
+
|
|
29
|
+
return await parseToM3U(j, x, d)
|
|
30
|
+
} catch ({ message }) {
|
|
31
|
+
error(message)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export * as tracks from './tracks'
|
|
36
|
+
export * as playlists from './playlists'
|
|
37
|
+
export * as transform from './transform'
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import debug from 'debug'
|
|
2
|
+
|
|
3
|
+
import * as musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
4
|
+
|
|
5
|
+
import normalise from '#music-library/common/normalise'
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
library: {
|
|
9
|
+
playlists: {
|
|
10
|
+
toM3U: parseToM3U
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
} = musicLibraryParser
|
|
14
|
+
|
|
15
|
+
const error = debug('@sequencemedia/music-library:error')
|
|
16
|
+
|
|
17
|
+
export async function toM3U (jar, xml, destination) {
|
|
18
|
+
try {
|
|
19
|
+
const j = jar
|
|
20
|
+
? normalise(jar)
|
|
21
|
+
: jar
|
|
22
|
+
|
|
23
|
+
const x = xml
|
|
24
|
+
? normalise(xml)
|
|
25
|
+
: xml
|
|
26
|
+
|
|
27
|
+
const d = destination
|
|
28
|
+
? normalise(destination)
|
|
29
|
+
: destination
|
|
30
|
+
|
|
31
|
+
return await parseToM3U(j, x, d)
|
|
32
|
+
} catch ({ message }) {
|
|
33
|
+
error(message)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export * as transform from './transform'
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import debug from 'debug'
|
|
2
|
+
|
|
3
|
+
import * as musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
4
|
+
|
|
5
|
+
import normalise from '#music-library/common/normalise'
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
library: {
|
|
9
|
+
playlists: {
|
|
10
|
+
transform: {
|
|
11
|
+
toJSON: transformToJSON,
|
|
12
|
+
toJS: transformToJS,
|
|
13
|
+
toES: transformToES
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
} = musicLibraryParser
|
|
18
|
+
|
|
19
|
+
const error = debug('@sequencemedia/music-library:transform:error')
|
|
20
|
+
|
|
21
|
+
export async function toJSON (jar, xml) {
|
|
22
|
+
try {
|
|
23
|
+
const j = jar
|
|
24
|
+
? normalise(jar)
|
|
25
|
+
: jar
|
|
26
|
+
|
|
27
|
+
const x = xml
|
|
28
|
+
? normalise(xml)
|
|
29
|
+
: xml
|
|
30
|
+
|
|
31
|
+
return await transformToJSON(j, x)
|
|
32
|
+
} catch ({ message }) {
|
|
33
|
+
error(message)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function toJS (jar, xml) {
|
|
38
|
+
try {
|
|
39
|
+
const j = jar
|
|
40
|
+
? normalise(jar)
|
|
41
|
+
: jar
|
|
42
|
+
|
|
43
|
+
const x = xml
|
|
44
|
+
? normalise(xml)
|
|
45
|
+
: xml
|
|
46
|
+
|
|
47
|
+
return await transformToJS(j, x)
|
|
48
|
+
} catch ({ message }) {
|
|
49
|
+
error(message)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function toES (jar, xml) {
|
|
54
|
+
try {
|
|
55
|
+
const j = jar
|
|
56
|
+
? normalise(jar)
|
|
57
|
+
: jar
|
|
58
|
+
|
|
59
|
+
const x = xml
|
|
60
|
+
? normalise(xml)
|
|
61
|
+
: xml
|
|
62
|
+
|
|
63
|
+
return await transformToES(j, x)
|
|
64
|
+
} catch ({ message }) {
|
|
65
|
+
error(message)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import debug from 'debug'
|
|
2
|
+
|
|
3
|
+
import * as musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
4
|
+
|
|
5
|
+
import normalise from '#music-library/common/normalise'
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
library: {
|
|
9
|
+
tracks: {
|
|
10
|
+
toM3U: parseToM3U
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
} = musicLibraryParser
|
|
14
|
+
|
|
15
|
+
const error = debug('@sequencemedia/music-library:error')
|
|
16
|
+
|
|
17
|
+
export async function toM3U (jar, xml, destination) {
|
|
18
|
+
try {
|
|
19
|
+
const j = jar
|
|
20
|
+
? normalise(jar)
|
|
21
|
+
: jar
|
|
22
|
+
|
|
23
|
+
const x = xml
|
|
24
|
+
? normalise(xml)
|
|
25
|
+
: xml
|
|
26
|
+
|
|
27
|
+
const d = destination
|
|
28
|
+
? normalise(destination)
|
|
29
|
+
: destination
|
|
30
|
+
|
|
31
|
+
return await parseToM3U(j, x, d)
|
|
32
|
+
} catch ({ message }) {
|
|
33
|
+
error(message)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export * as transform from './transform'
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import debug from 'debug'
|
|
2
|
+
|
|
3
|
+
import * as musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
4
|
+
|
|
5
|
+
import normalise from '#music-library/common/normalise'
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
library: {
|
|
9
|
+
tracks: {
|
|
10
|
+
transform: {
|
|
11
|
+
toJSON: transformToJSON,
|
|
12
|
+
toJS: transformToJS,
|
|
13
|
+
toES: transformToES
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
} = musicLibraryParser
|
|
18
|
+
|
|
19
|
+
const error = debug('@sequencemedia/music-library:transform:error')
|
|
20
|
+
|
|
21
|
+
export async function toJSON (jar, xml) {
|
|
22
|
+
try {
|
|
23
|
+
const j = jar
|
|
24
|
+
? normalise(jar)
|
|
25
|
+
: jar
|
|
26
|
+
|
|
27
|
+
const x = xml
|
|
28
|
+
? normalise(xml)
|
|
29
|
+
: xml
|
|
30
|
+
|
|
31
|
+
return await transformToJSON(j, x)
|
|
32
|
+
} catch ({ message }) {
|
|
33
|
+
error(message)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function toJS (jar, xml) {
|
|
38
|
+
try {
|
|
39
|
+
const j = jar
|
|
40
|
+
? normalise(jar)
|
|
41
|
+
: jar
|
|
42
|
+
|
|
43
|
+
const x = xml
|
|
44
|
+
? normalise(xml)
|
|
45
|
+
: xml
|
|
46
|
+
|
|
47
|
+
return await transformToJS(j, x)
|
|
48
|
+
} catch ({ message }) {
|
|
49
|
+
error(message)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function toES (jar, xml) {
|
|
54
|
+
try {
|
|
55
|
+
const j = jar
|
|
56
|
+
? normalise(jar)
|
|
57
|
+
: jar
|
|
58
|
+
|
|
59
|
+
const x = xml
|
|
60
|
+
? normalise(xml)
|
|
61
|
+
: xml
|
|
62
|
+
|
|
63
|
+
return await transformToES(j, x)
|
|
64
|
+
} catch ({ message }) {
|
|
65
|
+
error(message)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import debug from 'debug'
|
|
2
|
+
|
|
3
|
+
import * as musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
4
|
+
|
|
5
|
+
import normalise from '#music-library/common/normalise'
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
library: {
|
|
9
|
+
transform: {
|
|
10
|
+
toJSON: transformToJSON,
|
|
11
|
+
toJS: transformToJS,
|
|
12
|
+
toES: transformToES
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
} = musicLibraryParser
|
|
16
|
+
|
|
17
|
+
const error = debug('@sequencemedia/music-library:transform:error')
|
|
18
|
+
|
|
19
|
+
export async function toJSON (jar, xml) {
|
|
20
|
+
try {
|
|
21
|
+
const j = jar
|
|
22
|
+
? normalise(jar)
|
|
23
|
+
: jar
|
|
24
|
+
|
|
25
|
+
const x = xml
|
|
26
|
+
? normalise(xml)
|
|
27
|
+
: xml
|
|
28
|
+
|
|
29
|
+
return await transformToJSON(j, x)
|
|
30
|
+
} catch ({ message }) {
|
|
31
|
+
error(message)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function toJS (jar, xml) {
|
|
36
|
+
try {
|
|
37
|
+
const j = jar
|
|
38
|
+
? normalise(jar)
|
|
39
|
+
: jar
|
|
40
|
+
|
|
41
|
+
const x = xml
|
|
42
|
+
? normalise(xml)
|
|
43
|
+
: xml
|
|
44
|
+
|
|
45
|
+
return await transformToJS(j, x)
|
|
46
|
+
} catch ({ message }) {
|
|
47
|
+
error(message)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function toES (jar, xml) {
|
|
52
|
+
try {
|
|
53
|
+
const j = jar
|
|
54
|
+
? normalise(jar)
|
|
55
|
+
: jar
|
|
56
|
+
|
|
57
|
+
const x = xml
|
|
58
|
+
? normalise(xml)
|
|
59
|
+
: xml
|
|
60
|
+
|
|
61
|
+
return await transformToES(j, x)
|
|
62
|
+
} catch ({ message }) {
|
|
63
|
+
error(message)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as library from '#music-library/watch/library'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import chokidar from 'chokidar'
|
|
2
|
+
|
|
3
|
+
import debug from 'debug'
|
|
4
|
+
|
|
5
|
+
import musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
6
|
+
|
|
7
|
+
import normalise from '#music-library/common/normalise'
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
library: {
|
|
11
|
+
toM3U: parseToM3U
|
|
12
|
+
}
|
|
13
|
+
} = musicLibraryParser
|
|
14
|
+
|
|
15
|
+
const error = debug('@sequencemedia/music-library:error')
|
|
16
|
+
|
|
17
|
+
export function toM3U (jar, xml, destination) {
|
|
18
|
+
const j = jar
|
|
19
|
+
? normalise(jar)
|
|
20
|
+
: jar
|
|
21
|
+
|
|
22
|
+
const x = xml
|
|
23
|
+
? normalise(xml)
|
|
24
|
+
: xml
|
|
25
|
+
|
|
26
|
+
const d = destination
|
|
27
|
+
? normalise(destination)
|
|
28
|
+
: destination
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
chokidar.watch(x)
|
|
32
|
+
.on('ready', () => parseToM3U(j, x, d))
|
|
33
|
+
.on('change', () => parseToM3U(j, x, d))
|
|
34
|
+
.on('error', ({ message }) => {
|
|
35
|
+
error(`Error in watcher: "${message}"`)
|
|
36
|
+
})
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export * as tracks from '#music-library/watch/library/tracks'
|
|
41
|
+
export * as playlists from '#music-library/watch/library/playlists'
|
|
42
|
+
export * as transform from '#music-library/watch/library/transform'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import chokidar from 'chokidar'
|
|
2
|
+
|
|
3
|
+
import debug from 'debug'
|
|
4
|
+
|
|
5
|
+
import musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
6
|
+
|
|
7
|
+
import normalise from '#music-library/common/normalise'
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
library: {
|
|
11
|
+
playlists: {
|
|
12
|
+
toM3U: parseToM3U
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
} = musicLibraryParser
|
|
16
|
+
|
|
17
|
+
const error = debug('@sequencemedia/music-library:error')
|
|
18
|
+
|
|
19
|
+
export function toM3U (jar, xml, destination) {
|
|
20
|
+
const j = jar
|
|
21
|
+
? normalise(jar)
|
|
22
|
+
: jar
|
|
23
|
+
|
|
24
|
+
const x = xml
|
|
25
|
+
? normalise(xml)
|
|
26
|
+
: xml
|
|
27
|
+
|
|
28
|
+
const d = destination
|
|
29
|
+
? normalise(destination)
|
|
30
|
+
: destination
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
chokidar.watch(x)
|
|
34
|
+
.on('ready', () => parseToM3U(j, x, d))
|
|
35
|
+
.on('change', () => parseToM3U(j, x, d))
|
|
36
|
+
.on('error', ({ message }) => {
|
|
37
|
+
error(`Error in watcher: "${message}"`)
|
|
38
|
+
})
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export * as transform from '#music-library/watch/library/playlists/transform'
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import chokidar from 'chokidar'
|
|
2
|
+
|
|
3
|
+
import debug from 'debug'
|
|
4
|
+
|
|
5
|
+
import musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
6
|
+
|
|
7
|
+
import normalise from '#music-library/common/normalise'
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
library: {
|
|
11
|
+
playlists: {
|
|
12
|
+
transform: {
|
|
13
|
+
toJSON: transformToJSON,
|
|
14
|
+
toJS: transformToJS,
|
|
15
|
+
toES: transformToES
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
} = musicLibraryParser
|
|
20
|
+
|
|
21
|
+
const error = debug('@sequencemedia/music-library:transform:error')
|
|
22
|
+
|
|
23
|
+
export function toJSON (jar, xml, func = () => {}) {
|
|
24
|
+
const j = jar
|
|
25
|
+
? normalise(jar)
|
|
26
|
+
: jar
|
|
27
|
+
|
|
28
|
+
const x = xml
|
|
29
|
+
? normalise(xml)
|
|
30
|
+
: xml
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
chokidar.watch(x)
|
|
34
|
+
.on('ready', async function ready () {
|
|
35
|
+
func(
|
|
36
|
+
await transformToJSON(j, x)
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
.on('change', async function change () {
|
|
40
|
+
func(
|
|
41
|
+
await transformToJSON(j, x)
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
.on('error', ({ message }) => {
|
|
45
|
+
error(`Error in watcher: "${message}"`)
|
|
46
|
+
})
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function toJS (jar, xml, func = () => {}) {
|
|
51
|
+
const j = jar
|
|
52
|
+
? normalise(jar)
|
|
53
|
+
: jar
|
|
54
|
+
|
|
55
|
+
const x = xml
|
|
56
|
+
? normalise(xml)
|
|
57
|
+
: xml
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
chokidar.watch(x)
|
|
61
|
+
.on('ready', async function ready () {
|
|
62
|
+
func(
|
|
63
|
+
await transformToJS(j, x)
|
|
64
|
+
)
|
|
65
|
+
})
|
|
66
|
+
.on('change', async function change () {
|
|
67
|
+
func(
|
|
68
|
+
await transformToJS(j, x)
|
|
69
|
+
)
|
|
70
|
+
})
|
|
71
|
+
.on('error', ({ message }) => {
|
|
72
|
+
error(`Error in watcher: "${message}"`)
|
|
73
|
+
})
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function toES (jar, xml, func = () => {}) {
|
|
78
|
+
const j = jar
|
|
79
|
+
? normalise(jar)
|
|
80
|
+
: jar
|
|
81
|
+
|
|
82
|
+
const x = xml
|
|
83
|
+
? normalise(xml)
|
|
84
|
+
: xml
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
chokidar.watch(x)
|
|
88
|
+
.on('ready', async function ready () {
|
|
89
|
+
func(
|
|
90
|
+
await transformToES(j, x)
|
|
91
|
+
)
|
|
92
|
+
})
|
|
93
|
+
.on('change', async function change () {
|
|
94
|
+
func(
|
|
95
|
+
await transformToES(j, x)
|
|
96
|
+
)
|
|
97
|
+
})
|
|
98
|
+
.on('error', ({ message }) => {
|
|
99
|
+
error(`Error in watcher: "${message}"`)
|
|
100
|
+
})
|
|
101
|
+
)
|
|
102
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import chokidar from 'chokidar'
|
|
2
|
+
|
|
3
|
+
import debug from 'debug'
|
|
4
|
+
|
|
5
|
+
import musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
6
|
+
|
|
7
|
+
import normalise from '#music-library/common/normalise'
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
library: {
|
|
11
|
+
tracks: {
|
|
12
|
+
toM3U: parseToM3U
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
} = musicLibraryParser
|
|
16
|
+
|
|
17
|
+
const error = debug('@sequencemedia/music-library:error')
|
|
18
|
+
|
|
19
|
+
export function toM3U (jar, xml, destination) {
|
|
20
|
+
const j = jar
|
|
21
|
+
? normalise(jar)
|
|
22
|
+
: jar
|
|
23
|
+
|
|
24
|
+
const x = xml
|
|
25
|
+
? normalise(xml)
|
|
26
|
+
: xml
|
|
27
|
+
|
|
28
|
+
const d = destination
|
|
29
|
+
? normalise(destination)
|
|
30
|
+
: destination
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
chokidar.watch(x)
|
|
34
|
+
.on('ready', () => parseToM3U(j, x, d))
|
|
35
|
+
.on('change', () => parseToM3U(j, x, d))
|
|
36
|
+
.on('error', ({ message }) => {
|
|
37
|
+
error(`Error in watcher: "${message}"`)
|
|
38
|
+
})
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export * as transform from '#music-library/watch/library/tracks/transform'
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import chokidar from 'chokidar'
|
|
2
|
+
|
|
3
|
+
import debug from 'debug'
|
|
4
|
+
|
|
5
|
+
import musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
6
|
+
|
|
7
|
+
import normalise from '#music-library/common/normalise'
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
library: {
|
|
11
|
+
tracks: {
|
|
12
|
+
transform: {
|
|
13
|
+
toJSON: transformToJSON,
|
|
14
|
+
toJS: transformToJS,
|
|
15
|
+
toES: transformToES
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
} = musicLibraryParser
|
|
20
|
+
|
|
21
|
+
const error = debug('@sequencemedia/music-library:transform:error')
|
|
22
|
+
|
|
23
|
+
export function toJSON (jar, xml, func = () => {}) {
|
|
24
|
+
const j = jar
|
|
25
|
+
? normalise(jar)
|
|
26
|
+
: jar
|
|
27
|
+
|
|
28
|
+
const x = xml
|
|
29
|
+
? normalise(xml)
|
|
30
|
+
: xml
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
chokidar.watch(x)
|
|
34
|
+
.on('ready', async function ready () {
|
|
35
|
+
func(
|
|
36
|
+
await transformToJSON(j, x)
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
.on('change', async function change () {
|
|
40
|
+
func(
|
|
41
|
+
await transformToJSON(j, x)
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
.on('error', ({ message }) => {
|
|
45
|
+
error(`Error in watcher: "${message}"`)
|
|
46
|
+
})
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function toJS (jar, xml, func = () => {}) {
|
|
51
|
+
const j = jar
|
|
52
|
+
? normalise(jar)
|
|
53
|
+
: jar
|
|
54
|
+
|
|
55
|
+
const x = xml
|
|
56
|
+
? normalise(xml)
|
|
57
|
+
: xml
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
chokidar.watch(x)
|
|
61
|
+
.on('ready', async function ready () {
|
|
62
|
+
func(
|
|
63
|
+
await transformToJS(j, x)
|
|
64
|
+
)
|
|
65
|
+
})
|
|
66
|
+
.on('change', async function change () {
|
|
67
|
+
func(
|
|
68
|
+
await transformToJS(j, x)
|
|
69
|
+
)
|
|
70
|
+
})
|
|
71
|
+
.on('error', ({ message }) => {
|
|
72
|
+
error(`Error in watcher: "${message}"`)
|
|
73
|
+
})
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function toES (jar, xml, func = () => {}) {
|
|
78
|
+
const j = jar
|
|
79
|
+
? normalise(jar)
|
|
80
|
+
: jar
|
|
81
|
+
|
|
82
|
+
const x = xml
|
|
83
|
+
? normalise(xml)
|
|
84
|
+
: xml
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
chokidar.watch(x)
|
|
88
|
+
.on('ready', async function ready () {
|
|
89
|
+
func(
|
|
90
|
+
await transformToES(j, x)
|
|
91
|
+
)
|
|
92
|
+
})
|
|
93
|
+
.on('change', async function change () {
|
|
94
|
+
func(
|
|
95
|
+
await transformToES(j, x)
|
|
96
|
+
)
|
|
97
|
+
})
|
|
98
|
+
.on('error', ({ message }) => {
|
|
99
|
+
error(`Error in watcher: "${message}"`)
|
|
100
|
+
})
|
|
101
|
+
)
|
|
102
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import chokidar from 'chokidar'
|
|
2
|
+
|
|
3
|
+
import debug from 'debug'
|
|
4
|
+
|
|
5
|
+
import musicLibraryParser from '@sequencemedia/music-library-parser'
|
|
6
|
+
|
|
7
|
+
import normalise from '#music-library/common/normalise'
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
library: {
|
|
11
|
+
transform: {
|
|
12
|
+
toJSON: transformToJSON,
|
|
13
|
+
toJS: transformToJS,
|
|
14
|
+
toES: transformToES
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
} = musicLibraryParser
|
|
18
|
+
|
|
19
|
+
const error = debug('@sequencemedia/music-library:transform:error')
|
|
20
|
+
|
|
21
|
+
export function toJSON (jar, xml, func = () => {}) {
|
|
22
|
+
const j = jar
|
|
23
|
+
? normalise(jar)
|
|
24
|
+
: jar
|
|
25
|
+
|
|
26
|
+
const x = xml
|
|
27
|
+
? normalise(xml)
|
|
28
|
+
: xml
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
chokidar.watch(x)
|
|
32
|
+
.on('ready', async function ready () {
|
|
33
|
+
func(
|
|
34
|
+
await transformToJSON(j, x)
|
|
35
|
+
)
|
|
36
|
+
})
|
|
37
|
+
.on('change', async function change () {
|
|
38
|
+
func(
|
|
39
|
+
await transformToJSON(j, x)
|
|
40
|
+
)
|
|
41
|
+
})
|
|
42
|
+
.on('error', ({ message }) => {
|
|
43
|
+
error(`Error in watcher: "${message}"`)
|
|
44
|
+
})
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function toJS (jar, xml, func = () => {}) {
|
|
49
|
+
const j = jar
|
|
50
|
+
? normalise(jar)
|
|
51
|
+
: jar
|
|
52
|
+
|
|
53
|
+
const x = xml
|
|
54
|
+
? normalise(xml)
|
|
55
|
+
: xml
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
chokidar.watch(x)
|
|
59
|
+
.on('ready', async function ready () {
|
|
60
|
+
func(
|
|
61
|
+
await transformToJS(j, x)
|
|
62
|
+
)
|
|
63
|
+
})
|
|
64
|
+
.on('change', async function change () {
|
|
65
|
+
func(
|
|
66
|
+
await transformToJS(j, x)
|
|
67
|
+
)
|
|
68
|
+
})
|
|
69
|
+
.on('error', ({ message }) => {
|
|
70
|
+
error(`Error in watcher: "${message}"`)
|
|
71
|
+
})
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function toES (jar, xml, func = () => {}) {
|
|
76
|
+
const j = jar
|
|
77
|
+
? normalise(jar)
|
|
78
|
+
: jar
|
|
79
|
+
|
|
80
|
+
const x = xml
|
|
81
|
+
? normalise(xml)
|
|
82
|
+
: xml
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
chokidar.watch(x)
|
|
86
|
+
.on('ready', async function ready () {
|
|
87
|
+
func(
|
|
88
|
+
await transformToES(j, x)
|
|
89
|
+
)
|
|
90
|
+
})
|
|
91
|
+
.on('change', async function change () {
|
|
92
|
+
func(
|
|
93
|
+
await transformToES(j, x)
|
|
94
|
+
)
|
|
95
|
+
})
|
|
96
|
+
.on('error', ({ message }) => {
|
|
97
|
+
error(`Error in watcher: "${message}"`)
|
|
98
|
+
})
|
|
99
|
+
)
|
|
100
|
+
}
|