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
>

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