[Haskell-cafe] Re: RFC and Announcement: HLADSPA, LADSPA for Haskell

Alfonso Acosta alfonso.acosta at gmail.com
Mon Nov 20 22:39:35 EST 2006


Just in case anyone is interested. I finally overcame those
difficulties and  released HLADSPA 0.2 which can be found at

http://www.student.nada.kth.se/~alfonsoa/HLADSPA/HLADSPA-0.2.tgz

whose changelog is

2006-11-21  Version 0.2

        * API refactored (now the plugins are coded in pure haskell98 + TH
          and it doesnt depend on the latest (6.6) version of ghc anymore)
        * Created proper Make system
          (http://hackage.haskell.org/trac/ghc/ticket/933 + the use
           of template records didn't allow it)
        * Fixed lots of major and minor bugs
        * Added Amp and (currently broken) ForSyDeEq plugins




On 11/5/06, Alfonso Acosta <alfonso.acosta at gmail.com> wrote:
> The essential code snippet is,
>
> =====================
> -- Existentially quantified records allow the plugin developer
> -- to chose hd and id types at will and, allowing to declare "heterogeneous"
> -- Descriptor lists. Drawback: it only works in ghc 6.6 and
> -- makes the design tricky. The problem comes from modelling (void*) in Haskell
>
> -- id is the implementation data
> data Descriptor = forall id.
>      Descriptor {uniqueID               :: LadspaIndex,
>                  label                  :: String,
>                  properties             :: LadspaProperties,
>                  name, maker, copyright :: String,
>                  portCount              :: LadspaIndex,
>                  portDescriptors        :: [PortDescriptor],
>                  portNames              :: [String],
>                  portRangeHints         :: [PortRangeHint],
>                  _implementationData    :: id,
>                  _instantiate           :: Descriptor -> LadspaIndex ->
>                                            Maybe Instance}
>
> -- hd is the handle
> data Instance = forall hd.
>     Instance {
>               _this :: hd, -- initial handle
> -- In this case we are using lists to represent the port I/O buffers, so the
> -- port connections (buffer pointers of ports) is handled by the marshaller
> --            connectPort   :: (hd -> LadspaIndex -> Ptr LadspaData -> IO hd)
>               _activate               :: Maybe(hd -> IO ()),
>               -- (LadspaIndex,PortData) indicates the portnumber and its data
>               _run                    :: hd                       ->
>                                          LadspaIndex              ->
>                                          [(LadspaIndex,PortData)] ->
>                                          ([(LadspaIndex,PortData)], hd),
> -- Not yet implemented (is not mandatory for a plugin to provide them)
> --            _runAdding              ::
> --            _setAddingGain          ::
>               _deactivate             :: Maybe (hd -> IO ()),
>               _cleanup                :: hd -> IO () }
> =====================
>
>
> This is the best solution I could come up with and I'm not still happy
> with it. The trickiest part, was modelling (void*) in Haskell.
>
> I know that using lists for I/O buffers is inefficient but I coded it
> having ForSyDe in mind. If people show interest I can code a faster
> StorableArray-version.
>
>
> Here are my questions.
>
> * I'm using GHC's existentially quantified records extension to hide
> the hd and id parameters because the plugin programmer has to be able
> to provide a collection of Descriptor (a Descriptor list in current
> release). I would love to find a solution in plain Haskell98. Any
> ideas?
>
> * This approach requires splitting the original C LADSPA_Descriptor
> struct in the Descriptor and Instance Haskell types, which leads to a
> design error:  there are functions (e.g. _run, _activate ... ) in
> Instance which really belong to Descriptor (those functions shouldn't
> change with the plugin instance). For example, with this approach, it
> is not possible to tell the plugin host if activate() or deactivate()
> will be used because this is "asked" any instances is created.
>
> * Real Time support in HLADSPA. From LADSPA's documentation:
>
>    "Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin
>    is capable of running not only in a conventional host but also in a
>    `hard real-time' environment.  To qualify for this the plugin must
>    satisfy all of the following:
>       (1) The plugin must not use malloc(), free() or other heap memory
>    management within its run() or run_adding() functions. All new
>    memory used in run() must be managed via the stack. These
>    restrictions only apply to the run() function."
>
> Should I forget about HARD_RT_CAPABLE with Haskell? Is there a way to
> control the use of the heap by a function?
>
>
> * I'm not so sure about the types of _activate, _deactivate and
> _cleanup. I don't even know if I should include them because they only
> seem to be required by a language with side effects. Furthermore,
> _activate() and _deactivate() don't seem to have sense with current
> implementation cause they are "separated from instantiate() to aid
> real-time support" and using lists as I/O buffers discards RT support
> (see above)
>
>
> Thanks in advance for your comments/answers,
>
> Alfonso Acosta


More information about the Haskell-Cafe mailing list