gtk2mp3 0.7.0 → 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/LICENSE +21 -0
- data/README.md +30 -0
- data/bin/gtk2mp3 +39 -27
- data/cache/dbm.json +1 -0
- data/data/VERSION +1 -0
- data/lib/gtk2mp3/config.rb +33 -0
- data/lib/gtk2mp3/gui.rb +106 -0
- data/lib/gtk2mp3.rb +10 -186
- metadata +78 -51
- data/README.txt +0 -7
- data/lib/gtk2mp3/appconfig.rb +0 -56
- data/lib/gtk2mp3/couple.rb +0 -99
- data/lib/gtk2mp3/playlist.rb +0 -24
- data/pngs/icon.png +0 -0
- /data/{pngs → data}/logo.png +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e0d866ff929a7c03c6e19e83cfca86db84719676d4a9e613735c9ba0b88de06e
|
4
|
+
data.tar.gz: ee1c1383e5c900e7ffd40f2a2bbfe2a34bc0b31719cba081dfeb7aabe348fd72
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ad2ba586dd898b47f00ef0a49f4e6b4fe61b9f4659f7f4c5a489d9be7b0b85ab706125c8dc23f81849f038c748286511047a7e15c65c2bdd688644f95bda0c69
|
7
|
+
data.tar.gz: cf27a1781f38117f293521f365fcdcd702f7e1148a16977c5e56f665eb185fc19d27fba33163ccab7c5ab5880a211d4f7e0fea74346d4e5e25c4b3619350b814
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 carlosjhr64
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Gtk2Mp3 I: Posser
|
2
|
+
|
3
|
+
* [github](https://www.github.com/carlosjhr64/gtk2mp3)
|
4
|
+
* [rubygems]((https://rubygems.org/gems/gtk2mp3)
|
5
|
+
|
6
|
+
## DESCRIPTION:
|
7
|
+
|
8
|
+
A "Next!" button gui for [MPD/MPC](https://www.musicpd.org/).
|
9
|
+
|
10
|
+
## SYNOPSIS
|
11
|
+
|
12
|
+
gtk2mp3 --help
|
13
|
+
|
14
|
+
## HELP
|
15
|
+
|
16
|
+
Usage:
|
17
|
+
gtk2mp3 [:options+]
|
18
|
+
Options:
|
19
|
+
-h --help
|
20
|
+
-v --version
|
21
|
+
-f --force Skips mpd prechecks
|
22
|
+
--noinit Don't reset the playlist
|
23
|
+
# Notes #
|
24
|
+
# Requires MPD/MPC.
|
25
|
+
# See https://www.musicpd.org/clients/mpc/.
|
26
|
+
|
27
|
+
## INSTALL
|
28
|
+
|
29
|
+
$ sudo gem install gtk2mp3
|
30
|
+
|
data/bin/gtk2mp3
CHANGED
@@ -1,33 +1,45 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require '
|
3
|
-
gem 'gtk2applib', '~> 15.3'
|
4
|
-
$help = <<EOT
|
2
|
+
require 'help_parser'
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
module Gtk2Mp3
|
5
|
+
VERSION = '1.0.0'
|
6
|
+
end
|
7
|
+
OPTIONS = HelpParser[Gtk2Mp3::VERSION,<<HELP]
|
8
|
+
Usage:
|
9
|
+
gtk2mp3 [:options+]
|
10
|
+
Options:
|
11
|
+
-h --help
|
12
|
+
-v --version
|
13
|
+
-f --force \tSkips mpd prechecks
|
14
|
+
--noinit \tDon't reset the playlist
|
15
|
+
# Notes #
|
16
|
+
# Requires MPD/MPC.
|
17
|
+
# See https://www.musicpd.org/clients/mpc/.
|
18
|
+
HELP
|
11
19
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
unless OPTIONS.force?
|
21
|
+
unless ['/etc/mpd.conf','~/.mpdconf'].all?{|_|File.exist? File.expand_path _}
|
22
|
+
$stderr.puts 'Missing /etc/mpd.conf and/or ~/.mpdconf'
|
23
|
+
exit 72 # EX_OSFILE
|
24
|
+
end
|
25
|
+
unless system 'ps -C mpd'
|
26
|
+
unless system 'mpd'
|
27
|
+
$stderr.puts 'Could not start the mpd daemon.'
|
28
|
+
exit 69 # EX_UNAVAILABLE
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
20
32
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
Gtk2MP3::GUI.new(window,program)
|
26
|
-
window.show_all
|
33
|
+
unless OPTIONS.noinit?
|
34
|
+
unless system 'mpc clear' and system 'mpc ls | mpc add'
|
35
|
+
$stderr.puts 'Could not initialize mpd\'s playlist'
|
36
|
+
exit 76 # EX_PROTOCOL
|
27
37
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
Gtk2MP3::Couple.dump
|
32
|
-
program.finalize
|
38
|
+
system 'mpc random on'
|
39
|
+
system 'mpc consume off'
|
40
|
+
system 'mpc repeat on'
|
33
41
|
end
|
42
|
+
|
43
|
+
require 'gtk2mp3'
|
44
|
+
Gtk3App.main(Gtk2Mp3)
|
45
|
+
system 'mpc stop'
|
data/cache/dbm.json
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{}
|
data/data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Gtk2Mp3
|
2
|
+
using Rafini::String
|
3
|
+
APPDIR = File.dirname File.dirname __dir__
|
4
|
+
CONFIG = {
|
5
|
+
PLAYED: 30,
|
6
|
+
DBM: "#{XDG['CACHE']}/gtk3app/gtk2mp3/dbm.json",
|
7
|
+
thing: {
|
8
|
+
HelpFile: 'https://github.com/carlosjhr64/gtk2mp3',
|
9
|
+
Logo: "#{XDG['DATA']}/gtk3app/gtk2mp3/logo.png",
|
10
|
+
window: {
|
11
|
+
set_title: 'Gtk2Mp3',
|
12
|
+
set_default_size: [100,60],
|
13
|
+
set_window_position: :center,
|
14
|
+
},
|
15
|
+
NEXT: [label: 'Next!'],
|
16
|
+
next_button!: [:NEXT, 'clicked'],
|
17
|
+
next_item!: [:NEXT, 'activate'],
|
18
|
+
STOP: [label: 'Stop'],
|
19
|
+
stop_button!: [:STOP, 'clicked'],
|
20
|
+
stop_item!: [:STOP, 'activate'],
|
21
|
+
VBOX: [:vertical],
|
22
|
+
HBOX: [:horizontal],
|
23
|
+
about_dialog: {
|
24
|
+
set_program_name: 'Gtk2Mp3',
|
25
|
+
set_version: VERSION.semantic(0..1),
|
26
|
+
set_copyright: '(c) 2018 CarlosJHR64',
|
27
|
+
set_comments: 'A MPD/MPC "Next!" Button',
|
28
|
+
set_website: 'https://github.com/carlosjhr64/gtk2mp3',
|
29
|
+
set_website_label: 'See it at GitHub!',
|
30
|
+
},
|
31
|
+
}
|
32
|
+
}
|
33
|
+
end
|
data/lib/gtk2mp3/gui.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
module Gtk2Mp3
|
2
|
+
def self.run(program)
|
3
|
+
GUI.new(program)
|
4
|
+
end
|
5
|
+
|
6
|
+
class GUI
|
7
|
+
MUTEX = Mutex.new
|
8
|
+
ID = lambda{|_|File.basename(_.strip.split(/\n/).first.strip,'.*')}
|
9
|
+
|
10
|
+
def play?(id)
|
11
|
+
rand(@db[id].to_i+1)==0
|
12
|
+
end
|
13
|
+
|
14
|
+
def random_song
|
15
|
+
n = @list.length
|
16
|
+
loop do
|
17
|
+
id = @list[rand(n)]
|
18
|
+
return id if play?(id)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def next_song
|
23
|
+
@label.text = @playing = ID[`mpc searchplay filename '#{random_song}'`]
|
24
|
+
end
|
25
|
+
|
26
|
+
def down(id)
|
27
|
+
if count=@db[id]
|
28
|
+
count -= 1
|
29
|
+
if count>0
|
30
|
+
@db[id] = count
|
31
|
+
else
|
32
|
+
@db.delete(id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def up(id)
|
38
|
+
@db[id] = @db[id].to_i+1
|
39
|
+
end
|
40
|
+
|
41
|
+
def db_update
|
42
|
+
if @skipped
|
43
|
+
up(@skipped) if Time.now-@time<CONFIG[:PLAYED]
|
44
|
+
elsif @played
|
45
|
+
down(@played)
|
46
|
+
@playing = ID[`mpc current`]
|
47
|
+
if play?(@playing)
|
48
|
+
@label.text = @playing
|
49
|
+
else
|
50
|
+
next_song
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@time,@played,@skipped = Time.now,@playing,nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def mpc_idle_player
|
57
|
+
loop do
|
58
|
+
system 'mpc idle player'
|
59
|
+
MUTEX.synchronize{db_update}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def next_song!
|
64
|
+
MUTEX.synchronize do
|
65
|
+
@skipped = @playing
|
66
|
+
next_song
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def stop_song!
|
71
|
+
MUTEX.synchronize do
|
72
|
+
@skipped = @playing = @played = nil
|
73
|
+
system 'mpc stop'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def initialize(program)
|
78
|
+
window,minime,menu = program.window,program.mini_menu,program.app_menu
|
79
|
+
@db = JSON.parse File.read(CONFIG[:DBM])
|
80
|
+
window.signal_connect('delete-event'){File.write(CONFIG[:DBM], JSON.pretty_generate(@db))}
|
81
|
+
|
82
|
+
# Build
|
83
|
+
vbox = Such::Box.new(window, :VBOX)
|
84
|
+
hbox = Such::Box.new(vbox, :HBOX)
|
85
|
+
Such::Button.new(hbox, :next_button!){next_song!}
|
86
|
+
Such::Button.new(hbox, :stop_button!){stop_song!}
|
87
|
+
@label = Such::Label.new(vbox)
|
88
|
+
menu.each{|_|_.destroy if _.label=='Full Screen' or _.label=='Help'}
|
89
|
+
minime.each{|_|_.destroy}
|
90
|
+
minime.append_menu_item(:stop_item!){stop_song!}
|
91
|
+
minime.append_menu_item(:next_item!){next_song!}
|
92
|
+
|
93
|
+
# Inits
|
94
|
+
@list = `mpc listall`.lines.map{|_|ID[_]}.uniq
|
95
|
+
@skipped=@playing=nil
|
96
|
+
next_song!
|
97
|
+
@time,@played = Time.now,@playing
|
98
|
+
Thread.new do
|
99
|
+
sleep(1) # mpd needs a little time to settle
|
100
|
+
mpc_idle_player
|
101
|
+
end
|
102
|
+
|
103
|
+
window.show_all
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/lib/gtk2mp3.rb
CHANGED
@@ -1,189 +1,13 @@
|
|
1
|
-
|
2
|
-
require '
|
3
|
-
# Configuration defined in gtk2mp3/appconfig
|
4
|
-
# Gtk2AppLib defined
|
1
|
+
# This is a Gtk3App.
|
2
|
+
require 'gtk3app'
|
5
3
|
|
6
|
-
|
7
|
-
|
4
|
+
# Standard Libraries
|
5
|
+
require 'json'
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@pipe = nil
|
13
|
-
self.open
|
14
|
-
end
|
15
|
-
def _read
|
16
|
-
@gui.couple.promote
|
17
|
-
@gui.previous = @gui.current
|
18
|
-
@gui.load_song
|
19
|
-
end
|
20
|
-
def read
|
21
|
-
@pipe.each do |line|
|
22
|
-
line.strip!
|
23
|
-
$stderr.puts line if $trace
|
24
|
-
if line =~ /^\@I\s+(\S.*)$/ then
|
25
|
-
# :-??
|
26
|
-
elsif line =~ /^@E/ then
|
27
|
-
@gui.load_song
|
28
|
-
elsif line == '@P 0' then
|
29
|
-
_read if @gui.continue
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
def open
|
34
|
-
if !@pipe then
|
35
|
-
@pipe = IO.popen(Configuration::PLAYER,'w+') # IO defined
|
36
|
-
self.puts Configuration::C_SILENCE
|
37
|
-
@thread = Thread.new { self.read }
|
38
|
-
sleep(Configuration::SLEEP)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
def puts(string)
|
42
|
-
self.open
|
43
|
-
@pipe.puts string
|
44
|
-
@pipe.flush
|
45
|
-
end
|
46
|
-
def close
|
47
|
-
if @pipe then
|
48
|
-
@thread.kill
|
49
|
-
@thread = nil
|
50
|
-
@pipe.close
|
51
|
-
@pipe = nil
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
7
|
+
# This Gem.
|
8
|
+
require_relative 'gtk2mp3/config.rb'
|
9
|
+
require_relative 'gtk2mp3/gui.rb'
|
55
10
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
attr_writer :previous
|
60
|
-
|
61
|
-
def initialize(window,program)
|
62
|
-
@playlist = Gtk2MP3::Playlist.new(Configuration::DIRECTORY)
|
63
|
-
@current = ''
|
64
|
-
@previous = ''
|
65
|
-
@continue = true
|
66
|
-
@pipe = Pipe.new(self)
|
67
|
-
window.signal_connect('destroy'){ @pipe.close }
|
68
|
-
|
69
|
-
vbox = Gtk2AppLib::Widgets::VBox.new(window)
|
70
|
-
|
71
|
-
hbox = Gtk2AppLib::Widgets::HBox.new(vbox)
|
72
|
-
@info = Gtk2AppLib::Widgets::Label.new(*Configuration::INFO+[hbox])
|
73
|
-
|
74
|
-
hbox = Gtk2AppLib::Widgets::HBox.new(vbox)
|
75
|
-
Gtk2AppLib::Widgets::Label.new(*Configuration::SPACER1+[hbox]) # Spacer
|
76
|
-
Gtk2AppLib::Widgets::Button.new(*Configuration::NEXT+[hbox]){ self.skip_song }
|
77
|
-
spacer = Configuration::SPACER2+[hbox]
|
78
|
-
if Configuration::PAUSE then
|
79
|
-
Gtk2AppLib::Widgets::Label.new(*spacer) # Spacer
|
80
|
-
Gtk2AppLib::Widgets::Button.new(*Configuration::PAUSE+[hbox]){ self.pause_song }
|
81
|
-
end
|
82
|
-
if Configuration::STOP then
|
83
|
-
Gtk2AppLib::Widgets::Label.new(*spacer) # Spacer
|
84
|
-
Gtk2AppLib::Widgets::Button.new(*Configuration::STOP+[hbox]){ self.stop_song }
|
85
|
-
end
|
86
|
-
if Configuration::EDIT then
|
87
|
-
Gtk2AppLib::Widgets::Label.new(*spacer) # Spacer
|
88
|
-
Gtk2AppLib::Widgets::Button.new(*Configuration::EDIT+[hbox]) do
|
89
|
-
self.stop_song!
|
90
|
-
sleep(Configuration::SLEEP)
|
91
|
-
filename = self.current
|
92
|
-
copy = File.join( Gtk2AppLib::USERDIR, File.basename(filename) )
|
93
|
-
if system( "xterm -e cutmp3 -i #{filename} -O #{copy}" )
|
94
|
-
if File.exist?(copy)
|
95
|
-
File.rename( copy, filename ) # replace with edited file
|
96
|
-
end
|
97
|
-
end
|
98
|
-
sleep(Configuration::SLEEP)
|
99
|
-
self.play_current
|
100
|
-
end
|
101
|
-
end
|
102
|
-
if Configuration::DELETE then
|
103
|
-
Gtk2AppLib::Widgets::Label.new(*Configuration::SPACER3+[hbox]) # Spacer
|
104
|
-
Gtk2AppLib::Widgets.define_composite(:CheckButton,:Button)
|
105
|
-
Gtk2AppLib::Widgets::CheckButtonButton.new(*Configuration::DELETE+[hbox]){|is,*dummies|
|
106
|
-
cb = is.checkbutton
|
107
|
-
if cb.active? then
|
108
|
-
self.delete_song
|
109
|
-
cb.active = false
|
110
|
-
end
|
111
|
-
}
|
112
|
-
end
|
113
|
-
|
114
|
-
Gtk2AppLib::Widgets::Label.new(*Configuration::SPACER4+[hbox]) # Spacer
|
115
|
-
|
116
|
-
self.load_song
|
117
|
-
self.program_appends(program)
|
118
|
-
end
|
119
|
-
|
120
|
-
def program_appends(program)
|
121
|
-
program.append_app_menu(Configuration::RELOAD){ @playlist.reload }
|
122
|
-
program.append_dock_menu(Configuration::PAUSE.first){ self.pause_song } if Configuration::PAUSE
|
123
|
-
program.append_dock_menu(Configuration::STOP.first){ self.stop_song } if Configuration::STOP
|
124
|
-
program.append_dock_menu(Configuration::NEXT.first){ self.skip_song }
|
125
|
-
end
|
126
|
-
|
127
|
-
def _random_song
|
128
|
-
@current = @playlist.random
|
129
|
-
$stderr.puts @current if $trace
|
130
|
-
@couple = Gtk2MP3::Couple.new(@current,@previous)
|
131
|
-
$stderr.puts "#{@couple.keys.last} #{@couple.treshold}" if $trace
|
132
|
-
end
|
133
|
-
|
134
|
-
def random_song
|
135
|
-
plays = false
|
136
|
-
while !plays do
|
137
|
-
_random_song
|
138
|
-
plays = @couple.play?
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def play_current
|
143
|
-
@pipe.puts "#{Configuration::C_LOAD} #{@current}"
|
144
|
-
@time = Time.now
|
145
|
-
end
|
146
|
-
|
147
|
-
def load_song
|
148
|
-
self.random_song
|
149
|
-
@info.text = File.basename(@current,MP3) # File defined
|
150
|
-
self.play_current
|
151
|
-
end
|
152
|
-
|
153
|
-
def demote
|
154
|
-
@couple.demote if Time.now - @time < 60.0
|
155
|
-
end
|
156
|
-
|
157
|
-
def skip_song
|
158
|
-
(@continue)? demote: (@continue = true)
|
159
|
-
self.load_song
|
160
|
-
end
|
161
|
-
|
162
|
-
def stop_song!
|
163
|
-
@pipe.puts Configuration::C_STOP
|
164
|
-
@pipe.close
|
165
|
-
end
|
166
|
-
|
167
|
-
def stop_song
|
168
|
-
if @continue then
|
169
|
-
@previous = ''
|
170
|
-
@continue = false
|
171
|
-
stop_song!
|
172
|
-
else
|
173
|
-
@continue = true
|
174
|
-
self.load_song
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def pause_song
|
179
|
-
@pipe.puts Configuration::C_PAUSE
|
180
|
-
end
|
181
|
-
|
182
|
-
def delete_song
|
183
|
-
File.unlink(@current)
|
184
|
-
@playlist.delete(@current)
|
185
|
-
Couple.delete(@current)
|
186
|
-
self.load_song
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
11
|
+
# Requires:
|
12
|
+
#`ruby`
|
13
|
+
#`mpd`
|
metadata
CHANGED
@@ -1,71 +1,98 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: gtk2mp3
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.7.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
- carlosjhr64
|
6
|
+
authors:
|
7
|
+
- carlosjhr64
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
date: 2018-03-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: help_parser
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.3'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 6.3.0
|
23
|
+
type: :runtime
|
17
24
|
prerelease: false
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '6.3'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 6.3.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: gtk3app
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '2.0'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 2.0.2
|
24
43
|
type: :runtime
|
25
|
-
|
26
|
-
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '2.0'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 2.0.2
|
53
|
+
description: 'A "Next!" button gui for MPD/MPC.
|
54
|
+
|
55
|
+
'
|
27
56
|
email: carlosjhr64@gmail.com
|
28
|
-
executables:
|
57
|
+
executables:
|
29
58
|
- gtk2mp3
|
30
59
|
extensions: []
|
31
|
-
|
32
60
|
extra_rdoc_files: []
|
33
|
-
|
34
|
-
|
35
|
-
-
|
36
|
-
- ./lib/gtk2mp3/couple.rb
|
37
|
-
- ./lib/gtk2mp3/playlist.rb
|
38
|
-
- ./lib/gtk2mp3.rb
|
39
|
-
- ./pngs/icon.png
|
40
|
-
- ./pngs/logo.png
|
41
|
-
- ./README.txt
|
61
|
+
files:
|
62
|
+
- LICENSE
|
63
|
+
- README.md
|
42
64
|
- bin/gtk2mp3
|
43
|
-
|
44
|
-
|
45
|
-
|
65
|
+
- cache/dbm.json
|
66
|
+
- data/VERSION
|
67
|
+
- data/logo.png
|
68
|
+
- lib/gtk2mp3.rb
|
69
|
+
- lib/gtk2mp3/config.rb
|
70
|
+
- lib/gtk2mp3/gui.rb
|
71
|
+
homepage: https://github.com/carlosjhr64/gtk2mp3
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
metadata: {}
|
46
75
|
post_install_message:
|
47
76
|
rdoc_options: []
|
48
|
-
|
49
|
-
require_paths:
|
77
|
+
require_paths:
|
50
78
|
- lib
|
51
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
-
|
53
|
-
requirements:
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
54
81
|
- - ">="
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version:
|
57
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
-
|
59
|
-
requirements:
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
60
86
|
- - ">="
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
version:
|
63
|
-
requirements:
|
64
|
-
-
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements:
|
90
|
+
- 'mpc: off'
|
91
|
+
- 'ruby: ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]'
|
92
|
+
- 'mpd: Music Player Daemon 0.20.10'
|
65
93
|
rubyforge_project:
|
66
|
-
rubygems_version:
|
94
|
+
rubygems_version: 2.7.3
|
67
95
|
signing_key:
|
68
|
-
specification_version:
|
69
|
-
summary:
|
96
|
+
specification_version: 4
|
97
|
+
summary: A "Next!" button gui for MPD/MPC.
|
70
98
|
test_files: []
|
71
|
-
|
data/README.txt
DELETED
data/lib/gtk2mp3/appconfig.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
module Gtk2AppLib # Gtk2AppLib defined
|
2
|
-
module Configuration
|
3
|
-
WINDOW_DEFAULT_SIZE[0],WINDOW_DEFAULT_SIZE[1] = 0,0 # WINDOW_DEFAULT_SIZE defined in gtk2applib/configuration
|
4
|
-
MENU[:dock] = '_Dock' # MENU defined in gtk2applib/configuration
|
5
|
-
end
|
6
|
-
end
|
7
|
-
|
8
|
-
module Gtk2MP3
|
9
|
-
module Configuration
|
10
|
-
# File defined
|
11
|
-
# ARGV defined as command line arguments
|
12
|
-
# Gtk defined in gtk2
|
13
|
-
# Where is your MP3 directory?
|
14
|
-
dialog = Gtk::FileChooserDialog.new("Choose Mp3 Directory", nil, Gtk::FileChooser::ACTION_SELECT_FOLDER, nil,
|
15
|
-
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], [Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT])
|
16
|
-
directory = (ARGV.shift) || nil # '/path/to/mp3s' # give it a good default, dude!
|
17
|
-
if directory && File.exist?(directory) && File.directory?(directory) then
|
18
|
-
dialog.filename = directory
|
19
|
-
end
|
20
|
-
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
21
|
-
directory = dialog.filename
|
22
|
-
else
|
23
|
-
exit
|
24
|
-
end
|
25
|
-
dialog.destroy
|
26
|
-
DIRECTORY = directory
|
27
|
-
|
28
|
-
options = {:modify_font => Gtk2AppLib::Configuration::FONT[:LARGE]}.freeze
|
29
|
-
SPACER1 = [' ', options].freeze
|
30
|
-
SPACER2 = [' ', options].freeze
|
31
|
-
SPACER3 = [' ', options].freeze
|
32
|
-
SPACER4 = [' ', options].freeze
|
33
|
-
INFO = ['Gtk2 MP3 Next!!!!',{:modify_font => Gtk2AppLib::Configuration::FONT[:SMALL]}].freeze
|
34
|
-
|
35
|
-
RELOAD = '_Reload'
|
36
|
-
|
37
|
-
clicked = 'clicked'
|
38
|
-
NEXT = ['Next!', options, clicked].freeze
|
39
|
-
PAUSE = ['Pause', options, clicked].freeze # this one can be set to nil
|
40
|
-
STOP = ['Stop', options, clicked].freeze # this one can be set to nil
|
41
|
-
DELETE = ['Delete', options, clicked].freeze # this one can be set to nil
|
42
|
-
EDIT = (Gtk2AppLib::Configuration::X && Gtk2AppLib.which([['cutmp3', ' ']]))? ['Edit', options, clicked].freeze : nil # this one can be set to nil
|
43
|
-
|
44
|
-
SELECT_A_FILE = [['Select a file', Gtk::FileChooser::ACTION_OPEN],Gtk2AppLib::HNIL].freeze
|
45
|
-
|
46
|
-
PLAYER = 'mpg123 -q -a hw:0,0 -R' # 'mpg123 -q -R'
|
47
|
-
# mpg123 commands
|
48
|
-
C_PAUSE = 'P'
|
49
|
-
C_STOP = 'S'
|
50
|
-
C_SILENCE = 'SILENCE'
|
51
|
-
C_LOAD = 'L'
|
52
|
-
C_QUIT = 'Q'
|
53
|
-
|
54
|
-
SLEEP = 0.5
|
55
|
-
end
|
56
|
-
end
|
data/lib/gtk2mp3/couple.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
# Gtk2AppLib defined
|
2
|
-
# File defined
|
3
|
-
module Gtk2MP3 # Gtk2MP3 defined
|
4
|
-
class Couple # Couple defined
|
5
|
-
BASE = Hash.new(1.0)
|
6
|
-
BASE_DUMP = Gtk2AppLib::USERDIR + '/base.dump'
|
7
|
-
|
8
|
-
COUPLE = Hash.new(1.0)
|
9
|
-
COUPLE_DUMP = Gtk2AppLib::USERDIR + '/couple.dump'
|
10
|
-
|
11
|
-
LEARNING = Math.sqrt(2.0) # Math defined, built in
|
12
|
-
SEP = '/'
|
13
|
-
SEPX = Regexp.new(SEP) # Regexp defined, built in
|
14
|
-
|
15
|
-
def initialize(candidate,previous)
|
16
|
-
@candidate = candidate
|
17
|
-
@previous = previous
|
18
|
-
self.keys!
|
19
|
-
self.threshold!
|
20
|
-
end
|
21
|
-
|
22
|
-
def self._load(dump,hash)
|
23
|
-
fh = File.open(dump,'r')
|
24
|
-
fh.each do |line|
|
25
|
-
if line=~/^(.*)\s([\d\.]+)\s*$/ then
|
26
|
-
hash[$1.strip] = $2.to_f
|
27
|
-
end
|
28
|
-
end
|
29
|
-
fh.close
|
30
|
-
end
|
31
|
-
def self.load
|
32
|
-
Couple._load(BASE_DUMP,BASE) if File.exist?(BASE_DUMP)
|
33
|
-
Couple._load(COUPLE_DUMP,COUPLE) if File.exist?(COUPLE_DUMP)
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.delete(current)
|
37
|
-
key = File.basename(current,Gtk2MP3::MP3)
|
38
|
-
BASE.delete(key)
|
39
|
-
COUPLE.delete_if{|pair| pair.split(SEPX).include?(key)}
|
40
|
-
end
|
41
|
-
|
42
|
-
def self._dump(dump,hash)
|
43
|
-
# Note that the default value is 1.0, so no need to save 1.0 values.
|
44
|
-
# File.open(dump,'w'){|fh| hash.each{|k,v| fh.puts "#{k}\t#{v}" if v < 1.0 } }
|
45
|
-
fh = File.open(dump,'w')
|
46
|
-
hash.each{|key,value| fh.puts "#{key}\t#{value}" if value < 1.0 }
|
47
|
-
fh.close
|
48
|
-
end
|
49
|
-
def self.dump
|
50
|
-
Couple._dump(BASE_DUMP,BASE)
|
51
|
-
Couple._dump(COUPLE_DUMP,COUPLE)
|
52
|
-
end
|
53
|
-
|
54
|
-
def keys!
|
55
|
-
@base = File.basename(@candidate,Gtk2MP3::MP3)
|
56
|
-
@couple = @base + SEP + File.basename(@previous,Gtk2MP3::MP3)
|
57
|
-
end
|
58
|
-
|
59
|
-
def keys
|
60
|
-
return @base, @couple
|
61
|
-
end
|
62
|
-
|
63
|
-
def threshold!
|
64
|
-
@threshold = BASE[@base] * COUPLE[@couple]
|
65
|
-
end
|
66
|
-
|
67
|
-
def treshold
|
68
|
-
@threshold
|
69
|
-
end
|
70
|
-
|
71
|
-
def promote
|
72
|
-
BASE[@base] *= LEARNING
|
73
|
-
COUPLE[@couple] *= LEARNING
|
74
|
-
BASE[@base] = 1.0 if BASE[@base] > 1.0
|
75
|
-
COUPLE[@couple] = 1.0 if COUPLE[@couple] > 1.0
|
76
|
-
end
|
77
|
-
|
78
|
-
def promote!
|
79
|
-
self.promote
|
80
|
-
self.threshold!
|
81
|
-
end
|
82
|
-
|
83
|
-
def demote
|
84
|
-
BASE[@base] /= LEARNING
|
85
|
-
COUPLE[@couple] /= LEARNING
|
86
|
-
BASE[@base] = 0.25 if BASE[@base] < 0.25
|
87
|
-
COUPLE[@couple] = 0.25 if COUPLE[@couple] < 0.25
|
88
|
-
end
|
89
|
-
|
90
|
-
def demote!
|
91
|
-
self.demote
|
92
|
-
self.threshold!
|
93
|
-
end
|
94
|
-
|
95
|
-
def play?
|
96
|
-
return rand < @threshold
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
data/lib/gtk2mp3/playlist.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'find' # Find defined
|
2
|
-
|
3
|
-
module Gtk2MP3
|
4
|
-
class Playlist < Array # [] defined in Array
|
5
|
-
IS_MP3 = Regexp.new(/\.mp3$/) # Regexp defined, built in
|
6
|
-
|
7
|
-
def initialize(directory)
|
8
|
-
super()
|
9
|
-
@directory = directory
|
10
|
-
self.reload
|
11
|
-
$stderr.puts "Playlist length #{self.length}" if $trace
|
12
|
-
end
|
13
|
-
|
14
|
-
def reload
|
15
|
-
self.clear
|
16
|
-
Find.find(@directory){|fn| self.push(fn) if fn=~IS_MP3 }
|
17
|
-
raise 'no mp3s found' if self.length < 1
|
18
|
-
end
|
19
|
-
|
20
|
-
def random
|
21
|
-
self[ rand(self.length) ]
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/pngs/icon.png
DELETED
Binary file
|
/data/{pngs → data}/logo.png
RENAMED
File without changes
|