cui8tracks 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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