rumu 0.3.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rumu +121 -75
  3. metadata +25 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b10238932023ff15c41d24d35b464e641ab0296e3585b7b0810dfa2236af0667
4
- data.tar.gz: 4ca176a03fff38fb7ba458451cf55501dc54815521091678886faab1c853ebfc
3
+ metadata.gz: d4eb3a0747c545c987b03ae0bd8117cfb613f5b30ee9ced1e80105b7dd8f9ef1
4
+ data.tar.gz: 06a8c5ca36e3003a558f0336220f09e3fc6451d234ba10d9a233a6e010920733
5
5
  SHA512:
6
- metadata.gz: aaae6228959f26c275844f2082b67f95c49a312a867e6d1f3e4c6a5a8faa065b0e79631792b80462a4311910c8d3264c3fd7383749041a13689ba8937a497f88
7
- data.tar.gz: 72671d72da7b9572091257497f8a26132d8cf1ef1fba6e42a271302c1b505735ead974a7b31a2e88f93f04c76eba499bd6c2b26742c1730fb9fcb3fac3a33b3a
6
+ metadata.gz: dec6313820cd82b3c62b3be05678d57dc5ba514e212e0962f3186bd010c431b7e251ea19989f8efe64050214f2c1442b4d9893476b6ce7d740286df19ff9e688
7
+ data.tar.gz: 6c59f26842bf443479e56ddf020d3410cdfa8a90262f5b1ecbd15d04bceffe334b657b92981189c13b70293b148b2aa28b7a2566fa0311a089496811e2fd1da6
data/bin/rumu CHANGED
@@ -3,96 +3,142 @@ require 'open3'
3
3
  require 'shellwords'
4
4
  require 'io/console'
5
5
  require 'pathname'
6
+ require 'pulseaudio_simple_ffi'
6
7
 
7
- pkg='rumu'
8
- ver='0.3.2'
9
- pkgd="#{Dir.home}/.config/#{pkg}"
8
+ Pkg='rumu'
9
+ Ver='0.4.1'
10
+ ConfigDir="#{Dir.home}/.config/#{Pkg}"
11
+ Dir.mkdir(ConfigDir) unless File.directory?(ConfigDir)
10
12
 
11
- chan,rate,word=2,44100,4
12
- ff_fmt="-ac #{chan} -ar #{rate} -f f#{word*8}le"
13
+ Channels,Rate,WordSize=2,44100,4
14
+ FfmpegFmt="-ac #{Channels} -ar #{Rate} -f f#{WordSize*8}le"
13
15
 
14
- File.write(pkgd+"/dev","-f pulse default") unless File.file?("#{pkgd}/dev")
15
- ff_out=File.read(pkgd+"/dev")
16
+ class FfmpegPipeO
17
+ def initialize(device, channels: Channels, rate: Rate, wordsize: WordSize )
18
+ device = device.to_s.chomp.length>0 ? device.to_s.chomp : '-f pulse default'
19
+ @in,@out,@err,@thr = Open3.popen3("ffmpeg -loglevel -8 #{FfmpegFmt} -i - #{device}")
20
+ @out.close
21
+ @err.close
22
+ end
23
+ def write buf
24
+ @in.write buf
25
+ end
26
+ def close
27
+ @in.close
28
+ end
29
+ end
30
+
31
+ class ConfigO
32
+ def initialize file: ConfigDir+'/out'
33
+ @mode=:pulse
34
+ @device=nil
35
+ if File.file?(file)
36
+ cfg=File.read(file).split("\n")
37
+ @mode=cfg[0].to_sym
38
+ @device=cfg[1].to_s.chomp.length>0 ? cfg[1] : nil
39
+ end
40
+ File.write(file,@mode.to_s+"\n"+@device.to_s)
41
+ @out= :ffmpeg == @mode ?
42
+ FfmpegPipeO.new(@device) :
43
+ PulseAudioSimpleFFI::PulseAudioSimpleO.new(Pkg,'Music Playlist',channels:Channels,rate:Rate,device:@device)
44
+ end
45
+ def write buf
46
+ @out.write buf
47
+ end
48
+ def close
49
+ @out.close
50
+ end
51
+ end
16
52
 
