muzak 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc187bfa8da7fb7a6622bf25b063aed6ab25062b
4
- data.tar.gz: 85fea7679610e4f949be1b87ca8f141ba1c17d90
3
+ metadata.gz: 64f9b1939f3f50d2a64717f9becb02ed072f37e2
4
+ data.tar.gz: ff514441823414639bb1df7917517fae7e991eac
5
5
  SHA512:
6
- metadata.gz: 3b74e7a470a49f5fa099d89ae843b1d3eb0b3384136da673a0eecefa0c2b007a914a87bf6c0878e31c02943397ee3b475fbbdbce26b195c2e5581129927c41c2
7
- data.tar.gz: 62e8301ff354acc40ffd9d0ea858d899c9addc5fe776103e85681de2654fb1ecb57c6fe29006343a34807cb0061008a0540887e31a0d9b659350544861a3c3e5
6
+ metadata.gz: d49e644fb6ad60237635b412ec0c0595fcc51e60d3e2491deb9ad0aa4959afc074bd18fd0bf9d44e456baf60ed506fd5d1923756c39e2cc89f93388eef2cbbe0
7
+ data.tar.gz: be732cb96cf268795b9bf89f9b1eb2745c283d2fbbbd123af902bf56df13a45d97841ba3b784d56896a39d78b764cef8c80aa883d3816b0932bee18849e5e4cb
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "muzak"
4
5
  require "socket"
@@ -8,7 +9,7 @@ require "shellwords"
8
9
  begin
9
10
  server_host = Muzak::Config.daemon_host
10
11
  server_port = Muzak::Config.daemon_port
11
- sock = TCPSocket.new server_host, server_port
12
+ sock = TCPSocket.new server_host, server_port
12
13
  rescue
13
14
  error = { response: { error: "muzak is not running" } }.to_json
14
15
  puts error
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "muzak"
4
5
  require "socket"
5
6
  require "json"
6
7
  require "open3"
7
8
 
8
- DMENU_EXEC = Muzak::Config.dmenu_exec || "dmenu"
9
+ DMENU_EXEC = Muzak::Config.dmenu_exec || "dmenu"
9
10
  DMENU_LINES_EXEC = Muzak::Config.dmenu_lines_exec || "dmenu -l 10"
10
11
 
11
12
  def fatal(msg)
@@ -15,7 +16,8 @@ end
15
16
 
16
17
  def dmenu(options, lines: false)
17
18
  dmenu_cmd = lines ? DMENU_LINES_EXEC : DMENU_EXEC
18
- opts = options.join("\n")
19
+ opts = options.join("\n")
20
+
19
21
  Open3.popen2(dmenu_cmd) do |stdin, stdout|
20
22
  stdin.puts opts
21
23
  stdin.close
@@ -25,9 +27,7 @@ end
25
27
 
26
28
  def muzak_cmd(command)
27
29
  begin
28
- server_host = Muzak::Config.daemon_host
29
- server_port = Muzak::Config.daemon_port
30
- sock = TCPSocket.new server_host, server_port
30
+ sock = TCPSocket.new Muzak::Config.daemon_host, Muzak::Config.daemon_port
31
31
  rescue
32
32
  fatal "Is muzakd running?"
33
33
  end
@@ -60,4 +60,3 @@ command = "#{command.chomp} #{arguments}" if arguments
60
60
  puts command
61
61
 
62
62
  muzak_cmd command
63
-
@@ -1,37 +1,38 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "muzak"
4
5
 
5
- VERSION = 2
6
+ VERSION = 3
6
7
 
7
8
  OPTS = {
8
9
  deep: !!(ARGV.delete("--deep") || ARGV.delete("-d")),
9
10
  verbose: !!(ARGV.delete("--verbose") || ARGV.delete("-V")),
10
11
  help: !!(ARGV.delete("--help") || ARGV.delete("-h")),
11
- version: !!(ARGV.delete("--version") || ARGV.delete("-v"))
12
- }
12
+ version: !!(ARGV.delete("--version") || ARGV.delete("-v")),
13
+ }.freeze
13
14
 
