Patch title: Release 94 bulk changes
Abstract:
File: /pliant/linux/multimedia/libmad.pli
Key:
    Removed line
    Added line
   
module "/pliant/language/compiler.pli"
module "/pliant/language/stream.pli"
module "/pliant/util/pml/io.pli"
module "/pliant/language/type/misc/blob.pli"

constant libmad (shunt (file_query "file:/lib/libmad.so" standard)=defined or (file_query "file:/usr/lib/libmad.so" standard)=defined "libmad.so" (file_query "file:/usr/lib/libmad.so.0" standard)=defined "libmad.so.0" "libmad.so")


#------------------------------------------------------------------------


type mad_bitptr
  field Address byte
  field uInt16 cache left

type mad_stream
  field Address buffer bufend
  field Int skiplen
  field Int sync freerate
  field Address this_frame next_frame
  field mad_bitptr ptr anc_ptr
  field Int anc_bitlen
  field Address main_data
  field Int md_len
  field Int options
  field Int error
# console "mad_stream size = " mad_stream:size eol

function mad_stream_init stream
  arg_rw mad_stream stream
  external libmad "mad_stream_init"

function mad_stream_buffer stream adr size
  arg_rw mad_stream stream ; arg Address adr ; arg Int size
  external libmad "mad_stream_buffer"

function mad_stream_skip stream size
  arg_rw mad_stream stream ; arg Int size
  external libmad "mad_stream_skip"

function mad_stream_sync stream
  arg_rw mad_stream stream
  external libmad "mad_stream_sync"

function mad_stream_finish stream
  arg_rw mad_stream stream
  external libmad "mad_stream_finish"

constant MAD_FLOW_CONTINUE 0
constant MAD_FLOW_STOP 10h
constant MAD_FLOW_BREAK 11h
constant MAD_FLOW_IGNORE 20h

function mad_stream_errorstr stream -> s
  arg_rw mad_stream stream ; arg CStr s
  external libmad "mad_stream_errorstr"


#------------------------------------------------------------------------


type mad_async
  field Int pid in out

type mad_decoder
  field Int mode # sync=0, async=1
  field Int options
  field mad_async async
  field Address sync
  field Address cb_data
  field Address init_func header_func filter_func output_func error_func message_func
# console "mad_decoder size = " mad_decoder:size eol

function mad_decoder_init decoder data input_func header_func filter_func output_func error_func message_func
  arg_rw mad_decoder decoder ; arg Address data input_func header_func filter_func output_func error_func message_func
  external libmad "mad_decoder_init"

function mad_decoder_run decoder mode -> err
  arg_rw mad_decoder decoder ; arg Int mode err
  external libmad "mad_decoder_run"

function mad_decoder_finish decoder
  arg_rw mad_decoder decoder
  external libmad "mad_decoder_finish"

constant MAD_DECODER_MODE_SYNC 0
constant MAD_DECODER_MODE_ASYNC 1


#------------------------------------------------------------------------


type mad_header
  field Int layer
  field Int mode
  field Int mode_extension
  field Int emphasis
  field Int bitrate
  field Int samplerate
  field uInt16 crc_check crc_target
  field Int flags private_bits
  field Int seconds fraction
# console "mad_header size = " mad_header:size eol


type mad_pcm
  field Int samplerate
  field uInt16 channels length
  field (Array (Array Int32 1152) 2) samples
# console "mad_pcm size = " mad_pcm:size eol


#------------------------------------------------------------------------


type MadContext
  field Stream input
  field Address buffer <- null
  field Int bufsize <- 0
  field Stream output
  field (Array uInt16 1152*2) audio
  field Int rate <- 44100
  field CBool multiplexed
  field Pointer:Float late
  field Pointer:FastSem sem
  
function destroy c
  arg_w MadContext c
  memory_free c:buffer


function input c stream -> retcode
  arg_rw MadContext c ; arg_rw mad_stream stream ; arg Int retcode
  external_calling_convention
  var Int remain := (cast stream:bufend Int).-.(cast stream:next_frame Int)
  if remain>0
    memory_move stream:next_frame c:buffer remain
  var Address adr ; var Int extra
  if c:multiplexed
    if (c:input iraw (var Float ts))
      if ((c:output query "pending") parse (var Float pending))
        void
    if (c:input iraw (var Blob blob))
      adr := blob content
      extra := blob size
    else
      adr := null
      extra := 0
  else
    c:input read_available adr extra
  if extra>0
    if remain+extra>c:bufsize
      c buffer := memory_resize c:buffer remain+extra addressof:c
    memory_copy adr (c:buffer translate Byte remain) extra
  mad_stream_buffer stream c:buffer remain+extra
  retcode := shunt extra>0 MAD_FLOW_CONTINUE MAD_FLOW_STOP

function scale x -> y
  arg Int x y
  constant fractbits 28
  constant one 10000000h
  var Int v := x+2^(28-16)
  if v>=one
    v := one-1
  eif v<(-one)
    v := -one
  y := v\2^(fractbits+1-16)

function output c header pcm -> retcode
  arg_rw MadContext c ; arg_rw mad_header header ; arg_rw mad_pcm pcm ; arg Int retcode
  external_calling_convention
  if header:samplerate<>c:rate
    # console "sample rate is " header:samplerate eol
    c:output configure "rate "+(string header:samplerate)
    c rate := header samplerate
  for (var Int ch) 0 1
    for (var Int i) 0 1151
      c:audio i+i+ch := scale pcm:samples:ch:i
  c:output raw_write (addressof c:audio) 1152*2*uInt16:size
  c:output flush anytime
  retcode := MAD_FLOW_CONTINUE

function error c stream frame -> retcode
  arg_rw MadContext c ; arg_rw mad_stream stream ; arg Address frame ; arg Int retcode
  external_calling_convention
  console "mad error " (cast mad_stream_errorstr:stream Str) eol
  retcode := MAD_FLOW_CONTINUE


module "audio.pli"

function libmad_play filename options start late sem
  arg Str filename ; arg Str options ; arg DateTime start ; arg_rw Float late ; arg_rw FastSem sem
  var mad_decoder decoder
  var MadContext c
  c:input open filename in
  c:output open "audio:" "" out
  c multiplexed := options option "multiplexed"
  c late :> late
  c sem :> sem
  mad_decoder_init decoder addressof:c (the_function input MadContext mad_stream -> Int):executable null null (the_function output MadContext mad_header mad_pcm -> Int):executable (the_function error MadContext mad_stream Address -> Int):executable null
  var Int retcode := mad_decoder_run decoder MAD_DECODER_MODE_SYNC
  mad_decoder_finish decoder

function play filename
  arg Str filename
  libmad_play filename "" datetime (null map Float) (null map FastSem)

export libmad_play play