ektoplayer 0.1.12 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ektoplayer/application.rb +49 -19
- data/lib/ektoplayer/bindings.rb +91 -87
- data/lib/ektoplayer/browsepage.rb +14 -27
- data/lib/ektoplayer/common.rb +12 -67
- data/lib/ektoplayer/compat.rb +5 -11
- data/lib/ektoplayer/config.rb +52 -17
- data/lib/ektoplayer/controllers/browser.rb +10 -5
- data/lib/ektoplayer/database.rb +7 -20
- data/lib/ektoplayer/download/externaldownload.rb +65 -0
- data/lib/ektoplayer/download/rubydownload.rb +69 -0
- data/lib/ektoplayer/icurses/curses.rb +18 -2
- data/lib/ektoplayer/icurses/{ffi_ncurses.rb → ffi-ncurses.rb} +1 -0
- data/lib/ektoplayer/icurses/ncurses.rb +10 -0
- data/lib/ektoplayer/icurses.rb +13 -5
- data/lib/ektoplayer/models/browser.rb +11 -11
- data/lib/ektoplayer/models/player.rb +4 -5
- data/lib/ektoplayer/operations/browser.rb +9 -1
- data/lib/ektoplayer/operations/playlist.rb +1 -1
- data/lib/ektoplayer/players/mpg_wrapper_player.rb +98 -40
- data/lib/ektoplayer/theme.rb +78 -63
- data/lib/ektoplayer/trackloader.rb +25 -74
- data/lib/ektoplayer/ui/colors.rb +33 -5
- data/lib/ektoplayer/ui/widgets/container.rb +1 -1
- data/lib/ektoplayer/ui/widgets/listwidget.rb +35 -34
- data/lib/ektoplayer/ui/widgets.rb +19 -0
- data/lib/ektoplayer/ui.rb +22 -23
- data/lib/ektoplayer/updater.rb +3 -4
- data/lib/ektoplayer/views/browser.rb +7 -2
- data/lib/ektoplayer/views/help.rb +5 -2
- data/lib/ektoplayer/views/info.rb +22 -27
- data/lib/ektoplayer/views/playinginfo.rb +20 -19
- data/lib/ektoplayer/views/playlist.rb +8 -3
- data/lib/ektoplayer/views/progressbar.rb +26 -33
- data/lib/ektoplayer/views/splash.rb +14 -22
- data/lib/ektoplayer/views/trackrenderer.rb +14 -10
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1567475105c5b1d0e3a099a4324ca19cdd67efe8
|
4
|
+
data.tar.gz: e48caa107e5f934866a720023a5cb86fbb9153a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5b706485a36e6398a981314c93f244ad4c85e35afbe55cce4e2d211752059abd3cfe743316d5edc85011f01002ecf35b5895e0aab54551bff565e407b1e7db0
|
7
|
+
data.tar.gz: 12636fee134acc3f234ddbb6f7637e6a2ca0186998d76929820eb1f5a36c347ed5ec6c86aab8f128be13cf7240b9d01ad8e68c68b3dd15ac8347c783cb765ead
|
@@ -10,15 +10,39 @@ require 'date'
|
|
10
10
|
|
11
11
|
module Ektoplayer
|
12
12
|
class Application
|
13
|
-
VERSION = '0.1.
|
13
|
+
VERSION = '0.1.16'.freeze
|
14
14
|
GITHUB_URL = 'https://github.com/braph/ektoplayer'.freeze
|
15
15
|
EKTOPLAZM_URL = 'http://www.ektoplazm.com'.freeze
|
16
|
-
|
17
|
-
|
16
|
+
|
17
|
+
EKTOPLAZM_ALBUM_BASE_URL = "#{EKTOPLAZM_URL}/free-music".freeze
|
18
|
+
EKTOPLAZM_COVER_BASE_URL = "#{EKTOPLAZM_URL}/img".freeze
|
19
|
+
EKTOPLAZM_TRACK_BASE_URL = "#{EKTOPLAZM_URL}/mp3".freeze
|
20
|
+
EKTOPLAZM_STYLE_BASE_URL = "#{EKTOPLAZM_URL}/style".freeze
|
21
|
+
EKTOPLAZM_ARCHIVE_BASE_URL = "#{EKTOPLAZM_URL}/files".freeze
|
18
22
|
|
19
23
|
CONFIG_DIR = File.join(Dir.home, '.config', 'ektoplayer').freeze
|
20
24
|
CONFIG_FILE = File.join(CONFIG_DIR, 'ektoplayer.rc').freeze
|
21
25
|
|
26
|
+
def self.album_url(album)
|
27
|
+
"#{EKTOPLAZM_ALBUM_BASE_URL}/#{album}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.cover_url(cover)
|
31
|
+
"#{EKTOPLAZM_COVER_BASE_URL}/#{cover}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.track_url(track)
|
35
|
+
"#{EKTOPLAZM_TRACK_BASE_URL}/#{track}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.style_url(style)
|
39
|
+
"#{EKTOPLAZM_STYLE_BASE_URL}/#{style}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.archive_url(archive)
|
43
|
+
"#{EKTOPLAZM_ARCHIVE_BASE_URL}/#{archive}"
|
44
|
+
end
|
45
|
+
|
22
46
|
def self.log(from, *msgs)
|
23
47
|
func = caller[0][/`.*'/][1..-2]
|
24
48
|
from = from.class unless from.is_a?String
|
@@ -36,7 +60,7 @@ module Ektoplayer
|
|
36
60
|
end
|
37
61
|
|
38
62
|
def run
|
39
|
-
|
63
|
+
puts "\033]0;ektoplayer\007"
|
40
64
|
Thread.report_on_exception=(true) if Thread.respond_to? :report_on_exception
|
41
65
|
|
42
66
|
# make each configuration object globally accessible as a singleton
|
@@ -71,7 +95,7 @@ module Ektoplayer
|
|
71
95
|
end
|
72
96
|
|
73
97
|
UI::Canvas.run do
|
74
|
-
Application.log(self, '
|
98
|
+
Application.log(self, "using '#{$USING_CURSES}' with #{ICurses.colors} colors available")
|
75
99
|
|
76
100
|
if Config[:use_colors] == :auto
|
77
101
|
Theme.use_colors(ICurses.colors >= 256 ? 256 : 8)
|
@@ -90,7 +114,12 @@ module Ektoplayer
|
|
90
114
|
|
91
115
|
# ... operations ...
|
92
116
|
operations = Operations::Operations.new
|
93
|
-
operations.register(:quit
|
117
|
+
operations.register(:quit) do
|
118
|
+
Thread.list.each { |t| t.kill if t != Thread.current }
|
119
|
+
FileUtils.rm(Dir.glob(File.join(Config[:temp_dir], '~ekto-*'))) rescue nil
|
120
|
+
raise SystemExit
|
121
|
+
end
|
122
|
+
|
94
123
|
operations.register(:reload, &browser.method(:reload))
|
95
124
|
operations.register(:update, &database.method(:update))
|
96
125
|
operations.register(:refresh) { UI::Canvas.update_screen(true, true) }
|
@@ -117,25 +146,26 @@ module Ektoplayer
|
|
117
146
|
main_w.playinginfo.attach(playlist, player)
|
118
147
|
|
119
148
|
# ... events ...
|
120
|
-
database.events.on(:update_finished, &browser.method(:reload
|
149
|
+
database.events.on(:update_finished, &browser.method(:reload))
|
121
150
|
player.events.on(:stop) do |reason|
|
122
151
|
operations.send(:'playlist.play_next') if reason == :track_completed
|
123
152
|
end
|
124
153
|
|
125
154
|
if Config[:prefetch]
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
trackloader_mutex.synchronize do
|
132
|
-
trackloader.get_track_file(playlist[playlist.get_next_pos]['url'])
|
133
|
-
sleep 30
|
134
|
-
end
|
135
|
-
end
|
155
|
+
Thread.new do
|
156
|
+
current_download_track = nil
|
157
|
+
|
158
|
+
loop do
|
159
|
+
sleep 5
|
136
160
|
|
137
|
-
|
138
|
-
|
161
|
+
next_track = playlist.get_next_pos
|
162
|
+
next if current_download_track == next_track
|
163
|
+
|
164
|
+
if player.length > 30 and player.position_percent > 0.5
|
165
|
+
trackloader.get_track_file(playlist[next_track]['url'])
|
166
|
+
current_download_track = next_track
|
167
|
+
sleep 5
|
168
|
+
end
|
139
169
|
end
|
140
170
|
end
|
141
171
|
end
|
data/lib/ektoplayer/bindings.rb
CHANGED
@@ -69,104 +69,108 @@ module Ektoplayer
|
|
69
69
|
%w(browser playlist).each { |w| reg("#{w}.#{cmd}", desc) }
|
70
70
|
end
|
71
71
|
|
72
|
-
@bindings = {
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
72
|
+
@bindings = { }
|
73
|
+
@bindings[:global] = {
|
74
|
+
:'splash.show' => [?`, ?^ ],
|
75
|
+
:'playlist.show' => [?1 ],
|
76
|
+
:'browser.show' => [?2 ],
|
77
|
+
:'info.show' => [?3 ],
|
78
|
+
:'help.show' => [?4, ICurses::KEY_F1 ],
|
79
|
+
|
80
|
+
:'playinginfo.toggle' => [?!, ?\\, ICurses::KEY_F2 ],
|
81
|
+
:'progressbar.toggle' => [?%, ?~, ICurses::KEY_F3 ],
|
82
|
+
:'tabbar.toggle' => [?=, ICurses::KEY_F4 ],
|
83
|
+
|
84
|
+
:'player.forward' => [?f, ICurses::KEY_RIGHT ],
|
85
|
+
:'player.backward' => [?b, ICurses::KEY_LEFT ],
|
86
|
+
:'player.stop' => [?s ],
|
87
|
+
:'player.toggle' => [?p ],
|
88
|
+
|
89
|
+
:'playlist.play_next' => [?> ],
|
90
|
+
:'playlist.play_prev' => [?< ],
|
91
|
+
|
92
|
+
:'tabs.next' => [?l, ?}, '^i' ],
|
93
|
+
:'tabs.prev' => [?h, ?{, 353 ],
|
94
|
+
|
95
|
+
:quit => [?q ],
|
96
|
+
:refresh => ['^l' ],
|
97
|
+
:reload => ['^r' ],
|
98
|
+
:update => [?U ]
|
99
|
+
}
|
100
|
+
@bindings[:playlist] = {
|
101
|
+
# movement
|
102
|
+
:'playlist.top' => [?g, ICurses::KEY_HOME ],
|
103
|
+
:'playlist.bottom' => [?G, ICurses::KEY_END ],
|
104
|
+
:'playlist.up' => [?k, ICurses::KEY_UP ],
|
105
|
+
:'playlist.down' => [?j, ICurses::KEY_DOWN ],
|
106
|
+
:'playlist.page_down' => ['^d', ICurses::KEY_NPAGE ],
|
107
|
+
:'playlist.page_up' => ['^u', ICurses::KEY_PPAGE ],
|
108
|
+
# selection
|
109
|
+
:'playlist.toggle_selection' => ['^v' ],
|
110
|
+
# search
|
111
|
+
:'playlist.search_next' => [?n ],
|
112
|
+
:'playlist.search_prev' => [?N ],
|
113
|
+
:'playlist.search_up' => [?? ],
|
114
|
+
:'playlist.search_down' => [?/ ],
|
115
|
+
# playlist
|
116
|
+
:'playlist.play' => [ ICurses::KEY_ENTER ],
|
117
|
+
:'playlist.download_album' => [?$ ],
|
118
|
+
:'playlist.reload' => [?r ],
|
119
|
+
:'playlist.goto_current' => [?o ],
|
120
|
+
:'playlist.clear' => [?c ],
|
121
|
+
:'playlist.delete' => [?d ],
|
122
|
+
# other
|
123
|
+
:'player.toggle' => [' ' ]
|
124
|
+
}
|
125
|
+
@bindings[:browser] = {
|
126
|
+
# movement
|
127
|
+
:'browser.top' => [?g, ICurses::KEY_HOME ],
|
128
|
+
:'browser.bottom' => [?G, ICurses::KEY_END ],
|
129
|
+
:'browser.up' => [?k, ICurses::KEY_UP ],
|
130
|
+
:'browser.down' => [?j, ICurses::KEY_DOWN ],
|
131
|
+
:'browser.page_up' => ['^u', ICurses::KEY_PPAGE ],
|
132
|
+
:'browser.page_down' => ['^d', ICurses::KEY_NPAGE ],
|
133
|
+
# selection
|
134
|
+
:'browser.toggle_selection' => ['^v' ],
|
135
|
+
# search
|
136
|
+
:'browser.search_next' => [?n ],
|
137
|
+
:'browser.search_prev' => [?N ],
|
138
|
+
:'browser.search_up' => [?? ],
|
139
|
+
:'browser.search_down' => [?/ ],
|
140
|
+
# browser
|
141
|
+
:'browser.add_to_playlist' => [' ', ?a ],
|
142
|
+
:'browser.enter' => [ ICurses::KEY_ENTER ],
|
143
|
+
:'browser.back' => [?B, ICurses::KEY_BACKSPACE ]
|
144
|
+
}
|
145
|
+
@bindings[:help] = {
|
146
|
+
:'help.top' => [?g, ICurses::KEY_HOME ],
|
147
|
+
:'help.bottom' => [?G, ICurses::KEY_END ],
|
148
|
+
:'help.up' => [?k, ICurses::KEY_UP ],
|
149
|
+
:'help.down' => [?j, ICurses::KEY_DOWN ],
|
150
|
+
:'help.page_up' => ['^u', ICurses::KEY_PPAGE ],
|
151
|
+
:'help.page_down' => ['^d', ICurses::KEY_NPAGE ]
|
152
|
+
}
|
153
|
+
@bindings[:info] = {
|
154
|
+
:'info.top' => [?g, ICurses::KEY_HOME ],
|
155
|
+
:'info.bottom' => [?G, ICurses::KEY_END ],
|
156
|
+
:'info.up' => [?k, ICurses::KEY_UP ],
|
157
|
+
:'info.down' => [?j, ICurses::KEY_DOWN ],
|
158
|
+
:'info.page_up' => ['^u', ICurses::KEY_PPAGE ],
|
159
|
+
:'info.page_down' => ['^d', ICurses::KEY_NPAGE ]
|
157
160
|
}
|
161
|
+
@bindings[:splash] = {}
|
158
162
|
|
159
163
|
@bindings.default_proc = proc { |h,k| fail "Unknown widget #{k}" }
|
160
164
|
@bindings.each do |widget, hash|
|
161
165
|
hash.default_proc = proc { |h,k| h[k] = [] }
|
162
166
|
hash.values.each do |keys|
|
163
|
-
keys.map!
|
167
|
+
keys.map!(&method(:parse_key))
|
164
168
|
end
|
165
169
|
end
|
166
170
|
end
|
167
171
|
|
168
172
|
def keyname(key)
|
169
|
-
return 'SPACE'
|
173
|
+
return 'SPACE' if (key == ' ' or key == 32)
|
170
174
|
|
171
175
|
name = ICurses.keyname(key)
|
172
176
|
if name.start_with? 'KEY_'
|
@@ -9,8 +9,7 @@ require 'open-uri'
|
|
9
9
|
|
10
10
|
module Ektoplayer
|
11
11
|
class BrowsePage
|
12
|
-
ALBUM_KEYS = %w(url title artist date
|
13
|
-
download_count released_by released_by_url posted_by posted_by_url
|
12
|
+
ALBUM_KEYS = %w(url title artist date styles cover_url description download_count
|
14
13
|
archive_urls rating votes tracks).map(&:to_sym).freeze
|
15
14
|
|
16
15
|
TRACK_KEYS = %w(url album_url number title remix artist bpm).map(&:to_sym).freeze
|
@@ -21,7 +20,7 @@ module Ektoplayer
|
|
21
20
|
BrowsePage.new(src)
|
22
21
|
end
|
23
22
|
|
24
|
-
def styles;
|
23
|
+
def styles; @@styles or [] end
|
25
24
|
def first_page_url; @page_urls[0] end
|
26
25
|
def last_page_url; @page_urls[-1] end
|
27
26
|
def current_page_url; @page_urls[@current_page_index] end
|
@@ -40,24 +39,23 @@ module Ektoplayer
|
|
40
39
|
|
41
40
|
@page_urls = []
|
42
41
|
doc.css('.wp-pagenavi option').each_with_index do |option, i|
|
43
|
-
@current_page_index = i if option[
|
44
|
-
@page_urls << option[
|
42
|
+
@current_page_index = i if option['selected']
|
43
|
+
@page_urls << option['value']
|
45
44
|
end
|
46
45
|
|
47
46
|
@@styles ||= begin
|
48
47
|
doc.xpath('//a[contains(@href, "http") and contains(@href, "/style/")]').map do |a|
|
49
|
-
[ a.text, a[
|
48
|
+
[ a.text, File.basename(a['href']) ]
|
50
49
|
end.to_h
|
51
50
|
end
|
52
51
|
|
53
52
|
doc.xpath('//div[starts-with(@id, "post-")]').each do |post|
|
54
53
|
album = { tracks: [] }
|
55
54
|
album[:date] = Date.parse(post.at_css('.d').text).iso8601 rescue nil
|
56
|
-
album[:category] = post.at_css('.c a').text rescue nil
|
57
55
|
|
58
56
|
album[:styles] = []
|
59
57
|
post.css('.style a').map do |a|
|
60
|
-
@@styles[a.text] = a[
|
58
|
+
@@styles[a.text] = File.basename(a['href'])
|
61
59
|
album[:styles] << a.text
|
62
60
|
end
|
63
61
|
|
@@ -65,7 +63,7 @@ module Ektoplayer
|
|
65
63
|
to_html.sub(/^<p>/, '').sub(/<\/p>$/, '') rescue ''
|
66
64
|
|
67
65
|
begin album[:cover_url] = File.basename(
|
68
|
-
URI.parse(post.at_css('.cover')[
|
66
|
+
URI.parse(post.at_css('.cover')['src']).path
|
69
67
|
)
|
70
68
|
rescue
|
71
69
|
end
|
@@ -74,23 +72,11 @@ module Ektoplayer
|
|
74
72
|
|
75
73
|
post.css('h1 a').each do |a|
|
76
74
|
album[:title] = a.text
|
77
|
-
album[:url] = File.basename(URI.parse(a[
|
75
|
+
album[:url] = File.basename(URI.parse(a['href']).path)
|
78
76
|
end
|
79
77
|
|
80
|
-
post.xpath('.//a[@rel="tag"]').each do |a|
|
81
|
-
album[:released_by] = a.text
|
82
|
-
album[:released_by_url] = File.basename(URI.parse(a[:href]).path)
|
83
|
-
# todo
|
84
|
-
end
|
85
|
-
|
86
|
-
post.xpath('.//a[@rel="author external"]').each do |a|
|
87
|
-
album[:posted_by] = a.text
|
88
|
-
album[:posted_by_url] = File.basename(URI.parse(a[:href]).path)
|
89
|
-
# todo
|
90
|
-
end
|
91
|
-
|
92
78
|
album[:archive_urls] = post.css('.dll a').map do |a|
|
93
|
-
[ a.text.split[0] , a[
|
79
|
+
[ a.text.split[0] , File.basename(a['href']) ]
|
94
80
|
end.to_h
|
95
81
|
|
96
82
|
begin
|
@@ -102,8 +88,9 @@ module Ektoplayer
|
|
102
88
|
end
|
103
89
|
|
104
90
|
begin
|
105
|
-
base64_tracklist = post.at_css(
|
91
|
+
base64_tracklist = post.at_css('script').text.scan(/soundFile:"(.*)"/)[0][0]
|
106
92
|
tracklist_urls = Base64.decode64(base64_tracklist).split(?,)
|
93
|
+
tracklist_urls.map! { |url| File.basename(url) }
|
107
94
|
rescue
|
108
95
|
# Sometimes there are no tracks:
|
109
96
|
# http://www.ektoplazm.com/free-music/dj-basilisk-the-colours-of-ektoplazm
|
@@ -112,8 +99,8 @@ module Ektoplayer
|
|
112
99
|
|
113
100
|
post.css('.tl').each do |album_track_list|
|
114
101
|
track = nil
|
115
|
-
album_track_list.css(
|
116
|
-
case ti[
|
102
|
+
album_track_list.css('span').each do |ti|
|
103
|
+
case ti['class']
|
117
104
|
when ?n
|
118
105
|
album[:tracks] << track if track and track[:url]
|
119
106
|
track = { url: tracklist_urls.shift }
|
@@ -141,7 +128,7 @@ module Ektoplayer
|
|
141
128
|
@albums << album
|
142
129
|
end
|
143
130
|
|
144
|
-
Application.log(self, "
|
131
|
+
Application.log(self, "#{src} #{@albums.size} albums found")
|
145
132
|
rescue
|
146
133
|
Application.log(self, src, $!)
|
147
134
|
end
|
data/lib/ektoplayer/common.rb
CHANGED
@@ -1,63 +1,9 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'open3'
|
3
3
|
|
4
|
-
class ConditionSignals
|
5
|
-
def initialize
|
6
|
-
@mutex, @cond = Mutex.new, ConditionVariable.new
|
7
|
-
@curr_signal = nil
|
8
|
-
@signal_hooks = {}
|
9
|
-
|
10
|
-
Thread.new do
|
11
|
-
@mutex.synchronize do
|
12
|
-
loop do
|
13
|
-
@cond.wait(@mutex)
|
14
|
-
|
15
|
-
if @signal_hooks.key? @curr_signal
|
16
|
-
@signal_hooks[@curr_signal].()
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def wait(name, timeout=nil)
|
24
|
-
@mutex.synchronize do
|
25
|
-
loop do
|
26
|
-
@cond.wait(@mutex, timeout)
|
27
|
-
return if @curr_signal == name
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def signal(name)
|
33
|
-
@curr_signal = name
|
34
|
-
@cond.broadcast
|
35
|
-
end
|
36
|
-
|
37
|
-
def on(name, &block)
|
38
|
-
@signal_hooks[name] = block
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
4
|
class Dir
|
43
5
|
def Dir.size(path)
|
44
|
-
Dir.glob(File.join(path, '**', ?*)).map
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
class String
|
49
|
-
def chunks(n)
|
50
|
-
return [self] if n < 1
|
51
|
-
|
52
|
-
if (chunk_size = self.size / n) < 1
|
53
|
-
return [self]
|
54
|
-
end
|
55
|
-
|
56
|
-
(n - 1).times.map do |i|
|
57
|
-
self.slice((chunk_size * i)..(chunk_size * (i + 1) - 1))
|
58
|
-
end + [
|
59
|
-
self.slice((chunk_size * (n-1))..-1)
|
60
|
-
]
|
6
|
+
Dir.glob(File.join(path, '**', ?*)).map(&File.method(:size)).sum
|
61
7
|
end
|
62
8
|
end
|
63
9
|
|
@@ -81,28 +27,27 @@ module Common
|
|
81
27
|
end
|
82
28
|
|
83
29
|
def self.extract_zip(zip_file, dest)
|
30
|
+
absolute_path = File.absolute_path(zip_file)
|
31
|
+
# try 'unzip'
|
32
|
+
out, err, status = Open3.capture3('unzip', absolute_path, chdir: dest)
|
33
|
+
fail err unless status.exitstatus == 0
|
34
|
+
rescue Errno::ENOENT
|
35
|
+
# try '7zip'
|
36
|
+
out, err, status = Open3.capture3('7z', ?x, absolute_path, chdir: dest)
|
37
|
+
fail err unless status.exitstatus == 0
|
38
|
+
rescue Errno::ENOENT
|
84
39
|
# try RubyZip gem
|
85
40
|
require 'zip'
|
86
41
|
|
87
|
-
Zip::File.open(
|
42
|
+
Zip::File.open(absolute_path) do |zip_obj|
|
88
43
|
zip_obj.each do |f|
|
89
44
|
f.extract(File.join(dest, f.name))
|
90
45
|
end
|
91
46
|
end
|
92
47
|
rescue LoadError
|
93
|
-
# try 'unzip'
|
94
|
-
out, err, status = Open3.capture3('unzip', ?x, zip_file, chdir: dest)
|
95
|
-
fail err unless status.exitcode == 0
|
96
|
-
rescue Error::ENOENT
|
97
|
-
# try '7zip'
|
98
|
-
out, err, status = Open3.capture3('7z', ?x, zip_file, chdir: dest)
|
99
|
-
fail err unless status.exitcode == 0
|
100
|
-
rescue Error::ENOENT
|
101
48
|
fail 'neither RubzZip gem nor /bin/unzip or /bin/7z found'
|
102
49
|
rescue
|
103
|
-
|
104
|
-
Ektoplayer::Application.log(self, "error extracting zip", zip, dest, $!)
|
105
|
-
fail $!
|
50
|
+
Ektoplayer::Application.log(self, "error extracting zip", zip_file, dest, $!)
|
106
51
|
end
|
107
52
|
|
108
53
|
def self.with_hash_zip(keys, values)
|
data/lib/ektoplayer/compat.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
unless Array.respond_to? :sum
|
2
2
|
class Array
|
3
|
-
def sum
|
4
|
-
|
5
|
-
self.each { |i| result += i }
|
6
|
-
result
|
3
|
+
def sum
|
4
|
+
reduce(:+)
|
7
5
|
end
|
8
6
|
end
|
9
7
|
end
|
@@ -11,13 +9,9 @@ end
|
|
11
9
|
unless Integer.respond_to? :clamp
|
12
10
|
class Integer
|
13
11
|
def clamp(min, max)
|
14
|
-
if self < min
|
15
|
-
|
16
|
-
|
17
|
-
max
|
18
|
-
else
|
19
|
-
self
|
20
|
-
end
|
12
|
+
return min if self < min
|
13
|
+
return max if self > max
|
14
|
+
self
|
21
15
|
end
|
22
16
|
end
|
23
17
|
end
|