listlace 0.0.5 → 0.0.6

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.
@@ -1,52 +0,0 @@
1
- module Listlace
2
- # The queue command. Simply appends tracks to the queue. It creates a playlist
3
- # with the arguments you give it, so anything you can pass to the playlist()
4
- # method you can pass to this. It returns the queue, so you can use this
5
- # method as an accessor by not passing any arguments.
6
- def q(*args)
7
- $player.queue playlist(*args)
8
- $player.queue
9
- end
10
-
11
- # Clears the queue.
12
- def clear
13
- $player.clear
14
- puts "Queue cleared."
15
- end
16
-
17
- # Shuffles the queue, keeping the current track at the top.
18
- def shuffle
19
- $player.shuffle
20
- puts "Shuffled."
21
- end
22
-
23
- # Sorts the queue by a list of fields and directions in the form of a symbol,
24
- # or uses the proc given to it, which should take two Tracks and return -1, 0,
25
- # or 1.
26
- def sort(by = :artist_asc_album_asc_track_number_asc, &proc)
27
- if proc
28
- $player.sort(&proc)
29
- else
30
- $player.sort do |a, b|
31
- result = 0
32
- by.to_s.scan(/([a-z_]+?)_(asc|desc)(?:_|$)/).each do |column, direction|
33
- a_value = a.send(column)
34
- b_value = b.send(column)
35
- a_value = a_value.downcase if a_value.respond_to? :downcase
36
- b_value = b_value.downcase if b_value.respond_to? :downcase
37
- dir = (direction == "desc") ? -1 : 1
38
- if a_value != b_value
39
- if a_value.nil? || b_value.nil?
40
- result = dir
41
- else
42
- result = (a_value <=> b_value) * dir
43
- end
44
- break
45
- end
46
- end
47
- result
48
- end
49
- end
50
- puts "Sorted."
51
- end
52
- end
@@ -1,186 +0,0 @@
1
- module Listlace
2
- STRING_SELECTORS = %w(name artist composer album album_artist genre comments location)
3
- INTEGER_SELECTORS = %w(disc_number disc_count track_number track_count year bit_rate sample_rate play_count skip_count rating)
4
-
5
- STRING_SELECTORS.each do |column|
6
- define_method(column) do |*args|
7
- options = args.last.is_a?(Hash) ? args.pop : {}
8
-
9
- playlists = args.map { |query| string_selector(column, query, options) }
10
- playlist *playlists
11
- end
12
- end
13
-
14
- INTEGER_SELECTORS.each do |column|
15
- define_method(column) do |*args|
16
- playlists = args.map { |arg| integer_selector(column, arg) }
17
- playlist *playlists
18
- end
19
- end
20
-
21
- # rename the "name" selector to "song"
22
- alias_method :song, :name
23
- remove_method :name
24
-
25
- # The length selector is an integer selector for the length of a track. A
26
- # plain integer given to it represents the number of seconds. It can also take
27
- # a String in the format "1:23", to represent 83 seconds, for example. These
28
- # can be part of a Range, as usual: "1:23".."2:05", for example.
29
- def length(*args)
30
- normalize = lambda do |value|
31
- case value
32
- when String
33
- Track.parse_time(value)
34
- when Integer
35
- value * 1000
36
- when Range
37
- (normalize.(value.begin))..(normalize.(value.end))
38
- end
39
- end
40
-
41
- playlists = args.map do |arg|
42
- if arg.is_a? Hash
43
- key = arg.keys.first
44
- arg[key] = normalize.(arg[key])
45
- else
46
- arg = normalize.(arg)
47
- end
48
-
49
- # If they want tracks of length "0:05", for example, we need to look for
50
- # tracks that are from 5000 to 5999 milliseconds long.
51
- if arg.is_a? Integer
52
- arg = (arg)..(arg + 999)
53
- end
54
-
55
- integer_selector(:total_time, arg)
56
- end
57
-
58
- playlist *playlists
59
- end
60
-
61
- # Makes a playlist out of tracks that match the string query on the given
62
- # column. It's SQL underneath, so you can use % and _ as wildcards in the
63
- # query. By default, % wildcards are inserted on the left and right of your
64
- # query. Use the :match option to change this:
65
- #
66
- # :match => :middle "%query%" (default)
67
- # :match => :left "query%"
68
- # :match => :right "%query"
69
- # :match => :exact "query"
70
- #
71
- # This method shouldn't have to be used directly. Many convenient methods are
72
- # generated for you, one for each string field you may want to select on.
73
- # These are: artist, composer, album, album_artist, genre, comments, location.
74
- # For example:
75
- #
76
- # artist :muse, match: :exact #=> playlist (108 tracks)
77
- # composer :rachmanino #=> playlist (33 tracks)
78
- #
79
- # To match the name of a track, use song:
80
- #
81
- # song "frontier psychiatrist" #=> playlist (1 track)
82
- #
83
- def string_selector(column, query, options = {})
84
- options[:match] ||= :middle
85
-
86
- query = {
87
- exact: "#{query}",
88
- left: "#{query}%",
89
- right: "%#{query}",
90
- middle: "%#{query}%"
91
- }[options[:match]]
92
-
93
- tracks = Track.arel_table
94
- PlaylistArray.new(Track.where(tracks[column].matches(query)).all)
95
- end
96
-
97
- # Makes a playlist out of tracks that satisfy certain conditions on the given
98
- # integer column. You can pass an exact value to check for equality, a range,
99
- # or a hash that specifies greater-than and less-than options like this:
100
- #
101
- # integer_selector :year, greater_than: 2000 #=> playlist (3555 tracks)
102
- #
103
- # The possible operators, with their shortcuts, are:
104
- #
105
- # :greater_than / :gt
106
- # :less_than / :lt
107
- # :greater_than_or_equal / :gte
108
- # :less_than_or_equal / :lte
109
- # :not_equal / :ne
110
- #
111
- # Note: You can only use one of these operators at a time. If you want a
112
- # range, use a Range.
113
- #
114
- # This method shouldn't have to be used directly. Many convenient methods are
115
- # generated for you, one for each integer field you may want to select on.
116
- # These are: disc_number, disc_count, track_number, track_count, year,
117
- # bit_rate, sample_rate, play_count, skip_count, rating, length. Length is
118
- # special, it can take any of the time formats that the seek command can. For
119
- # example:
120
- #
121
- # year 2010..2012 #=> playlist (1060 tracks)
122
- # length gt: "4:00" #=> playlist (2543 tracks)
123
- #
124
- def integer_selector(column, value_or_options)
125
- if value_or_options.is_a? Hash
126
- operator = {
127
- greater_than: ">",
128
- gt: ">",
129
- less_than: "<",
130
- lt: "<",
131
- greater_than_or_equal: ">=",
132
- gte: ">=",
133
- less_than_or_equal: "<=",
134
- lte: "<=",
135
- not_equal: "<>",
136
- ne: "<>"
137
- }[value_or_options.keys.first]
138
- tracks = Track.where("tracks.#{column} #{operator} ?", value_or_options.values.first)
139
- PlaylistArray.new(tracks.all)
140
- else
141
- tracks = Track.arel_table
142
- PlaylistArray.new(Track.where(column => value_or_options).all)
143
- end
144
- end
145
-
146
- # Creates or looks up a playlist. You can pass any number of multiple types of
147
- # objects to make a playlist:
148
- #
149
- # Track: Makes a playlist with one track
150
- # ActiveRecord::Relation: Makes a playlist out of the resulting Track or Playlist records
151
- # Symbol or String: Tries to retrieve a saved playlist with the given name.
152
- # If it can't find one, it creates a new one.
153
- #
154
- # You can also pass in the results of a selector. In this way you can create a
155
- # playlist out of many smaller pieces.
156
- #
157
- # If given no arguments, it returns a blank playlist.
158
- #
159
- def playlist(*args)
160
- args.map do |object|
161
- case object
162
- when Track
163
- PlaylistArray.new([object])
164
- when Playlist
165
- PlaylistArray.new([object.tracks.all], object.name)
166
- when PlaylistArray
167
- object
168
- when Array
169
- playlist *object
170
- when ActiveRecord::Relation
171
- if object.table.name == "tracks"
172
- PlaylistArray.new([object.all])
173
- elsif object.table.name == "playlists"
174
- playlist *object.all
175
- end
176
- when Symbol, String
177
- playlists = Playlist.arel_table
178
- if playlist = Playlist.where(playlists[:name].matches(object.to_s)).first
179
- PlaylistArray.new(playlist)
180
- else
181
- PlaylistArray.new([], object)
182
- end
183
- end
184
- end.inject(:+)
185
- end
186
- end
File without changes
@@ -1,74 +0,0 @@
1
- module Listlace
2
- module Database
3
- extend self
4
-
5
- ADAPTER = "sqlite3"
6
- PATH = "#{Listlace::DIR}/library.sqlite3"
7
-
8
- def connect
9
- ActiveRecord::Base.establish_connection(adapter: ADAPTER, database: PATH)
10
- end
11
-
12
- def exists?
13
- File.exists? PATH
14
- end
15
-
16
- def delete
17
- FileUtils.rm PATH
18
- end
19
-
20
- def wipe
21
- delete
22
- connect
23
- generate_schema
24
- end
25
-
26
- def generate_schema
27
- ActiveRecord::Schema.define do
28
- create_table :tracks do |t|
29
- t.integer :original_id
30
- t.string :name
31
- t.string :artist
32
- t.string :composer
33
- t.string :album
34
- t.string :album_artist
35
- t.string :genre
36
- t.string :kind
37
- t.integer :size
38
- t.integer :total_time
39
- t.integer :disc_number
40
- t.integer :disc_count
41
- t.integer :track_number
42
- t.integer :track_count
43
- t.integer :year
44
- t.datetime :date_modified
45
- t.datetime :date_added
46
- t.integer :bit_rate
47
- t.integer :sample_rate
48
- t.text :comments
49
- t.integer :play_count
50
- t.integer :play_date
51
- t.datetime :play_date_utc
52
- t.integer :skip_count
53
- t.datetime :skip_date
54
- t.integer :rating
55
- t.integer :album_rating
56
- t.boolean :album_rating_computed
57
- t.string :location
58
- end
59
-
60
- create_table :playlists do |t|
61
- t.string :name
62
- t.datetime :created_at
63
- t.datetime :updated_at
64
- end
65
-
66
- create_table :playlist_items do |t|
67
- t.references :playlist, null: false
68
- t.references :track, null: false
69
- t.integer :position
70
- end
71
- end
72
- end
73
- end
74
- end
@@ -1,51 +0,0 @@
1
- module Listlace
2
- # This is a simple MPlayer wrapper, it just handles opening the MPlayer
3
- # process, hooking into when mplayer exits (when the song is done), and
4
- # issuing commands through the slave protocol.
5
- class MPlayer
6
- def initialize(track, &on_quit)
7
- cmd = "/usr/bin/mplayer -slave -quiet #{Shellwords.shellescape(track.location)}"
8
- @pid, @stdin, @stdout, @stderr = Open4.popen4(cmd)
9
- @paused = false
10
- @extra_lines = 0
11
-
12
- until @stdout.gets["playback"]
13
- end
14
-
15
- @quit_hook_active = false
16
- @quit_hook = Thread.new do
17
- Process.wait(@pid)
18
- @quit_hook_active = true
19
- on_quit.call
20
- end
21
- end
22
-
23
- def command(cmd, options = {})
24
- if cmd == "pause"
25
- @paused = !@paused
26
- elsif @paused
27
- cmd = "pausing #{cmd}"
28
- end
29
-
30
- @stdin.puts cmd
31
-
32
- if options[:expect_answer]
33
- answer = "\n"
34
- answer = @stdout.gets.sub("\e[A\r\e[K", "") while answer == "\n"
35
- answer
36
- end
37
- end
38
-
39
- def quit
40
- @quit_hook.kill unless @quit_hook_active
41
- command "quit" if alive?
42
- end
43
-
44
- def alive?
45
- Process.getpgid(@pid)
46
- true
47
- rescue Errno::ESRCH
48
- false
49
- end
50
- end
51
- end
@@ -1,82 +0,0 @@
1
- module Listlace
2
- class PlaylistArray < Array
3
- attr_accessor :name, :model
4
-
5
- def initialize(tracks_or_playlist = [], name = :playlist)
6
- if tracks_or_playlist.is_a? Playlist
7
- replace tracks_or_playlist.tracks.to_a
8
- @name = tracks_or_playlist.name
9
- @model = tracks_or_playlist
10
- else
11
- replace tracks_or_playlist.to_a
12
- @name = name.to_s
13
- @model = nil
14
- end
15
- end
16
-
17
- def save(name = nil)
18
- if @model
19
- @model.playlist_items.destroy_all
20
- @model.name = @name = name if name
21
- else
22
- @name = name if name
23
- @model = Playlist.new(name: @name)
24
- end
25
-
26
- if @model.save
27
- each.with_index do |track, i|
28
- item = PlaylistItem.new(position: i)
29
- item.playlist = @model
30
- item.track = track
31
- item.save!
32
- end
33
- @model
34
- else
35
- false
36
- end
37
- end
38
-
39
- def <<(other)
40
- if other.is_a? Track
41
- super
42
- else
43
- other.each do |track|
44
- self << track
45
- end
46
- end
47
- end
48
-
49
- def +(other)
50
- result = self.dup
51
- result << Listlace.playlist(other)
52
- result
53
- end
54
-
55
- def &(other)
56
- replace super
57
- end
58
-
59
- def shuffle_except(track)
60
- ary = dup
61
- dup.shuffle_except! track
62
- dup
63
- end
64
-
65
- def shuffle_except!(track)
66
- replace([track] + (self - [track]).shuffle)
67
- end
68
-
69
- def to_s
70
- "%s (%d track%s)" % [@name || "playlist", length, ("s" if length != 1)]
71
- end
72
-
73
- def inspect
74
- to_s
75
- end
76
-
77
- # override pry
78
- def pretty_inspect
79
- inspect
80
- end
81
- end
82
- end