rumu 0.3.1 → 0.4.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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rumu +69 -29
  3. metadata +19 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: caa90367efb46acc18ef760c9c8aaa7b419c76647e5363b298820e75f6470c5e
4
- data.tar.gz: 8a2f3f3bf5538bdba349ddfbc87976305bbf5dc0f5c8c2f4804f2a1c24dd0c87
3
+ metadata.gz: a1965b7e8026eb72e0cfd4c9f4b74523adf96c2d64a30508df01283a51f6ef80
4
+ data.tar.gz: 287bb2634da8ce13cf4d1380ac29561b4f747bafdd8c79b69c05acbdc3910907
5
5
  SHA512:
6
- metadata.gz: c7d7101a7a9d234e418c973b20790291eb719199bea093255c6c5c09da3e11520c5806c293c513caaa574c73edd5c79a29c4aec4f907191146b6c857c3588df0
7
- data.tar.gz: d1d6370be84e12e1b693eabb6381ac4e2497a46fd56bd694c5366a2fb5083a4e4e1c09adb706c75a7fc445d9849071f530d8cfe471f4169df3ee41178eb05313
6
+ metadata.gz: 2139d62a2b4eac691d693a2092b9fb4721382fe10295f811b6a98d25a7852005567641974e50c52c06f5f3a79ab95d40c5dd678cb26579bd41a40f02b585e909
7
+ data.tar.gz: 94a7861eebfc123955fa8315ac111fc44b2c85945127d62cfef552bfd733ff4c2f28e448f2bb5690002deb28cfda0c3cc4b41032ec8317974b87a23eae7c592e
data/bin/rumu CHANGED
@@ -3,26 +3,60 @@ require 'open3'
3
3
  require 'shellwords'
4
4
  require 'io/console'
5
5
  require 'pathname'
6
+ require 'ffi'
7
+ require 'pulseaudio_simple_ffi'
6
8
 
7
9
  pkg='rumu'
8
- ver='0.3.1'
9
- pkgd="#{Dir.home}/.config/#{pkg}"
10
+ ver='0.4.0'
11
+ ConfigDir="#{Dir.home}/.config/#{pkg}"
12
+ Dir.mkdir(ConfigDir) unless File.directory?(ConfigDir)
10
13
 
11
- word=4
12
- rate=44100
13
- chan=2
14
- ff_fmt="-ac #{chan} -ar #{rate} -f f#{word*8}le"
14
+ Channels,Rate,WordSize=2,44100,4
15
+ FfmpegFmt="-ac #{Channels} -ar #{Rate} -f f#{WordSize*8}le"
15
16
 
16
- cycle=0
17
- list=[]
18
- list_i=0
19
- mode=:load
20
- ssoff=''
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
30
+ end
31
+
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
52
+ end
53
+
54
+ list,list_i,cycle,mode,ssoff,help=[],0,0,:load,'',''
21
55
  if ARGV.length==0
22
- if File.file?("#{pkgd}/list")
23
- list=File.read("#{pkgd}/list").split("\n")
24
- if File.file?("#{pkgd}/pos")
25
- pos=File.read("#{pkgd}/pos").split("\n")
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")
26
60
  list_i=pos[0].to_i
27
61
  cycle=pos[1].to_i
28
62
  cycle-=3 if cycle>3
@@ -36,10 +70,10 @@ else
36
70
  list=ARGV.map{|x|Pathname(x).realpath.to_s}
37
71
  end
38
72
  prefix=/\A(.*).*(\n\1.*)*\Z/.match(list.join("\n"))[1]
73
+ puts prefix
39
74
 
40
75
  ii,io,ie,it=nil,nil,nil,nil
41
- oi,oo,oe,ot=Open3.popen3("ffmpeg #{ff_fmt} -i - -f pulse default")
42
- oo.close
76
+ oo=ConfigO.new
43
77
 
44
78
  pt=Thread.new{
45
79
  until :quit == mode
@@ -50,44 +84,50 @@ pt=Thread.new{
50
84
  case mode
51
85
  when :load #load new track
52
86
  [io,ie].each{|x|x.close} unless !io or io.closed?
53
- ii,io,ie,it = Open3.popen3 "ffmpeg -i #{Shellwords.escape(list[list_i])} #{ssoff} #{ff_fmt} -"
54
- puts "\r#{list[list_i][prefix.length..-1]}"
87
+ ii,io,ie,it = Open3.popen3 "ffmpeg -loglevel -8 -i #{Shellwords.escape(list[list_i])} #{ssoff} #{FfmpegFmt} -"
55
88
  ii.close
56
89
  cycle=0 unless ssoff.length > 0
90
+ puts "#{' '*help.length}\r#{list[list_i][prefix.length..-1]}"
57
91
  ssoff=''
92
+ help=''
58
93
  mode=:play
59
94
  when :play
60
- oi.write(io.read(word*chan*rate))
95
+ oo.write(io.read(Channels*Rate*WordSize))
61
96
  cycle+=1
62
97
  end
63
98
  end
99
+ oo.close
64
100
  }
65
101
 
66
102
  until :quit == mode
67
103
  print "\r#{cycle/60}:#{"%02d"%(cycle%60)} > "
68
- case ch=IO.console.raw{|c|c.read_nonblock(1) rescue ''}
104
+ case ch=IO.console.raw{|c|c.read_nonblock(1) rescue ''}.downcase
69
105
  when 'n'
70
106
  list_i+=1
71
107
  mode= list_i<list.count ? :load : :quit
108
+ when 'r'
109
+ mode=:load
72
110
  when 'p'
73
111
  if list_i>0
74
112
  list_i-=1
75
113
  mode=:load
76
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
77
121
  when 'q'
78
122
  mode=:quit
123
+ File.write(ConfigDir+"/list",list.join("\n"))
124
+ File.write(ConfigDir+"/pos",list_i.to_s+"\n"+cycle.to_s)
79
125
  when ''
80
126
  sleep rand
81
127
  else
82
- print "#{ch} < [N]ext #{list_i>0?"[P]rev ":""}[Q]uit"
128
+ print (help="#{ch} < #{list_i>0?"[P]rev ":""}[R]estart [S]eek [N]ext [Q]uit")
83
129
  end
84
130
  end
85
131
 
86
- if list_i<list.count
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
- end
91
-
92
- puts "\r ] #{pkg} ✝ v#{ver} [ "
132
+ puts "\r ] #{pkg} ✝ v#{ver} [ "
93
133
  pt.join
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rumu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
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-02 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.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.1
13
27
  description: rumu is an aggressively minimized audio player that plays a playlist
14
28
  gaplessly leveraging command-line ffmpeg and pipes. After a quit, it will return
15
29
  to where it left off when run next.
@@ -31,7 +45,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
31
45
  requirements:
32
46
  - - ">="
33
47
  - !ruby/object:Gem::Version
34
- version: '2.7'
48
+ version: '3.0'
35
49
  required_rubygems_version: !ruby/object:Gem::Requirement
36
50
  requirements:
37
51
  - - ">="
@@ -39,7 +53,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
39
53
  version: '0'
40
54
  requirements:
41
55
  - ffmpeg
42
- rubygems_version: 3.2.13
56
+ rubygems_version: 3.2.15
43
57
  signing_key:
44
58
  specification_version: 4
45
59
  summary: "(ru)by (mu)usic - a minimal ffmpeg-based gapless audio playlist player"