17
53
  list,list_i,cycle,mode,ssoff,help=[],0,0,:load,'',''
18
54
  if ARGV.length==0
19
- if File.file?("#{pkgd}/list")
20
- list=File.read("#{pkgd}/list").split("\n")
21
- if File.file?("#{pkgd}/pos")
22
- pos=File.read("#{pkgd}/pos").split("\n")
23
- list_i=pos[0].to_i
24
- cycle=pos[1].to_i
25
- cycle-=3 if cycle>3
26
- ssoff="-ss #{cycle} " if cycle>0
27
- end
28
- else
29
- puts "Usage: #{pkg} files_to_play"
30
- exit 1
31
- end
55
+ if File.file?("#{ConfigDir}/list")
56
+ list=File.read("#{ConfigDir}/list").split("\n")
57
+ if File.file?("#{ConfigDir}/pos")
58
+ pos=File.read("#{ConfigDir}/pos").split("\n")
59
+ list_i=pos[0].to_i
60
+ cycle=pos[1].to_i
61
+ cycle-=3 if cycle>3
62
+ ssoff="-ss #{cycle} " if cycle>0
63
+ end
64
+ else
65
+ puts "Usage: #{Pkg} files_to_play"
66
+ exit 1
67
+ end
32
68
  else
33
- list=ARGV.map{|x|Pathname(x).realpath.to_s}
69
+ list=ARGV.map{|x|Pathname(x).realpath.to_s}
34
70
  end
35
71
  prefix=/\A(.*).*(\n\1.*)*\Z/.match(list.join("\n"))[1]
36
72
  puts prefix
37
73
 
38
74
  ii,io,ie,it=nil,nil,nil,nil
39
- oi,oo,oe,ot=Open3.popen3("ffmpeg #{ff_fmt} -i - #{ff_out}")
40
- oo.close
75
+ oo=ConfigO.new
76
+
77
+ bq=SizedQueue.new 4
78
+
79
+ iit=Thread.new {
80
+ until :quit == mode
81
+ if io and io.eof?
82
+ list_i+=1
83
+ mode=list_i>=list.count ? :quit : :load
84
+ end
85
+ if :load == mode
86
+ [io,ie].each{|x|x.close} unless !io or io.closed?
87
+ ii,io,ie,it = Open3.popen3 "ffmpeg -loglevel -8 -i #{Shellwords.escape(list[list_i])} #{ssoff} #{FfmpegFmt} -"
88
+ ii.close
89
+ cycle=0 unless ssoff.length > 0
90
+ puts "#{' '*help.length}\r#{list[list_i][prefix.length..-1]}"
91
+ ssoff=''
92
+ help=''
93
+ mode=:play
94
+ end
95
+ bq.push io.read(Channels*Rate*WordSize)
96
+ end
97
+ io.close
98
+ }
41
99
 
