2011/3/13 Boris Zhidkov <[email protected]>:
> Hi!

Hi,

> Thanks. I haven't noticed. Now it works.
> But I have another question: I need to set a mount when adding playlists.
> But server.register takes one argument only.

Yes, that is where you need to cook up your own version of these
ideas. The scripting language has all the required parsing
functionalities. You can see for instance the url.split function
defined in utils.liq:

# Split an url of the form foo?arg=bar&arg2=bar2
# into ("foo",[("arg","bar"),("arg2","bar2")]
# @category String
# @param uri Url to split
def url.split(uri) =
 ret = string.extract(pattern="([^\?]*)\?(.*)",uri)
 args = ret["2"]
 if args != "" then
   l = string.split(separator="&",args)
   def f(x) =
     ret = string.split(separator="=",x)
     (url.decode(list.nth(ret,0)),
      url.decode(list.nth(ret,1)))
   end
   l = list.map(f,l)
   (ret["1"],l)
 else
   (uri,[])
 end
end

Romain

> On Sun, Mar 13, 2011 at 1:13 AM, Romain Beauxis <[email protected]>
> wrote:
>>
>> 2011/3/12 Boris Zhidkov <[email protected]>:
>> > Hi, Romain.
>>
>> Hi!
>>
>> > Can you give an example of usage for these functions?
>> > I've started an instance of liquidsoap:
>> > $ liquidsoap -t dynamic_playlist.liq 'output.dummy(blank())'
>> > Then connected via telnet:
>> > telnet localhost 1234
>> > and tried to add a playlist:
>> > dynamic_playlist.start "~/pl.pls"
>> > ERROR: Lang.Invalid_value(_, "Either name or mount must be defined")
>> > END
>> > dynamic_playlist.start (~/pl.pls)
>> > ERROR: Lang.Invalid_value(_, "Either name or mount must be defined")
>> > END
>> > dynamic_playlist.start("/home/alius/pl.pls")
>> > ERROR: Lang.Invalid_value(_, "Either name or mount must be defined")
>>
>> Some of the arguments for output.icecast are not defined. you need to
>> add at least the mountpoint:
>>  out = output.icecast(%mp3, host="foo", password="bar",
>> mount="bla.mp3", fallible=true)
>> You may as well use an output to the local soundcard to test locally:
>>  out = output.ao(fallible=true)
>>
>> Also, you use the command this way:
>>  dynamic_playlist.start /home/alius/pl.pls
>> (no double quotes/quotes..)
>>
>> Romain
>>
>> > On Fri, Mar 11, 2011 at 11:13 PM, Romain Beauxis <[email protected]>
>> > wrote:
>> >>
>> >> Hey,
>> >>
>> >> 2011/3/11 Boris Zhidkov <[email protected]>:
>> >> > Hi.
>> >> >>
>> >> >> You may as well use a recent liquidsoap (SVN/hg) and dynamically
>> >> >>
>> >> >> create/destroy sources in your script. For instance, you can
>> >> >> register
>> >> >>
>> >> >> a telnet/server command that creates a new source/output and a
>> >> >> command
>> >> >>
>> >> >> that destroys that source.
>> >> >>
>> >> >> I can give more details about this if you are interested.
>> >> >
>> >> > Yes, I think it's an optimal way for me.
>> >>
>> >> Cool :)
>> >>
>> >> So first some outlines:
>> >>  * It is not possible in a natural way to change a source currently
>> >> being streamed. it should be possible using source.dynamic but this is
>> >> still experimental and I'll let David comment on it. I will show a
>> >> hack to work around that tho.
>> >>  * You need a recent liquidsoap, prob. at least beta1 but most likely
>> >> SVN/hg
>> >>  * The idea is to create a new output using a telnet command.
>> >>
>> >> Now let's see one possible way to do it. In this example, we will
>> >> register a command that creates a playlist source using an uri passed
>> >> as argument and outputs it to a fixed icecast output.
>> >>
>> >> With more work on parsing the argument passed to the telnet command,
>> >> you may create more evolved sources, such as the possibility to change
>> >> the output parameters etc..
>> >>
>> >> Due to some limitations of the language, I have had to use some
>> >> intricate (but classic) functional programming tricks. I have
>> >> commented them in order to help reading the code..
>> >>
>> >> 8<-------------->8
>> >> # First, we create a list referencing the dynamic sources:
>> >> dyn_sources = ref []
>> >>
>> >> # This is our icecast output.
>> >> # It is a partial function: the source needs to be given!
>> >> out = output.icecast(%mp3,
>> >>                     host="test",
>> >>                     password="hackme",
>> >>                     fallible=true)
>> >>
>> >> # Now we write a function to create
>> >> # a playlist source and output it.
>> >> def create_playlist(uri) =
>> >>  # The playlist source
>> >>  s = playlist(uri)
>> >>
>> >>  # The output
>> >>  output = out(s)
>> >>
>> >>  # Register output is the list of sources
>> >>  dyn_sources :=
>> >>      list.append( [(uri,output)],
>> >>                    !dyn_sources )
>> >>
>> >>  "Done!"
>> >>  # PS: we need a x :: l syntactic sugar :)
>> >> end
>> >>
>> >> # And a function to destroy a dynamic source
>> >> def destroy_playlist(uri) =
>> >>  # We need to find the source in the list,
>> >>  # remove it and destroy it. Currently, the language
>> >>  # lacks some nice operators for that so we do it
>> >>  # the functional way
>> >>
>> >>  # This function is executed on every item in the list
>> >>  # of dynamic sources
>> >>  def parse_list(ret, current_element) =
>> >>   # ret is of the form: (matching_sources, remaining_sources)
>> >>   # We extract those two:
>> >>   matching_sources = fst(ret)
>> >>   remaining_sources = snd(ret)
>> >>
>> >>   # current_element is of the form: ("uri", source) so we check the
>> >> first element
>> >>   current_uri = fst(current_element)
>> >>   if current_uri == uri then
>> >>     # In this case, we add the source to the list of
>> >>     # matched sources
>> >>     (list.append( [snd(current_element)],
>> >>                    matching_sources), remaining_sources)
>> >>   else
>> >>     # In this case, we put the element in the list of remaining
>> >>     # sources
>> >>     (matching_sources,
>> >>      list.append([current_element],
>> >>                   remaining_sources))
>> >>
>> >>   end
>> >>  end
>> >>
>> >>   # Now we execute the function:
>> >>   result = list.fold(parse_list, ([], []), !dyn_sources)
>> >>   matching_sources = fst(result)
>> >>   remaining_sources = snd(result)
>> >>
>> >>   # We store the remaining sources in dyn_sources
>> >>   dyn_sources := remaining_sources
>> >>
>> >>   # If no source matched, we return an error
>> >>   if list.length(matching_sources) == 0 then
>> >>     "Error: no matching sources!"
>> >>   else
>> >>     # If more than one source matched, we return a warning
>> >>     msg =
>> >>       if list.length(matching_sources) > 1 then
>> >>        "Warning: more than one source matched the given uri!\n"
>> >>       else
>> >>        ""
>> >>       end
>> >>     # Now we stop all sources
>> >>     list.iter(source.shutdown, matching_sources)
>> >>     # And return
>> >>     "#{msg}Done!"
>> >>   end
>> >>  # PS: we could use a universal type for list.assoc and a (x,y)
>> >> implicit
>> >>  # matching :)
>> >> end
>> >>
>> >>
>> >> # Now we register the telnet commands:
>> >> server.register(namespace="dynamic_playlist",
>> >>                description="Start a new dynamic playlist.",
>> >>                usage="start <uri>",
>> >>                "start",
>> >>                create_playlist)
>> >> server.register(namespace="dynamic_playlist",
>> >>                description="Stop a dynamic playlist.",
>> >>                usage="stop <uri>",
>> >>                "stop",
>> >>                destroy_playlist)
>> >> 8<-------------->8
>> >>
>> >> Now, if you execute this code (add a output.dummy(blank()) if you have
>> >> no other output..), you have two new telnet commands:
>> >>  * dynamic_playlist.start <uri>
>> >>  * dynamic_playlist.stop <uri>
>> >> which you can use to create/destroy dynamically your sources.
>> >>
>> >> With more tweaking, you should be able to adapt these ideas to your
>> >> precise needs.
>> >>
>> >> If you want to plug those sources into an existing output, you may
>> >> want to use an input.harbor in the main output and change the
>> >> output.icecast in the dynamic source creation to send everything to
>> >> this input.harbor. You can use the %wav format in this case to avoid
>> >> compressing/decompressing the data..
>> >>
>> >> Hope this inspires you, let us know if you have more tricks using this
>> >> :)
>> >>
>> >> (And I should really put that in the doc :))
>> >>
>> >> Romain
>> >>
>> >> > On Fri, Mar 11, 2011 at 1:33 AM, Romain Beauxis
>> >> > <[email protected]>
>> >> > wrote:
>> >> >>
>> >> >> Hi Boris!
>> >> >>
>> >> >> Le 10 mars 2011 13:15, Boris Zhidkov <[email protected]> a
>> >> >> écrit
>> >> >> :
>> >> >> > Hi, all.
>> >> >> > I want to manage streams dynamically, so I need to generate .liq
>> >> >> > scripts
>> >> >> > and
>> >> >> > execute them in some way.
>> >> >> > How can I realize it?
>> >> >> > Is it possible to run liquidsoap scripts via telnet? Or must I
>> >> >> > replace
>> >> >> > scripts in /etc/liquidsoap and restart init.d/liquidsoap everytime
>> >> >> > I
>> >> >> > generate new scripts?
>> >> >>
>> >> >> You have many possible ways.
>> >> >> The simplier is to generate .liq scripts in /etc/liquidsoap and
>> >> >> start/stop them using init.d. However, current init script
>> >> >> starts/stop
>> >> >> all scripts I believe..
>> >> >>
>> >> >> You may as well use a recent liquidsoap (SVN/hg) and dynamically
>> >> >> create/destroy sources in your script. For instance, you can
>> >> >> register
>> >> >> a telnet/server command that creates a new source/output and a
>> >> >> command
>> >> >> that destroys that source.
>> >> >> I can give more details about this if you are interested.
>> >> >>
>> >> >> Romain
>> >> >>
>> >> >>
>> >> >> > ---------------------------
>> >> >> > Thanks, Boris Zhidkov
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > ------------------------------------------------------------------------------
>> >> >> > Colocation vs. Managed Hosting
>> >> >> > A question and answer guide to determining the best fit
>> >> >> > for your organization - today and in the future.
>> >> >> > http://p.sf.net/sfu/internap-sfd2d
>> >> >> > _______________________________________________
>> >> >> > Savonet-users mailing list
>> >> >> > [email protected]
>> >> >> > https://lists.sourceforge.net/lists/listinfo/savonet-users
>> >> >> >
>> >> >> >
>> >> >
>> >> >
>> >> >
>> >> > --
>> >> > -------------------------------------------
>> >> > WBR, Boris Zhidkov
>> >> >
>> >
>> >
>> >
>> > --
>> > -------------------------------------------
>> > WBR, Boris Zhidkov
>> >
>
>
>
> --
> -------------------------------------------
> WBR, Boris Zhidkov
>

------------------------------------------------------------------------------
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d
_______________________________________________
Savonet-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/savonet-users

Reply via email to