cuegrowler 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5e72d27fdece7f08e2f64deaf3ae1882ca45871f
4
+ data.tar.gz: 07029311faa3c698b1c18f3059948de6eb9f0d74
5
+ SHA512:
6
+ metadata.gz: 5ea399e1686df230920e4543f68d9edd4571f03173e323c0bf5b506d64335d41cff69d9f3d50092a0d77971df0aa16651684d76839990e97a68af20cbb709fdb
7
+ data.tar.gz: ec0c2af26a3a69a91a3fd17621d5093d28f7e8e6bf31113e170ed6c38dc71f1697d584a766115a083bddc24ffa8b9369fefedb11e6fe065db695c106fea5d3e7
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cuegrowler.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Thai Pangsakulyanont
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # Cuegrowler
2
+
3
+ Displays a Growl notification when a song changes in a mix.
4
+
5
+
6
+ ## Installation
7
+
8
+ gem install cuegrowler
9
+
10
+
11
+ ## Usage
12
+
13
+
14
+ ### Using .cue Files
15
+
16
+ cuegrowler <path to .cue file>
17
+
18
+
19
+ ### Using Description in iTunes
20
+
21
+ Some podcasts include the tracklist in form of [HH:MM:SS].
22
+ `cuegrowler` can parse the tracklist from that too.
23
+ Just
24
+
25
+ cuegrowler
26
+
27
+
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it ( https://github.com/[my-github-username]/cuegrowler/fork )
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/cuegrowler ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'cuegrowler'
4
+
5
+ Cuegrowler.main
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cuegrowler/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cuegrowler"
8
+ spec.version = Cuegrowler::VERSION
9
+ spec.authors = ["Thai Pangsakulyanont"]
10
+ spec.email = ["org.yi.dttvb@gmail.com"]
11
+ spec.summary = %q{Growl the current track using a cuesheet.}
12
+ spec.description = %q{Growl the current track using a cuesheet.}
13
+ spec.homepage = "https://github.com/dtinth/cuegrowler"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_runtime_dependency "rubycue"
24
+ spec.add_runtime_dependency "docopt"
25
+ spec.add_runtime_dependency "osaka"
26
+ spec.add_runtime_dependency "growl"
27
+ end
data/lib/cuegrowler.rb ADDED
@@ -0,0 +1,171 @@
1
+ require 'cuegrowler/version'
2
+ require 'rubycue'
3
+ require 'osaka'
4
+ require 'growl'
5
+ require 'open-uri'
6
+
7
+ module Cuegrowler
8
+
9
+ class ITunes
10
+
11
+ def self.get_player_position
12
+ Osaka::ScriptRunner.execute(%q(tell application "iTunes" to get the player position)).to_f
13
+ end
14
+
15
+ def self.get_track_description
16
+ Osaka::ScriptRunner.execute(%q(tell application "iTunes" to get the current track's long description))
17
+ end
18
+
19
+ end
20
+
21
+ module Tracklist
22
+
23
+ class ITunes
24
+
25
+ def get
26
+ parse_tracklist(Cuegrowler::ITunes.get_track_description)
27
+ end
28
+
29
+ def to_s
30
+ "From iTunes description"
31
+ end
32
+
33
+ protected
34
+ def parse_tracklist(description)
35
+ description.lines.map(&:strip)
36
+ .map { |line| [line, line.match(/\[(\d+):(\d+):(\d+)\]/)] }
37
+ .reject { |text, match| match.nil? }
38
+ .map { |text, match| { text: text, time: tracklist_match_to_time(match) } }
39
+ end
40
+
41
+ def tracklist_match_to_time(m)
42
+ m[1].to_f * 3600 + m[2].to_f * 60 + m[3].to_f
43
+ end
44
+
45
+ end
46
+
47
+ class Cuesheet
48
+
49
+ def initialize(filename)
50
+
51
+ @filename = filename
52
+ @data = []
53
+
54
+ cuesheet = RubyCue::Cuesheet.new(open(filename).read)
55
+ cuesheet.parse!
56
+
57
+ cuesheet.songs.each_with_index do |song, index|
58
+ time = song[:index].to_f
59
+ text = "#{index + 1}. #{format time} #{song[:performer]} — #{song[:title]}"
60
+ @data << { text: text, time: time }
61
+ end
62
+
63
+ end
64
+
65
+ def get
66
+ @data
67
+ end
68
+
69
+ def to_s
70
+ "From cuesheet #{@filename}"
71
+ end
72
+
73
+ private
74
+ def format(time)
75
+ hours, time = time.divmod(3600)
76
+ minutes, seconds = time.divmod(60)
77
+ "[%d:%02d:%02d]" % [hours, minutes, seconds]
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ class Growler
85
+
86
+ def initialize(player, tracklist)
87
+ @current_position = -Float::INFINITY
88
+ @player = player
89
+ @tracklist = tracklist
90
+ end
91
+
92
+ def loop_forever!
93
+ loop do
94
+ tick
95
+ sleep 2
96
+ end
97
+ end
98
+
99
+ def tick
100
+ update_position
101
+ tracklist = @tracklist.get
102
+ new_song = tracklist.reverse.find { |track|
103
+ @last_position < track[:time] && track[:time] <= @current_position }
104
+ notify(new_song) if new_song
105
+ end
106
+
107
+ protected
108
+
109
+ def update_position
110
+ @last_position = @current_position
111
+ @current_position = @player.get_player_position
112
+ end
113
+
114
+ def notify(new_song)
115
+ Growl.notify new_song[:text], name: 'cuegrowler', title: 'New Track'
116
+ puts "\n[#{Time.now}]"
117
+ puts new_song[:text]
118
+ end
119
+
120
+ end
121
+
122
+ class << self
123
+
124
+ def start(filename=nil)
125
+
126
+ player = ITunes
127
+
128
+ tracklist = if filename
129
+ Tracklist::Cuesheet.new(filename)
130
+ else
131
+ Tracklist::ITunes.new
132
+ end
133
+
134
+ puts "\n== Cuegrowler is running! =="
135
+ puts "Player: #{player}"
136
+ puts "Tracklist: #{tracklist}"
137
+ Growler.new(player, tracklist).loop_forever!
138
+
139
+ end
140
+
141
+ def main
142
+
143
+ require 'docopt'
144
+
145
+ doc = <<DOCOPT
146
+ Displays Growl notifications from .cue files based on current time in iTunes.
147
+
148
+ Usage:
149
+ cuegrowler [<filename>]
150
+ cuegrowler -h | --help
151
+
152
+ Options:
153
+ -h, --help Shows this screen.
154
+ <filename> The .cue filename. If specified, cuegrowler will read the
155
+ tracklist from this file. Otherwise, the tracklist is parsed
156
+ from the current podcast episode's descriptions.
157
+ DOCOPT
158
+
159
+ opts = Docopt::docopt(doc)
160
+
161
+ start opts["<filename>"]
162
+
163
+ rescue Docopt::Exit => e
164
+
165
+ puts e.message
166
+
167
+ end
168
+
169
+ end
170
+
171
+ end
@@ -0,0 +1,3 @@
1
+ module Cuegrowler
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cuegrowler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Thai Pangsakulyanont
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubycue
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: docopt
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: osaka
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: growl
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Growl the current track using a cuesheet.
98
+ email:
99
+ - org.yi.dttvb@gmail.com
100
+ executables:
101
+ - cuegrowler
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - README.md
109
+ - Rakefile
110
+ - bin/cuegrowler
111
+ - cuegrowler.gemspec
112
+ - lib/cuegrowler.rb
113
+ - lib/cuegrowler/version.rb
114
+ homepage: https://github.com/dtinth/cuegrowler
115
+ licenses:
116
+ - MIT
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 2.2.2
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: Growl the current track using a cuesheet.
138
+ test_files: []