rumu 0.3.1 → 0.4.0

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 +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"