14
- def help
15
- puts <<~EOS
16
- Usage: #{$PROGRAM_NAME} [options] [tree] [index]
15
+ HELP = <<~EOS
16
+ Usage: #{$PROGRAM_NAME} [options] [tree] [index]
17
17
 
18
- Options:
19
- --deep, -d Build a "deep" index (contains metadata)
20
- --verbose, -V Be verbose while indexing
21
- --help, -h Print this help message
22
- --version, -v Print version information
18
+ Options:
19
+ --deep, -d Build a "deep" index (contains metadata)
20
+ --verbose, -V Be verbose while indexing
21
+ --help, -h Print this help message
22
+ --version, -v Print version information
23
23
 
24
- Arguments:
25
- [tree] The filesystem tree to index (default: #{Muzak::Config.music})
26
- [index] The saved index (default: #{Muzak::Config::INDEX_FILE})
27
- EOS
24
+ Arguments:
25
+ [tree] The filesystem tree to index (default: #{Muzak::Config.music})
26
+ [index] The saved index (default: #{Muzak::Config::INDEX_FILE})
27
+ EOS
28
28
 
29
+ def help
30
+ puts HELP
29
31
  exit
30
32
  end
31
33
 
32
34
  def version
33
35
  puts "muzak-index version #{VERSION}."
34
-
35
36
  exit
36
37
  end
37
38
 
@@ -55,7 +56,7 @@ index_file = ARGV.shift || Muzak::Config::INDEX_FILE
55
56
  index_hash = {
56
57
  "tree" => tree,
57
58
  "timestamp" => Time.now.to_i,
58
- "deep" => OPTS[:deep]
59
+ "deep" => OPTS[:deep],
59
60
  }
60
61
 
61
62
  artist_names = Dir.entries(tree).reject! { |ent| ent.start_with?(".") }
@@ -70,8 +71,8 @@ artist_names.each do |artist|
70
71
 
71
72
  info "indexing '#{artist}' - '#{album}'..."
72
73
 
73
- album_hash = {}
74
- album_hash["songs"] = []
74
+ album_hash = {}
75
+ album_hash["songs"] = []
75
76
  album_hash["deep-songs"] = []
76
77
 
77
78
  Dir.glob(File.join(tree, artist, album, "**")) do |file|
@@ -79,9 +80,7 @@ artist_names.each do |artist|
79
80
 
80
81
  if Muzak::Utils.music?(file)
81
82
  album_hash["songs"] << file
82
- if OPTS[:deep]
83
- album_hash["deep-songs"] << Muzak::Song.new(file)
84
- end
83
+ album_hash["deep-songs"] << Muzak::Song.new(file) if OPTS[:deep]
85
84
  end
86
85
  end
87
86
 
@@ -90,7 +89,7 @@ artist_names.each do |artist|
90
89
  # if any of the track numbers in the album are > 0 (the fallback),
91
90
  # sort by ID3 track numbers. otherwise, hope that the song
92
91
  # paths contain track numbers (e.g, "01 song.mp3").
93
- if album_hash["deep-songs"].any? { |s| s.track > 0 }
92
+ if album_hash["deep-songs"].any? { |s| s.track.positive? }
94
93
  album_hash["deep-songs"].sort_by!(&:track)
95
94
  else
96
95
  album_hash["deep-songs"].sort_by!(&:path)
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "tty-prompt"
4
5
  require "muzak"
5
6
 
6
- VERSION = 1
7
+ VERSION = 2
7
8
 
8
9
  prompt = TTY::Prompt.new
9
10
 
data/bin/muzakd CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "muzak"
4
5
  require "shellwords"
@@ -8,8 +9,7 @@ require "thread"
8
9
 
9
10
  Process.daemon unless Muzak::Config.debug || Muzak::Config.verbose
10
11
 
11
- muzak = Muzak::Instance.new
12
-
12
+ muzak = Muzak::Instance.new
13
13
  server = TCPServer.new Muzak::Config.daemon_port
14
14
 
15
15
  loop do
@@ -18,10 +18,10 @@ loop do
18
18
  cmd_argv = Shellwords.split(client.readline)
19
19
  client.puts(muzak.command(*cmd_argv).to_json)
20
20
  exit! 0 if cmd_argv.first == "quit"
21
- rescue Exception => e
21
+ rescue => e
22
22
  client.puts({ response: { error: e.to_s } }.to_json)
23
23
  ensure
24
- client.close if client
24
+ client&.close
25
25
  end
26
26
  end
27
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "muzak/config"
2
4
  require_relative "muzak/utils"
3
5
  require_relative "muzak/plugin"
@@ -12,5 +14,5 @@ require_relative "muzak/instance"
12
14
  # The primary namespace for muzak.
13
15
  module Muzak
14
16
  # Muzak's current version
15
- VERSION = "0.4.2".freeze
17
+ VERSION = "0.5.0"
16
18
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  # Represents a collection of songs for muzak.
3
5
  class Album
@@ -14,8 +16,8 @@ module Muzak
14
16
  # @param songs [Array<Song>] the album's songs
15
17
  # @param cover_art [String] the album's cover art
16
18
  def initialize(title, songs, cover_art = nil)
17
- @title = title
18
- @songs = songs
19
+ @title = title
20
+ @songs = songs
19
21
  @cover_art = cover_art
20
22
  end
21
23
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Dir.glob(File.join(__dir__, "cmd/*")) { |f| require_relative f }
2
4
 
3
5
  module Muzak
@@ -5,7 +7,7 @@ module Muzak
5
7
  # @see file:COMMANDS.md User Commands
6
8
  module Cmd
7
9
  # load commands included by the user
8
- Dir.glob(File.join(Config::USER_COMMAND_DIR, "*")) { |file| require file }
10
+ Dir[Config::USER_COMMAND_GLOB].each { |cmd| require cmd }
9
11
 
10
12
  # @return [Array<String>] all valid muzak commands
11
13
  def self.commands
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "yaml"
2
4
 
3
5
  module Muzak
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  module Cmd
3
5
  # Reload the active index from the index file.
@@ -19,7 +21,7 @@ module Muzak
19
21
  # @cmdexample `muzak> dump-index`
20
22
  def dump_index
21
23
  build_response data: {
22
- index: index.hash
24
+ index: index.hash,
23
25
  }
24
26
  end
25
27
 
@@ -28,7 +30,7 @@ module Muzak
28
30
  # @cmdexample `muzak> list-artists`
29
31
  def list_artists
30
32
  build_response data: {
31
- artists: index.artists
33
+ artists: index.artists,
32
34
  }
33
35
  end
34
36
 
@@ -37,7 +39,7 @@ module Muzak
37
39
  # @cmdexample `muzak> list-albums`
38
40
  def list_albums
39
41
  build_response data: {
40
- albums: index.album_names
42
+ albums: index.album_names,
41
43
  }
42
44
  end
43
45
 
@@ -50,7 +52,7 @@ module Muzak
50
52
  albums = index.albums_by(artist).map(&:title)
51
53
 
52
54
  build_response data: {
53
- albums: albums
55
+ albums: albums,
54
56
  }
55
57
  end
56
58
 
@@ -63,7 +65,7 @@ module Muzak
63
65
  songs = index.songs_by(artist).map(&:title)
64
66
 
65
67
  build_response data: {
66
- songs: songs
68
+ songs: songs,
67
69
  }
68
70
  end
69
71
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  module Cmd
3
5
  # Return a simple heartbeat message.
@@ -8,16 +10,16 @@ module Muzak
8
10
  debug "pong: #{timestamp}"
9
11
 
10
12
  build_response data: {
11
- pong: timestamp
13
+ pong: timestamp,
12
14
  }
13
15
  end
14
16
 
15
17
  # Return a "helpful" listing of commands.
16
18
  # @command `help`
17
19
  # @cmdexample `muzak> help`
18
- def help(*args)
20
+ def help(*_args)
19
21
  build_response data: {
20
- commands: Muzak::Cmd.commands
22
+ commands: Muzak::Cmd.commands,
21
23
  }
22
24
  end
23
25
 
@@ -28,7 +30,7 @@ module Muzak
28
30
  # plugins are configured.
29
31
  def list_plugins
30
32
  build_response data: {
31
- plugins: Plugin.plugin_names
33
+ plugins: Plugin.plugin_names,
32
34
  }
33
35
  end
34
36
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  module Cmd
3
5
  # Activate the configured player.
@@ -12,7 +14,7 @@ module Muzak
12
14
  end
13
15
 
14
16
  build_response data: {
15
- player: player.class.name
17
+ player: player.class.name,
16
18
  }
17
19
  end
18
20
 
@@ -27,7 +29,7 @@ module Muzak
27
29
  player.deactivate!
28
30
 
29
31
  build_response data: {
30
- player: player.class.name
32
+ player: player.class.name,
31
33
  }
32
34
  end
33
35
 
@@ -87,7 +89,7 @@ module Muzak
87
89
  artist = args.join(" ")
88
90
  albums = index.albums_by(artist)
89
91
 
90
- unless albums.empty?
92
+ if albums.any?
91
93
  albums.each do |album|
92
94
  player.enqueue_album album
93
95
  end
@@ -102,8 +104,7 @@ module Muzak
102
104
  # @cmdexample `muzak> enqueue-album Your Favorite Album`
103
105
  def enqueue_album(*args)
104
106
  album_name = args.join(" ")
105
-
106
- album = index.albums[album_name]
107
+ album = index.albums[album_name]
107
108
 
108
109
  if album
109
110
  player.enqueue_album album
@@ -122,7 +123,7 @@ module Muzak
122
123
  songs.each { |s| player.enqueue_song s }
123
124
 
124
125
  build_response data: {
125
- jukebox: songs.map(&:full_title)
126
+ jukebox: songs.map(&:full_title),
126
127
  }
127
128
  end
128
129
 
@@ -131,7 +132,7 @@ module Muzak
131
132
  # @cmdexample `muzak> list-queue`
132
133
  def list_queue
133
134
  build_response data: {
134
- queue: player.list_queue.map(&:title)
135
+ queue: player.list_queue.map(&:title),
135
136
  }
136
137
  end
137
138
 
@@ -160,7 +161,7 @@ module Muzak
160
161
  def now_playing
161
162
  if player.playing?
162
163
  build_response data: {
163
- playing: player.now_playing&.full_title
164
+ playing: player.now_playing&.full_title,
164
165
  }
165
166
  else
166
167
  build_response error: "no currently playing song"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  module Cmd
3
5
  # List all currently available playlists.
@@ -5,7 +7,7 @@ module Muzak
5
7
  # @cmdexample `muzak> list-playlists`
6
8
  def list_playlists
7
9
  build_response data: {
8
- playlists: Playlist.playlist_names
10
+ playlists: Playlist.playlist_names,
9
11
  }
10
12
  end
11
13
 
@@ -53,7 +55,7 @@ module Muzak
53
55
  artist = args.join(" ")
54
56
  songs = index.songs_by(artist)
55
57
 
56
- unless songs.empty?
58
+ if songs.any?
57
59
  playlists[pname].add(songs)
58
60
  build_response
59
61
  else
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "yaml"
2
4
  require "fileutils"
3
5
 
@@ -23,12 +25,18 @@ module Muzak
23
25
  # The directory for all user playlists
24
26
  PLAYLIST_DIR = File.join(CONFIG_DIR, "playlists").freeze
25
27
 
28
+ # The glob pattern for all user playlists
29
+ PLAYLIST_GLOB = File.join(PLAYLIST_DIR, "*.yml").freeze
30
+
26
31
  # The directory for all user plugins
27
32
  USER_PLUGIN_DIR = File.join(CONFIG_DIR, "plugins").freeze
28
33
 
29
34
  # The directory for all user commands
30
35
  USER_COMMAND_DIR = File.join(CONFIG_DIR, "commands").freeze
31
36
 
37
+ # The glob pattern for all user commands
38
+ USER_COMMAND_GLOB = File.join(USER_COMMAND_DIR, "*.rb").freeze
39
+
32
40
  # All filename suffixes that muzak recognizes as music.
33
41
  MUSIC_SUFFIXES = [
34
42
  ".mp3",
@@ -41,17 +49,17 @@ module Muzak
41
49
  ].freeze
42
50
 
43
51
  # The regular expression that muzak uses to find album art.
44
- ALBUM_ART_REGEX = /(cover)|(folder).(jpg)|(png)/i.freeze
52
+ ALBUM_ART_REGEX = /(cover)|(folder).(jpg)|(png)/i
45
53
 
46
54
  # All events currently propagated by {Muzak::Instance#event}
47
- PLUGIN_EVENTS = [
48
- :instance_started,
49
- :instance_quitting,
50
- :player_activated,
51
- :player_deactivated,
52
- :song_loaded,
53
- :song_unloaded,
54
- :playlist_enqueued,
55
+ PLUGIN_EVENTS = %i[
56
+ instance_started
57
+ instance_quitting
58
+ player_activated
59
+ player_deactivated
60
+ song_loaded
61
+ song_unloaded
62
+ playlist_enqueued
55
63
  ].freeze
56
64
 
57
65
  # The default configuration keys and values.
@@ -91,7 +99,19 @@ module Muzak
91
99
  # Catches all undefined configuration keys and defaults them to false.
92
100
  # @return [false]
93
101
  def self.method_missing(method, *args)
94
- false
102
+ # this is basically useless, since respond_to_missing? will always be true,
103
+ # but it gets RuboCop to shut up.
104
+ if respond_to_missing? method, *args
105
+ false
106
+ else
107
+ super
108
+ end
109
+ end
110
+
111
+ # We "respond" to all methods with a default of false, so this is always true.
112
+ # @return [true]
113
+ def self.respond_to_missing?(*_args)
114
+ true
95
115
  end
96
116
 
97
117
  # @return [Boolean] whether or not the given plugin is configured
@@ -102,7 +122,7 @@ module Muzak
102
122
  end
103
123
 
104
124
  if File.exist?(CONFIG_FILE)
105
- user_config = YAML::load_file(CONFIG_FILE)
125
+ user_config = YAML.load_file(CONFIG_FILE)
106
126
  else
107
127
  user_config = DEFAULT_CONFIG
108
128
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  # Represents muzak's music index.
3
5
  class Index
@@ -26,8 +28,7 @@ module Muzak
26
28
  debug "loading index from '#{file}'..."
27
29
 
28
30
  @file = file
29
-
30
- @hash = Marshal.load(File.read file)
31
+ @hash = Marshal.load File.read(file) # rubocop:disable Security/MarshalLoad
31
32
 
32
33
  memoize_collections!
33
34
  end
@@ -37,7 +38,7 @@ module Muzak
37
38
  # @return [void]
38
39
  def reload!
39
40
  debug "reloading index from '#{file}'..."
40
- @hash = Marshal.load(File.read file)
41
+ @hash = Marshal.load File.read(file) # rubocop:disable Security/MarshalLoad
41
42
  @albums_hash = nil
42
43
  memoize_collections!
43
44
  end
@@ -65,11 +66,7 @@ module Muzak
65
66
 
66
67
  artists.each do |a|
67
68
  @hash["artists"][a]["albums"].each do |title, album_hash|
68
- if deep?
69
- songs = album_hash["deep-songs"]
70
- else
71
- songs = album_hash["songs"].map { |s| Song.new(s) }
72
- end
69
+ songs = load_songs album_hash
73
70
  albums_hash[title] = Album.new(title, songs, album_hash["cover"])
74
71
  end
75
72
  end
@@ -101,11 +98,7 @@ module Muzak
101
98
  def albums_by(artist)
102
99
  if artists.include?(artist)
103
100
  @hash["artists"][artist]["albums"].map do |title, album_hash|
104
- if deep?
105
- songs = album_hash["deep-songs"]
106
- else
107
- songs = album_hash["songs"].map { |s| Song.new(s) }
108
- end
101
+ songs = load_songs album_hash
109
102
  Album.new(title, songs, album_hash["cover"])
110
103
  end
111
104
  else
@@ -133,10 +126,8 @@ module Muzak
133
126
  error "no such artist: '#{artist}'" unless @hash["artists"].key?(artist)
134
127
 
135
128
  begin
136
- albums_by(artist).map do |album|
137
- album.songs
138
- end.flatten
139
- rescue Exception => e
129
+ albums_by(artist).map(&:songs).flatten
130
+ rescue
140
131
  []
141
132
  end
142
133
  end
@@ -148,10 +139,23 @@ module Muzak
148
139
  @all_albums = @hash["artists"].map { |_, a| a["albums"] }.flatten
149
140
 
150
141
  if deep?
151
- @all_deep_songs = @all_albums.map { |aa| aa.map { |_, a| a["deep-songs"] } }.flatten
142
+ @all_deep_songs = @all_albums.map do |aa|
143
+ aa.map { |_, a| a["deep-songs"] }
144
+ end.flatten
152
145
  else
153
146
  @all_songs = @all_albums.map { |aa| aa.map { |_, a| a["songs"] } }.flatten
154
147
  end
155
148
  end
149
+
150
+ # Load the songs from an album hash into {Song} instances.
151
+ # @param ah [Hash] the album hash
152
+ # @api private
153
+ def load_songs(ah)
154
+ if deep?
155
+ ah["deep-songs"]
156
+ else
157
+ ah["songs"].map { |s| Song.new s }
158
+ end
159
+ end
156
160
  end
157
161
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  # Encapsulates the entirety of muzak's running state.
3
5
  class Instance
@@ -15,7 +17,7 @@ module Muzak
15
17
  if Cmd.commands.include?(cmd)
16
18
  meth = method(Config.resolve_command(cmd))
17
19
  if meth.arity == args.size || meth.arity <= -1
18
- meth.call *args
20
+ meth.call(*args)
19
21
  else
20
22
  build_response error: "got #{args.size} args, needed #{meth.arity}"
21
23
  end
@@ -42,12 +44,9 @@ module Muzak
42
44
 
43
45
  error! "#{Config.music} doesn't exist" unless File.exist?(Config.music)
44
46
 
45
- @index = Index.load_index!
46
-
47
- @player = Player.load_player!(self)
48
-
49
- @plugins = Plugin.load_plugins!
50
-
47
+ @index = Index.load_index!
48
+ @player = Player.load_player!(self)
49
+ @plugins = Plugin.load_plugins!
51
50
  @playlists = Playlist.load_playlists!
52
51
 
53
52
  enqueue_playlist Config.default_playlist if Config.default_playlist
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # we have to require StubPlayer first because ruby's module resolution is bad
2
4
  require_relative "player/stub_player"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "ruby-mpd"
2
4
 
3
5
  module Muzak
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "tempfile"
2
4
  require "socket"
3
5
  require "json"
@@ -8,6 +10,14 @@ module Muzak
8
10
  module Player
9
11
  # Exposes MPV's IPC to muzak for playback control.
10
12
  class MPV < StubPlayer
13
+ DEFAULT_MPV_ARGS = [
14
+ "--no-osc",
15
+ "--no-osd-bar",
16
+ "--no-input-default-bindings",
17
+ "--no-input-cursor",
18
+ "--load-scripts=no", # autoload and other scripts clobber our mpv management
19
+ ].freeze
20
+
11
21
  # @return [Boolean] whether or not MPV is available for execution
12
22
  def self.available?
13
23
  ::MPV::Server.available?
@@ -25,24 +35,7 @@ module Muzak
25
35
 
26
36
  debug "activating #{self.class}"
27
37
 
28
- args = [
29
- # there's also this, which (might) also work
30
- # "--audio-display=no",
31
- "--no-osc",
32
- "--no-osd-bar",
33
- "--no-input-default-bindings",
34
- "--no-input-cursor",
35
- "--load-scripts=no", # autoload and other scripts with clobber our mpv management
36
- ]
37
-
38
- args.concat ["--no-force-window", "--no-video"] if Config.mpv_no_art
39
-
40
- args << "--geometry=#{Config.art_geometry}" if Config.art_geometry
41
-
42
- # this is an experimental flag, but it could improve
43
- # muzak's load times substantially when used with a network
44
- # mounted music library
45
- args << "--prefetch-playlist" if ::MPV::Server.has_flag?("--prefetch-playlist")
38
+ args = DEFAULT_MPV_ARGS + configured_mpv_args
46
39
 
47
40
  @mpv = ::MPV::Session.new(user_args: args)
48
41
  @mpv.callbacks << ::MPV::Callback.new(self, :dispatch_event!)
@@ -172,7 +165,22 @@ module Muzak
172
165
  # Get mpv's currently loaded song.
173
166
  # @return [Song, nil] the currently loaded song
174
167
  def now_playing
175
- @_now_playing ||= Song.new(@mpv.get_property "path")
168
+ @_now_playing ||= Song.new @mpv.get_property("path")
169
+ end
170
+
171
+ def configured_mpv_args
172
+ args = []
173
+
174
+ args.concat ["--no-force-window", "--no-video"] if Config.mpv_no_art
175
+
176
+ args << "--geometry=#{Config.art_geometry}" if Config.art_geometry
177
+
178
+ # this is an experimental flag, but it could improve
179
+ # muzak's load times substantially when used with a network
180
+ # mounted music library
181
+ args << "--prefetch-playlist" if ::MPV::Server.has_flag?("--prefetch-playlist")
182
+
183
+ args
176
184
  end
177
185
 
178
186
  # Load a song and optional album art into mpv.
@@ -184,7 +192,7 @@ module Muzak
184
192
  append_type = Config.autoplay ? "append-play" : "append"
185
193
  cmds = ["loadfile", song.path, append_type]
186
194
  cmds << "external-file=\"#{art}\"" if art
187
- @mpv.command *cmds
195
+ @mpv.command(*cmds)
188
196
  end
189
197
 
190
198
  # Dispatch the given event to the active {Muzak::Instance}.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  module Player
3
5
  # Wraps multiple players into a single class.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  module Player
3
5
  # A no-op player that all players inherit from.
@@ -85,7 +87,7 @@ module Muzak
85
87
  # @param song [Song] the song to enqueue
86
88
  # @return [void]
87
89
  # @note NO-OP
88
- def enqueue_song(song)
90
+ def enqueue_song(_song)
89
91
  debug "#enqueue_song"
90
92
  end
91
93
 
@@ -93,7 +95,7 @@ module Muzak
93
95
  # @param album [Album] the album to enqueue
94
96
  # @return [void]
95
97
  # @note NO-OP
96
- def enqueue_album(album)
98
+ def enqueue_album(_album)
97
99
  debug "#enqueue_album"
98
100
  end
99
101
 
@@ -101,7 +103,7 @@ module Muzak
101
103
  # @param playlist [Playlist] the playlist to enqueue
102
104
  # @return [void]
103
105
  # @note NO-OP
104
- def enqueue_playlist(playlist)
106
+ def enqueue_playlist(_playlist)
105
107
  debug "#enqueue_playlist"
106
108
  end
107
109
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "vlc-client"
2
4
 
3
5
  module Muzak
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  # Represents a sequential list of songs for muzak.
3
5
  class Playlist
@@ -30,11 +32,7 @@ module Muzak
30
32
 
31
33
  # @return [Array<String>] the names of all currently available playlists
32
34
  def self.playlist_names
33
- Dir.entries(Config::PLAYLIST_DIR).reject do |ent|
34
- ent.start_with?(".")
35
- end.map do |ent|
36
- File.basename(ent, File.extname(ent))
37
- end
35
+ Dir[Config::PLAYLIST_GLOB].map { |p| File.basename(p, File.extname(p)) }
38
36
  end
39
37
 
40
38
  # Instantiates all playlists by loading them from disk.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # we have to require StubPlugin first because ruby's module resolution is bad
2
4
  require_relative "plugin/stub_plugin"
3
5
 
@@ -30,7 +32,7 @@ module Muzak
30
32
  Config.plugin?(pk.plugin_name) && pk.available?
31
33
  end
32
34
 
33
- pks.map { |pk| pk.new }
35
+ pks.map(&:new)
34
36
  end
35
37
  end
36
38
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "taglib"
2
4
  require "json"
3
5
 
@@ -39,15 +41,14 @@ module Muzak
39
41
  @path = path
40
42
 
41
43
  TagLib::FileRef.open(path) do |ref|
42
- break if ref.null?
43
- @title = ref.tag.title
44
- @artist = ref.tag.artist
45
- @album = ref.tag.album
46
- @year = ref.tag.year
47
- @track = ref.tag.track
48
- @genre = ref.tag.genre
49
- @comment = ref.tag.comment
50
- @length = ref.audio_properties.length
44
+ @title = ref&.tag&.title
45
+ @artist = ref&.tag&.artist
46
+ @album = ref&.tag&.album
47
+ @year = ref&.tag&.year
48
+ @track = ref&.tag&.track
49
+ @genre = ref&.tag&.genre
50
+ @comment = ref&.tag&.comment
51
+ @length = ref&.audio_properties&.length
51
52
  end
52
53
 
53
54
  # provide some sane fallbacks
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Muzak
2
4
  # A collection of convenience utilities for use throughout muzak.
3
5
  module Utils
@@ -38,13 +40,13 @@ module Muzak
38
40
  # @param color [Symbol] the color to use on the string
39
41
  # @param str [String] the string to format
40
42
  # @return [String] the color-formatted string
41
- def pretty(color = :none, str)
43
+ def pretty(str, color = :none)
42
44
  colors = {
43
45
  none: 0,
44
46
  red: 31,
45
47
  green: 32,
46
48
  yellow: 33,
47
- blue: 34
49
+ blue: 34,
48
50
  }
49
51
 
50
52
  "\e[#{colors[color]}m#{str}\e[0m"
@@ -63,22 +65,22 @@ module Muzak
63
65
  # @param args [Array<String>] the message(s)
64
66
  # @return [void]
65
67
  def danger(*args)
66
- output pretty(:yellow, "warn"), args
68
+ output pretty("warn", :yellow), args
67
69
  end
68
70
 
69
71
  # Outputs a boxed error message.
70
72
  # @param args [Array<String>] the message(s)
71
73
  # @return [void]
72
74
  def error(*args)
73
- context = self.is_a?(Module) ? name : self.class.name
74
- output pretty(:red, "error"), "[#{context}]", args
75
+ context = is_a?(Module) ? name : self.class.name
76
+ output pretty("error", :red), "[#{context}]", args
75
77
  end
76
78
 
77
79
  # Outputs a boxed error message and then exits.
78
80
  # @param args [Array<String>] the message(s)
79
81
  # @return [void]
80
82
  def error!(*args)
81
- error *args
83
+ error(*args)
82
84
  exit 1
83
85
  end
84
86
 
@@ -87,8 +89,8 @@ module Muzak
87
89
  # @return [void]
88
90
  def debug(*args)
89
91
  return unless debug?
90
- context = self.is_a?(Module) ? name : self.class.name
91
- output pretty(:yellow, "debug"), "[#{context}]", args
92
+ context = is_a?(Module) ? name : self.class.name
93
+ output pretty("debug", :yellow), "[#{context}]", args
92
94
  end
93
95
 
94
96
  # Outputs a boxed verbose message.
@@ -97,18 +99,19 @@ module Muzak
97
99
  def verbose(*args)
98
100
  return unless verbose?
99
101
 
100
- output pretty(:blue, "verbose"), args
102
+ output pretty("verbose", :blue), args
101
103
  end
102
104
 
103
105
  # Returns a response hash containing the given data and error.
104
106
  # @param error [String] the error string, if needed
105
107
  # @param data [String, Hash] the data, if needed
106
108
  def build_response(error: nil, data: nil)
107
- { response: {
109
+ {
110
+ response: {
108
111
  error: error,
109
112
  data: data,
110
- method: caller_locations.first.label
111
- }
113
+ method: caller_locations.first.label,
114
+ },
112
115
  }
113
116
  end
114
117
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: muzak
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Woodruff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-28 00:00:00.000000000 Z
11
+ date: 2017-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: taglib-ruby