ampt 0.2.0.pre2 → 0.2.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,9 +1,10 @@
1
- Copyright (c) 2009 The Board of Trustees of the University of Illinois.
1
+ Copyright (c) 2009,2010 Association for Computing Machinery at University of
2
+ Illinois Urbana-Champaign
2
3
  All rights reserved.
3
4
 
4
- Developed by: ACM@UIUC
5
+ Developed by: Association for Computing Machinery
5
6
  University of Illinois at Urbana-Champaign
6
- www.acm.uiuc.edu
7
+ http://www.acm.uiuc.edu
7
8
 
8
9
  Permission is hereby granted, free of charge, to any person obtaining a copy
9
10
  of this software and associated documentation files (the "Software"), to
@@ -16,10 +17,10 @@ furnished to do so, subject to the following conditions:
16
17
  2. Redistributions in binary form must reproduce the above copyright
17
18
  notice, this list of conditions and the following disclaimers in the
18
19
  documentation and/or other materials provided with the distribution.
19
- 3. Neither the names of ACM@UIUC, University of Illinois at Urbana-
20
- Champaign, nor the names of its contributors may be used to endorse
21
- or promote products derived from this Software without specific prior
22
- written permission.
20
+ 3. Neither the names of Association for Computing Machinery, University of
21
+ Illinois at Urbana-Champaign, nor the names of its contributors may be
22
+ used to endorse or promote products derived from this Software without
23
+ specific prior written permission.
23
24
 
24
25
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
26
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
data/README.rdoc CHANGED
@@ -1,21 +1,23 @@
1
1
  = ampt
2
2
 
3
- http://www.interhacktive.com/ampt
3
+ Command-fu for amp.
4
4
 
5
5
  == DESCRIPTION:
6
6
 
7
- This is a command line client for the Acoustics Media Player (amp).
7
+ A command line client for the Acoustics Media Player (amp).
8
8
  Amp is available here: http://www.github.com/avuserow/amp
9
9
 
10
10
  This is a work in progress.
11
11
 
12
12
  == FEATURES:
13
13
 
14
- * Control things from the command line!
15
- * Extremely scriptable!
14
+ * Control amp from the command line!
15
+ * Completely scriptable and reconfigurable.
16
16
 
17
17
  == SYNOPSIS:
18
18
 
19
+ === Usage:
20
+
19
21
  $ ampt --help
20
22
  Usage ampt [command] [options] [args]
21
23
 
@@ -57,6 +59,12 @@ This is a work in progress.
57
59
  25 songs queued for a total time of 2:13:51
58
60
  You have 20 songs queued for a total time of 1:49:20
59
61
 
62
+ === Scripting:
63
+
64
+ See lib/ampt_cfg/default.rb to see how configurations work -- all of ampt's
65
+ commands are written the same way you would write your own custom command or
66
+ configuration.
67
+
60
68
  == REQUIREMENTS:
61
69
 
62
70
  * libopenssl bindings for ruby
@@ -64,11 +72,11 @@ This is a work in progress.
64
72
 
65
73
  == INSTALL:
66
74
 
67
- $ sudo gem install ampt
75
+ $ sudo gem install ampt --pre
68
76
 
69
77
  == TODO:
70
- * Add an option to change default flags of a command
71
- * Make aliases more powerful (eg, be able to handle options tacked on)
78
+ * Fix error handling when getting invalid data from the server.
79
+ * Write up a bit of documentation on writing configurations.
72
80
 
73
81
  == LICENSE:
74
82
 
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ begin
12
12
  gem.email = "rich@interhacktive.com"
13
13
  gem.homepage = "http://github.com/capslock/ampt"
14
14
  gem.authors = ["Rich"]
15
- gem.add_dependency 'curb'
15
+ gem.add_dependency 'curb', '>= 0.6.2.0'
16
16
  gem.add_dependency 'trollop'
17
17
  gem.add_dependency 'json'
