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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -79
  3. data/Rakefile +38 -4
  4. data/bin/cultome_player +16 -4
  5. data/config/environment.yml +4 -0
  6. data/cultome_player.gemspec +8 -1
  7. data/lib/cultome_player.rb +45 -19
  8. data/lib/cultome_player/command/language.rb +3 -4
  9. data/lib/cultome_player/command/processor.rb +9 -7
  10. data/lib/cultome_player/command/reader.rb +11 -2
  11. data/lib/cultome_player/environment.rb +21 -13
  12. data/lib/cultome_player/events.rb +7 -7
  13. data/lib/cultome_player/objects/album.rb +9 -2
  14. data/lib/cultome_player/objects/artist.rb +9 -2
  15. data/lib/cultome_player/objects/command.rb +10 -1
  16. data/lib/cultome_player/objects/drive.rb +4 -1
  17. data/lib/cultome_player/objects/genre.rb +4 -1
  18. data/lib/cultome_player/objects/parameter.rb +21 -1
  19. data/lib/cultome_player/objects/response.rb +5 -1
  20. data/lib/cultome_player/objects/song.rb +9 -4
  21. data/lib/cultome_player/player/adapter/mpg123.rb +3 -4
  22. data/lib/cultome_player/player/interactive.rb +67 -11
  23. data/lib/cultome_player/player/interface/basic.rb +13 -9
  24. data/lib/cultome_player/player/interface/extended.rb +26 -12
  25. data/lib/cultome_player/player/interface/helper.rb +73 -9
  26. data/lib/cultome_player/plugins.rb +44 -18
  27. data/lib/cultome_player/plugins/alias.rb +85 -0
  28. data/lib/cultome_player/plugins/gestures.rb +90 -0
  29. data/lib/cultome_player/plugins/help.rb +4 -4
  30. data/lib/cultome_player/plugins/keyboard_special_keys.rb +22 -0
  31. data/lib/cultome_player/plugins/points.rb +51 -0
  32. data/lib/cultome_player/utils.rb +117 -7
  33. data/lib/cultome_player/version.rb +1 -1
  34. data/xbindkeys/xbindkeysrc +12 -0
  35. metadata +37 -89
  36. data/.coveralls.yml +0 -1
  37. data/.gitignore +0 -24
  38. data/.rspec +0 -2
  39. data/.travis.yml +0 -7
  40. data/db/001_create_schema.rb +0 -58
  41. data/spec/config.yml +0 -0
  42. data/spec/cultome_player/command/processor_spec.rb +0 -168
  43. data/spec/cultome_player/command/reader_spec.rb +0 -45
  44. data/spec/cultome_player/cultome_player_spec.rb +0 -17
  45. data/spec/cultome_player/environment_spec.rb +0 -65
  46. data/spec/cultome_player/events_spec.rb +0 -22
  47. data/spec/cultome_player/media_spec.rb +0 -41
  48. data/spec/cultome_player/player/adapter/mpg123_spec.rb +0 -82
  49. data/spec/cultome_player/player/interface/basic_spec.rb +0 -168
  50. data/spec/cultome_player/player/interface/extended/connect_spec.rb +0 -117
  51. data/spec/cultome_player/player/interface/extended/search_spec.rb +0 -90
  52. data/spec/cultome_player/player/interface/extended/show_spec.rb +0 -36
  53. data/spec/cultome_player/player/interface/extended/shuffle_spec.rb +0 -26
  54. data/spec/cultome_player/player/interface/extended_spec.rb +0 -136
  55. data/spec/cultome_player/player/interface/helper_spec.rb +0 -63
  56. data/spec/cultome_player/player/interface_spec.rb +0 -17
  57. data/spec/cultome_player/player/playlist_spec.rb +0 -301
  58. data/spec/cultome_player/plugins/help_spec.rb +0 -21
  59. data/spec/cultome_player/plugins_spec.rb +0 -19
  60. data/spec/cultome_player/utils_spec.rb +0 -15
  61. data/spec/spec_helper.rb +0 -108
  62. data/spec/test/uno/dos/dos.mp3 +0 -0
  63. data/spec/test/uno/dos/tres/tres.mp3 +0 -0
  64. data/spec/test/uno/uno.mp3 +0 -0
  65. data/tasks/console.rake +0 -19
  66. data/tasks/db.rake +0 -19
  67. 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{@library @search @playlist @history @queue @song @artist @album @drives}.grep(/^#{word}/)
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, check_db=true)
82
- env_config = YAML.load_file File.expand_path('config/environment.yml')
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
- private
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 listener to an event.
11
+ # Register a callback to an event.
12
12
  #
13
13
  # @param event [Symbol] The event name.
14
- # @param listener [Object] Implements a callback with the name on_<event name>.
15
- # @return [Object] The registered listener.
16
- def register_listener(event, listener)
17
- listeners[event] << listener
18
- return listener
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.send("on_#{event}".to_sym, *data) }
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 += c13(self.name)
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 += c11(self.name)
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.class.send(:define_method, k) do
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 += c10(self.name)
28
+ str += c14(self.name)
24
29
 
25
30
  unless self.artist.nil?
26
31
  str += c4(" \\ Artist: ")
27
- str += c11(self.artist.name)
32
+ str += c15(self.artist.name)
28
33
  end
29
34
 
30
35
  unless self.album.nil?
31
36
  str += c4(" \\ Album: ")
32
- str += c13(self.album.name)
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(:playback_finish) unless @user_stopped
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
- r = execute read_command(PROMPT)
14
- show_response(r)
14
+ cmd = read_command(PROMPT)
15
+ execute_interactively cmd
15
16
  rescue Exception => e
16
- display e.message
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
- res_obj.each.with_index do |elem, idx|
40
- display "#{(idx + 1).to_s.ljust(3)} | #{elem.to_s}"
41
- end
94
+ # es una lista
95
+ display to_display_list(res_obj)
42
96
  elsif res_obj.class == String
43
- display res_obj.to_s
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 "!!!#{r}!!!"
107
+ display c3("!!! #{r} !!!")
52
108
  end
53
109
  end
54
110