Class: Drum::MusicService

Inherits:
Service show all
Includes:
Log
Defined in:
lib/drum/service/music.rb

Overview

Instance Method Summary collapse

Methods included from Log

#log

Methods inherited from Service

#remove

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_proxyObject



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

#nameObject



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_scptObject



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