18
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
data/ampt.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ampt}
8
- s.version = "0.2.0.pre2"
8
+ s.version = "0.2.0.pre3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Rich"]
12
- s.date = %q{2010-01-09}
12
+ s.date = %q{2010-01-10}
13
13
  s.default_executable = %q{ampt}
14
14
  s.description = %q{This is a command line client for the Acoustics Media Player (amp).}
15
15
  s.email = %q{rich@interhacktive.com}
@@ -47,16 +47,16 @@ Gem::Specification.new do |s|
47
47
  s.specification_version = 3
48
48
 
49
49
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
50
- s.add_runtime_dependency(%q<curb>, [">= 0"])
50
+ s.add_runtime_dependency(%q<curb>, [">= 0.6.2.0"])
51
51
  s.add_runtime_dependency(%q<trollop>, [">= 0"])
52
52
  s.add_runtime_dependency(%q<json>, [">= 0"])
53
53
  else
54
- s.add_dependency(%q<curb>, [">= 0"])
54
+ s.add_dependency(%q<curb>, [">= 0.6.2.0"])
55
55
  s.add_dependency(%q<trollop>, [">= 0"])
56
56
  s.add_dependency(%q<json>, [">= 0"])
57
57
  end
58
58
  else
59
- s.add_dependency(%q<curb>, [">= 0"])
59
+ s.add_dependency(%q<curb>, [">= 0.6.2.0"])
60
60
  s.add_dependency(%q<trollop>, [">= 0"])
61
61
  s.add_dependency(%q<json>, [">= 0"])
62
62
  end
data/bin/ampt CHANGED
@@ -3,7 +3,7 @@ require 'ampt'
3
3
 
4
4
  # You CAN specify configs over here... or you can just load them from your .amptrc.
5
5
  Ampt.init do
6
- load_config "#{ENV['HOME']}/.amptrc"
7
6
  load_config 'ampt_cfg/default.rb'
7
+ load_config "#{ENV['HOME']}/.amptrc"
8
8
  end
9
9
 
data/lib/ampt.rb CHANGED
@@ -2,17 +2,25 @@ require 'rubygems'
2
2
  require 'trollop'
3
3
 
4
4
  module Ampt
5
- VERSION = '0.2.0.pre2'
5
+ VERSION = '0.2.0.pre3'
6
6
  # This is the module that holds the API for the current music player. Defined in
7
7
  # ampt_api/acoustics.rb
8
8
  module API
9
9
  end
10
10
 
11
+ # Raised if an invalid command is encountered.
12
+ class InvalidCommand < StandardError
13
+ attr :cmd
14
+ def initialize(cmd)
15
+ @cmd = cmd
16
+ end
17
+ end
18
+
11
19
  # The typical entry point for an Ampt app. Configures a new instance of ampt
12
20
  # using the specified block, and runs that configuration.
13
- def self.init args = ARGV.dup, *a, &b
14
- @c = Config.new(*a, &b)
15
- @c.run(args)
21
+ def self.init args = ARGV, *a, &b
22
+ c = Config.new(*a, &b)
23
+ c.run(args)
16
24
  end
17
25
 
18
26
  # Class to hold all of the user-defined functions and variables
@@ -37,17 +45,10 @@ module Ampt
37
45
  @alias = {}
38
46
  @default = nil
39
47
  @api = nil
48
+ @base_url = nil
40
49
  cloaker(&b).bind(self).call(*a) if b
41
50
  end
42
51
 
43
- def extras s, *a, &b
44
- @extras.send(s, *a, &b)
45
- end
46
-
47
- def user
48
- @extras
49
- end
50
-
51
52
  # Specify a file path from which to load the config from. If a relative path
52
53
  # is provided, the path is taken as relative to the Ampt library directory.
53
54
  def load_config file
@@ -64,22 +65,24 @@ module Ampt
64
65
  File.open(name, 'r') do |f|
65
66
  # Create a new copy of the User module for holding our
66
67
  # user-defined methods and variables.
