gtk2mp3 0.0.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.
- data/README.txt +5 -0
- data/bin/gtk2mp3 +29 -0
- data/lib/gtk2mp3/appconfig.rb +48 -0
- data/lib/gtk2mp3/couple.rb +94 -0
- data/lib/gtk2mp3/playlist.rb +22 -0
- data/lib/gtk2mp3.rb +93 -0
- data/pngs/icon.png +0 -0
- data/pngs/logo.png +0 -0
- metadata +90 -0
data/README.txt
ADDED
data/bin/gtk2mp3
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
gem 'gtk2applib', '~> 9.2'
|
4
|
+
require 'gtk2applib'
|
5
|
+
include Gtk2AppLib
|
6
|
+
include Configuration
|
7
|
+
|
8
|
+
Lock.lock_mode
|
9
|
+
program = Program.new( {
|
10
|
+
'name' => 'Ruby-Gnome MP3',
|
11
|
+
'authors' => ['carlosjhr64@gmail.com'],
|
12
|
+
'website' => 'http://ruby-gnome-apps.blogspot.com/search/label/MP3',
|
13
|
+
'website-label' => 'Ruby-Gnome MP3',
|
14
|
+
'license' => 'GPL',
|
15
|
+
'copyright' => '2010-10-07 17:34:04',
|
16
|
+
} )
|
17
|
+
|
18
|
+
IO.popen(PLAYER,'w+') do |pipe|
|
19
|
+
begin
|
20
|
+
require 'gtk2mp3'
|
21
|
+
Gtk2MP3::Couple.load
|
22
|
+
program.window{|window| Gtk2MP3::GUI.new(window,pipe,program)}
|
23
|
+
rescue Exception
|
24
|
+
$!.puts_bang!
|
25
|
+
ensure
|
26
|
+
Gtk2MP3::Couple.dump
|
27
|
+
program.finalize
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Gtk2AppLib
|
2
|
+
module Configuration
|
3
|
+
directory = nil # '/path/to/mp3s' # give it a good default, dude!
|
4
|
+
dialog = Gtk::FileChooserDialog.new("Choose Mp3 Directory", nil, Gtk::FileChooser::ACTION_SELECT_FOLDER, nil,
|
5
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
6
|
+
[Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT])
|
7
|
+
dialog.filename = directory if directory
|
8
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
9
|
+
directory = dialog.filename
|
10
|
+
end
|
11
|
+
dialog.destroy
|
12
|
+
DIRECTORY = directory
|
13
|
+
|
14
|
+
WINDOW_DEFAULT_SIZE[0],WINDOW_DEFAULT_SIZE[1] = 0,0
|
15
|
+
OPTIONS = {:modify_font => FONT[:Large]}.freeze
|
16
|
+
|
17
|
+
SPACER1 =
|
18
|
+
SPACER2 =
|
19
|
+
SPACER3 =
|
20
|
+
SPACER4 = [' ', OPTIONS].freeze
|
21
|
+
INFO = {:modify_font => FONT[:Small]}.freeze
|
22
|
+
|
23
|
+
|
24
|
+
RELOAD = '_Reload'
|
25
|
+
|
26
|
+
CLICKED = 'clicked' # Signal (should be no need to edit)
|
27
|
+
NEXT = ['Next!', OPTIONS, CLICKED].freeze
|
28
|
+
PAUSE = ['Pause', OPTIONS, CLICKED].freeze
|
29
|
+
DELETE = ['Delete', OPTIONS, CLICKED].freeze
|
30
|
+
|
31
|
+
SELECT_A_FILE = [['Select a file', Gtk::FileChooser::ACTION_OPEN],HNIL].freeze
|
32
|
+
|
33
|
+
PLAYER = 'mpg123 -q -a hw:0,0 -R'
|
34
|
+
# mpg123 commands
|
35
|
+
C_PAUSE = 'P'
|
36
|
+
C_SILENCE = 'SILENCE'
|
37
|
+
C_LOAD = 'L'
|
38
|
+
C_QUIT = 'Q'
|
39
|
+
|
40
|
+
### Unused ####
|
41
|
+
# C_LOADPAUSED = 'LP'
|
42
|
+
# C_STOP = 'S'
|
43
|
+
# C_VOLUME = 'V'
|
44
|
+
# C_TAG = 'T'
|
45
|
+
|
46
|
+
MENU[:dock] = '_Dock'
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Gtk2MP3
|
2
|
+
class Couple
|
3
|
+
BASE = Hash.new(1.0)
|
4
|
+
BASE_DUMP = USERDIR + '/base.dump'
|
5
|
+
|
6
|
+
COUPLE = Hash.new(1.0)
|
7
|
+
COUPLE_DUMP = USERDIR + '/couple.dump'
|
8
|
+
|
9
|
+
LEARNING = Math.sqrt(2.0)
|
10
|
+
SEP = '/'
|
11
|
+
SEPX = Regexp.new(SEP)
|
12
|
+
|
13
|
+
def self._load(dump,hash)
|
14
|
+
File.open(dump,'r'){|fh|
|
15
|
+
fh.each{|line|
|
16
|
+
if line=~/^(.*)\s([\d\.]+)\s*$/ then
|
17
|
+
hash[$1.strip] = $2.to_f
|
18
|
+
end
|
19
|
+
}
|
20
|
+
} if File.exist?(dump)
|
21
|
+
end
|
22
|
+
def self.load
|
23
|
+
Couple._load(BASE_DUMP,BASE)
|
24
|
+
Couple._load(COUPLE_DUMP,COUPLE)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.delete(current)
|
28
|
+
key = File.basename(current,MP3)
|
29
|
+
BASE.delete(key)
|
30
|
+
COUPLE.delete_if{|k| k.split(SEPX).include?(key)}
|
31
|
+
end
|
32
|
+
|
33
|
+
def self._dump(dump,hash)
|
34
|
+
# Note that the default value is 1.0, so no need to save 1.0 values.
|
35
|
+
File.open(dump,'w'){|fh| hash.each{|k,v| fh.puts "#{k}\t#{v}" if v < 1.0 } }
|
36
|
+
end
|
37
|
+
def self.dump
|
38
|
+
Couple._dump(BASE_DUMP,BASE)
|
39
|
+
Couple._dump(COUPLE_DUMP,COUPLE)
|
40
|
+
end
|
41
|
+
|
42
|
+
def keys!
|
43
|
+
@base = File.basename(@candidate,MP3)
|
44
|
+
@couple = @base + SEP + File.basename(@previous,MP3)
|
45
|
+
end
|
46
|
+
|
47
|
+
def keys
|
48
|
+
return @base, @couple
|
49
|
+
end
|
50
|
+
|
51
|
+
def threshold!
|
52
|
+
@threshold = BASE[@base] * COUPLE[@couple]
|
53
|
+
end
|
54
|
+
|
55
|
+
def treshold
|
56
|
+
@threshold
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(candidate,previous)
|
60
|
+
@candidate = candidate
|
61
|
+
@previous = previous
|
62
|
+
self.keys!
|
63
|
+
self.threshold!
|
64
|
+
end
|
65
|
+
|
66
|
+
def promote
|
67
|
+
BASE[@base] *= LEARNING
|
68
|
+
COUPLE[@couple] *= LEARNING
|
69
|
+
BASE[@base] = 1.0 if BASE[@base] > 1.0
|
70
|
+
COUPLE[@couple] = 1.0 if COUPLE[@couple] > 1.0
|
71
|
+
end
|
72
|
+
|
73
|
+
def promote!
|
74
|
+
self.promote
|
75
|
+
self.threshold!
|
76
|
+
end
|
77
|
+
|
78
|
+
def demote
|
79
|
+
BASE[@base] /= LEARNING
|
80
|
+
COUPLE[@couple] /= LEARNING
|
81
|
+
BASE[@base] = 0.25 if BASE[@base] < 0.25
|
82
|
+
COUPLE[@couple] = 0.25 if COUPLE[@couple] < 0.25
|
83
|
+
end
|
84
|
+
|
85
|
+
def demote!
|
86
|
+
self.demote
|
87
|
+
self.threshold!
|
88
|
+
end
|
89
|
+
|
90
|
+
def play?
|
91
|
+
return rand < @threshold
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gtk2MP3
|
2
|
+
class Playlist < Array
|
3
|
+
IS_MP3 = Regexp.new(/\.mp3$/)
|
4
|
+
|
5
|
+
def reload
|
6
|
+
self.clear
|
7
|
+
Find.find(@directory){|fn| self.push(fn) if fn=~IS_MP3 }
|
8
|
+
raise 'no mp3s found' if self.length < 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(directory)
|
12
|
+
super()
|
13
|
+
@directory = directory
|
14
|
+
self.reload
|
15
|
+
$stderr.puts "Playlist length #{self.length}" if $trace
|
16
|
+
end
|
17
|
+
|
18
|
+
def random
|
19
|
+
self[ rand(self.length) ]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/gtk2mp3.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'gtk2mp3/playlist'
|
2
|
+
require 'gtk2mp3/couple'
|
3
|
+
|
4
|
+
module Gtk2MP3
|
5
|
+
MP3 = '.mp3'
|
6
|
+
|
7
|
+
class GUI
|
8
|
+
include Configuration
|
9
|
+
def random_song
|
10
|
+
plays = false
|
11
|
+
while !plays do
|
12
|
+
@current = @playlist.random
|
13
|
+
$stderr.puts @current if $trace
|
14
|
+
@couple = Gtk2MP3::Couple.new(@current,@previous)
|
15
|
+
$stderr.puts "#{@couple.keys.last} #{@couple.treshold}" if $trace
|
16
|
+
plays = @couple.play?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def load_song
|
21
|
+
self.random_song
|
22
|
+
@info.text = File.basename(@current,MP3)
|
23
|
+
@pipe.puts "#{C_LOAD} #{@current}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def skip_song
|
27
|
+
@couple.demote
|
28
|
+
self.load_song
|
29
|
+
end
|
30
|
+
|
31
|
+
def pause_song
|
32
|
+
@pipe.puts C_PAUSE
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete_song
|
36
|
+
File.unlink(@current)
|
37
|
+
@playlist.delete(@current)
|
38
|
+
@couple.delete(@current)
|
39
|
+
self.load_song
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize(window,pipe,program)
|
43
|
+
pipe.puts C_SILENCE
|
44
|
+
window.signal_connect('destroy'){ pipe.puts C_QUIT }
|
45
|
+
|
46
|
+
@pipe = pipe
|
47
|
+
@playlist = Gtk2MP3::Playlist.new(DIRECTORY)
|
48
|
+
@current = ''
|
49
|
+
@previous = ''
|
50
|
+
|
51
|
+
vbox = Widgets::VBox.new(window)
|
52
|
+
|
53
|
+
hbox = Widgets::HBox.new(vbox)
|
54
|
+
@info = Widgets::Label.new('Gtk2 MP3 Next!!!!', INFO, hbox)
|
55
|
+
|
56
|
+
hbox = Widgets::HBox.new(vbox)
|
57
|
+
Widgets::Label.new(*SPACER1, hbox) # Spacer
|
58
|
+
Widgets::Button.new(*NEXT, hbox){ self.skip_song }
|
59
|
+
Widgets::Label.new(*SPACER2, hbox) # Spacer
|
60
|
+
Widgets::Button.new(*PAUSE, hbox){ self.pause_song }
|
61
|
+
Widgets::Label.new(*SPACER3, hbox) # Spacer
|
62
|
+
Widgets.define_composite(:CheckButton,:Button)
|
63
|
+
Widgets::CheckButtonButton.new(*DELETE, hbox){|is,*dummies|
|
64
|
+
if is.checkbutton.active? then
|
65
|
+
self.delete_song
|
66
|
+
is.checkbutton.active = false
|
67
|
+
end
|
68
|
+
}
|
69
|
+
Widgets::Label.new(*SPACER4, hbox) # Spacer
|
70
|
+
|
71
|
+
self.load_song
|
72
|
+
Thread.new do
|
73
|
+
pipe.each do |line|
|
74
|
+
line.strip!
|
75
|
+
$stderr.puts line if $trace
|
76
|
+
if line =~ /^\@I\s+(\S.*)$/ then
|
77
|
+
# :-??
|
78
|
+
elsif line == '@P 0' then
|
79
|
+
@couple.promote
|
80
|
+
@previous = @current
|
81
|
+
self.load_song
|
82
|
+
end
|
83
|
+
end
|
84
|
+
false
|
85
|
+
end
|
86
|
+
|
87
|
+
program.append_app_menu(RELOAD){ @playlist.reload }
|
88
|
+
program.append_dock_menu(PAUSE.first){ self.pause_song }
|
89
|
+
program.append_dock_menu(NEXT.first){ self.skip_song }
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/pngs/icon.png
ADDED
Binary file
|
data/pngs/logo.png
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gtk2mp3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 0.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- carlosjhr64@gmail.com
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-07 00:00:00 -07:00
|
19
|
+
default_executable: gtk2mp3
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: gtk2applib
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 43
|
30
|
+
segments:
|
31
|
+
- 9
|
32
|
+
- 2
|
33
|
+
version: "9.2"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
description: a "Next!" button gui for mpg123
|
37
|
+
email: carlosjhr64@gmail.com
|
38
|
+
executables:
|
39
|
+
- gtk2mp3
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- README.txt
|
44
|
+
files:
|
45
|
+
- ./lib/gtk2mp3/playlist.rb
|
46
|
+
- ./lib/gtk2mp3/couple.rb
|
47
|
+
- ./lib/gtk2mp3/appconfig.rb
|
48
|
+
- ./lib/gtk2mp3.rb
|
49
|
+
- ./pngs/logo.png
|
50
|
+
- ./pngs/icon.png
|
51
|
+
- ./README.txt
|
52
|
+
- README.txt
|
53
|
+
- bin/gtk2mp3
|
54
|
+
has_rdoc: true
|
55
|
+
homepage: http://ruby-gnome-apps.blogspot.com/search/label/MP3
|
56
|
+
licenses: []
|
57
|
+
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options:
|
60
|
+
- --main
|
61
|
+
- README.txt
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 3
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
requirements:
|
83
|
+
- mpg123
|
84
|
+
rubyforge_project: gtk2mp3
|
85
|
+
rubygems_version: 1.3.7
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: Gtk2MP3
|
89
|
+
test_files: []
|
90
|
+
|