apple_music_library 0.3.0 → 0.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/Gemfile.lock +1 -1
- data/README.md +6 -0
- data/apple_music_library.gemspec +1 -1
- data/lib/apple_music_library/library.rb +12 -80
- data/lib/apple_music_library/playlist.rb +27 -20
- data/lib/apple_music_library/playlist_folder.rb +55 -0
- data/lib/apple_music_library/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90fcf6cf83ff9c5cf4bf0cf022ad5b4038c0464277a86e20c658580661cb233a
|
4
|
+
data.tar.gz: 3498457024ed7a40644dc14baa9eccb7b1f072e92d28f7739cf49959c86d90ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86f0e0d87e57d27a93034f0b055399c37c2a265984726eba7b1dc2e6ddd15a2ebb34a11676c64411417e772320ec170bad7b52eb91c35f703a9cd6286c923a74
|
7
|
+
data.tar.gz: 4ebe190007f3e9426dfe6968b61934cea5bc23e63cb72d4a824de9ff5a97061abd27b9dc91639c4af8492f438d04623338581a5c99697dbb920cbc1f89d6af19
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [Unreleased]
|
4
|
+
- Ability to print out playlist folder hierarchy
|
5
|
+
|
6
|
+
## 0.4.0 - 2022-03-10
|
7
|
+
### Added
|
8
|
+
- Basic functionality for Playlist Folders
|
9
|
+
### Fixed
|
10
|
+
- The #find_by_name methods for Playlists and PlaylistFolders now return a single object when only a single exact match is found (the most common case) but continue to return an array of objects when there are multiple matches.
|
11
|
+
|
12
|
+
## 0.3.0 - 2022-03-10
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
- Fixed handling of albums, genres, and playlists as accessed via methods on artists/tracks.
|
16
|
+
|
17
|
+
## 0.2.0 - 2022-03-10
|
18
|
+
### Added
|
19
|
+
- Basic functionality to parse a library plist into Track, Album, Artist, Genre, and Playlist objects.
|
20
|
+
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -28,6 +28,12 @@ library = AppleMusicLibrary.new('path/to/Library.xml')
|
|
28
28
|
# Count albums
|
29
29
|
puts library.albums.count
|
30
30
|
|
31
|
+
# Show playlist inside playlist folder
|
32
|
+
playlist_folder = library.playlist_folder('Folder for Testing')
|
33
|
+
playlist_folder.playlists.each do |playlist|
|
34
|
+
puts playlist.name
|
35
|
+
end
|
36
|
+
|
31
37
|
# Show tracks in a specific playlist
|
32
38
|
playlist = library.playlist('XTC Favorites')
|
33
39
|
playlist.tracks.each do |track|
|
data/apple_music_library.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ["Todd Gehman"]
|
9
9
|
spec.email = ["github@pugetive.com"]
|
10
10
|
|
11
|
-
spec.summary = "Provides a
|
11
|
+
spec.summary = "Provides a Ruby interface to the information stored in an Apple Music (formerly iTunes) Library xml file."
|
12
12
|
# spec.description = "TODO: Write a longer description or delete this line."
|
13
13
|
spec.homepage = "https://github.com/pugetive/apple_music_library"
|
14
14
|
spec.license = "MIT"
|
@@ -2,6 +2,7 @@ require_relative 'album'
|
|
2
2
|
require_relative 'artist'
|
3
3
|
require_relative 'genre'
|
4
4
|
require_relative 'playlist'
|
5
|
+
require_relative 'playlist_folder'
|
5
6
|
require_relative 'track'
|
6
7
|
require_relative "utils"
|
7
8
|
require 'plist'
|
@@ -67,6 +68,14 @@ module AppleMusicLibrary
|
|
67
68
|
Playlist.find_by_name(playlist_name)
|
68
69
|
end
|
69
70
|
|
71
|
+
def playlist_folders
|
72
|
+
@playlist_folders ||= PlaylistFolder.all
|
73
|
+
end
|
74
|
+
|
75
|
+
def playlist_folder(playlist_folder_name)
|
76
|
+
PlaylistFolder.find_by_name(playlist_folder_name)
|
77
|
+
end
|
78
|
+
|
70
79
|
def tracks
|
71
80
|
@tracks ||= Track.all
|
72
81
|
end
|
@@ -108,89 +117,12 @@ module AppleMusicLibrary
|
|
108
117
|
|
109
118
|
def extract_playlists_from_plist
|
110
119
|
plist['Playlists'].each do |playlist_info|
|
111
|
-
|
120
|
+
# The distinction between playlists and playlist folders
|
121
|
+
# is made inside the Playlist instantiation
|
122
|
+
Playlist.new(playlist_info)
|
112
123
|
end
|
113
124
|
end
|
114
125
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
# def track(track_id)
|
120
|
-
# track = @tracks_hash[track_id.to_i]
|
121
|
-
# if track.nil?
|
122
|
-
# message("Cound not find track with ID [#{track_id}]")
|
123
|
-
# message("Searched tracks: [#{@tracks_hash.keys.sort.join(', ')}]")
|
124
|
-
# end
|
125
|
-
# track
|
126
|
-
# end
|
127
|
-
|
128
|
-
# private
|
129
|
-
|
130
|
-
# def extract_plist_info
|
131
|
-
# non_music_formats = {}
|
132
|
-
# plist['Tracks'].each do |track|
|
133
|
-
# if MUSIC_FORMATS.include?(track[1]['Kind'])
|
134
|
-
# track = Track.new(track[1])
|
135
|
-
# # next if track.artist.name == 'NPR'
|
136
|
-
# @tracks_hash[track.id] = track
|
137
|
-
# # @locations_hash[track.location] = track
|
138
|
-
|
139
|
-
# artist = Artist.find_or_create(track.artist_name)
|
140
|
-
# album = add_track_to_album(track, track.album)
|
141
|
-
# artist.add_album(album)
|
142
|
-
|
143
|
-
# if track.genre_name.present?
|
144
|
-
# genre = add_track_to_genre(track)
|
145
|
-
# end
|
146
|
-
# else
|
147
|
-
# non_music_formats[track[1]['Kind']] = true
|
148
|
-
# end
|
149
|
-
# end
|
150
|
-
|
151
|
-
# plist['Playlists'].each do |playlist_info|
|
152
|
-
# playlist = Playlist.new(playlist_info, self)
|
153
|
-
# next if playlist.folder?
|
154
|
-
# @playlists_hash[playlist.id] = playlist
|
155
|
-
# end
|
156
|
-
|
157
|
-
# if non_music_formats.any?
|
158
|
-
# message("Skipped the following non-music formats:\n#{non_music_formats.keys.join(', ')}")
|
159
|
-
# end
|
160
|
-
# end
|
161
|
-
|
162
|
-
|
163
|
-
# def add_artist(artist)
|
164
|
-
# Artist.find_or_create(artist_name)
|
165
|
-
# end
|
166
|
-
|
167
|
-
# def add_track_to_album(track, album)
|
168
|
-
# unless album = @albums_hash[album.id]
|
169
|
-
# @albums_hash[album.id] = album
|
170
|
-
# end
|
171
|
-
# album.add_track(track)
|
172
|
-
# album
|
173
|
-
# end
|
174
|
-
|
175
|
-
# def find_or_create_album(album)
|
176
|
-
# unless @albums_hash[album.id]
|
177
|
-
# @albums_hash[album.id] = album
|
178
|
-
# end
|
179
|
-
# album.artist.add_album(album)
|
180
|
-
# end
|
181
|
-
|
182
|
-
|
183
|
-
# def add_track_to_genre(track)
|
184
|
-
# if @genres_hash[track.genre_name]
|
185
|
-
# return @genres_hash[track.genre_name]
|
186
|
-
# end
|
187
|
-
# # message("Creating new artist #{artist.name}")
|
188
|
-
# genre = AppleMusicLibrary::Genre.new(track.genre_name)
|
189
|
-
# @genres_hash[track.genre_name] = genre
|
190
|
-
# genre.add_track(track)
|
191
|
-
# genre
|
192
|
-
# end
|
193
|
-
|
194
126
|
end
|
195
127
|
|
196
128
|
end
|
@@ -1,17 +1,3 @@
|
|
1
|
-
# <key>Name</key><string>Non-XTC</string>
|
2
|
-
# <key>Description</key><string></string>
|
3
|
-
# <key>Playlist ID</key><integer>79359</integer>
|
4
|
-
# <key>Playlist Persistent ID</key><string>59C95825DF1F0DCC</string>
|
5
|
-
# <key>All Items</key><true/>
|
6
|
-
# <key>Smart Info</key>
|
7
|
-
# <data>
|
8
|
-
# AQEAAwAAAAIAAAAZAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
9
|
-
# AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
10
|
-
# AAAAAA==
|
11
|
-
# </data>
|
12
|
-
# <key>Smart Criteria</key>
|
13
|
-
# <data>
|
14
|
-
|
15
1
|
require 'facets'
|
16
2
|
|
17
3
|
module AppleMusicLibrary
|
@@ -25,18 +11,20 @@ module AppleMusicLibrary
|
|
25
11
|
'Description',
|
26
12
|
'Playlist ID',
|
27
13
|
'Playlist Persistent ID',
|
14
|
+
'Parent Persistent ID',
|
28
15
|
'All Items',
|
29
16
|
'Smart Info',
|
30
17
|
'Smart Criteria',
|
31
18
|
'Playlist Items',
|
32
19
|
'Folder']
|
33
20
|
|
34
|
-
def initialize(info
|
21
|
+
def initialize(info)
|
35
22
|
@info = info
|
36
23
|
|
37
|
-
|
24
|
+
if folder?
|
25
|
+
return PlaylistFolder.new(info)
|
26
|
+
end
|
38
27
|
|
39
|
-
@library = library
|
40
28
|
@tracks = []
|
41
29
|
|
42
30
|
load_tracks
|
@@ -49,11 +37,15 @@ module AppleMusicLibrary
|
|
49
37
|
end
|
50
38
|
|
51
39
|
def self.find_by_name(playlist_name)
|
52
|
-
@@playlists.values.select{|p| p.name == playlist_name}
|
40
|
+
results = @@playlists.values.select{|p| p.name == playlist_name}
|
41
|
+
if results.size == 1
|
42
|
+
return results.first
|
43
|
+
end
|
44
|
+
results
|
53
45
|
end
|
54
46
|
|
55
47
|
def id
|
56
|
-
|
48
|
+
playlist_persistent_id
|
57
49
|
end
|
58
50
|
|
59
51
|
ATTRIBUTES.each do |attribute|
|
@@ -72,7 +64,7 @@ module AppleMusicLibrary
|
|
72
64
|
if playlist_items and playlist_items.any?
|
73
65
|
playlist_items.each do |playlist_item|
|
74
66
|
track_id = playlist_item['Track ID']
|
75
|
-
track =
|
67
|
+
track = Track.find(track_id)
|
76
68
|
@tracks << track
|
77
69
|
end
|
78
70
|
end
|
@@ -81,3 +73,18 @@ module AppleMusicLibrary
|
|
81
73
|
|
82
74
|
end
|
83
75
|
end
|
76
|
+
|
77
|
+
# <key>Name</key><string>Non-XTC</string>
|
78
|
+
# <key>Description</key><string></string>
|
79
|
+
# <key>Playlist ID</key><integer>79359</integer>
|
80
|
+
# <key>Playlist Persistent ID</key><string>59C95825DF1F0DCC</string>
|
81
|
+
# <key>All Items</key><true/>
|
82
|
+
# <key>Smart Info</key>
|
83
|
+
# <data>
|
84
|
+
# AQEAAwAAAAIAAAAZAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
85
|
+
# AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
86
|
+
# AAAAAA==
|
87
|
+
# </data>
|
88
|
+
# <key>Smart Criteria</key>
|
89
|
+
# <data>
|
90
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'facets'
|
2
|
+
|
3
|
+
module AppleMusicLibrary
|
4
|
+
class PlaylistFolder
|
5
|
+
|
6
|
+
attr_reader :info
|
7
|
+
|
8
|
+
@@playlist_folders = {}
|
9
|
+
|
10
|
+
def initialize(info)
|
11
|
+
@info = info
|
12
|
+
|
13
|
+
@@playlist_folders[id] = self
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.all
|
17
|
+
@@playlist_folders.values
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.find_by_name(playlist_folder_name)
|
21
|
+
results = @@playlist_folders.values.select{|pf| pf.name == playlist_folder_name}
|
22
|
+
if results.size == 1
|
23
|
+
return results.first
|
24
|
+
end
|
25
|
+
results
|
26
|
+
end
|
27
|
+
|
28
|
+
def id
|
29
|
+
playlist_persistent_id
|
30
|
+
end
|
31
|
+
|
32
|
+
def children
|
33
|
+
playlist_folders.concat(playlists)
|
34
|
+
end
|
35
|
+
|
36
|
+
def playlist_folders
|
37
|
+
@@playlist_folders.values.select{|pf| pf.parent_persistent_id == id}
|
38
|
+
end
|
39
|
+
|
40
|
+
def playlists
|
41
|
+
Playlist.all.select{|p| p.parent_persistent_id == id}
|
42
|
+
end
|
43
|
+
|
44
|
+
Playlist::ATTRIBUTES.each do |attribute|
|
45
|
+
define_method(attribute.to_s.snakecase) do
|
46
|
+
info[attribute]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apple_music_library
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Todd Gehman
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-03-
|
11
|
+
date: 2022-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|
@@ -116,6 +116,7 @@ extensions: []
|
|
116
116
|
extra_rdoc_files: []
|
117
117
|
files:
|
118
118
|
- ".rspec"
|
119
|
+
- CHANGELOG.md
|
119
120
|
- Gemfile
|
120
121
|
- Gemfile.lock
|
121
122
|
- LICENSE.txt
|
@@ -128,6 +129,7 @@ files:
|
|
128
129
|
- lib/apple_music_library/genre.rb
|
129
130
|
- lib/apple_music_library/library.rb
|
130
131
|
- lib/apple_music_library/playlist.rb
|
132
|
+
- lib/apple_music_library/playlist_folder.rb
|
131
133
|
- lib/apple_music_library/track.rb
|
132
134
|
- lib/apple_music_library/utils.rb
|
133
135
|
- lib/apple_music_library/version.rb
|
@@ -156,6 +158,6 @@ requirements: []
|
|
156
158
|
rubygems_version: 3.3.3
|
157
159
|
signing_key:
|
158
160
|
specification_version: 4
|
159
|
-
summary: Provides a
|
160
|
-
|
161
|
+
summary: Provides a Ruby interface to the information stored in an Apple Music (formerly
|
162
|
+
iTunes) Library xml file.
|
161
163
|
test_files: []
|