67
- unless @extras
68
- @extras = User.dup
69
- @extras.parent_config = self
68
+ unless @__user
69
+ @__user = User.dup
70
+ @__user.parent_config = self
70
71
  end
71
72
  # Read in the configuration file.
72
- @extras.module_eval(f.read)
73
+ @__user.module_eval(f.read)
73
74
  end
74
75
  rescue Errno::ENOENT => e
75
76
  end
77
+ @base_url ||= "https://www-s.acm.uiuc.edu/acoustics"
76
78
  # If the user has configured an API, try to require it in.
77
79
  # Otherwise, use the default acoustics API.
78
80
  if @api
79
81
  begin
80
82
  require @api
81
- rescue
83
+ rescue Exception => e
82
84
  $stderr.puts "Couldn't load API #{@api}"
85
+ $stderr.puts e.message
83
86
  exit
84
87
  end
85
88
  else
@@ -91,11 +94,8 @@ module Ampt
91
94
  end
92
95
  end
93
96
 
94
- # Select an API to use. Defaults to the acoustics API. The path should
95
- # be an absolute path.
96
- def api path
97
- @api = path
98
- end
97
+ # Holds on to user config data
98
+ attr_reader :__user
99
99
 
100
100
  # Alias a command. Takes a hash of 'new command' => 'previous command'.
101
101
  def alias_cmd cmd
@@ -107,6 +107,21 @@ module Ampt
107
107
  @default = cmd
108
108
  end
109
109
 
110
+ # Select an API to use. Defaults to the acoustics API. The path should
111
+ # be an absolute path.
112
+ def api api
113
+ @api = api
114
+ end
115
+
116
+ # Base URL of music player
117
+ def base_url url = nil
118
+ if url.nil?
119
+ @base_url
120
+ else
121
+ @base_url = url
122
+ end
123
+ end
124
+
110
125
  # Define a new Ampt command. Must specify a name, and a block containing
111
126
  # the configuration for the command.
112
127
  # The configuration should contain one or more desc and opt's, plus an on_run
@@ -123,8 +138,7 @@ module Ampt
123
138
 
124
139
  # Run the config. Usually not called manually.
125
140
  def run args
126
- Trollop::options args, [@commands, @alias] do |cmds, *a|
127
- commands, aliases = cmds
141
+ Trollop::options args, @commands, @alias do |commands, aliases|
128
142
  banner "Usage ampt [command] [options] [args]"
129
143
  banner "\nCommands include:\n"
130
144
  # Print out a nice listing of each command
@@ -138,18 +152,27 @@ module Ampt
138
152
  end
139
153
  cmd = args.shift
140
154
  # Try to figure out if it's an alias or a command or nothing or invalid
141
- if @commands[cmd]
142
- @commands[cmd].run(args)
143
- elsif @alias[cmd]
144
- begin
145
- cmd, *a = @alias[cmd].split(' ')
146
- args = a + args
147
- end until @alias[cmd].nil?
148
- @commands[cmd].run(ARGV)
149
- elsif cmd.nil? and not @default.nil?
150
- @commands[@default].run(ARGV)
155
+ begin
156
+ if @alias[cmd]
157
+ # Go down through the chain of aliases to find the original command.
158
+ # A command could be aliased to itself
159
+ begin
160
+ cmd, *a = @alias[cmd].split(' ')
161
+ args = a + args
162
+ end until @alias[cmd].nil? or cmd == @alias[cmd].split(' ').first
163
+ unless @commands[cmd]
164
+ raise InvalidCommand.new(cmd)
165
+ end
166
+ elsif cmd.nil? and (@default.nil? or @commands[@default].nil?)
167
+ raise InvalidCommand.new(cmd)
168
+ elsif @commands[cmd].nil?
169
+ raise InvalidCommand.new(cmd)
170
+ end
171
+ rescue InvalidCommand => e
172
+ Trollop::die "#{e.cmd} is not an ampt command" if e.cmd
173
+ Trollop::die "No command specified, and no default is set"
151
174
  else
