gtk2mp3 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|