Class: Drum::MusicService
- Includes:
- Log
- Defined in:
- lib/drum/service/music.rb
Overview
A service that uses AppleScript to interact with the local Apple Music (Music.app) library.
Useful resources:
Instance Method Summary collapse
-
#download(ref) ⇒ Object
Service.
- #get_library_proxy ⇒ Object
- #name ⇒ Object
-
#parse_ref(raw_ref) ⇒ Object
Ref parsing.
- #require_rb_scpt ⇒ Object
-
#to_track_proxy(library_proxy, playlist, track) ⇒ Object
Upload helpers.
- #upload(ref, playlists) ⇒ Object
- #upload_playlist(library_proxy, playlist) ⇒ Object
Methods included from Log
Methods inherited from Service
Instance Method Details
#download(ref) ⇒ Object
Service
101 102 103 |
# File 'lib/drum/service/music.rb', line 101 def download(ref) raise 'Downloading is not implemented yet' end |
#get_library_proxy ⇒ Object
34 35 36 37 38 39 40 41 42 |
# File 'lib/drum/service/music.rb', line 34 def get_library_proxy self.require_rb_scpt music = Appscript.app('Music') source = music.sources[1] unless source.kind.get == :library raise 'Could not get music library source' end return source end |
#name ⇒ Object
22 23 24 |
# File 'lib/drum/service/music.rb', line 22 def name 'music' end |
#parse_ref(raw_ref) ⇒ Object
Ref parsing
46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/drum/service/music.rb', line 46 def parse_ref(raw_ref) if raw_ref.is_token location = case raw_ref.text when "#{self.name}/playlists" then :playlists else return nil end Ref.new(self.name, :special, location) else nil end end |
#require_rb_scpt ⇒ Object
26 27 28 29 30 31 32 |
# File 'lib/drum/service/music.rb', line 26 def require_rb_scpt begin require 'rb-scpt' rescue LoadError raise "Using the local Apple Music importer requires the 'rb-scpt' gem (which requires macOS)" end end |
#to_track_proxy(library_proxy, playlist, track) ⇒ Object
Upload helpers
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/drum/service/music.rb', line 60 def to_track_proxy(library_proxy, playlist, track) # Get track metadata name = track.name artists = track.artist_ids.map { |id| playlist.artists[id].name } # Match the track with a track in the local library # TODO: Don't require exact 100% matches name_query = Appscript.its.name.eq(name) artists_query = artists .map { |a| Appscript.its.artist.contains(a) } .reduce { |q1, q2| q1.or(q2) } query = name_query.and(artists_query) # Find a matching track in the track # TODO: Instead of choosing the first, prefer iTunes-matched/higher bitrate ones etc. track_proxy = library_proxy.tracks[query].get.first if track_proxy.nil? log.warn "No match found for '#{track.name}' by '#{artists.first}'" else log.info "Matched '#{track.name}' with '#{track_proxy.name.get}' by '#{track_proxy.artist.get}'" end track_proxy end |
#upload(ref, playlists) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/drum/service/music.rb', line 105 def upload(ref, playlists) library_proxy = self.get_library_proxy unless ref.resource_type == :special && ref.resource_location == :playlists raise "Cannot upload to anything other than @#{self.name}/playlists yet!" end playlists.each do |playlist| self.upload_playlist(library_proxy, playlist) end end |
#upload_playlist(library_proxy, playlist) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/drum/service/music.rb', line 85 def upload_playlist(library_proxy, playlist) playlist_proxy = library_proxy.make(new: :playlist, with_properties: { name: playlist.name, description: playlist.description, }.compact) playlist.tracks.each do |track| track_proxy = self.to_track_proxy(library_proxy, playlist, track) unless track_proxy.nil? track_proxy.duplicate(to: playlist_proxy) end end end |