152
- Trollop::die "#{cmd} is not an ampt command"
175
+ @commands[cmd].run(args)
153
176
  end
154
177
  end
155
178
 
@@ -179,8 +202,9 @@ module Ampt
179
202
  @conflicts = []
180
203
  @depends = []
181
204
  @on_run = lambda {}
205
+ @config = config
182
206
  (class << self; self; end).instance_eval do
183
- include config.user
207
+ include config.__user
184
208
  end
185
209
  cloaker(&b).bind(self).call
186
210
  end
@@ -226,8 +250,8 @@ module Ampt
226
250
  # Executed when a command is run. Usually not called manually.
227
251
  def run args
228
252
  opts = Trollop::options args,
229
- [@name, @desc, @arg, @opts, @conflicts, @depends] do |params, *args|
230
- name, description, arg, opts, conflicts, depends = params
253
+ @name, @desc, @arg, @opts, @conflicts, @depends do |*params|
254
+ name, description, arg, opts, conflicts, depends = *params
231
255
  banner "ampt #{name}#{arg.join(' ')}: #{description.join " "}"
232
256
  banner ""
233
257
  # Parse each of the specified opts
@@ -244,8 +268,9 @@ module Ampt
244
268
  depends(*d)
245
269
  end
246
270
  end
271
+ @base_url = @config.base_url
247
272
  # Call the on_run block with the options and arguments.
248
- @on_run.call(opts, ARGV)
273
+ @on_run.call(opts, args)
249
274
  end
250
275
 
251
276
  # Provide a description for the command. If called with no arguments,
@@ -5,29 +5,23 @@ require 'uri'
5
5
  module Ampt
6
6
  # Provides the API for Acoustics
7
7
  module API
8
- # The base url which all of our requests will be relative to.
9
- BASEURL = "https://www-s.acm.uiuc.edu/acoustics"
10
-
11
8
  # Request the player's status. gets the session first so we can tell
12
9
  # whether or not we can skip the current song, which songs are ours, etc.
13
10
  def status
14
- auth do
15
- player_status req
16
- end
11
+ auth
12
+ player_status req
17
13
  end
18
14
 
19
15
  # Unvotes a song. Takes a song_id (string)
20
16
  def unvote song_id
21
- auth do
22
- player_status req 'unvote', 'song_id' => song_id
23
- end
17
+ auth
18
+ player_status req 'unvote', 'song_id' => song_id
24
19
  end
25
20
 
26
21
  # Votes up a song. Takes a song_id (string)
27
22
  def vote song_id
28
- auth do
29
- player_status req 'vote', 'song_id' => song_id
30
- end
23
+ auth
24
+ player_status req 'vote', 'song_id' => song_id
31
25
  end
32
26
 
33
27
  # Searches the database for the specified value in the given field.
@@ -52,30 +46,26 @@ module Ampt
52
46
 
53
47
  # Sets the volume to the specified level. level should be a string.
54
48
  def volume level
55
- auth do
56
- player_status req 'volume', 'value' => level
57
- end
49
+ auth
50
+ player_status req 'volume', 'value' => level
58
51
  end
59
52
 
60
53
  # Start the player.
61
54
  def start
62
- auth do
63
- player_status req 'start'
64
- end
55
+ auth
56
+ player_status req 'start'
65
57
  end
66
58
 
67
59
  # Skip the current song. Will probably fail horribly if you aren't allowed to skip.
68
60
  def skip
69
- auth do
70
- player_status req 'skip'
71
- end
61
+ auth
62
+ player_status req 'skip'
72
63
  end
73
64
 
74
65
  # Stop the player.
75
66
  def stop
76
- auth do
77
- player_status req 'stop'
78
- end
67
+ auth
68
+ player_status req 'stop'
79
69
  end
80
70
 
81
71
  # takes field => value pair of what to list. Only one of the given pairs is used.
@@ -102,11 +92,11 @@ module Ampt
102
92
  "#{URI::escape key}=#{URI::escape value}"
