mikeplayer 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +51 -0
- data/Gemfile +4 -0
- data/LICENSE +674 -0
- data/README.md +2 -0
- data/Rakefile +10 -0
- data/bin/MikePlayer.rb +26 -0
- data/lib/mikeplayer/executable.rb +27 -0
- data/lib/mikeplayer/play_thread.rb +14 -0
- data/lib/mikeplayer/playlist.rb +101 -0
- data/lib/mikeplayer/settings.rb +74 -0
- data/lib/mikeplayer/song.rb +51 -0
- data/lib/mikeplayer/version.rb +3 -0
- data/lib/mikeplayer.rb +254 -0
- data/mikeplayer.gemspec +36 -0
- data/test/mikeplayer/settings_test.rb +17 -0
- data/test/mikeplayer_test.rb +9 -0
- data/test/test_helper.rb +5 -0
- metadata +142 -0
data/Rakefile
ADDED
data/bin/MikePlayer.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mikeplayer'
|
4
|
+
|
5
|
+
options = {}
|
6
|
+
OptionParser.new do |opt|
|
7
|
+
opt.banner = <<-EOF
|
8
|
+
Usage: MikePlayer.rb [options] <search || file>
|
9
|
+
|
10
|
+
Example: `MikePlayer.rb --shuffle --directory /User/Catman/Music cats /MyMusic/GreatestBand-Song.mp3`
|
11
|
+
Finds all songs matching 'cats' in directory /User/Catman/Music ignoring case
|
12
|
+
and specific song /MyMusic/GreatestBand-Song.mp3
|
13
|
+
and randomizes the order
|
14
|
+
|
15
|
+
EOF
|
16
|
+
opt.on('-s', '--shuffle', 'Shuffle playlist.') { |o| options[:shuffle] = true }
|
17
|
+
opt.on('-r', '--random n', 'Create playlist with randomly picked n songs.') { |o| options[:random] = o.to_i }
|
18
|
+
opt.on('-o', '--overwrite', 'Overwrite playlist.') { |o| options[:overwrite] = true }
|
19
|
+
opt.on('-v', '--volume n', 'Changes default volume.') { |o| options[:volume] = o }
|
20
|
+
opt.on('-p', '--playlist name', 'Play playlist name.') { |o| options[:playlist] = o }
|
21
|
+
opt.on('-l', '--list', 'List songs in playlist.') { |o| options[:list] = true; }
|
22
|
+
opt.on('-d', '--directory name', 'Directory to find mp3s.') { |o| options[:directory] = o }
|
23
|
+
opt.on('-t', '--time minutes', 'Limit time to number of minutes.') { |o| options[:minutes] = o }
|
24
|
+
end.parse!
|
25
|
+
|
26
|
+
MikePlayer::Player.new(options, ARGV).play
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module MikePlayer
|
2
|
+
class PlayThread
|
3
|
+
def initialize(filename)
|
4
|
+
@filename = filename
|
5
|
+
@mp3info = Mp3Info.new(filename)
|
6
|
+
end
|
7
|
+
|
8
|
+
def info
|
9
|
+
artist = "#{@mp3info.tag.artist}"
|
10
|
+
title = "#{@mp3info.tag.title}"
|
11
|
+
|
12
|
+
if (true == artist.empty?) && (true == title.empty?)
|
13
|
+
return File.basename(filename, '.mp3')
|
14
|
+
elsif (true == artist.empty?)
|
15
|
+
artist = "?????"
|
16
|
+
elsif (true == title.empty?)
|
17
|
+
title = "?????"
|
18
|
+
end
|
19
|
+
|
20
|
+
return "#{artist} - #{title}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_json
|
24
|
+
return @filename
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module MikePlayer
|
2
|
+
class Playlist
|
3
|
+
attr_reader :songs
|
4
|
+
|
5
|
+
def initialize(filename)
|
6
|
+
@filename = filename
|
7
|
+
@songs = []
|
8
|
+
@song_i = 0
|
9
|
+
@length = 0
|
10
|
+
|
11
|
+
load_songs
|
12
|
+
|
13
|
+
@loaded_song_count = @songs.size
|
14
|
+
end
|
15
|
+
|
16
|
+
def <<(song)
|
17
|
+
if ((true == File.file?(song)) && (false == @songs.any? { |s| s.filename == song }))
|
18
|
+
@songs << Song.new(song)
|
19
|
+
@length += @songs.last.length
|
20
|
+
end
|
21
|
+
|
22
|
+
return self
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_random(n, directory)
|
26
|
+
files = Dir.glob(File.join(directory, "**", "*.mp3"), File::FNM_CASEFOLD) - @songs
|
27
|
+
|
28
|
+
files.sample(n).each do |file|
|
29
|
+
self << file
|
30
|
+
end
|
31
|
+
|
32
|
+
return self
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_song(file, directory)
|
36
|
+
if (true == File.file?(file))
|
37
|
+
self << file
|
38
|
+
else
|
39
|
+
Dir.glob(File.join(directory, "**", "*#{file}*"), File::FNM_CASEFOLD).each do |f|
|
40
|
+
self << f
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
return self
|
45
|
+
end
|
46
|
+
|
47
|
+
def current
|
48
|
+
return @songs[@song_i]
|
49
|
+
end
|
50
|
+
|
51
|
+
def next
|
52
|
+
@song_i += 1
|
53
|
+
|
54
|
+
return self.current
|
55
|
+
end
|
56
|
+
|
57
|
+
def previous
|
58
|
+
@song_i -= 1 unless @song_i <= 0
|
59
|
+
|
60
|
+
return self.current
|
61
|
+
end
|
62
|
+
|
63
|
+
def shuffle!
|
64
|
+
@songs.shuffle!
|
65
|
+
|
66
|
+
return self
|
67
|
+
end
|
68
|
+
|
69
|
+
def save
|
70
|
+
File.open(@filename, 'w') do |f|
|
71
|
+
f.puts(JSON.pretty_generate(@songs.map {|s| s.to_json }))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def name
|
76
|
+
return File.basename(@filename, Settings::PL_FILE_ENDING)
|
77
|
+
end
|
78
|
+
|
79
|
+
def info
|
80
|
+
return "#{self.name} loaded #{@loaded_song_count} songs with length #{Song.as_duration_str(@length)}, added #{@songs.size - @loaded_song_count}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def current_song_info
|
84
|
+
song_i_str = "#{@song_i + 1}".rjust(@songs.size.to_s.size)
|
85
|
+
|
86
|
+
return "Playing (#{song_i_str}/#{@songs.size}): #{current.info}".freeze
|
87
|
+
end
|
88
|
+
|
89
|
+
def finished?
|
90
|
+
return @song_i == @songs.size
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def load_songs
|
96
|
+
if File.file?(@filename)
|
97
|
+
JSON.parse(File.read(@filename)).each {|song| self << song}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module MikePlayer
|
2
|
+
class Settings
|
3
|
+
DEFAULT_DIRECTORY = 'Music'.freeze
|
4
|
+
DEFAULT_VOLUME = '0.1'
|
5
|
+
SETTINGS_DIRECTORY = '.mikeplayer'.freeze
|
6
|
+
PL_FILE_ENDING = '.mpl'.freeze
|
7
|
+
|
8
|
+
attr_reader :random, :music_dir, :playlist, :volume
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
@shuffle = options[:shuffle]
|
12
|
+
@overwrite = options[:overwrite]
|
13
|
+
@list = options[:list]
|
14
|
+
@home = options[:home] || Dir.home
|
15
|
+
@volume = options[:volume] || DEFAULT_VOLUME
|
16
|
+
@music_dir = options[:directory] || File.join(@home, DEFAULT_DIRECTORY)
|
17
|
+
@settings_dir = options[:settings] || File.join(@home, SETTINGS_DIRECTORY)
|
18
|
+
@minutes = options[:minutes].to_i
|
19
|
+
@random = options[:random].to_i
|
20
|
+
|
21
|
+
if (false == Dir.exist?(@settings_dir))
|
22
|
+
Dir.mkdir(@settings_dir)
|
23
|
+
end
|
24
|
+
|
25
|
+
@playlist = find_playlist(options[:playlist])
|
26
|
+
|
27
|
+
remove_playlist_if_needed(@playlist)
|
28
|
+
end
|
29
|
+
|
30
|
+
def shuffle?
|
31
|
+
return true == @shuffle
|
32
|
+
end
|
33
|
+
|
34
|
+
def random?
|
35
|
+
return 0 < @random
|
36
|
+
end
|
37
|
+
|
38
|
+
def overwrite?
|
39
|
+
return true == @overwrite
|
40
|
+
end
|
41
|
+
|
42
|
+
def list?
|
43
|
+
return true == @list
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def find_playlist(user_option)
|
49
|
+
name = nil
|
50
|
+
|
51
|
+
if (false == user_option.nil?)
|
52
|
+
if (true == File.file?(user_option))
|
53
|
+
return user_option
|
54
|
+
else
|
55
|
+
name = File.basename(user_option, PL_FILE_ENDING)
|
56
|
+
end
|
57
|
+
elsif (true == self.random?)
|
58
|
+
name = "random_n#{@random}"
|
59
|
+
else
|
60
|
+
name = 'default'
|
61
|
+
end
|
62
|
+
|
63
|
+
return File.join(@settings_dir, "#{name}#{PL_FILE_ENDING}")
|
64
|
+
end
|
65
|
+
|
66
|
+
def remove_playlist_if_needed(filename)
|
67
|
+
if (true == File.file?(filename))
|
68
|
+
if ((true == overwrite?) || (true == random?))
|
69
|
+
File.delete(filename)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module MikePlayer
|
2
|
+
class Song
|
3
|
+
attr_reader :filename
|
4
|
+
|
5
|
+
def initialize(filename)
|
6
|
+
@filename = filename
|
7
|
+
@mp3info = Mp3Info.new(filename)
|
8
|
+
end
|
9
|
+
|
10
|
+
def info
|
11
|
+
artist = "#{@mp3info.tag.artist}"
|
12
|
+
title = "#{@mp3info.tag.title}"
|
13
|
+
|
14
|
+
if (true == artist.empty?) && (true == title.empty?)
|
15
|
+
return File.basename(@filename, '.mp3')
|
16
|
+
elsif (true == artist.empty?)
|
17
|
+
artist = "?????"
|
18
|
+
elsif (true == title.empty?)
|
19
|
+
title = "?????"
|
20
|
+
end
|
21
|
+
|
22
|
+
return "#{artist} - #{title}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def length
|
26
|
+
return @mp3info.length
|
27
|
+
end
|
28
|
+
|
29
|
+
def length_str(elapsed_time)
|
30
|
+
return Song.as_duration_str(self.length, elapsed_time)
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_json
|
34
|
+
return @filename.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.as_duration_str(l, t = nil)
|
38
|
+
l_hr = "%02d" % (l / 3600).floor
|
39
|
+
l_min = "%02d" % ((l % 3600 )/ 60).floor
|
40
|
+
l_sec = "%02d" % (l % 60)
|
41
|
+
e_min = "%02d" % (t / 60).floor unless t.nil?
|
42
|
+
e_sec = "%02d" % (t % 60) unless t.nil?
|
43
|
+
|
44
|
+
result = "#{l_min}:#{l_sec}"
|
45
|
+
result = "#{l_hr}:#{result}" if l >= 3600
|
46
|
+
result = "#{e_min}:#{e_sec} [#{result}]" unless t.nil?
|
47
|
+
|
48
|
+
return result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/mikeplayer.rb
ADDED
@@ -0,0 +1,254 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'json'
|
3
|
+
require 'open3'
|
4
|
+
require 'io/console'
|
5
|
+
require 'mp3info'
|
6
|
+
require 'mikeplayer/version'
|
7
|
+
require 'mikeplayer/settings'
|
8
|
+
require 'mikeplayer/playlist'
|
9
|
+
require 'mikeplayer/song'
|
10
|
+
|
11
|
+
module MikePlayer
|
12
|
+
class Player
|
13
|
+
PAUSE_INDICATOR = " ||".freeze
|
14
|
+
SLEEP_SETTING = 0.5
|
15
|
+
STOPPED = :stopped
|
16
|
+
PLAYING = :playing
|
17
|
+
PAUSED = :paused
|
18
|
+
|
19
|
+
def initialize(options, *args)
|
20
|
+
@settings = Settings.new(options)
|
21
|
+
@playlist = Playlist.new(@settings.playlist)
|
22
|
+
@command = ''
|
23
|
+
@pid = nil
|
24
|
+
@timer_start = nil
|
25
|
+
@state = STOPPED
|
26
|
+
|
27
|
+
check_system
|
28
|
+
|
29
|
+
if (true == @settings.list?)
|
30
|
+
@songs.map { |song| File.basename(song) }.sort.each {|song| puts "#{File.basename(song)}"}
|
31
|
+
|
32
|
+
exit 0
|
33
|
+
end
|
34
|
+
|
35
|
+
args.flatten.each do |arg|
|
36
|
+
@playlist.find_song(arg, @settings.music_dir)
|
37
|
+
end
|
38
|
+
|
39
|
+
if (true == @settings.random?)
|
40
|
+
@playlist.add_random(@settings.random, @settings.music_dir)
|
41
|
+
end
|
42
|
+
|
43
|
+
@playlist.save
|
44
|
+
end
|
45
|
+
|
46
|
+
def play
|
47
|
+
@playlist.shuffle! if @settings.shuffle?
|
48
|
+
|
49
|
+
print "Playlist #{@playlist.info}\n"
|
50
|
+
|
51
|
+
if @playlist.finished?
|
52
|
+
puts "No songs in playlist."
|
53
|
+
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
|
57
|
+
@thread = Thread.new do
|
58
|
+
display_width = 0
|
59
|
+
|
60
|
+
while (false == @playlist.finished?)
|
61
|
+
song = @playlist.current
|
62
|
+
@song_start = Time.now
|
63
|
+
info_prefix = "\r#{@playlist.current_song_info}".freeze
|
64
|
+
|
65
|
+
stdin, stdother, thread_info = Open3.popen2e('play', '--no-show-progress', '--volume', @settings.volume, song.filename)
|
66
|
+
|
67
|
+
@state = PLAYING
|
68
|
+
@pid = thread_info.pid
|
69
|
+
indicator = ''
|
70
|
+
|
71
|
+
while (true == pid_alive?)
|
72
|
+
pause_if_over_time_limit
|
73
|
+
|
74
|
+
if (true == playing?)
|
75
|
+
indicator = "#{'>' * (playing_time % 4)}"
|
76
|
+
info_changed = true
|
77
|
+
elsif (true == paused?) && (PAUSE_INDICATOR != indicator)
|
78
|
+
indicator = PAUSE_INDICATOR
|
79
|
+
info_changed = true
|
80
|
+
end
|
81
|
+
|
82
|
+
if (true == info_changed)
|
83
|
+
mindicator = ""
|
84
|
+
|
85
|
+
if (0 < minutes_remaining)
|
86
|
+
mindicator = "(#{minutes_remaining}↓) "
|
87
|
+
end
|
88
|
+
|
89
|
+
info = "#{info_prefix} #{song.length_str(playing_time)} #{mindicator}#{indicator}".ljust(display_width)
|
90
|
+
|
91
|
+
display_width = info.size
|
92
|
+
|
93
|
+
print(info)
|
94
|
+
|
95
|
+
$stdout.flush
|
96
|
+
end
|
97
|
+
|
98
|
+
sleep SLEEP_SETTING
|
99
|
+
end
|
100
|
+
|
101
|
+
stdin.close
|
102
|
+
stdother.close
|
103
|
+
|
104
|
+
@pid = nil
|
105
|
+
|
106
|
+
if (true == playing?)
|
107
|
+
next_song
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
@pid = nil
|
112
|
+
exit
|
113
|
+
end
|
114
|
+
|
115
|
+
wait_on_user
|
116
|
+
|
117
|
+
puts ""
|
118
|
+
end
|
119
|
+
|
120
|
+
def cmd_exist?(cmd)
|
121
|
+
if (true != system('command'))
|
122
|
+
raise "Missing 'command' command, which is used to test compatibility."
|
123
|
+
end
|
124
|
+
|
125
|
+
if (true != system("command -v #{cmd} >/dev/null 2>&1"))
|
126
|
+
return false
|
127
|
+
end
|
128
|
+
|
129
|
+
return true
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def check_system
|
135
|
+
%w(play).each do |cmd|
|
136
|
+
if (false == cmd_exist?(cmd))
|
137
|
+
raise "#{cmd} failed, do you have sox installed?"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
return nil
|
142
|
+
end
|
143
|
+
|
144
|
+
def wait_on_user
|
145
|
+
while ('q' != @command)
|
146
|
+
@command = STDIN.getch
|
147
|
+
|
148
|
+
if ('c' == @command)
|
149
|
+
press_pause
|
150
|
+
elsif ('v' == @command)
|
151
|
+
next_song
|
152
|
+
elsif ('z' == @command)
|
153
|
+
previous_song
|
154
|
+
elsif ('q' == @command) && (false == @pid.nil?)
|
155
|
+
stop_song
|
156
|
+
@thread.kill
|
157
|
+
elsif ('t' == @command)
|
158
|
+
@timer_start = Time.now
|
159
|
+
elsif (false == @timer_start.nil?) && ("#{@command.to_i}" == @command)
|
160
|
+
if (0 == @minutes)
|
161
|
+
@minutes = @command.to_i
|
162
|
+
else
|
163
|
+
@minutes *= 10
|
164
|
+
@minutes += @command.to_i
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def playing?
|
171
|
+
return (PLAYING == @state)
|
172
|
+
end
|
173
|
+
|
174
|
+
def paused?
|
175
|
+
return (PAUSED == @state)
|
176
|
+
end
|
177
|
+
|
178
|
+
def press_pause
|
179
|
+
if (true == playing?)
|
180
|
+
kill("STOP")
|
181
|
+
@state = PAUSED
|
182
|
+
elsif (true == paused?)
|
183
|
+
kill("CONT")
|
184
|
+
@state = PLAYING
|
185
|
+
else
|
186
|
+
print("Confused state #{@state}.")
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def stop_song
|
191
|
+
if (true == paused?)
|
192
|
+
kill("CONT")
|
193
|
+
end
|
194
|
+
|
195
|
+
kill("INT")
|
196
|
+
|
197
|
+
sleep 0.2
|
198
|
+
|
199
|
+
if (true == pid_alive?)
|
200
|
+
kill("KILL")
|
201
|
+
end
|
202
|
+
|
203
|
+
@state = STOPPED
|
204
|
+
end
|
205
|
+
|
206
|
+
def pid_alive?(pid = @pid)
|
207
|
+
if (false == pid.nil?)
|
208
|
+
return system("ps -p #{pid} > /dev/null")
|
209
|
+
end
|
210
|
+
|
211
|
+
return false
|
212
|
+
end
|
213
|
+
|
214
|
+
def next_song
|
215
|
+
stop_song
|
216
|
+
|
217
|
+
@playlist.next
|
218
|
+
end
|
219
|
+
|
220
|
+
def previous_song
|
221
|
+
stop_song
|
222
|
+
|
223
|
+
@playlist.previous
|
224
|
+
end
|
225
|
+
|
226
|
+
def kill(signal)
|
227
|
+
if (false == @pid.nil?)
|
228
|
+
Process.kill(signal, @pid)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def pause_if_over_time_limit
|
233
|
+
if (false == @timer_start.nil?) && (0 < @minutes) && (true == playing?)
|
234
|
+
if (0 > minutes_remaining)
|
235
|
+
press_pause
|
236
|
+
@timer_start = nil
|
237
|
+
@minutes = 0
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def playing_time
|
243
|
+
return (Time.now - @song_start).to_i
|
244
|
+
end
|
245
|
+
|
246
|
+
def minutes_remaining
|
247
|
+
if ((0 == @minutes) || (@timer_start.nil?))
|
248
|
+
return -1
|
249
|
+
else
|
250
|
+
return (@minutes - ((Time.now - @timer_start).to_i / 60).to_i)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
data/mikeplayer.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mikeplayer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = 'mikeplayer'
|
8
|
+
gem.version = MikePlayer::VERSION
|
9
|
+
gem.authors = ['Mike Crockett']
|
10
|
+
gem.email = ['rubygems@mmcrockett.com']
|
11
|
+
gem.summary = 'Wraps Sox\'s `play` command, allowing playslists, find, random and time limit.'
|
12
|
+
gem.executables << 'MikePlayer.rb'
|
13
|
+
gem.description = <<-EOF.gsub(/^\s+/, '')
|
14
|
+
#{gem.summary}
|
15
|
+
|
16
|
+
Once a song is playing you can:
|
17
|
+
'x' to previous
|
18
|
+
'c' to pause/play
|
19
|
+
'v' to next
|
20
|
+
'q' to quit
|
21
|
+
't' n to set a timer that will pause the music after n minutes
|
22
|
+
EOF
|
23
|
+
gem.homepage = 'https://github.com/mmcrockett/mikeplayer'
|
24
|
+
|
25
|
+
gem.files = `git ls-files`.split($/)
|
26
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
27
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
28
|
+
gem.require_paths = ['lib']
|
29
|
+
gem.licenses = ['MIT']
|
30
|
+
|
31
|
+
gem.add_dependency 'json', '~> 1.8'
|
32
|
+
gem.add_dependency 'ruby-mp3info', '~> 0.8'
|
33
|
+
gem.add_dependency 'minitest', '~> 5'
|
34
|
+
gem.add_development_dependency 'rake', '~> 12'
|
35
|
+
gem.add_development_dependency 'byebug', '~> 11'
|
36
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SettingsTest < Minitest::Test
|
4
|
+
describe 'settings' do
|
5
|
+
let(:home) { File.join('', 'tmp') }
|
6
|
+
let(:sdir) { File.join(home, MikePlayer::Settings::SETTINGS_DIRECTORY) }
|
7
|
+
|
8
|
+
before do
|
9
|
+
Dir.delete(sdir) if Dir.exist?(sdir)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'creates a settings directory' do
|
13
|
+
MikePlayer::Settings.new(home: home)
|
14
|
+
assert(Dir.exist?(sdir))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|