cui8tracks 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'pit'
4
+ gem 'notify'
5
+
6
+ group :development do
7
+ gem "rspec", "~> 2.3.0"
8
+ gem "bundler", "~> 1.0.0"
9
+ gem "jeweler", "~> 1.5.2"
10
+ gem "rcov", ">= 0"
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.3)
5
+ git (1.2.5)
6
+ jeweler (1.5.2)
7
+ bundler (~> 1.0.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ notify (0.3.0)
11
+ pit (0.0.6)
12
+ rake (0.8.7)
13
+ rcov (0.9.9)
14
+ rspec (2.3.0)
15
+ rspec-core (~> 2.3.0)
16
+ rspec-expectations (~> 2.3.0)
17
+ rspec-mocks (~> 2.3.0)
18
+ rspec-core (2.3.1)
19
+ rspec-expectations (2.3.0)
20
+ diff-lcs (~> 1.1.2)
21
+ rspec-mocks (2.3.0)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ bundler (~> 1.0.0)
28
+ jeweler (~> 1.5.2)
29
+ notify
30
+ pit
31
+ rcov
32
+ rspec (~> 2.3.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 hitode909
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,22 @@
1
+ = cui8tracks
2
+
3
+ cui 8tracks player
4
+
5
+ == How to Use
6
+
7
+ cui8tracks.rb
8
+
9
+ == Help
10
+
11
+ cui8tracks.rb --help
12
+
13
+ == Requirements
14
+
15
+ - 8tracks account
16
+ - mplayer
17
+
18
+ == Copyright
19
+
20
+ Copyright (c) 2011 hitode909. See LICENSE.txt for
21
+ further details.
22
+
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "cui8tracks"
16
+ gem.homepage = "http://github.com/hitode909/cui8tracks"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{cui 8tracks player}
19
+ gem.description = %Q{cui8tracks is CUI 8tracks player for terminal}
20
+ gem.email = "hitode909@gmail.com"
21
+ gem.authors = ["hitode909"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+
27
+ gem.executables = ["cui8tracks.rb"]
28
+ end
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rspec/core'
32
+ require 'rspec/core/rake_task'
33
+ RSpec::Core::RakeTask.new(:spec) do |spec|
34
+ spec.pattern = FileList['spec/**/*_spec.rb']
35
+ end
36
+
37
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
38
+ spec.pattern = 'spec/**/*_spec.rb'
39
+ spec.rcov = true
40
+ end
41
+
42
+ task :default => :spec
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "cui8tracks #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
data/bin/cui8tracks.rb ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ self_file =
5
+ if File.symlink?(__FILE__)
6
+ require 'pathname'
7
+ Pathname.new(__FILE__).realpath
8
+ else
9
+ __FILE__
10
+ end
11
+ $:.unshift(File.dirname(self_file) + "/../lib")
12
+
13
+ require 'cui8tracks'
14
+
15
+ CUI8Tracks::CLI.execute(STDOUT, ARGV)
@@ -0,0 +1,78 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{cui8tracks}
8
+ s.version = "0.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{hitode909}]
12
+ s.date = %q{2011-10-17}
13
+ s.description = %q{cui8tracks is CUI 8tracks player for terminal}
14
+ s.email = %q{hitode909@gmail.com}
15
+ s.executables = [%q{cui8tracks.rb}]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/cui8tracks.rb",
28
+ "cui8tracks.gemspec",
29
+ "lib/cui8tracks.rb",
30
+ "lib/cui8tracks/api.rb",
31
+ "lib/cui8tracks/cli.rb",
32
+ "lib/cui8tracks/mix.rb",
33
+ "lib/cui8tracks/session.rb",
34
+ "lib/cui8tracks/set.rb",
35
+ "lib/cui8tracks/thing.rb",
36
+ "lib/cui8tracks/track.rb",
37
+ "lib/cui8tracks/user.rb",
38
+ "spec/cui8tracks_spec.rb",
39
+ "spec/spec_helper.rb"
40
+ ]
41
+ s.homepage = %q{http://github.com/hitode909/cui8tracks}
42
+ s.licenses = [%q{MIT}]
43
+ s.require_paths = [%q{lib}]
44
+ s.rubygems_version = %q{1.8.6}
45
+ s.summary = %q{cui 8tracks player}
46
+ s.test_files = [
47
+ "spec/cui8tracks_spec.rb",
48
+ "spec/spec_helper.rb"
49
+ ]
50
+
51
+ if s.respond_to? :specification_version then
52
+ s.specification_version = 3
53
+
54
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
55
+ s.add_runtime_dependency(%q<pit>, [">= 0"])
56
+ s.add_runtime_dependency(%q<notify>, [">= 0"])
57
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
58
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
59
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
60
+ s.add_development_dependency(%q<rcov>, [">= 0"])
61
+ else
62
+ s.add_dependency(%q<pit>, [">= 0"])
63
+ s.add_dependency(%q<notify>, [">= 0"])
64
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
65
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
66
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
67
+ s.add_dependency(%q<rcov>, [">= 0"])
68
+ end
69
+ else
70
+ s.add_dependency(%q<pit>, [">= 0"])
71
+ s.add_dependency(%q<notify>, [">= 0"])
72
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
73
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
74
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
75
+ s.add_dependency(%q<rcov>, [">= 0"])
76
+ end
77
+ end
78
+
@@ -0,0 +1,61 @@
1
+ class CUI8Tracks::API
2
+ include CUI8Tracks::Thing
3
+
4
+ API_KEY = '3bed6bc564136c299324e205ffaf3fa1b44f094e'
5
+
6
+ def initialize(username, password)
7
+ @username = username
8
+ @password = password
9
+ @logged_in = false
10
+ end
11
+
12
+ def login
13
+ return if @logged_in
14
+ res = post('/sessions', :login => @username, :password => @password, :https => true)
15
+ @logged_in = true if res['logged_in']
16
+ end
17
+
18
+ def to_param_str(hash = { })
19
+ raise ArgumentError, 'Argument must be a Hash object' unless hash.is_a?(Hash)
20
+ hash.to_a.map{|i| i[0].to_s + '=' + CGI.escape(i[1].to_s) }.join('&')
21
+ end
22
+
23
+ def http_request(klass, path, param = { })
24
+ path += '.json' unless path =~ /\.json$/
25
+ logger.debug "#{klass.to_s.split(/::/).last} #{path} #{param.inspect}"
26
+ req = klass.new(path)
27
+ req.basic_auth(@username, @password) if @logged_in
28
+ param[:api_key] = API_KEY
29
+ port = param.delete(:https) ? 443 : 80 # XXX
30
+ param_str = to_param_str(param)
31
+ proxy_host, proxy_port = (ENV["http_proxy"] || ENV["HTTP_PROXY"] || '').sub(/http:\/\//, '').split(':')
32
+ connection = Net::HTTP::Proxy(proxy_host, proxy_port).new('8tracks.com', port)
33
+ connection.use_ssl = true if port == 443
34
+ res = connection.start do |http|
35
+ if param_str
36
+ http.request(req, param_str)
37
+ else
38
+ http.request(req)
39
+ end
40
+ end
41
+ json_data = JSON.parse(res.body)
42
+ logger.debug json_data.inspect
43
+ case res.code
44
+ when '200'
45
+ json_data
46
+ else
47
+ # XXX
48
+ pp res
49
+ raise 'api'
50
+ end
51
+ end
52
+
53
+ def get(path, param = { })
54
+ http_request(Net::HTTP::Get, path, param)
55
+ end
56
+
57
+ def post(path, param = { })
58
+ http_request(Net::HTTP::Post, path, param)
59
+ end
60
+
61
+ end
@@ -0,0 +1,18 @@
1
+ module CUI8Tracks
2
+ class CLI
3
+ def self.execute(stdout, arguments=[])
4
+
5
+ pit = Pit.get('8tracks_login', :require => {
6
+ 'username' => 'username',
7
+ 'password' => 'password',
8
+ })
9
+
10
+ session = CUI8Tracks::Session.new
11
+ session.load_config(ARGV)
12
+ session.authorize(pit['username'], pit['password'])
13
+ session.start_input_thread
14
+ session.play
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,59 @@
1
+ class CUI8Tracks::Mix
2
+ include CUI8Tracks::Thing
3
+
4
+ def user
5
+ return @user if @user
6
+ @user = CUI8Tracks::User.new(@data['user'])
7
+ @user.session = self.session
8
+ @user
9
+ end
10
+
11
+ def info
12
+ %w{ name description user tag_list_cache restful_url plays_count liked_by_current_user}.each{ |key|
13
+ value = case key
14
+ when 'user'
15
+ data[key]['slug']
16
+ else
17
+ data[key]
18
+ end
19
+ super(key => value)
20
+ }
21
+ notify "Playing mix #{self.name}", self.description
22
+ end
23
+
24
+ def id
25
+ @data['id']
26
+ end
27
+
28
+ def each_track(&block)
29
+ got = api.get("/sets/#{set.play_token}/play", {:mix_id => self.id})
30
+ track = CUI8Tracks::Track.new(got['set']['track'])
31
+ @track = track
32
+ track.session = self.session
33
+ track.mix = self
34
+ yield track
35
+ return if @skipped
36
+ loop {
37
+ got = api.get("/sets/#{set.play_token}/next", {:mix_id => self.id})
38
+ break if got['set']['at_end']
39
+ track = CUI8Tracks::Track.new(got['set']['track'])
40
+ @track = track
41
+ track.session = self.session
42
+ yield track
43
+ return if @skipped
44
+ }
45
+ end
46
+
47
+ def skip
48
+ @skipped = true
49
+ @track.stop
50
+ end
51
+
52
+ %w{ toggle_like like unlike}.each{ |method|
53
+ eval <<-EOS
54
+ def #{method}
55
+ api.post(path('#{method}'))
56
+ end
57
+ EOS
58
+ }
59
+ end
@@ -0,0 +1,152 @@
1
+ class CUI8Tracks::Session
2
+ attr_accessor :api, :config, :set, :current_track, :current_mix
3
+
4
+ def logger
5
+ return @logger if @logger
6
+ @logger = Logger.new STDOUT
7
+ @logger.level = self.config[:debug] ? Logger::DEBUG : Logger::INFO
8
+ @logger
9
+ end
10
+
11
+ def load_config(argv)
12
+ opt = OptionParser.new
13
+ @config = {:per_page => 1, :page => 1 }
14
+
15
+ OptionParser.new {|opt|
16
+ opt.on('-q QUERY', '--query') {|v| @config[:q] = v}
17
+ opt.on('-t TAG', '--tag') {|v| @config[:tag] = v}
18
+ opt.on('-u USER', '--user') {|v| @config[:user] = v}
19
+ opt.on('-s SORT', '--sort', '[recent|hot|popular|random]') {|v| @config[:sort] = v}
20
+ opt.on('--no-play', "don't play tracks") {|v| @config[:no_play] = true}
21
+ opt.on('--play_from FROM', 'play from [FROM]th mix') {|v| @config[:play_from] = v.to_i}
22
+ opt.on('--verbose', 'print mplayer output') {|v| @config[:verbose] = v}
23
+ opt.on('--debug', 'debug-mode') {|v| @config[:debug] = v}
24
+ opt.parse(argv)
25
+ }
26
+ logger.debug @config
27
+
28
+ system 'mplayer >& /dev/null' or raise 'mplayer seems not installed'
29
+ end
30
+
31
+ def authorize(username, password)
32
+ raise 'config sesms not loaded.' unless config
33
+ @api = CUI8Tracks::API.new(username, password)
34
+ @api.session = self
35
+ @api.login
36
+ end
37
+
38
+ def play
39
+ @set = set = CUI8Tracks::Set.new
40
+ set.session = self
41
+ %w{q tag user sort}.each{ |key|
42
+ set.instance_variable_set('@' + key, config[key.to_sym])
43
+ }
44
+ if config[:play_from]
45
+ set.page = config[:play_from]
46
+ end
47
+ set.each_mix{ |mix|
48
+ @current_mix = mix
49
+ logger.info "Playing mix #{set.page} / #{set.total_entries}"
50
+ mix.info
51
+ mix.each_track{ |track|
52
+ @current_track = track
53
+ logger.info "Playing track"
54
+ track.info
55
+ track.play
56
+ while track.playing?
57
+ sleep 1
58
+ end
59
+ }
60
+ }
61
+ end
62
+
63
+ def avail_commands
64
+ %w{ pause skip skip_mix toggle_like like unlike toggle_fav fav unfav toggle_follow follow unfollow open help exit}
65
+ end
66
+
67
+ def execute(command)
68
+ case command
69
+ when 'p'
70
+ execute 'pause'
71
+ when 'pause'
72
+ logger.info 'pause'
73
+ current_track.pause
74
+ when 'skip'
75
+ logger.info 'skip track'
76
+ current_track.stop
77
+ when 'skip_mix'
78
+ logger.info 'skip mix'
79
+ current_mix.skip
80
+ when 's'
81
+ execute 'skip'
82
+ when 'h'
83
+ execute 'help'
84
+ when '?'
85
+ execute 'help'
86
+ when 'help'
87
+ logger.info "available commands:"
88
+ logger.info avail_commands
89
+ when 'exit'
90
+ current_track.stop
91
+ exit
92
+
93
+ when 'toggle_like'
94
+ current_mix.toggle_like
95
+ logger.info "toggled like mix"
96
+ when 'like'
97
+ current_mix.like
98
+ logger.info "liked mix"
99
+ when 'unlike'
100
+ current_mix.unlike
101
+ logger.info "unliked mix"
102
+
103
+ when 'toggle_fav'
104
+ current_track.toggle_fav
105
+ logger.info "toggled favorite track"
106
+ when 'fav'
107
+ current_track.fav
108
+ logger.info "favorited track"
109
+ when 'unfav'
110
+ current_track.unfav
111
+ logger.info "unfavorited track"
112
+
113
+ when 'toggle_follow'
114
+ current_mix.user.toggle_follow
115
+ logger.info "toggled follow user"
116
+ when 'follow'
117
+ current_mix.user.follow
118
+ logger.info "followed user"
119
+ when 'unfollow'
120
+ current_mix.user.unfollow
121
+ logger.info "unfollowed user"
122
+
123
+ when 'open'
124
+ logger.info "open current mix"
125
+ system "open #{current_mix.restful_url}"
126
+ else
127
+ logger.info "unknown command: #{command}"
128
+ execute 'help'
129
+ end
130
+ end
131
+
132
+ def start_input_thread
133
+ Thread.new {
134
+ Readline.completion_proc = lambda {|input|
135
+ avail_commands.grep(/\A#{Regexp.quote input}/)
136
+ }
137
+ while line = Readline.readline('> ')
138
+ begin
139
+ line = line.chomp.strip rescue ''
140
+ if line.empty?
141
+ Readline::HISTORY.pop
142
+ next
143
+ end
144
+ execute line
145
+ rescue => e
146
+ logger.error "#{e.class}, #{e.message}"
147
+ puts e.backtrace.join("\n")
148
+ end
149
+ end
150
+ }
151
+ end
152
+ end
@@ -0,0 +1,60 @@
1
+ class CUI8Tracks::Set
2
+ include CUI8Tracks::Thing
3
+ attr_accessor :per_page, :page, :sort, :user, :q, :tag
4
+ def initialize
5
+ # default config
6
+ @per_page = 1
7
+ @page = 1
8
+ @sort = 'hot'
9
+ end
10
+
11
+ def info
12
+ super(self.query)
13
+ end
14
+
15
+ # to access session.set.play_token
16
+ def data
17
+ @data ||= api.get('/sets/new')
18
+ end
19
+
20
+ attr_reader :total_entries
21
+ def mixes
22
+ got = api.get(path, query)
23
+ @total_entries = got['total_entries']
24
+ got['mixes'].map{|mix_data|
25
+ mix = CUI8Tracks::Mix.new(mix_data)
26
+ mix.session = self.session
27
+ mix
28
+ }
29
+ end
30
+
31
+ def each_mix(&block)
32
+ loop {
33
+ current_mixes = mixes
34
+ return if current_mixes.empty?
35
+
36
+ current_mixes.each{ |mix|
37
+ yield mix
38
+ }
39
+ @page += 1
40
+ }
41
+ end
42
+
43
+ def path
44
+ @user ? "/users/#{@user}/mixes" : "/mixes"
45
+ end
46
+
47
+ def query
48
+ {
49
+ :q => @q,
50
+ :tag => @tag,
51
+ :sort => @sort,
52
+ :page => @page,
53
+ :per_page => @per_page
54
+ }.each_pair.inject({}){|a, pair|
55
+ key, value = *pair
56
+ a.update({key => value}) if value
57
+ a
58
+ }
59
+ end
60
+ end
@@ -0,0 +1,56 @@
1
+ module CUI8Tracks::Thing
2
+ attr_accessor :session
3
+
4
+ def initialize(data = nil)
5
+ @data = data
6
+ end
7
+
8
+ def logger
9
+ session.logger
10
+ end
11
+
12
+ def api
13
+ session.api
14
+ end
15
+
16
+ def set
17
+ session.set
18
+ end
19
+
20
+ def method_missing(name, *args, &block)
21
+ if data && data.has_key?(name.to_s)
22
+ data[name.to_s]
23
+ else
24
+ super
25
+ end
26
+ end
27
+
28
+ def data
29
+ @data
30
+ end
31
+
32
+ def info(data = self.data)
33
+ data.each_key{ |key|
34
+ logger.info "#{self.class.to_s}::#{key} = #{data[key]}"
35
+ }
36
+ end
37
+
38
+ def id
39
+ @data['id']
40
+ end
41
+
42
+ def path(method = '')
43
+ classname = self.class.to_s.split(/::/).last.downcase
44
+ classname += 'e' if classname =~ /x$/
45
+ classname += 's'
46
+ "/#{classname}/#{self.id}/" + method
47
+ end
48
+
49
+ def notify(title, message)
50
+ Notify.notify(title, message)
51
+ # Thread.new {
52
+ # @@notifier = Growl.new 'localhost', 'ruby', ['notify']
53
+ # @@notifier.notify 'notify', title, message
54
+ # }
55
+ end
56
+ end
@@ -0,0 +1,119 @@
1
+ class CUI8Tracks::Track
2
+ include CUI8Tracks::Thing
3
+ attr_accessor :user, :mix
4
+
5
+ def user
6
+ return @user if @user
7
+ @user = CUI8Tracks::User.new(@data['user'])
8
+ @user.session = self.session
9
+ end
10
+
11
+ def info
12
+ %w{ performer name release_name year url faved_by_current_user}.each{ |key|
13
+ super(key => data[key])
14
+ }
15
+ notify self.name, [self.performer, self.release_name].join("\n")
16
+ end
17
+
18
+ def escape_for_shell(path)
19
+ escaped = path
20
+ ' ;&()|^<>?*[]$`"\'{}'.split(//).each{|c|
21
+ escaped.gsub!(c){ |c| '\\' + c }
22
+ }
23
+ escaped
24
+ end
25
+
26
+ def play
27
+ @playing = true
28
+ if self.has_cache?
29
+ logger.info "cache hit" if self.has_cache?
30
+ else
31
+ if session.config[:no_play]
32
+ self.download
33
+ else
34
+ Thread.new {
35
+ self.download
36
+ }
37
+ end
38
+ end
39
+ return true if session.config[:no_play]
40
+ path = self.has_cache? ? self.cache_path : self.url
41
+
42
+ cmd = "mplayer #{escape_for_shell(path)} #{session.config[:verbose] ? "" : "-really-quiet"} 2> /dev/null"
43
+ logger.debug cmd
44
+ @io = IO.popen(cmd, 'r+')
45
+ Thread.new {
46
+ begin
47
+ loop {
48
+ s = @io.read 1
49
+ print s if s && session.config[:verbose]
50
+ break if s.nil?
51
+ break if @io.closed?
52
+ }
53
+ ensure
54
+ @playing = false
55
+ end
56
+ }
57
+ end
58
+
59
+ def playing?
60
+ @playing
61
+ end
62
+
63
+ def pause
64
+ @io.write 'p'
65
+ end
66
+
67
+ def stop
68
+ @playing = false
69
+ return if @io.closed?
70
+ @io.write 'q'
71
+ end
72
+
73
+ def cache_path
74
+ 'cache/' + [self.performer, self.name].map{ |s| s.gsub(/\//, '_')}.join(' - ') + File.extname(url)
75
+ end
76
+
77
+ def has_cache?
78
+ File.size? self.cache_path
79
+ end
80
+
81
+ def download
82
+ unless File.directory?('cache')
83
+ logger.debug('make cache directory')
84
+ Dir.mkdir('cache')
85
+ end
86
+
87
+ logger.info "downloading #{self.url}"
88
+ total = nil
89
+ from = Time.now
90
+ open(self.cache_path, 'w') {|local|
91
+ got = open(url,
92
+ :content_length_proc => proc{|_total|
93
+ total = _total
94
+ },
95
+ :progress_proc => proc{ |now|
96
+ if Time.now - from > 0.2
97
+ from = Time.now
98
+ print "%3d%% #{now}/#{total}\r" % (now/total.to_f*100)
99
+ $stdout.flush
100
+ end
101
+ }
102
+ ) {|remote|
103
+ local.write(remote.read)
104
+ }
105
+ }
106
+ rescue Exception => e
107
+ logger.fatal "failed to download #{self.url}"
108
+ File.unlink(self.cache_path) if File.exist?(self.cache_path)
109
+ end
110
+
111
+ %w{ toggle_fav fav unfav}.each{ |method|
112
+ eval <<-EOS
113
+ def #{method}
114
+ api.post(path('#{method}'))
115
+ end
116
+ EOS
117
+ }
118
+
119
+ end
@@ -0,0 +1,12 @@
1
+ class CUI8Tracks::User
2
+ include CUI8Tracks::Thing
3
+
4
+ %w{ toggle_follow follow unfollow}.each{ |method|
5
+ eval <<-EOS
6
+ def #{method}
7
+ api.post(path('#{method}'))
8
+ end
9
+ EOS
10
+ }
11
+
12
+ end
data/lib/cui8tracks.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'logger'
2
+ require 'open-uri'
3
+ require 'optparse'
4
+ require 'cgi'
5
+ require 'net/http'
6
+ require 'pp'
7
+ require 'json'
8
+ require 'cgi'
9
+ require 'readline'
10
+
11
+ require 'pit'
12
+ require 'notify'
13
+
14
+ module CUI8Tracks
15
+ require 'cui8tracks/cli'
16
+ require 'cui8tracks/thing'
17
+ require 'cui8tracks/api'
18
+ require 'cui8tracks/mix'
19
+ require 'cui8tracks/session'
20
+ require 'cui8tracks/set'
21
+ require 'cui8tracks/track'
22
+ require 'cui8tracks/user'
23
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe CUI8Tracks do
4
+ it "ok" do
5
+ 1.should == 1
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'cui8tracks'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cui8tracks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - hitode909
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-17 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pit
16
+ requirement: &70333077879140 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70333077879140
25
+ - !ruby/object:Gem::Dependency
26
+ name: notify
27
+ requirement: &70333077878640 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70333077878640
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70333077878120 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 2.3.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70333077878120
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: &70333077877600 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70333077877600
58
+ - !ruby/object:Gem::Dependency
59
+ name: jeweler
60
+ requirement: &70333077877120 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 1.5.2
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70333077877120
69
+ - !ruby/object:Gem::Dependency
70
+ name: rcov
71
+ requirement: &70333077834600 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70333077834600
80
+ description: cui8tracks is CUI 8tracks player for terminal
81
+ email: hitode909@gmail.com
82
+ executables:
83
+ - cui8tracks.rb
84
+ extensions: []
85
+ extra_rdoc_files:
86
+ - LICENSE.txt
87
+ - README.rdoc
88
+ files:
89
+ - Gemfile
90
+ - Gemfile.lock
91
+ - LICENSE.txt
92
+ - README.rdoc
93
+ - Rakefile
94
+ - VERSION
95
+ - bin/cui8tracks.rb
96
+ - cui8tracks.gemspec
97
+ - lib/cui8tracks.rb
98
+ - lib/cui8tracks/api.rb
99
+ - lib/cui8tracks/cli.rb
100
+ - lib/cui8tracks/mix.rb
101
+ - lib/cui8tracks/session.rb
102
+ - lib/cui8tracks/set.rb
103
+ - lib/cui8tracks/thing.rb
104
+ - lib/cui8tracks/track.rb
105
+ - lib/cui8tracks/user.rb
106
+ - spec/cui8tracks_spec.rb
107
+ - spec/spec_helper.rb
108
+ homepage: http://github.com/hitode909/cui8tracks
109
+ licenses:
110
+ - MIT
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ segments:
122
+ - 0
123
+ hash: 2539025416605640759
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ! '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubyforge_project:
132
+ rubygems_version: 1.8.6
133
+ signing_key:
134
+ specification_version: 3
135
+ summary: cui 8tracks player
136
+ test_files:
137
+ - spec/cui8tracks_spec.rb
138
+ - spec/spec_helper.rb