From: David B. <dav...@gm...> - 2009-10-11 17:59:56
|
Hi, Nice adaptation of playlist.once()! Let me comment it. 2009/10/11 Аркадий Левин <poi...@gm...>: > def dynamic(process) > x = string.ref("0") > get = fst(x) > set = snd(x) The variable "x" is going to be the current position in the playlist. Precisely, "x" consists of two functions that work on an underlying reference. A reference is a mutable cell. Like all variables in liquidsoap, "x" will always be the same thing: the same two function, the same reference. But the content of the reference can change over time. The extra level of indirection through the mutable cell is important here. I'm insisting here because this is the reason of the problem, we'll see that below. > files = get_process_lines(process) > length = list.length(files) Here you get the length of your playlist, which is created by one call to your process. You store the result in files, which is an _immutable_ list of strings. It can never be changed. > def next() > state = int_of_string(get()) > if state < length then > set(string_of(state + 1)) > request.create(audio=true,list.nth(files,state)) > else > set(string_of(1)) > log("playlist end! request new") > files = get_process_lines(process) > length = list.length(files) This is the mistake. Here you are only giving new _local_ definitions of "files" and "length". They have nothing to do with the ones above -- except that they mask them until the end of the else block. How to fix this problem? You need to use another reference for "files" (and also for "length", but this is easy and secondary, you can always compute the length from the list everytime you need it). The problem is that you need a reference to a string of list, and we don't have this -- I'll propose a solution below. As you might have noticed, the "mutable" business in liquidsoap is currently ugly, it's just a hack on top of the clean part of the language. This will change soon, in a branch that I'm working on. But it will come with other changes that will take some time to stabilize. Anyways, here's an idea for simulating string list references. Note that it could also be used for int, float and strings. Use the settings mechanism. You already know the function set which sets a configuration setting: set("log.stdout",false). Well you can also set something that is not a configuration key (you might get a warning in the logs though): set("playlist_files",get_process_lines(command)). You can also get them using the function get(), which requires a parameter telling what to return when the setting is undefined: get(default=[],"playlist_files") -- the parameter is really necessary even if you're sure that the setting is defined; it is needed to know if get() should look for a string, int, float, bool or string list configuration key. The downside of using configuration settings is that you need to use a global name for your "reference", which doesn't help modular programming. But it should be fine until we have real references in the language. > request.create(audio=true,list.nth(files,0)) > end > end > request.dynamic(next) > end > if playlist is end, in log write "playlist end! request new" but > playing old requested playlist, why? This was because the variables "files" and "length" (their first occurrence) never get changed. Precisely, you should be hearing one file from the new playlist (the request.create() from the else block) and then the old playlist again. Cheers, -- David |