103
93
  end
104
94
  end
105
- c.url = "#{BASEURL}/json.pl?mode=#{mode};" + param_str.join(';')
95
+ c.url = "#{@base_url}/json.pl?mode=#{mode};" + param_str.join(';')
106
96
  elsif mode
107
- c.url = "#{BASEURL}/json.pl?mode=#{mode};"
97
+ c.url = "#{@base_url}/json.pl?mode=#{mode};"
108
98
  else
109
- c.url = "#{BASEURL}/json.pl"
99
+ c.url = "#{@base_url}/json.pl"
110
100
  end
111
101
  c.perform
112
102
  c.body_str
@@ -135,12 +125,12 @@ module Ampt
135
125
  end
136
126
 
137
127
  # Perform an authenticated request
138
- def auth &b
128
+ def auth
139
129
  unless @sess
140
130
  c = Curl::Easy.new
141
131
  c.http_auth_types = Curl::CURLAUTH_GSSNEGOTIATE
142
132
  c.userpwd = ":"
143
- c.url = "#{BASEURL}/www-data/auth/"
133
+ c.url = "#{@base_url}/www-data/auth/"
144
134
  c.perform
145
135
  sessid = c.header_str[/CGISESSID=(.+);/]
146
136
  if sessid.nil?
@@ -149,7 +139,6 @@ module Ampt
149
139
  end
150
140
  @sess = sessid.chop
151
141
  end
152
- (yield) if b
153
142
  end
154
143
  end
155
144
  end
@@ -1,18 +1,18 @@
1
1
  require 'tempfile'
2
2
 
3
- def colorize(text, color_code)
4
- if @no_colorize
5
- text
6
- else
3
+ def color(text, color_code)
4
+ if @color
7
5
  "#{color_code}#{text}\e[0m"
6
+ else
7
+ text
8
8
  end
9
9
  end
10
10
 
11
- def red(text); colorize(text, "\e[31m"); end
12
- def green(text); colorize(text, "\e[32m"); end
13
- def bold(text); colorize(text, "\e[1m"); end
14
- def under(text); colorize(text, "\e[4m"); end
15
- def bggreen(text); colorize(text, "\e[42m"); end
11
+ def red(text); color(text, "\e[31m"); end
12
+ def green(text); color(text, "\e[32m"); end
13
+ def bold(text); color(text, "\e[1m"); end
14
+ def under(text); color(text, "\e[4m"); end
15
+ def bggreen(text); color(text, "\e[42m"); end
16
16
 
17
17
  def pp_song song, options={:title => true, :artist => true, :album => false, :track => false}
18
18
  song_id = song.song_id
@@ -96,12 +96,9 @@ default 'status'
96
96
 
97
97
  command 'status' do
98
98
  desc "Prints the currently playing song and playlist."
99
- opt :colorize, "Colorize the output", :short => '-c', :default => true
100
- opt :no_colorize, "Disable color"
99
+ opt :color, "Toggle colors", :short => '-c', :default => true
101
100
  on_run do |opts, args|
102
- if opts[:no_colorize]
103
- @no_colorize = true
104
- end
101
+ @color = opts[:color]
105
102
  st = status
106
103
  puts bold("Now Playing:") + "\n"
107
104
  begin
@@ -250,13 +247,10 @@ command 'search' do
250
247
  opt :title, "Search by title", :type => :string
251
248
  opt :path, "Search by path", :type => :string
252
249
  opt :any, "Search by any parameter. This is the default", :type => :string
253
- opt :colorize, "Colorize the output", :short => '-c', :default => true
254
- opt :no_colorize, "Disable color"
250
+ opt :color, "Toggle colors", :short => '-c', :default => true
255
251
  conflicts :artist, :album, :title, :path, :any
256
252
  on_run do |opts, args|
257
- if opts[:no_colorize]
258
- @no_colorize = true
259
- end
253
+ @color = opts[:color]
260
254
  if opts[:artist_given]||opts[:album_given]||opts[:title_given]
