rumu 0.4.0 → 0.4.2

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