cultome_player 2.0.0 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -79
- data/Rakefile +38 -4
- data/bin/cultome_player +16 -4
- data/config/environment.yml +4 -0
- data/cultome_player.gemspec +8 -1
- data/lib/cultome_player.rb +45 -19
- data/lib/cultome_player/command/language.rb +3 -4
- data/lib/cultome_player/command/processor.rb +9 -7
- data/lib/cultome_player/command/reader.rb +11 -2
- data/lib/cultome_player/environment.rb +21 -13
- data/lib/cultome_player/events.rb +7 -7
- data/lib/cultome_player/objects/album.rb +9 -2
- data/lib/cultome_player/objects/artist.rb +9 -2
- data/lib/cultome_player/objects/command.rb +10 -1
- data/lib/cultome_player/objects/drive.rb +4 -1
- data/lib/cultome_player/objects/genre.rb +4 -1
- data/lib/cultome_player/objects/parameter.rb +21 -1
- data/lib/cultome_player/objects/response.rb +5 -1
- data/lib/cultome_player/objects/song.rb +9 -4
- data/lib/cultome_player/player/adapter/mpg123.rb +3 -4
- data/lib/cultome_player/player/interactive.rb +67 -11
- data/lib/cultome_player/player/interface/basic.rb +13 -9
- data/lib/cultome_player/player/interface/extended.rb +26 -12
- data/lib/cultome_player/player/interface/helper.rb +73 -9
- data/lib/cultome_player/plugins.rb +44 -18
- data/lib/cultome_player/plugins/alias.rb +85 -0
- data/lib/cultome_player/plugins/gestures.rb +90 -0
- data/lib/cultome_player/plugins/help.rb +4 -4
- data/lib/cultome_player/plugins/keyboard_special_keys.rb +22 -0
- data/lib/cultome_player/plugins/points.rb +51 -0
- data/lib/cultome_player/utils.rb +117 -7
- data/lib/cultome_player/version.rb +1 -1
- data/xbindkeys/xbindkeysrc +12 -0
- metadata +37 -89
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -24
- data/.rspec +0 -2
- data/.travis.yml +0 -7
- data/db/001_create_schema.rb +0 -58
- data/spec/config.yml +0 -0
- data/spec/cultome_player/command/processor_spec.rb +0 -168
- data/spec/cultome_player/command/reader_spec.rb +0 -45
- data/spec/cultome_player/cultome_player_spec.rb +0 -17
- data/spec/cultome_player/environment_spec.rb +0 -65
- data/spec/cultome_player/events_spec.rb +0 -22
- data/spec/cultome_player/media_spec.rb +0 -41
- data/spec/cultome_player/player/adapter/mpg123_spec.rb +0 -82
- data/spec/cultome_player/player/interface/basic_spec.rb +0 -168
- data/spec/cultome_player/player/interface/extended/connect_spec.rb +0 -117
- data/spec/cultome_player/player/interface/extended/search_spec.rb +0 -90
- data/spec/cultome_player/player/interface/extended/show_spec.rb +0 -36
- data/spec/cultome_player/player/interface/extended/shuffle_spec.rb +0 -26
- data/spec/cultome_player/player/interface/extended_spec.rb +0 -136
- data/spec/cultome_player/player/interface/helper_spec.rb +0 -63
- data/spec/cultome_player/player/interface_spec.rb +0 -17
- data/spec/cultome_player/player/playlist_spec.rb +0 -301
- data/spec/cultome_player/plugins/help_spec.rb +0 -21
- data/spec/cultome_player/plugins_spec.rb +0 -19
- data/spec/cultome_player/utils_spec.rb +0 -15
- data/spec/spec_helper.rb +0 -108
- data/spec/test/uno/dos/dos.mp3 +0 -0
- data/spec/test/uno/dos/tres/tres.mp3 +0 -0
- data/spec/test/uno/uno.mp3 +0 -0
- data/tasks/console.rake +0 -19
- data/tasks/db.rake +0 -19
- data/tasks/run.rake +0 -7
@@ -8,7 +8,16 @@ module CultomePlayer::Command
|
|
8
8
|
# @param prompt [String] The message to display to user for arcking for input.
|
9
9
|
# @return [String] The user input readed.
|
10
10
|
def read_command(prompt)
|
11
|
-
command_reader.readline(prompt, true)
|
11
|
+
input = command_reader.readline(c5(prompt), true)
|
12
|
+
|
13
|
+
# evitamos que comando consecutivos repetidos o vacios queden en el historial
|
14
|
+
if input.empty?
|
15
|
+
command_reader::HISTORY.pop
|
16
|
+
elsif command_reader::HISTORY.to_a.reverse[1] == input
|
17
|
+
command_reader::HISTORY.pop
|
18
|
+
end
|
19
|
+
|
20
|
+
return input
|
12
21
|
end
|
13
22
|
|
14
23
|
# Lazy getter for readline object.
|
@@ -69,7 +78,7 @@ module CultomePlayer::Command
|
|
69
78
|
expanded_path += "/" if File.directory?(expanded_path)
|
70
79
|
Dir[expanded_path + "*"].grep(/^#{Regexp.escape(expanded_path)}/).collect{|d| "#{d}/"}
|
71
80
|
elsif word.start_with?("@")
|
72
|
-
%w{@
|
81
|
+
%w{@playlist @current @history @queue @search @song @artist @album @drives @artists @albums @genres @library @recently_added @recently_played @most_played @less_played @populars}.grep(/^#{word}/)
|
73
82
|
end
|
74
83
|
end
|
75
84
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'yaml'
|
2
|
-
require 'rake'
|
3
2
|
|
4
3
|
module CultomePlayer
|
5
4
|
module Environment
|
@@ -39,6 +38,13 @@ module CultomePlayer
|
|
39
38
|
env_config['config_file'] || raise('environment problem:environment information not loaded')
|
40
39
|
end
|
41
40
|
|
41
|
+
# Get the command_pipe environment configuration value.
|
42
|
+
#
|
43
|
+
# @return [String] The command_pipe value for teh selected environment.
|
44
|
+
def command_pipe
|
45
|
+
env_config['command_pipe'] || raise('environment problem:environment information not loaded')
|
46
|
+
end
|
47
|
+
|
42
48
|
# Get the mplayer_pipe environment configuration value.
|
43
49
|
#
|
44
50
|
# @return [String] The mplayer_pipe value for teh selected environment.
|
@@ -74,29 +80,31 @@ module CultomePlayer
|
|
74
80
|
@current_env
|
75
81
|
end
|
76
82
|
|
83
|
+
def load_environment_properties(env)
|
84
|
+
env_config = YAML.load_file File.expand_path('config/environment.yml', File.join(File.dirname(__FILE__), "../.."))
|
85
|
+
@env_config = env_config[env.to_s]
|
86
|
+
expand_paths @env_config
|
87
|
+
@current_env = env.to_sym
|
88
|
+
return @env_config
|
89
|
+
end
|
90
|
+
|
77
91
|
# Extract the configuration for the environment and setup valriables.
|
78
92
|
#
|
79
93
|
# @param env [Symbol] The name of the environment to load.
|
80
94
|
# @param check_db [Boolean] Flag to decide if the database schema should be checked.
|
81
|
-
def prepare_environment(env
|
82
|
-
|
83
|
-
@env_config = env_config[env.to_s]
|
84
|
-
@current_env = env.to_sym
|
95
|
+
def prepare_environment(env)
|
96
|
+
load_environment_properties(env)
|
85
97
|
raise 'environment problem:environment not found' if @env_config.nil?
|
86
|
-
expand_paths @env_config
|
87
98
|
create_required_files @env_config
|
88
99
|
load_master_config @env_config['config_file']
|
89
|
-
check_db_schema if check_db
|
90
100
|
end
|
91
101
|
|
92
|
-
|
93
|
-
|
94
|
-
def check_db_schema
|
95
|
-
Rake.load_rakefile 'Rakefile'
|
96
|
-
Rake.application.load_imports
|
97
|
-
swallow_stdout{ Rake.application.invoke_task("db:create[#{current_env}]") }
|
102
|
+
def save_player_configurations
|
103
|
+
open(config_file, 'w'){|f| f.write player_config.to_yaml }
|
98
104
|
end
|
99
105
|
|
106
|
+
private
|
107
|
+
|
100
108
|
def load_master_config(config_file)
|
101
109
|
@player_config = YAML.load_file(config_file) || {}
|
102
110
|
@player_config['main'] ||= {}
|
@@ -8,14 +8,14 @@ module CultomePlayer
|
|
8
8
|
@listeners ||= Hash.new{|h,k| h[k] = [] }
|
9
9
|
end
|
10
10
|
|
11
|
-
# Register a
|
11
|
+
# Register a callback to an event.
|
12
12
|
#
|
13
13
|
# @param event [Symbol] The event name.
|
14
|
-
# @param
|
15
|
-
# @return [Object] The registered
|
16
|
-
def register_listener(event,
|
17
|
-
listeners[event] <<
|
18
|
-
return
|
14
|
+
# @param callback [Object] Implements a callback with the name on_<event name>.
|
15
|
+
# @return [Object] The registered callback.
|
16
|
+
def register_listener(event, &callback)
|
17
|
+
listeners[event] << callback
|
18
|
+
return callback
|
19
19
|
end
|
20
20
|
|
21
21
|
# Broadcast an event to all the registered listeners.
|
@@ -23,7 +23,7 @@ module CultomePlayer
|
|
23
23
|
# @param event [Symbol] The event name.
|
24
24
|
# @param data [Array] The information sended to the listeners.
|
25
25
|
def emit_event(event, *data)
|
26
|
-
listeners[event].collect{|l| l.
|
26
|
+
listeners[event].collect{|l| l.call(*data) }
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -4,18 +4,25 @@ module CultomePlayer
|
|
4
4
|
module Objects
|
5
5
|
# The ActiveRecord model for Album objects.
|
6
6
|
class Album < ActiveRecord::Base
|
7
|
+
|
8
|
+
include CultomePlayer::Utils
|
9
|
+
|
7
10
|
has_many :songs
|
8
11
|
has_many :artists, through: :songs
|
9
12
|
|
10
13
|
def to_s
|
11
14
|
str = c4(":::: Album: ")
|
12
|
-
str +=
|
15
|
+
str += c16(self.name)
|
13
16
|
str += c4(" \\ Artist: ")
|
14
17
|
unless self.artists.nil? || self.artists.empty?
|
15
18
|
str += c11(self.artists.uniq.collect{|a| a.name}.join(', '))
|
16
19
|
end
|
17
20
|
str += c4(" ::::")
|
18
21
|
end
|
22
|
+
|
23
|
+
def readonly?
|
24
|
+
false
|
25
|
+
end
|
19
26
|
end
|
20
27
|
end
|
21
|
-
end
|
28
|
+
end
|
@@ -4,15 +4,22 @@ module CultomePlayer
|
|
4
4
|
module Objects
|
5
5
|
# The ActiveRecord model for Artist objects.
|
6
6
|
class Artist < ActiveRecord::Base
|
7
|
+
|
8
|
+
include CultomePlayer::Utils
|
9
|
+
|
7
10
|
has_many :songs
|
8
11
|
has_many :albums, through: :songs
|
9
12
|
has_many :similars, as: :similar
|
10
13
|
|
11
14
|
def to_s
|
12
15
|
str = c4(":::: Artist: ")
|
13
|
-
str +=
|
16
|
+
str += c15(self.name)
|
14
17
|
str += c4(" ::::")
|
15
18
|
end
|
19
|
+
|
20
|
+
def readonly?
|
21
|
+
false
|
22
|
+
end
|
16
23
|
end
|
17
24
|
end
|
18
|
-
end
|
25
|
+
end
|
@@ -7,6 +7,11 @@ module CultomePlayer
|
|
7
7
|
def initialize(action, parameters)
|
8
8
|
@action = action[:value]
|
9
9
|
@parameters = parameters.collect{|p| Parameter.new(p) }
|
10
|
+
@no_history = params(:literal).any?{|p| p.value == 'no_history'}
|
11
|
+
end
|
12
|
+
|
13
|
+
def history?
|
14
|
+
!@no_history
|
10
15
|
end
|
11
16
|
|
12
17
|
# Returns the parameters, optionally filtered by type
|
@@ -32,6 +37,10 @@ module CultomePlayer
|
|
32
37
|
def params_values(type)
|
33
38
|
params(type).map{|p| p.value }
|
34
39
|
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
"#{action} #{@parameters.join(" ")}"
|
43
|
+
end
|
35
44
|
end
|
36
45
|
end
|
37
|
-
end
|
46
|
+
end
|
@@ -4,6 +4,9 @@ module CultomePlayer
|
|
4
4
|
module Objects
|
5
5
|
# The ActiveRecord model for Drive objects.
|
6
6
|
class Drive < ActiveRecord::Base
|
7
|
+
|
8
|
+
include CultomePlayer::Utils
|
9
|
+
|
7
10
|
has_many :songs
|
8
11
|
|
9
12
|
def connected?
|
@@ -23,4 +26,4 @@ module CultomePlayer
|
|
23
26
|
end
|
24
27
|
end
|
25
28
|
end
|
26
|
-
end
|
29
|
+
end
|
@@ -4,6 +4,9 @@ module CultomePlayer
|
|
4
4
|
module Objects
|
5
5
|
# The ActiveRecord model for Genre objects.
|
6
6
|
class Genre < ActiveRecord::Base
|
7
|
+
|
8
|
+
include CultomePlayer::Utils
|
9
|
+
|
7
10
|
has_and_belongs_to_many :songs
|
8
11
|
|
9
12
|
def to_s
|
@@ -13,4 +16,4 @@ module CultomePlayer
|
|
13
16
|
end
|
14
17
|
end
|
15
18
|
end
|
16
|
-
end
|
19
|
+
end
|
@@ -23,6 +23,13 @@ module CultomePlayer
|
|
23
23
|
return is_true_value?(@data[:value]) if @data[:type] == :boolean
|
24
24
|
return @data[:value].to_i if @data[:type] == :number
|
25
25
|
return @data[:value].to_sym if @data[:type] == :object
|
26
|
+
return raw_value
|
27
|
+
end
|
28
|
+
|
29
|
+
# Return the value as the user input typed (no conversions).
|
30
|
+
#
|
31
|
+
# @return [String] The values of the parameter as the user typed.
|
32
|
+
def raw_value
|
26
33
|
@data[:value]
|
27
34
|
end
|
28
35
|
|
@@ -32,6 +39,19 @@ module CultomePlayer
|
|
32
39
|
def type
|
33
40
|
@data[:type]
|
34
41
|
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
return case @data[:type]
|
45
|
+
when :literal then @data[:value]
|
46
|
+
when :criteria then "#{@data[:criteria]}:#{@data[:value]}"
|
47
|
+
when :number then @data[:value]
|
48
|
+
when :object then "@#{@data[:value]}"
|
49
|
+
when :boolean then @data[:value]
|
50
|
+
when :path then @data[:value]
|
51
|
+
when :bubble then @data[:value]
|
52
|
+
else value
|
53
|
+
end
|
54
|
+
end
|
35
55
|
end
|
36
56
|
end
|
37
|
-
end
|
57
|
+
end
|
@@ -8,7 +8,7 @@ module CultomePlayer
|
|
8
8
|
@data = data
|
9
9
|
|
10
10
|
@data.each do |k,v|
|
11
|
-
self.
|
11
|
+
self.singleton_class.send(:define_method, k) do
|
12
12
|
v
|
13
13
|
end
|
14
14
|
end
|
@@ -37,6 +37,10 @@ module CultomePlayer
|
|
37
37
|
data = @data.merge response.data
|
38
38
|
return Response.new(type, data)
|
39
39
|
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
"Response #{success? ? 'successful' : 'failed'} => #{@data}"
|
43
|
+
end
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
@@ -2,8 +2,12 @@ require 'active_record'
|
|
2
2
|
|
3
3
|
module CultomePlayer
|
4
4
|
module Objects
|
5
|
+
|
5
6
|
# The ActiveRecord model for Song objects.
|
6
7
|
class Song < ActiveRecord::Base
|
8
|
+
|
9
|
+
include CultomePlayer::Utils
|
10
|
+
|
7
11
|
belongs_to :artist
|
8
12
|
belongs_to :album
|
9
13
|
has_and_belongs_to_many :genres
|
@@ -11,6 +15,7 @@ module CultomePlayer
|
|
11
15
|
has_many :similars, as: :similar
|
12
16
|
|
13
17
|
scope :connected, -> {joins(:drive).where('drives.connected' => true)}
|
18
|
+
|
14
19
|
# Get the full path to the song file.
|
15
20
|
#
|
16
21
|
# @return [String] The full path to the song file.
|
@@ -20,19 +25,19 @@ module CultomePlayer
|
|
20
25
|
|
21
26
|
def to_s
|
22
27
|
str = c4(":::: Song: ")
|
23
|
-
str +=
|
28
|
+
str += c14(self.name)
|
24
29
|
|
25
30
|
unless self.artist.nil?
|
26
31
|
str += c4(" \\ Artist: ")
|
27
|
-
str +=
|
32
|
+
str += c15(self.artist.name)
|
28
33
|
end
|
29
34
|
|
30
35
|
unless self.album.nil?
|
31
36
|
str += c4(" \\ Album: ")
|
32
|
-
str +=
|
37
|
+
str += c16(self.album.name)
|
33
38
|
end
|
34
39
|
str += c4(" ::::")
|
35
40
|
end
|
36
41
|
end
|
37
42
|
end
|
38
|
-
end
|
43
|
+
end
|
@@ -109,16 +109,15 @@ module CultomePlayer::Player::Adapter
|
|
109
109
|
when 0 # stopped
|
110
110
|
@playing = @paused = false
|
111
111
|
@stopped = true
|
112
|
-
emit_event(:
|
113
|
-
@user_stopped = false
|
112
|
+
@user_stopped ? emit_event(:playback_stopped, current_song) : emit_event(:playback_finish, current_song)
|
114
113
|
when 1 # paused
|
115
114
|
@stopped = @playing = false
|
116
115
|
@paused = true
|
117
|
-
emit_event(:playback_paused)
|
116
|
+
emit_event(:playback_paused, current_song)
|
118
117
|
when 2 # unpaused
|
119
118
|
@playing = true
|
120
119
|
@paused = @stopped = false
|
121
|
-
emit_event(:playback_resumed)
|
120
|
+
emit_event(:playback_resumed, current_song)
|
122
121
|
end
|
123
122
|
when /^@F ([\d]+) ([\d]+) ([\d.]+) ([\d.]+)$/
|
124
123
|
@playback_time_position = $3.to_f
|
@@ -6,18 +6,49 @@ module CultomePlayer::Player
|
|
6
6
|
# Begin a REP loop inside player.
|
7
7
|
def begin_session
|
8
8
|
@in_session = true
|
9
|
-
display "Cultome Player v#{CultomePlayer::VERSION}"
|
9
|
+
display c5("Cultome Player v#{CultomePlayer::VERSION}")
|
10
|
+
emit_event(:interactive_session_started)
|
10
11
|
|
11
12
|
while in_session?
|
12
13
|
begin
|
13
|
-
|
14
|
-
|
14
|
+
cmd = read_command(PROMPT)
|
15
|
+
execute_interactively cmd
|
15
16
|
rescue Exception => e
|
16
|
-
|
17
|
+
show_error(e.message)
|
18
|
+
e.backtrace.each{|b| display c3(b) } if current_env == :test
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
23
|
+
def execute_interactively(cmd)
|
24
|
+
begin
|
25
|
+
if cmd.empty?
|
26
|
+
# tomamos en ultimo comando
|
27
|
+
cmd = last_command
|
28
|
+
|
29
|
+
else
|
30
|
+
# agregamos el comando al historia de la session_history
|
31
|
+
session_history << cmd
|
32
|
+
# seteamos el ultimo comando ejecutado
|
33
|
+
# # seteamos el ultimo comando ejecutado
|
34
|
+
set_last_command(cmd)
|
35
|
+
end
|
36
|
+
|
37
|
+
return false if cmd.nil?
|
38
|
+
|
39
|
+
r = execute cmd
|
40
|
+
|
41
|
+
if r.size > 1
|
42
|
+
display c1("#{r.size} commands were executed, Showing result of the last one.")
|
43
|
+
end
|
44
|
+
|
45
|
+
show_response(r.last)
|
46
|
+
rescue Exception => e
|
47
|
+
emit_event(:interactive_exception, e)
|
48
|
+
raise e
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
21
52
|
# Check if there is an interactive session in progress.
|
22
53
|
#
|
23
54
|
# @return [Boolean] True if session in progress. False otherwise.
|
@@ -28,27 +59,52 @@ module CultomePlayer::Player
|
|
28
59
|
# Terminates a interactive session.
|
29
60
|
def terminate_session
|
30
61
|
@in_session = false
|
62
|
+
save_player_configurations
|
63
|
+
emit_event(:interactive_session_ended)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Command history of this session
|
67
|
+
#
|
68
|
+
# @return [Array<Command>] The history of commands of this session.
|
69
|
+
def session_history
|
70
|
+
@session_history ||= []
|
71
|
+
end
|
72
|
+
|
73
|
+
def set_last_command(cmd)
|
74
|
+
@last_command = cmd
|
75
|
+
end
|
76
|
+
|
77
|
+
def last_command
|
78
|
+
@last_command
|
31
79
|
end
|
32
80
|
|
33
81
|
private
|
34
82
|
|
83
|
+
def show_error(msg)
|
84
|
+
type, message = msg.split(":")
|
85
|
+
display c3("[#{type}] #{message}")
|
86
|
+
end
|
87
|
+
|
35
88
|
def show_response(r)
|
89
|
+
return if r.respond_to?(:no_response)
|
90
|
+
|
36
91
|
if r.respond_to?(:response_type)
|
37
92
|
res_obj = r.send(r.response_type)
|
38
93
|
if res_obj.respond_to?(:each)
|
39
|
-
|
40
|
-
|
41
|
-
end
|
94
|
+
# es una lista
|
95
|
+
display to_display_list(res_obj)
|
42
96
|
elsif res_obj.class == String
|
43
|
-
|
97
|
+
# es un mensaje
|
98
|
+
display r.success? ? res_obj : c3(res_obj.to_s)
|
44
99
|
else
|
45
|
-
display "(((#{res_obj.to_s})))"
|
100
|
+
display c3("(((#{res_obj.to_s})))")
|
46
101
|
end
|
47
102
|
|
103
|
+
# Dont has response_type, eg has a message
|
48
104
|
elsif r.respond_to?(:message)
|
49
|
-
display r.message
|
105
|
+
display r.success? ? c15(r.message) : c3(r.message)
|
50
106
|
else
|
51
|
-
display "
|
107
|
+
display c3("!!! #{r} !!!")
|
52
108
|
end
|
53
109
|
end
|
54
110
|
|