88
88
--- @diagnostic disable-next-line no-unknown
89
89
local concurrent_loadlist_wrapper
90
90
91
- --- @alias ConcurrentRefMap table<List | Item ,{ directory : string , sublist : List } >
91
+ --- @alias ConcurrentRefMap table<List | Item ,{ directory : string ? , sublist : List ?, recurse : boolean ? } >
92
92
93
93
--- This function recursively loads directories concurrently in separate coroutines.
94
94
--- Results are saved in a tree of tables that allows asynchronous access.
@@ -100,6 +100,8 @@ local concurrent_loadlist_wrapper
100
100
--- @param refs ConcurrentRefMap
101
101
--- @return boolean ?
102
102
local function concurrent_loadlist_parse (directory , load_opts , prev_dirs , item_t , refs )
103
+ if not refs [item_t ] then refs [item_t ] = {} end
104
+
103
105
-- prevents infinite recursion from the item.path or opts.directory fields
104
106
if prev_dirs [directory ] then return end
105
107
prev_dirs [directory ] = true
@@ -110,22 +112,23 @@ local function concurrent_loadlist_parse(directory, load_opts, prev_dirs, item_t
110
112
-- if we can't parse the directory then append it and hope mpv fares better
111
113
if list == nil then
112
114
msg .warn (" Could not parse" , directory , " appending to playlist anyway" )
113
- item_t . type = " file "
115
+ refs [ item_t ]. recurse = false
114
116
return
115
117
end
116
118
117
119
directory = list_opts .directory or directory
118
- if directory == " " then return end
119
120
120
121
-- we must declare these before we start loading sublists otherwise the append thread will
121
122
-- need to wait until the whole list is loaded (when synchronous IO is used)
122
123
refs [item_t ].sublist = list or {}
123
- refs [list ].directory = directory
124
+ refs [list ] = {directory = directory }
125
+
126
+ if directory == " " then return end
124
127
125
128
-- launches new parse operations for directories, each in a different coroutine
126
129
for _ , item in ipairs (list ) do
127
130
if fb_utils .parseable_item (item ) then
128
- fb_utils .coroutine .run (concurrent_loadlist_wrapper , fb_utils .get_new_directory (item , directory ), load_opts , prev_dirs , item )
131
+ fb_utils .coroutine .run (concurrent_loadlist_wrapper , fb_utils .get_new_directory (item , directory ), load_opts , prev_dirs , item , refs )
129
132
end
130
133
end
131
134
return true
@@ -167,11 +170,11 @@ local function concurrent_loadlist_append(list, load_opts, refs)
167
170
if not g .sub_extensions [ fb_utils .get_extension (item .name , " " ) ]
168
171
and not g .audio_extensions [ fb_utils .get_extension (item .name , " " ) ]
169
172
then
170
- while ( not refs [item ]. sublist and fb_utils . parseable_item ( item ) ) do
173
+ while fb_utils . parseable_item ( item ) and ( not refs [item ] or not refs [ item ]. sublist ) do
171
174
coroutine.yield ()
172
175
end
173
176
174
- if fb_utils .parseable_item (item ) then
177
+ if fb_utils .parseable_item (item ) and refs [ item ] ~= false then
175
178
concurrent_loadlist_append (refs [item ].sublist , load_opts , refs )
176
179
else
177
180
loadfile (fb_utils .get_full_path (item , directory ), load_opts , item .mpv_options )
@@ -233,12 +236,15 @@ local function loadlist(item, opts)
233
236
opts .co = fb_utils .coroutine .assert ()
234
237
opts .concurrency = 0
235
238
236
- local refs = setmetatable ({}, {__mode = ' k' })
239
+ --- @type List
240
+ local v_list = {item }
241
+ --- @type ConcurrentRefMap
242
+ local refs = setmetatable ({[v_list ] = {directory = opts .directory }}, {__mode = ' k' })
237
243
238
244
-- we need the current coroutine to suspend before we run the first parse operation, so
239
245
-- we schedule the coroutine to run on the mpv event queue
240
246
fb_utils .coroutine .queue (concurrent_loadlist_wrapper , dir , opts , {}, item , refs )
241
- concurrent_loadlist_append ({ item , _directory = opts . directory } , opts , refs )
247
+ concurrent_loadlist_append (v_list , opts , refs )
242
248
else
243
249
custom_loadlist_recursive (dir , opts , {})
244
250
end
0 commit comments