muzak 0.4.2 → 0.5.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 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