42
- pt=Thread.new{
43
- until :quit == mode
44
- if io and io.eof?
45
- list_i+=1
46
- mode=list_i>=list.count ? :quit : :load
47
- end
48
- case mode
49
- when :load #load new track
50
- [io,ie].each{|x|x.close} unless !io or io.closed?
51
- ii,io,ie,it = Open3.popen3 "ffmpeg -i #{Shellwords.escape(list[list_i])} #{ssoff} #{ff_fmt} -"
52
- print ' '*help.length
53
- help=''
54
- puts "\r#{list[list_i][prefix.length..-1]}"
55
- ii.close
56
- cycle=0 unless ssoff.length > 0
57
- ssoff=''
58
- mode=:play
59
- when :play
60
- oi.write(io.read(word*chan*rate))
61
- cycle+=1
62
- end
63
- end
100
+ oot=Thread.new{
101
+ until :quit == mode
102
+ if :play == mode
103
+ oo.write bq.pop
104
+ cycle+=1
105
+ else
106
+ sleep rand
107
+ end
108
+ end
109
+ oo.close
64
110
  }
65
111
 
66
112
  until :quit == mode
67
- print "\r#{cycle/60}:#{"%02d"%(cycle%60)} > "
68
- case ch=IO.console.raw{|c|c.read_nonblock(1) rescue ''}.downcase
69
- when 'n'
70
- list_i+=1
71
- mode= list_i<list.count ? :load : :quit
72
- when 'r'
73
- mode=:load
74
- when 'p'
75
- if list_i>0
76
- list_i-=1
77
- mode=:load
78
- end
79
- when 's'
80
- print "Seek to: "
81
- ti=(ts=IO.console.readline.chomp).split(':')
82
- ssoff="-ss #{ts}"
83
- cycle=(ti[-1].to_f + ti[-2].to_f*60 + ti[-3].to_f*60*60).to_i
84
- mode=:load
85
- when 'q'
86
- mode=:quit
87
- Dir.mkdir(pkgd) unless File.directory?(pkgd)
88
- File.write(pkgd+"/list",list.join("\n"))
89
- File.write(pkgd+"/pos",list_i.to_s+"\n"+cycle.to_s)
90
- when ''
91
- sleep rand
92
- else
93
- print (help="#{ch} < #{list_i>0?"[P]rev ":""}[R]estart [S]eek [N]ext [Q]uit")
94
- end
113
+ print "\r#{cycle/60}:#{"%02d"%(cycle%60)} > "
114
+ case ch=IO.console.raw{|c|c.read_nonblock(1) rescue ''}.downcase
115
+ when 'n'
116
+ list_i+=1
117
+ mode= list_i<list.count ? :load : :quit
118
+ when 'r'
119
+ mode=:load
120
+ when 'p'
121
+ if list_i>0
122
+ list_i-=1
123
+ mode=:load
124
+ end
125
+ when 's'
126
+ print "Seek to: "
127
+ ti=(ts=IO.console.readline.chomp).split(':')
128
+ ssoff="-ss #{ts}"
129
+ cycle=(ti[-1].to_f + ti[-2].to_f*60 + ti[-3].to_f*60*60).to_i
130
+ mode=:load
131
+ when 'q'
132
+ mode=:quit
133
+ File.write(ConfigDir+"/list",list.join("\n"))
134
+ File.write(ConfigDir+"/pos",list_i.to_s+"\n"+cycle.to_s)
135
+ when ''
136
+ sleep rand
137
+ else
138
+ print (help="#{ch} < #{list_i>0?"[P]rev ":""}[R]estart [S]eek [N]ext [Q]uit")
139
+ end
95
140
  end
96
141
 
97
- puts "\r ] #{pkg} ✝ v#{ver} [ "
98
- pt.join
142
+ puts "\r ] #{Pkg} ✝ v#{Ver} [ "
143
+ iit.join
144
+ oot.join
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rumu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin Cook
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-27 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-04-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pulseaudio_simple_ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.1
13
33
  description: rumu is an aggressively minimized audio player that plays a playlist
14
34
  gaplessly leveraging command-line ffmpeg and pipes. After a quit, it will return
15
35
  to where it left off when run next.
@@ -31,7 +51,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
31
51
  requirements:
32
52
  - - ">="
33
53
  - !ruby/object:Gem::Version
34
- version: '2.7'
54
+ version: '3.0'
35
55
  required_rubygems_version: !ruby/object:Gem::Requirement
36
56
  requirements:
37
57
  - - ">="
@@ -39,7 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
39
59
  version: '0'
40
60
  requirements:
41
61
  - ffmpeg
42
- rubygems_version: 3.2.13
62
+ rubygems_version: 3.2.15
43
63
  signing_key:
44
64
  specification_version: 4
45
65
  summary: "(ru)by (mu)usic - a minimal ffmpeg-based gapless audio playlist player"