rumu 0.3.2 → 0.4.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.
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"