listlace 0.1.0 → 0.2.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/Gemfile.lock +3 -3
- data/README.md +137 -1
- data/lib/listlace/commands.rb +64 -10
- data/lib/listlace/core_ext/array.rb +25 -0
- data/lib/listlace/selectors.rb +44 -0
- data/lib/listlace.rb +7 -3
- data/listlace.gemspec +3 -3
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e2d5c543763b463ddeb7d210dd9462eaca05944
|
4
|
+
data.tar.gz: a91502ded9981eade141ba10f7ee90b4fdf0e9ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da90361e229cf18c7f273ea58fa1bae79f2ae6e7f8b3fbfbf9d7e7163798c3653299562602863030a36937c0b98fd9a57b785ce119e707992a9a34fd0057142b
|
7
|
+
data.tar.gz: 116b0aa40716b9cde245cb3042fcf0efd37b89a119f17fcbe36ad8697de08c30fa7f72966d73e1378d78e5d9f60337c3f7fbdd0519c42a438e11de7d77189823
|
data/Gemfile.lock
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
listlace (0.0
|
4
|
+
listlace (0.1.0)
|
5
5
|
bundler
|
6
|
-
mpd_client
|
7
6
|
pry
|
7
|
+
ruby-mpd
|
8
8
|
|
9
9
|
GEM
|
10
10
|
remote: http://rubygems.org/
|
11
11
|
specs:
|
12
12
|
coderay (1.1.0)
|
13
13
|
method_source (0.8.2)
|
14
|
-
mpd_client (0.0.3)
|
15
14
|
pry (0.9.12.6)
|
16
15
|
coderay (~> 1.0)
|
17
16
|
method_source (~> 0.8)
|
18
17
|
slop (~> 3.4)
|
19
18
|
rake (0.9.2.2)
|
19
|
+
ruby-mpd (0.3.1)
|
20
20
|
slop (3.5.0)
|
21
21
|
|
22
22
|
PLATFORMS
|
data/README.md
CHANGED
@@ -19,13 +19,149 @@ The gem gives you an executable, so do this:
|
|
19
19
|
|
20
20
|
It gives you a prompt, which is just a Ruby prompt, with the commands below implemented as methods.
|
21
21
|
|
22
|
+
## Selectors
|
23
|
+
|
24
|
+
Query your music library and build playlists using selectors. There are selectors for each tag (artist, album, title, etc.) As an example, here is how `artist` works:
|
25
|
+
|
26
|
+
♫> artist "thirsty cups"
|
27
|
+
=> [8 songs]
|
28
|
+
|
29
|
+
It returned an Array of 8 Songs. To do an exact, case-sensitive search, use `artist_exact`:
|
30
|
+
|
31
|
+
♫> artist_exact "thirsty cups"
|
32
|
+
=> []
|
33
|
+
♫> artist_exact "The Thirsty Cups"
|
34
|
+
=> [8 songs]
|
35
|
+
|
36
|
+
The first one didn't match anything, the second one matched the same 8 songs.
|
37
|
+
|
38
|
+
You can also pass in a `Regexp` or a `Symbol`:
|
39
|
+
|
40
|
+
♫> artist :the_thirsty_cups
|
41
|
+
=> [8 songs]
|
42
|
+
♫> artist /the thirst(y|ier|iest) cups/
|
43
|
+
=> [8 songs]
|
44
|
+
|
45
|
+
Underscores in symbols are interpreted as spaces.
|
46
|
+
|
47
|
+
Here's a list of all tag selectors: `title`, `title_exact`, `artist`, `artist_exact`, `album`, `album_exact`, `genre`, and `genre_exact`.
|
48
|
+
|
49
|
+
In addition to tag selectors, here are some special selectors:
|
50
|
+
|
51
|
+
### all
|
52
|
+
|
53
|
+
`all` returns all the songs in your library.
|
54
|
+
|
55
|
+
♫> all
|
56
|
+
=> [3560 songs]
|
57
|
+
|
58
|
+
### none
|
59
|
+
|
60
|
+
`none` returns an empty playlist.
|
61
|
+
|
62
|
+
♫> none
|
63
|
+
=> []
|
64
|
+
|
65
|
+
### search
|
66
|
+
|
67
|
+
`search` will match **any** tag that contains your query.
|
68
|
+
|
69
|
+
♫> search "thirsty"
|
70
|
+
=> [8 songs]
|
71
|
+
|
72
|
+
### where, where\_exact
|
73
|
+
|
74
|
+
`where` and `where_exact` let you specify multiple queries for different tags:
|
75
|
+
|
76
|
+
♫> where(artist: "thirsty", title: "belljar")
|
77
|
+
=> [1 song]
|
78
|
+
|
22
79
|
## Commands
|
23
80
|
|
24
81
|
### p
|
25
82
|
|
26
|
-
`p` is like a play/pause button. If the player is paused, it unpauses. If the player is playing, then it pauses. If the player is stopped, then it starts playing.
|
83
|
+
`p` is like a play/pause button. If the player is paused, it unpauses. If the player is playing, then it pauses. If the player is stopped, then it starts playing. If you pass it a playlist, it will set the queue to that playlist and begin playing it.
|
84
|
+
|
85
|
+
♫> p
|
86
|
+
♫> p album :in_the_faxed_atmosphere
|
87
|
+
|
88
|
+
### q
|
89
|
+
|
90
|
+
`q` without any arguments returns the queue (the current playlist). If you call `q` with a playlist as an argument, it will replace the queue with that playlist.
|
91
|
+
|
92
|
+
|
93
|
+
♫> q genre :trance
|
94
|
+
♫> q
|
95
|
+
=> [53 songs]
|
96
|
+
|
97
|
+
### stop
|
98
|
+
|
99
|
+
`stop` stops playback.
|
100
|
+
|
101
|
+
♫> stop
|
102
|
+
|
103
|
+
### list
|
104
|
+
|
105
|
+
`list` with no arguments lists all the songs in your music library. If you pass it a playlist, it will list all the songs in that playlist.
|
106
|
+
|
107
|
+
♫> list
|
108
|
+
Air - 10 000 Hz Legend - Electronic Performers
|
109
|
+
Air - 10 000 Hz Legend - How Does It Make You Feel?
|
110
|
+
Air - 10 000 Hz Legend - Radio #1
|
111
|
+
...
|
112
|
+
♫> list title :fish
|
113
|
+
Eisley - Currents - Blue Fish
|
114
|
+
Moonboots - Elfin Princess - The Fish Said Hello
|
115
|
+
Radiohead - In Rainbows - Weird Fishes/Arpeggi
|
116
|
+
Thee More Shallows - A History of Sport Fishing - A History of Sport Fishing
|
117
|
+
|
118
|
+
### artists
|
119
|
+
|
120
|
+
`artists` with no arguments lists all the artists in your music library. If you pass it a playlist, it will list all the artists in that playlist.
|
121
|
+
|
122
|
+
♫> artists
|
123
|
+
Air (55 songs)
|
124
|
+
Amplifier (53 songs)
|
125
|
+
Andrew Bird (93 songs)
|
126
|
+
...
|
127
|
+
♫> artists genre(:trance)
|
128
|
+
Infected Mushroom (13 songs)
|
129
|
+
Gouryella (3 songs)
|
130
|
+
Safri Duo feat. Clark Anderson (6 songs)
|
131
|
+
Safri Duo (16 songs)
|
132
|
+
|
133
|
+
### albums
|
134
|
+
|
135
|
+
`albums` with no arguments lists all the albums in your music library. If you pass it a playlist, it will list all the albums in that playlist.
|
136
|
+
|
137
|
+
♫> albums
|
138
|
+
Air - 10 000 Hz Legend (11 songs)
|
139
|
+
Air - Love 2 (12 songs)
|
140
|
+
Air - Moon Safari (10 songs)
|
141
|
+
...
|
142
|
+
♫> albums artist(:infected_mushroom)
|
143
|
+
Infected Mushroom - Converting Vegetarians (22 songs)
|
144
|
+
Infected Mushroom - IM the Supervisor (9 songs)
|
145
|
+
Infected Mushroom - Legend of the Black Shawarma (11 songs)
|
146
|
+
Infected Mushroom - Stretched (4 songs)
|
147
|
+
Infected Mushroom - Vicious Delicious (11 songs)
|
148
|
+
|
149
|
+
### genres
|
150
|
+
|
151
|
+
`genres` with no arguments lists all the genres in your music library. If you pass it a playlist, it will list all the genres in that playlist.
|
152
|
+
|
153
|
+
♫> genres
|
154
|
+
Trance (53 songs)
|
155
|
+
Hip-Hop (14 songs)
|
156
|
+
Jazz (10 songs)
|
157
|
+
...
|
158
|
+
♫> genres title(:constantinople)
|
159
|
+
TMBG (1 song)
|
27
160
|
|
28
161
|
### mpd
|
29
162
|
|
30
163
|
`mpd` gives you an instance of the `MPDClient` object, which you can use to send any `mpd` command that isn't available in Listlace yet. This'll probably be removed once I actually implement all the commands.
|
31
164
|
|
165
|
+
♫> mpd.version
|
166
|
+
=> "0.16.0"
|
167
|
+
|
data/lib/listlace/commands.rb
CHANGED
@@ -1,17 +1,71 @@
|
|
1
1
|
class Listlace
|
2
2
|
module Commands
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
def p(*playlist)
|
4
|
+
if playlist.empty?
|
5
|
+
case mpd.status[:state]
|
6
|
+
when :play
|
7
|
+
mpd.pause = true
|
8
|
+
when :pause
|
9
|
+
mpd.pause = false
|
10
|
+
when :stop
|
11
|
+
mpd.play
|
12
|
+
end
|
13
|
+
else
|
14
|
+
mpd.clear
|
15
|
+
playlist.flatten.each do |song|
|
16
|
+
mpd.add song.file
|
17
|
+
end
|
13
18
|
mpd.play
|
14
19
|
end
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def stop
|
24
|
+
mpd.stop
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def q(*playlist)
|
29
|
+
if playlist.empty?
|
30
|
+
mpd.queue
|
31
|
+
else
|
32
|
+
mpd.clear
|
33
|
+
playlist.flatten.each do |song|
|
34
|
+
mpd.add song.file
|
35
|
+
end
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def list(playlist = nil)
|
41
|
+
(playlist || all).each do |song|
|
42
|
+
puts "#{song.artist} - #{song.album} - #{song.title}"
|
43
|
+
end
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def artists(playlist = nil)
|
48
|
+
(playlist || all).group_by(&:artist).each do |artist, songs|
|
49
|
+
plural = (songs.length == 1) ? "" : "s"
|
50
|
+
puts "#{artist} (#{songs.length} song#{plural})"
|
51
|
+
end
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def albums(playlist = nil)
|
56
|
+
(playlist || all).group_by(&:album).each do |album, songs|
|
57
|
+
plural = (songs.length == 1) ? "" : "s"
|
58
|
+
puts "#{songs.first.artist} - #{album} (#{songs.length} song#{plural})"
|
59
|
+
end
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def genres(playlist = nil)
|
64
|
+
(playlist || all).group_by(&:genre).each do |genre, songs|
|
65
|
+
plural = (songs.length == 1) ? "" : "s"
|
66
|
+
puts "#{genre} (#{songs.length} song#{plural})"
|
67
|
+
end
|
68
|
+
nil
|
15
69
|
end
|
16
70
|
end
|
17
71
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Array
|
2
|
+
def playlist?
|
3
|
+
@is_playlist ||= all? { |x| x.is_a? MPD::Song }
|
4
|
+
end
|
5
|
+
|
6
|
+
alias _original_inspect inspect
|
7
|
+
def inspect
|
8
|
+
if playlist?
|
9
|
+
plural = (length == 1) ? "" : "s"
|
10
|
+
"[#{length} song#{plural}]"
|
11
|
+
else
|
12
|
+
_original_inspect
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
alias _original_pretty_inspect pretty_inspect
|
17
|
+
def pretty_inspect
|
18
|
+
if playlist?
|
19
|
+
inspect
|
20
|
+
else
|
21
|
+
_original_pretty_inspect
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Listlace
|
2
|
+
module Selectors
|
3
|
+
TAG_SELECTORS = %w(title artist album genre)
|
4
|
+
|
5
|
+
TAG_SELECTORS.each do |tag|
|
6
|
+
define_method(tag) do |what|
|
7
|
+
case what
|
8
|
+
when Regexp
|
9
|
+
what = Regexp.new(what.source, Regexp::IGNORECASE) # case-insensitize
|
10
|
+
all.select { |song| song.send(tag).to_s =~ what }
|
11
|
+
when Symbol
|
12
|
+
mpd.where(tag => what.to_s.tr("_", " "))
|
13
|
+
when String
|
14
|
+
mpd.where(tag => what)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
define_method("#{tag}_exact") do |what|
|
19
|
+
mpd.where({tag => what}, {strict: true})
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def all
|
24
|
+
mpd.songs
|
25
|
+
end
|
26
|
+
|
27
|
+
def none
|
28
|
+
[]
|
29
|
+
end
|
30
|
+
|
31
|
+
def search(what)
|
32
|
+
mpd.where any: what
|
33
|
+
end
|
34
|
+
|
35
|
+
def where(params)
|
36
|
+
mpd.where(params)
|
37
|
+
end
|
38
|
+
|
39
|
+
def where_exact(params)
|
40
|
+
mpd.where(params, {strict: true})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
data/lib/listlace.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
-
require "
|
1
|
+
require "ruby-mpd"
|
2
|
+
|
3
|
+
require "listlace/core_ext/array"
|
2
4
|
|
3
5
|
require "listlace/commands"
|
6
|
+
require "listlace/selectors"
|
4
7
|
|
5
8
|
class Listlace
|
6
9
|
attr_reader :mpd
|
7
10
|
|
8
11
|
include Commands
|
12
|
+
include Selectors
|
9
13
|
|
10
14
|
def initialize(host, port)
|
11
|
-
@mpd =
|
12
|
-
@mpd.connect
|
15
|
+
@mpd = MPD.new(host, port)
|
16
|
+
@mpd.connect
|
13
17
|
end
|
14
18
|
|
15
19
|
def disconnect
|
data/listlace.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "listlace"
|
3
|
-
s.version = "0.
|
4
|
-
s.date = "2014-03-
|
3
|
+
s.version = "0.2.0"
|
4
|
+
s.date = "2014-03-22"
|
5
5
|
s.summary = "An mpd (music player daemon) client with a Ruby shell as the interface."
|
6
6
|
s.description = "Listlace is an mpd (music player daemon) client with a Ruby shell as the interface."
|
7
7
|
s.author = "Jeremy Ruten"
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.files += ["bin/listlace"]
|
16
16
|
s.files += Dir["lib/**/*.rb"]
|
17
17
|
|
18
|
-
%w(bundler pry
|
18
|
+
%w(bundler pry ruby-mpd).each do |gem_name|
|
19
19
|
s.add_runtime_dependency gem_name
|
20
20
|
end
|
21
21
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: listlace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Ruten
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: ruby-mpd
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -81,6 +81,8 @@ files:
|
|
81
81
|
- bin/listlace
|
82
82
|
- lib/listlace.rb
|
83
83
|
- lib/listlace/commands.rb
|
84
|
+
- lib/listlace/core_ext/array.rb
|
85
|
+
- lib/listlace/selectors.rb
|
84
86
|
- listlace.gemspec
|
85
87
|
homepage: http://github.com/yjerem/listlace
|
86
88
|
licenses:
|