261
255
  list_of = {}
262
256
  list_of[:artist] = opts[:artist]
@@ -332,13 +326,10 @@ command 'list' do
332
326
  opt :artist, "List by artist", :type => :string
333
327
  opt :album, "List by album", :type => :string
334
328
  opt :title, "List by title", :type => :string
335
- opt :colorize, "Colorize the output", :short => '-c', :default => true
336
- opt :no_colorize, "Disable color"
329
+ opt :color, "Toggle colors", :short => '-c', :default => true
337
330
  conflicts :artist, :album, :title
338
331
  on_run do |opts, args|
339
- if opts[:no_colorize]
340
- @no_colorize = true
341
- end
332
+ @color = opts[:color]
342
333
  if not (opts[:artist_given]||opts[:album_given]||opts[:title_given])
343
334
  die "You must specify one of the options"
344
335
  else
@@ -358,13 +349,10 @@ end
358
349
  command 'show' do
359
350
  desc 'Show more info about a song. Takes a song id as the single ' +
360
351
  'parameter.'
361
- opt :colorize, "Colorize the output", :short => '-c', :default => true
362
- opt :no_colorize, "Disable color"
352
+ opt :color, "Toggle colors", :short => '-c', :default => true
363
353
  arg 'song_id'
364
354
  on_run do |opts,args|
365
- if opts[:no_colorize]
366
- @no_colorize = true
367
- end
355
+ @color = opts[:color]
368
356
  (die "Not enough arguments") unless args[0]
369
357
  song_id = args[0]
370
358
  song = (list 'song_id' => song_id)[0]
@@ -382,13 +370,10 @@ end
382
370
  alias_cmd 'rand' => 'random'
383
371
  command 'random' do
384
372
  desc 'Get [num] random songs. Defaults to 20.'
385
- opt :colorize, "Colorize the output", :short => '-c', :default => true
386
- opt :no_colorize, "Disable color"
373
+ opt :color, "Toggle colors", :short => '-c', :default => true
387
374
  arg 'num'
388
375
  on_run do |opts,args|
389
- if opts[:no_colorize]
390
- @no_colorize = true
391
- end
376
+ @color = opts[:color]
392
377
  puts "#{args[0]||20} random songs:"
393
378
  pp_songs_full random args[0]
394
379
  end
@@ -396,13 +381,10 @@ end
396
381
 
397
382
  command 'new' do
398
383
  desc 'Get [num] newest songs. Defaults to 50.'
399
- opt :colorize, "Colorize the output", :short => '-c', :default => true
400
- opt :no_colorize, "Disable color"
384
+ opt :color, "Toggle colors", :short => '-c', :default => true
401
385
  arg 'num'
402
386
  on_run do |opts,args|
403
- if opts[:no_colorize]
404
- @no_colorize = true
405
- end
387
+ @color = opts[:color]
406
388
  puts "#{args[0]||'50'} newest songs:"
407
389
  pp_songs_full recent args[0]
408
390
  end
@@ -410,13 +392,10 @@ end
410
392
 
411
393
  command 'history' do
412
394
  desc 'Get [num] last-played songs. Defaults to 25.'
413
- opt :colorize, "Colorize the output", :short => '-c', :default => true
414
- opt :no_colorize, "Disable color"
395
+ opt :color, "Toggle colors", :short => '-c', :default => true
415
396
  arg 'num'
416
397
  on_run do |opts,args|
417
- if opts[:no_colorize]
418
- @no_colorize = true
419
- end
398
+ @color = opts[:color]
420
399
  puts "#{args[0]||'25'} last-played:"
421
400
  pp_songs_full history(args[0]), :show_all_voters => true
422
401
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ampt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.pre2
4
+ version: 0.2.0.pre3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rich
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-09 00:00:00 -06:00
12
+ date: 2010-01-10 00:00:00 -06:00
13
13
  default_executable: ampt
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: "0"
23
+ version: 0.6.2.0
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: trollop