aniview 3.2.1 → 5.1.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.
- checksums.yaml +4 -4
- data/README.md +8 -9
- data/bin/aniview +17 -9
- data/config/view.yml +3 -0
- data/lib/aniview.rb +1 -60
- data/modules/animeio/README.md +2 -0
- data/modules/animeio/config/daemon.yml +4 -0
- data/modules/animeio/config/view.yml +22 -0
- data/modules/animeio/lib/animeio.rb +24 -0
- data/modules/animeio/lib/animeio/anime_indexer.rb +99 -0
- data/modules/animeio/lib/animeio/animefile.rb +91 -0
- data/modules/animeio/lib/animeio/animeio.rb +175 -0
- data/modules/animeio/lib/animeio/animeio_view.rb +41 -0
- data/modules/animeio/lib/animeio/animeseries.rb +61 -0
- data/modules/mpv/README.md +2 -0
- data/modules/mpv/config/daemon.yml +2 -0
- data/modules/mpv/lib/mpv.rb +27 -0
- data/modules/mpv/lib/mpv/filename_widget.rb +16 -0
- data/modules/mpv/lib/mpv/mpv_controller.rb +85 -0
- data/modules/mpv/lib/mpv/time_widget.rb +29 -0
- metadata +33 -107
- data/lib/aniview/client/aniclient.rb +0 -118
- data/lib/aniview/interface/animeio/animefile.rb +0 -93
- data/lib/aniview/interface/animeio/animeio.rb +0 -321
- data/lib/aniview/interface/animeio/animeseries.rb +0 -60
- data/lib/aniview/interface/bridge.rb +0 -11
- data/lib/aniview/interface/deluge/delugec.rb +0 -172
- data/lib/aniview/interface/deluge/torrentitem.rb +0 -24
- data/lib/aniview/interface/item.rb +0 -24
- data/lib/aniview/interface/mpv/mpvbridge.rb +0 -149
- data/lib/aniview/interface/pref/defaults.json +0 -105
- data/lib/aniview/interface/pref/pref.rb +0 -209
- data/lib/aniview/interface/pref/prefitem.rb +0 -19
- data/lib/aniview/interface/pref/validate.json +0 -105
- data/lib/aniview/interface/schedule/schedule.rb +0 -99
- data/lib/aniview/interface/schedule/scheduleitem.rb +0 -59
- data/lib/aniview/interface/subscription/subscription.rb +0 -123
- data/lib/aniview/util/error.rb +0 -9
- data/lib/aniview/util/folder_listen.rb +0 -53
- data/lib/aniview/util/term.rb +0 -44
- data/lib/aniview/util/util.rb +0 -167
- data/lib/aniview/view/aiomenu.rb +0 -69
- data/lib/aniview/view/color.rb +0 -69
- data/lib/aniview/view/delugemenu.rb +0 -38
- data/lib/aniview/view/menu.rb +0 -325
- data/lib/aniview/view/prefmenu.rb +0 -26
- data/lib/aniview/view/schedulemenu.rb +0 -28
- data/lib/aniview/view/statusline.rb +0 -60
- data/lib/aniview/view/subscriptionmenu.rb +0 -37
- data/lib/application.rb +0 -306
- data/lib/daemon.rb +0 -188
@@ -1,118 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
require_relative '../util/util'
|
3
|
-
|
4
|
-
|
5
|
-
module Aniview
|
6
|
-
module Client
|
7
|
-
class AniClient
|
8
|
-
include Aniview::Util
|
9
|
-
|
10
|
-
# initializes a new AniClient @
|
11
|
-
#
|
12
|
-
# @param pref see preferences
|
13
|
-
#
|
14
|
-
# @return nil
|
15
|
-
#
|
16
|
-
def initialize(pref)
|
17
|
-
@pref = pref
|
18
|
-
end
|
19
|
-
|
20
|
-
# connects to aniview daemon
|
21
|
-
#
|
22
|
-
# @return [TCPSocket, false] false if unsuccessful
|
23
|
-
#
|
24
|
-
def connect
|
25
|
-
begin
|
26
|
-
TCPSocket.new 'localhost', @pref.get("daemon")["port"]
|
27
|
-
rescue Errno::ECONNREFUSED
|
28
|
-
return false
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# sends message to aniview daemon
|
33
|
-
#
|
34
|
-
# @param msg the message to send
|
35
|
-
#
|
36
|
-
# @return the daemons response, or "" if there is an error. If the
|
37
|
-
# daemon is offline, "offline" is returned
|
38
|
-
#
|
39
|
-
def sendMsg msg
|
40
|
-
begin
|
41
|
-
s = connect
|
42
|
-
return "offline" if s == false
|
43
|
-
s.puts msg
|
44
|
-
r = s.gets.chomp
|
45
|
-
s.close
|
46
|
-
return r
|
47
|
-
rescue Errno::ECONNRESET
|
48
|
-
return ""
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# sends the message "quit" to the daemon
|
53
|
-
#
|
54
|
-
# see #sendMsg
|
55
|
-
#
|
56
|
-
# @return "okay"
|
57
|
-
#
|
58
|
-
def stopDaemon
|
59
|
-
sendMsg "quit"
|
60
|
-
end
|
61
|
-
|
62
|
-
# sends the message "info" to the daemon
|
63
|
-
#
|
64
|
-
# see #sendMsg
|
65
|
-
#
|
66
|
-
# @return daemon info string including uptime and number of loops and
|
67
|
-
# matches
|
68
|
-
#
|
69
|
-
def info
|
70
|
-
sendMsg "info"
|
71
|
-
end
|
72
|
-
|
73
|
-
# sends the message "lastchecked" to the daemon
|
74
|
-
#
|
75
|
-
# see #sendMsg
|
76
|
-
#
|
77
|
-
# @return string of the last time the daemon checked the rss feed for
|
78
|
-
# new matches
|
79
|
-
#
|
80
|
-
def lastchecked
|
81
|
-
sendMsg "lastchecked"
|
82
|
-
end
|
83
|
-
|
84
|
-
# sends the message "items" to the daemon and decodes the serialized
|
85
|
-
# object using Util.decode_object
|
86
|
-
#
|
87
|
-
# see #sendMsg
|
88
|
-
#
|
89
|
-
# @return The items.
|
90
|
-
#
|
91
|
-
def getItems
|
92
|
-
Util.decode_object(sendMsg "items")
|
93
|
-
end
|
94
|
-
|
95
|
-
# sends the message "itemshash" to the daemon
|
96
|
-
#
|
97
|
-
# see #sendMsg
|
98
|
-
#
|
99
|
-
# @return item.cereal of all items
|
100
|
-
#
|
101
|
-
def getAllCereal
|
102
|
-
sendMsg "itemshash"
|
103
|
-
end
|
104
|
-
|
105
|
-
# checks if the server is online (sends message "up?" to the daemon)
|
106
|
-
#
|
107
|
-
# see #sendMsg
|
108
|
-
#
|
109
|
-
# @return [true, false]
|
110
|
-
#
|
111
|
-
def server?
|
112
|
-
return false unless sendMsg("up?") == "true"
|
113
|
-
return true
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
@@ -1,93 +0,0 @@
|
|
1
|
-
require 'streamio-ffmpeg'
|
2
|
-
require 'date'
|
3
|
-
|
4
|
-
require_relative '../../util/util'
|
5
|
-
require_relative '../item'
|
6
|
-
|
7
|
-
module Aniview
|
8
|
-
module Interface
|
9
|
-
class AnimeFile < Item
|
10
|
-
|
11
|
-
include Aniview::Util
|
12
|
-
|
13
|
-
attr_accessor :last_modified
|
14
|
-
attr_accessor :accessible
|
15
|
-
attr_accessor :path
|
16
|
-
|
17
|
-
def initialize(path_, seen: false, watched_on: 0)
|
18
|
-
@watched = seen
|
19
|
-
@accessible = true
|
20
|
-
begin
|
21
|
-
@last_modified = File::Stat.new(path_).mtime
|
22
|
-
rescue Errno::ENOENT
|
23
|
-
@last_modified = "0"
|
24
|
-
end
|
25
|
-
@watched_on = watched_on
|
26
|
-
@path = path_
|
27
|
-
|
28
|
-
@attr = {
|
29
|
-
"t" => "empty",
|
30
|
-
"d" => 0,
|
31
|
-
"D" => "0",
|
32
|
-
"s" => 0,
|
33
|
-
"S" => "0",
|
34
|
-
"r" => 0x0,
|
35
|
-
"a" => "n.a.",
|
36
|
-
"v" => "",
|
37
|
-
"l" => "",
|
38
|
-
"f" => "",
|
39
|
-
"b" => "",
|
40
|
-
"w" => seen? ? "x" : " "
|
41
|
-
}
|
42
|
-
|
43
|
-
if (@path == "empty")
|
44
|
-
else
|
45
|
-
mov = FFMPEG::Movie.new(@path)
|
46
|
-
|
47
|
-
@attr = {
|
48
|
-
"t" => self.string,
|
49
|
-
"d" => mov.duration,
|
50
|
-
"D" => Util.format_duration(mov.duration),
|
51
|
-
"s" => mov.size,
|
52
|
-
"S" => Util.format_size(mov.size),
|
53
|
-
"r" => mov.resolution,
|
54
|
-
"a" => mov.audio_codec,
|
55
|
-
"v" => mov.video_codec,
|
56
|
-
"l" => mov.colorspace,
|
57
|
-
"f" => mov.frame_rate,
|
58
|
-
"b" => String(mov.bitrate) + "kb/s",
|
59
|
-
"w" => seen? ? "x" : " "
|
60
|
-
}
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def title
|
65
|
-
return @attr["t"]
|
66
|
-
end
|
67
|
-
|
68
|
-
def seen?
|
69
|
-
return @watched
|
70
|
-
end
|
71
|
-
|
72
|
-
def seenOn
|
73
|
-
return @watched_on
|
74
|
-
end
|
75
|
-
|
76
|
-
def watch
|
77
|
-
@watched = true
|
78
|
-
@watched_on = DateTime.now.strftime('%Q')
|
79
|
-
@attr["w"] = "x"
|
80
|
-
end
|
81
|
-
|
82
|
-
def unwatch
|
83
|
-
@watched = false
|
84
|
-
@attr["w"] = " "
|
85
|
-
end
|
86
|
-
|
87
|
-
def string
|
88
|
-
return (File.basename("#{@path}").gsub(/\s*\[.+?\]\s*/) {}).gsub(/(\.mkv)|(\.avi)|(\.mp4)/, "").gsub("_", " ").gsub(/\s*\(.+?\)\s*/) {}
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
@@ -1,321 +0,0 @@
|
|
1
|
-
require 'mkmf'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'observer'
|
4
|
-
require 'listen'
|
5
|
-
require 'benchmark'
|
6
|
-
|
7
|
-
require_relative 'animefile'
|
8
|
-
require_relative 'animeseries'
|
9
|
-
require_relative '../../util/util'
|
10
|
-
require_relative '../../util/folder_listen'
|
11
|
-
require_relative '../bridge'
|
12
|
-
|
13
|
-
module Aniview
|
14
|
-
module Interface
|
15
|
-
|
16
|
-
class AnimeIO < Bridge
|
17
|
-
|
18
|
-
include Aniview::Util
|
19
|
-
|
20
|
-
include Observable
|
21
|
-
|
22
|
-
def initialize(pref, mpvbridge)
|
23
|
-
@pref = pref
|
24
|
-
@mpvbridge = mpvbridge
|
25
|
-
@empty_hash = make_empty_hash
|
26
|
-
@watch_log_tag = "♪"
|
27
|
-
@dir_last_modified = {}
|
28
|
-
@made_changes = true
|
29
|
-
|
30
|
-
self.load
|
31
|
-
pref_changed!(verbose: false)
|
32
|
-
#relisten
|
33
|
-
|
34
|
-
@pref.add_observer(self, :pref_changed!)
|
35
|
-
@mpvbridge.add_observer(self, :animefile_changed!)
|
36
|
-
#@@local_anime.each { |key, obj| obj.add_observer(self, :animefile_changed!)}
|
37
|
-
end
|
38
|
-
|
39
|
-
def listen_to_all_dirs
|
40
|
-
#listen to all
|
41
|
-
all_dirs = (@pref.get("anime_locations").split(":")).map { |dir| @pref.parseDir(dir) }
|
42
|
-
@folder_listener = FolderListen.to(all_dirs) { index_anime }
|
43
|
-
@folder_listener.start
|
44
|
-
end
|
45
|
-
|
46
|
-
def relisten
|
47
|
-
cleanup
|
48
|
-
|
49
|
-
listen_to_all_dirs
|
50
|
-
|
51
|
-
return if @anime_dirs == nil or @anime_dirs[0] == "" or @anime_dirs.length == 0
|
52
|
-
|
53
|
-
@listener = Listen.to(*@anime_dirs, only: /\.mkv$/) { index_anime }
|
54
|
-
@listener.start
|
55
|
-
end
|
56
|
-
|
57
|
-
def cleanup
|
58
|
-
@folder_listener.stop unless @folder_listener == nil
|
59
|
-
@listener.stop unless @listener == nil
|
60
|
-
end
|
61
|
-
|
62
|
-
def make_empty_hash
|
63
|
-
af = AnimeFile.new("empty")
|
64
|
-
{AnimeSeries.new("empty", [af]) => [af]}
|
65
|
-
end
|
66
|
-
|
67
|
-
def save
|
68
|
-
@pref.set "local_anime", Util.encode_object(@@local_anime)
|
69
|
-
end
|
70
|
-
|
71
|
-
def load
|
72
|
-
raw = @pref.get "local_anime"
|
73
|
-
if not raw == nil and raw.class == String
|
74
|
-
@@local_anime = Util.decode_object raw
|
75
|
-
else
|
76
|
-
@@local_anime = {}
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def pref_changed!(verbose: true)
|
81
|
-
new_dirs = (@pref.get("anime_locations").split(":")).collect { |dir|
|
82
|
-
parsed_dir = @pref.parseDir(dir)
|
83
|
-
parsed_dir if File.exist?(parsed_dir)
|
84
|
-
}.compact
|
85
|
-
if new_dirs != @anime_dirs
|
86
|
-
@anime_dirs = new_dirs
|
87
|
-
index_anime(verbose: verbose)
|
88
|
-
relisten
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def animefile_changed!
|
93
|
-
return unless @mpvbridge.what_changed[:local_anime]
|
94
|
-
save
|
95
|
-
changed
|
96
|
-
notify_observers
|
97
|
-
end
|
98
|
-
|
99
|
-
##
|
100
|
-
## @brief Indexes anime files up to 1 level deep in specified anime directories
|
101
|
-
##
|
102
|
-
## @param force The force
|
103
|
-
## @param verbose The verbose
|
104
|
-
##
|
105
|
-
## @return { description_of_the_return_value }
|
106
|
-
##
|
107
|
-
def index_anime(force: false, verbose: true, very_verbose: false)
|
108
|
-
puts "Indexing anime" if very_verbose
|
109
|
-
Thread.new {
|
110
|
-
ret = {}
|
111
|
-
made_changes = false
|
112
|
-
lal = @@local_anime.length
|
113
|
-
|
114
|
-
@anime_dirs.each_with_index { |dir, i|
|
115
|
-
|
116
|
-
avs_file = dir + "/.avs"
|
117
|
-
|
118
|
-
if File.exist?(avs_file)
|
119
|
-
puts "found avs_data" if very_verbose
|
120
|
-
avs_data = JSON.parse(File.open(avs_file, "r") { |f| f.read })
|
121
|
-
else
|
122
|
-
puts "no avs_data" if very_verbose
|
123
|
-
avs_data = {}
|
124
|
-
end
|
125
|
-
|
126
|
-
|
127
|
-
# check if the directory exists
|
128
|
-
unless File.exist? dir
|
129
|
-
unless @dir_last_modified[dir] == "check"
|
130
|
-
@dir_last_modified[dir] = "check"
|
131
|
-
made_changes = true
|
132
|
-
end
|
133
|
-
next
|
134
|
-
end
|
135
|
-
|
136
|
-
puts "checking #{dir}" if very_verbose
|
137
|
-
|
138
|
-
# skip indexing a directory if it hasn't been modified since the last
|
139
|
-
# check (disabled because doesn't save to much time)
|
140
|
-
#
|
141
|
-
#dir_mtime = File::Stat.new(dir).mtime
|
142
|
-
#
|
143
|
-
#if @dir_last_modified.key? dir
|
144
|
-
# if @dir_last_modified[dir] == dir_mtime
|
145
|
-
# next
|
146
|
-
# else
|
147
|
-
# @dir_last_modified[dir] = dir_mtime
|
148
|
-
# end
|
149
|
-
#else
|
150
|
-
# @dir_last_modified.merge!(dir => dir_mtime)
|
151
|
-
#end
|
152
|
-
|
153
|
-
# get all files in the directory and in all subfolders of the directory
|
154
|
-
files = Dir.glob("#{dir}*/*.{mkv,avi,mp4}") + Dir.glob("#{dir}/*.{mkv,avi,mp4}")
|
155
|
-
|
156
|
-
files.each_with_index { |file, j|
|
157
|
-
if verbose
|
158
|
-
pct = Util.format_progress ((j + 1) / Float(files.length)) * ( (i + 1) / Float(@anime_dirs.length)) * 100
|
159
|
-
Util.error_message("#{pct}% #{File.basename(file)}")
|
160
|
-
end
|
161
|
-
|
162
|
-
print "indexing #{file} -> " if very_verbose
|
163
|
-
params = {:seen => false, :watched_on => 0}
|
164
|
-
|
165
|
-
#check if this anime has a stored watched value
|
166
|
-
if avs_data.key?(file)
|
167
|
-
puts "found stored data for this file" if very_verbose
|
168
|
-
params = {
|
169
|
-
:seen => avs_data[file]["seen"],
|
170
|
-
:watched_on => avs_data[file]["watched_on"]
|
171
|
-
}
|
172
|
-
puts params if very_verbose
|
173
|
-
else
|
174
|
-
puts "no data on this file" if very_verbose
|
175
|
-
avs_data.merge!({file => params})
|
176
|
-
end
|
177
|
-
|
178
|
-
# we have already indexed this file
|
179
|
-
if @@local_anime != nil and @@local_anime.key?(file)
|
180
|
-
|
181
|
-
puts "this file is in the index" if very_verbose
|
182
|
-
|
183
|
-
# get its seen data
|
184
|
-
params[:seen] = @@local_anime[file].seen?
|
185
|
-
params[:watched_on] = @@local_anime[file].seenOn
|
186
|
-
puts params if very_verbose
|
187
|
-
# get its last modifed data
|
188
|
-
last_modified = File::Stat.new(file).mtime
|
189
|
-
# get wether or not it is accessible
|
190
|
-
@@local_anime[file].accessible = true
|
191
|
-
|
192
|
-
# if we arent forcing or the anime hasn't been modified since the
|
193
|
-
# last check, skip it
|
194
|
-
if not force or last_modified == @@local_anime[file].last_modified
|
195
|
-
puts "unchanged" if very_verbose
|
196
|
-
ret.merge!(file => @@local_anime[file])
|
197
|
-
next
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
#puts "changed!"
|
202
|
-
|
203
|
-
# okay we are making changes to local_anime
|
204
|
-
made_changes = true
|
205
|
-
|
206
|
-
# this is the anime file we are adding
|
207
|
-
ret.merge!(
|
208
|
-
file => AnimeFile.new(file, params)
|
209
|
-
)
|
210
|
-
}
|
211
|
-
|
212
|
-
mavsf = @pref.get("avs_files")["create?"]
|
213
|
-
oimfs = @pref.get("avs_files")["only_on_mounted_fs?"]
|
214
|
-
if mavsf and ((oimfs and Util.mounted_filesystem?(dir)) or not oimfs)
|
215
|
-
File.open(avs_file, "w") { |f| f.puts JSON.generate(avs_data)}
|
216
|
-
end
|
217
|
-
}
|
218
|
-
|
219
|
-
#if @@local_anime != nil
|
220
|
-
# @@local_anime.merge!(ret)
|
221
|
-
#else
|
222
|
-
@@local_anime = ret
|
223
|
-
#end
|
224
|
-
|
225
|
-
#pruned = {}
|
226
|
-
#@@local_anime.each{ |a|
|
227
|
-
# pruned.merge!(a[0] => a[1]) if File.exist? a[1].path
|
228
|
-
#}
|
229
|
-
#@@local_anime = pruned
|
230
|
-
made_changes = true if @@local_anime.length != lal
|
231
|
-
if @made_changes
|
232
|
-
self.save
|
233
|
-
changed
|
234
|
-
notify_observers
|
235
|
-
end
|
236
|
-
#
|
237
|
-
}
|
238
|
-
end
|
239
|
-
|
240
|
-
#returns the parent directory of a file
|
241
|
-
def parent(file)
|
242
|
-
return File.basename(File.dirname(file))
|
243
|
-
end
|
244
|
-
|
245
|
-
#convert an AnimeFile array to a hash structured like
|
246
|
-
#(string)parent => (AnimeFile array)[child0, child1, child2] and return it
|
247
|
-
def makeHash arr
|
248
|
-
#return @empty_hash if arr[0] == nil
|
249
|
-
|
250
|
-
keys = {}
|
251
|
-
hash = {}
|
252
|
-
|
253
|
-
arr.sort_by {|i| i.title}.each { |file|
|
254
|
-
unless keys.key?(parent file.path)
|
255
|
-
key = AnimeSeries.new parent(file.path)
|
256
|
-
keys.merge! parent(file.path) => key
|
257
|
-
hash.merge! key => []
|
258
|
-
else
|
259
|
-
key = keys[parent file.path]
|
260
|
-
end
|
261
|
-
|
262
|
-
hash[key] << file
|
263
|
-
key << file
|
264
|
-
}
|
265
|
-
hash.sort_by{ |j| j[0].title }.to_h
|
266
|
-
end
|
267
|
-
|
268
|
-
#return the difference of getAired and getWatched
|
269
|
-
def unwatched
|
270
|
-
makeHash @@local_anime.reject { |f, a| a.seen? }.values
|
271
|
-
end
|
272
|
-
|
273
|
-
#return an AnimeFile array of all mkvs in any dir specified in $pref["dirs"]
|
274
|
-
def items
|
275
|
-
makeHash @@local_anime.values
|
276
|
-
end
|
277
|
-
|
278
|
-
def logWatched(file)
|
279
|
-
open(@pref.parseDir(@pref.get("watch_log")), 'a') do |f|
|
280
|
-
f.puts %x(date).chomp + " ./" + File.basename(file) + " " + @watch_log_tag
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
def addWatched(file)
|
285
|
-
@@local_anime[file].watch
|
286
|
-
save
|
287
|
-
changed
|
288
|
-
notify_observers
|
289
|
-
end
|
290
|
-
|
291
|
-
def rmWatched(path = "")
|
292
|
-
if @@local_anime.key? path
|
293
|
-
@@local_anime[path].unwatch
|
294
|
-
else
|
295
|
-
r = []
|
296
|
-
@@local_anime.values.each_with_index{ |v, i| r << {Integer(v.seenOn) => @@local_anime.keys[i]} if v.seen? }
|
297
|
-
return if r.length == 0
|
298
|
-
last_watched = (r.sort_by{ |h| h.keys.first}.reverse)[0].values[0]
|
299
|
-
@@local_anime[last_watched].unwatch
|
300
|
-
end
|
301
|
-
save
|
302
|
-
changed
|
303
|
-
notify_observers
|
304
|
-
end
|
305
|
-
|
306
|
-
def watch(file)
|
307
|
-
@mpvbridge.play file
|
308
|
-
end
|
309
|
-
|
310
|
-
def watch_list(files)
|
311
|
-
File.open("/tmp/aniview_list.m3u", "w") { |f|
|
312
|
-
files.each { |file|
|
313
|
-
f.puts file.path
|
314
|
-
}
|
315
|
-
}
|
316
|
-
@mpvbridge.playlist("/tmp/aniview_list.m3u", files.map { |f| [f.path, f] }.to_h)
|
317
|
-
end
|
318
|
-
|
319
|
-
end
|
320
|
-
end
|
321
|
-
end
|