/*----------------------------------------------------------------------
|   Mp4Parser_Construct
+---------------------------------------------------------------------*/
static void
Mp4Parser_Construct(Mp4Parser* self, BLT_Module* module, BLT_Core* core)
{
    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(self, BLT_BaseMediaNode), module, core);

    /* initialize some fields */
    self->key_manager = NULL;
    
    /* construct the members */
    Mp4ParserInput_Construct(&self->input, module);
    Mp4ParserOutput_Construct(&self->audio_output, self);
    Mp4ParserOutput_Construct(&self->video_output, self);
    
    /* setup media types */
    Mp4ParserModule* mp4_parser_module = (Mp4ParserModule*)module;
    self->audio_output.mp4_es_type_id = mp4_parser_module->mp4_audio_es_type_id;
    self->audio_output.iso_base_es_type_id = mp4_parser_module->iso_base_audio_es_type_id;
    self->video_output.mp4_es_type_id = mp4_parser_module->mp4_video_es_type_id;
    self->video_output.iso_base_es_type_id = mp4_parser_module->iso_base_video_es_type_id;
    
    /* setup interfaces */
    ATX_SET_INTERFACE_EX(self, Mp4Parser, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(self, Mp4Parser, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE(&self->input,  Mp4ParserInput,  BLT_MediaPort);
    ATX_SET_INTERFACE(&self->input,  Mp4ParserInput,  BLT_InputStreamUser);
    ATX_SET_INTERFACE(&self->audio_output, Mp4ParserOutput, BLT_MediaPort);
    ATX_SET_INTERFACE(&self->audio_output, Mp4ParserOutput, BLT_PacketProducer);
    ATX_SET_INTERFACE(&self->video_output, Mp4ParserOutput, BLT_MediaPort);
    ATX_SET_INTERFACE(&self->video_output, Mp4ParserOutput, BLT_PacketProducer);
}
/*----------------------------------------------------------------------
|    AlsaOutput_Create
+---------------------------------------------------------------------*/
static BLT_Result
AlsaOutput_Create(BLT_Module*              module,
                  BLT_Core*                core, 
                  BLT_ModuleParametersType parameters_type,
                  BLT_AnyConst             parameters, 
                  BLT_MediaNode**          object)
{
    AlsaOutput*               output;
    BLT_MediaNodeConstructor* constructor = 
        (BLT_MediaNodeConstructor*)parameters;

    ATX_LOG_FINE("creating output");

    /* check parameters */
    if (parameters == NULL || 
        parameters_type != BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR) {
        return BLT_ERROR_INVALID_PARAMETERS;
    }

    /* allocate memory for the object */
    output = ATX_AllocateZeroMemory(sizeof(AlsaOutput));
    if (output == NULL) {
        *object = NULL;
        return BLT_ERROR_OUT_OF_MEMORY;
    }

    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(output, BLT_BaseMediaNode), module, core);

    /* construct the object */
    output->state                      = BLT_ALSA_OUTPUT_STATE_CLOSED;
    output->device_handle              = NULL;
    output->media_type.sample_rate     = 0;
    output->media_type.channel_count   = 0;
    output->media_type.bits_per_sample = 0;

    /* parse the name */
    if (constructor->name && ATX_StringLength(constructor->name) > 5) {
        output->device_name = ATX_String_Create(constructor->name+5);
    } else {
        output->device_name = ATX_String_Create("default");
    }
    
    /* setup the expected media type */
    BLT_PcmMediaType_Init(&output->expected_media_type);

    /* setup interfaces */
    ATX_SET_INTERFACE_EX(output, AlsaOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(output, AlsaOutput, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE(output, AlsaOutput, BLT_PacketConsumer);
    ATX_SET_INTERFACE(output, AlsaOutput, BLT_OutputNode);
    ATX_SET_INTERFACE(output, AlsaOutput, BLT_MediaPort);
    *object = &ATX_BASE_EX(output, BLT_BaseMediaNode, BLT_MediaNode);

    return BLT_SUCCESS;
}
Exemple #3
0
    PcmAdapterOutput_GetPacket
ATX_END_INTERFACE_MAP

/*----------------------------------------------------------------------
|    PcmAdapter_Create
+---------------------------------------------------------------------*/
static BLT_Result
PcmAdapter_Create(BLT_Module*              module,
                  BLT_Core*                core, 
                  BLT_ModuleParametersType parameters_type,
                  BLT_AnyConst             parameters, 
                  BLT_MediaNode**          object)
{
    BLT_MediaNodeConstructor* constructor = (BLT_MediaNodeConstructor*)parameters;
    PcmAdapter*               self;

    ATX_LOG_FINE("PcmAdapter::Create");

    /* check parameters */
    if (parameters == NULL || 
        parameters_type != BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR) {
        return BLT_ERROR_INVALID_PARAMETERS;
    }

    /* allocate memory for the object */
    self = ATX_AllocateZeroMemory(sizeof(PcmAdapter));
    if (self == NULL) {
        *object = NULL;
        return BLT_ERROR_OUT_OF_MEMORY;
    }

    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(self, BLT_BaseMediaNode), module, core);

    /* check the media type */
    if (constructor->spec.output.media_type->id != BLT_MEDIA_TYPE_ID_AUDIO_PCM) {
        return BLT_ERROR_INVALID_MEDIA_TYPE;
    }

    /* construct the object */
    self->output.pcm_type = *(BLT_PcmMediaType*)constructor->spec.output.media_type;

    /* setup interfaces */
    ATX_SET_INTERFACE_EX(self, PcmAdapter, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(self, PcmAdapter, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE(&self->input,  PcmAdapterInput,  BLT_MediaPort);
    ATX_SET_INTERFACE(&self->input,  PcmAdapterInput,  BLT_PacketConsumer);
    ATX_SET_INTERFACE(&self->output, PcmAdapterOutput, BLT_MediaPort);
    ATX_SET_INTERFACE(&self->output, PcmAdapterOutput, BLT_PacketProducer);
    *object = &ATX_BASE_EX(self, BLT_BaseMediaNode, BLT_MediaNode);

    return BLT_SUCCESS;
}
    WaveFormatterOutput_SetStream
ATX_END_INTERFACE_MAP

/*----------------------------------------------------------------------
|    WaveFormatter_Create
+---------------------------------------------------------------------*/
static BLT_Result
WaveFormatter_Create(BLT_Module*              module,
                     BLT_Core*                core, 
                     BLT_ModuleParametersType parameters_type,
                     BLT_CString              parameters, 
                     BLT_MediaNode**          object)
{
    WaveFormatter* self;

    ATX_LOG_FINE("WaveFormatter::Create");

    /* check parameters */
    if (parameters == NULL || 
        parameters_type != BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR) {
        return BLT_ERROR_INVALID_PARAMETERS;
    }

    /* allocate memory for the object */
    self = ATX_AllocateZeroMemory(sizeof(WaveFormatter));
    if (self == NULL) {
        *object = NULL;
        return BLT_ERROR_OUT_OF_MEMORY;
    }

    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(self, BLT_BaseMediaNode), module, core);

    /* setup the input media type */
    BLT_PcmMediaType_Init(&self->input.media_type);
    self->input.media_type.sample_format = BLT_PCM_SAMPLE_FORMAT_SIGNED_INT_LE;

    /* setup the output media type */
    BLT_MediaType_Init(&self->output.media_type, 
                       ((WaveFormatterModule*)module)->wav_type_id);

    /* setup interfaces */
    ATX_SET_INTERFACE_EX(self, WaveFormatter, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(self, WaveFormatter, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE(&self->input,  WaveFormatterInput,  BLT_MediaPort);
    ATX_SET_INTERFACE(&self->input,  WaveFormatterInput,  BLT_OutputStreamProvider);
    ATX_SET_INTERFACE(&self->output, WaveFormatterOutput, BLT_MediaPort);
    ATX_SET_INTERFACE(&self->output, WaveFormatterOutput, BLT_OutputStreamUser);
    *object = &ATX_BASE_EX(self, BLT_BaseMediaNode, BLT_MediaNode);

    return BLT_SUCCESS;
}
/*----------------------------------------------------------------------
|    SilenceRemover_Create
+---------------------------------------------------------------------*/
static BLT_Result
SilenceRemover_Create(BLT_Module*              module,
                      BLT_Core*                core, 
                      BLT_ModuleParametersType parameters_type,
                      BLT_AnyConst             parameters, 
                      BLT_MediaNode**          object)
{
    SilenceRemover* self;
    BLT_Result  result;

    ATX_LOG_FINE("SilenceRemover::Create");

    /* check parameters */
    if (parameters == NULL || 
        parameters_type != BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR) {
        return BLT_ERROR_INVALID_PARAMETERS;
    }

    /* allocate memory for the object */
    self = ATX_AllocateZeroMemory(sizeof(SilenceRemover));
    if (self == NULL) {
        *object = NULL;
        return BLT_ERROR_OUT_OF_MEMORY;
    }

    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(self, BLT_BaseMediaNode), module, core);

    /* construct the object */
    self->state = SILENCE_REMOVER_STATE_START_OF_STREAM;

    /* setup the input and output ports */
    result = SilenceRemover_SetupPorts(self);
    if (BLT_FAILED(result)) {
        BLT_BaseMediaNode_Destruct(&ATX_BASE(self, BLT_BaseMediaNode));
        ATX_FreeMemory(self);
        *object = NULL;
        return result;
    }

    /* setup interfaces */
    ATX_SET_INTERFACE_EX(self, SilenceRemover, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(self, SilenceRemover, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE(&self->input,  SilenceRemoverInput,  BLT_MediaPort);
    ATX_SET_INTERFACE(&self->input,  SilenceRemoverInput,  BLT_PacketConsumer);
    ATX_SET_INTERFACE(&self->output, SilenceRemoverOutput, BLT_MediaPort);
    ATX_SET_INTERFACE(&self->output, SilenceRemoverOutput, BLT_PacketProducer);
    *object = &ATX_BASE_EX(self, BLT_BaseMediaNode, BLT_MediaNode);

    return BLT_SUCCESS;
}
/*----------------------------------------------------------------------
|    AacDecoder_Create
+---------------------------------------------------------------------*/
static BLT_Result
AacDecoder_Create(BLT_Module*              module,
                  BLT_Core*                core, 
                  BLT_ModuleParametersType parameters_type,
                  BLT_CString              parameters, 
                  BLT_MediaNode**          object)
{
    AacDecoder*       self;
    AacDecoderModule* aac_decoder_module = (AacDecoderModule*)module;
    BLT_Result        result;

    ATX_LOG_FINE("AacDecoder::Create");

    /* check parameters */
    if (parameters == NULL || 
        parameters_type != BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR) {
        return BLT_ERROR_INVALID_PARAMETERS;
    }

    /* allocate memory for the object */
    self = ATX_AllocateZeroMemory(sizeof(AacDecoder));
    if (self == NULL) {
        *object = NULL;
        return BLT_ERROR_OUT_OF_MEMORY;
    }

    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(self, BLT_BaseMediaNode), module, core);

    /* setup the input and output ports */
    result = AacDecoder_SetupPorts(self, aac_decoder_module->mp4es_type_id);
    if (BLT_FAILED(result)) {
        ATX_FreeMemory(self);
        *object = NULL;
        return result;
    }

    /* setup interfaces */
    ATX_SET_INTERFACE_EX(self, AacDecoder, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(self, AacDecoder, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE(&self->input,  AacDecoderInput,  BLT_MediaPort);
    ATX_SET_INTERFACE(&self->input,  AacDecoderInput,  BLT_PacketConsumer);
    ATX_SET_INTERFACE(&self->output, AacDecoderOutput, BLT_MediaPort);
    ATX_SET_INTERFACE(&self->output, AacDecoderOutput, BLT_PacketProducer);
    *object = &ATX_BASE_EX(self, BLT_BaseMediaNode, BLT_MediaNode);

    return BLT_SUCCESS;
}
/*----------------------------------------------------------------------
|   DcfParser_Construct
+---------------------------------------------------------------------*/
static void
DcfParser_Construct(DcfParser* self, BLT_Module* module, BLT_Core* core)
{
    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(self, BLT_BaseMediaNode), module, core);

    /* construct the members */
    DcfParserInput_Construct(&self->input, module);
    DcfParserOutput_Construct(&self->output);
    
    /* look for a key manager */
    ATX_Properties* properties = NULL;
    if (BLT_SUCCEEDED(BLT_Core_GetProperties(core, &properties))) {
        ATX_PropertyValue value;
        if (ATX_SUCCEEDED(ATX_Properties_GetProperty(properties, 
                                                     BLT_KEY_MANAGER_PROPERTY, 
                                                     &value))) {
            if (value.type == ATX_PROPERTY_VALUE_TYPE_POINTER) {
                self->key_manager = (BLT_KeyManager*)value.data.pointer;
            }
        } else {
            ATX_LOG_FINE("no key manager");
        }

        /* check if we need to use a cipher factory */
        if (ATX_SUCCEEDED(ATX_Properties_GetProperty(properties, 
                                                     BLT_CIPHER_FACTORY_PROPERTY, 
                                                     &value))) {
            if (value.type == ATX_PROPERTY_VALUE_TYPE_POINTER) {
                self->cipher_factory = new BLT_Ap4CipherFactoryAdapter((BLT_CipherFactory*)value.data.pointer);
            }
        } else {
            ATX_LOG_FINE("no cipher factory");
        }
    }

    /* setup interfaces */
    ATX_SET_INTERFACE_EX(self, DcfParser, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(self, DcfParser, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE(&self->input,  DcfParserInput,  BLT_MediaPort);
    ATX_SET_INTERFACE(&self->input,  DcfParserInput,  BLT_InputStreamUser);
    ATX_SET_INTERFACE(&self->output, DcfParserOutput, BLT_MediaPort);
    ATX_SET_INTERFACE(&self->output, DcfParserOutput, BLT_InputStreamProvider);
}
/*----------------------------------------------------------------------
|    SdlVideoOutput_Create
+---------------------------------------------------------------------*/
static BLT_Result
SdlVideoOutput_Create(BLT_Module*              module,
                      BLT_Core*                core, 
                      BLT_ModuleParametersType parameters_type,
                      BLT_CString              parameters, 
                      BLT_MediaNode**          object)
{
    SdlVideoOutput* self;
    
    /* check parameters */
    if (parameters == NULL || 
        parameters_type != BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR) {
        return BLT_ERROR_INVALID_PARAMETERS;
    }

    /* allocate memory for the object */
    self = ATX_AllocateZeroMemory(sizeof(SdlVideoOutput));
    if (self == NULL) {
        *object = NULL;
        return BLT_ERROR_OUT_OF_MEMORY;
    }

    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(self, BLT_BaseMediaNode), module, core);

    /* construct the object */

    /* setup the expected media type */
    BLT_MediaType_Init(&self->expected_media_type, BLT_MEDIA_TYPE_ID_VIDEO_RAW);
    /*self->expected_media_type.sample_format = BLT_PCM_SAMPLE_FORMAT_SIGNED_INT_NE;*/

    SdlVideoOutput_CreateWindow(self);
    
    /* setup interfaces */
    ATX_SET_INTERFACE_EX(self, SdlVideoOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(self, SdlVideoOutput, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE   (self, SdlVideoOutput, BLT_PacketConsumer);
    ATX_SET_INTERFACE   (self, SdlVideoOutput, BLT_OutputNode);
    ATX_SET_INTERFACE   (self, SdlVideoOutput, BLT_MediaPort);
    *object = &ATX_BASE_EX(self, BLT_BaseMediaNode, BLT_MediaNode);

    return BLT_SUCCESS;
}
/*----------------------------------------------------------------------
|    DebugOutput_Create
+---------------------------------------------------------------------*/
static BLT_Result
DebugOutput_Create(BLT_Module*              module,
                   BLT_Core*                core, 
                   BLT_ModuleParametersType parameters_type,
                   BLT_CString              parameters, 
                   BLT_MediaNode**          object)
{
    DebugOutput*              self;
    BLT_MediaNodeConstructor* constructor = 
        (BLT_MediaNodeConstructor*)parameters;
    
    ATX_LOG_FINE("DebugOutput::Create");

    /* check parameters */
    if (parameters == NULL || 
        parameters_type != BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR) {
        return BLT_ERROR_INVALID_PARAMETERS;
    }

    /* allocate memory for the object */
    self = ATX_AllocateZeroMemory(sizeof(DebugOutput));
    if (self == NULL) {
        *object = NULL;
        return BLT_ERROR_OUT_OF_MEMORY;
    }

    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(self, BLT_BaseMediaNode), module, core);

    /* keep the media type info */
    BLT_MediaType_Clone(constructor->spec.input.media_type, 
                        &self->expected_media_type); 

    /* setup interfaces */
    ATX_SET_INTERFACE_EX(self, DebugOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(self, DebugOutput, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE(self, DebugOutput, BLT_PacketConsumer);
    ATX_SET_INTERFACE(self, DebugOutput, BLT_MediaPort);
    *object = &ATX_BASE_EX(self, BLT_BaseMediaNode, BLT_MediaNode);

    return BLT_SUCCESS;
}
/*----------------------------------------------------------------------
|    OsxAudioUnitsOutput_Create
+---------------------------------------------------------------------*/
static BLT_Result
OsxAudioUnitsOutput_Create(BLT_Module*              module,
                           BLT_Core*                core, 
                           BLT_ModuleParametersType parameters_type,
                           const void*              parameters, 
                           BLT_MediaNode**          object)
{
    OsxAudioUnitsOutput*      self;
    BLT_MediaNodeConstructor* constructor = (BLT_MediaNodeConstructor*)parameters;
    AudioDeviceID             audio_device_id = 0;
    AudioUnit                 audio_unit = NULL;
    Component                 component;
    ComponentDescription      component_desc;
    ComponentResult           result;
    BLT_Result                blt_result;
    
    /* check parameters */
    if (parameters == NULL || 
        parameters_type != BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR) {
        return BLT_ERROR_INVALID_PARAMETERS;
    }

    /* parse the name */
    if (!ATX_StringsEqualN(constructor->name, "osxau:", 6)) {
        return BLT_ERROR_INTERNAL;
    }

    /* map the name into a device ID */
    blt_result = OsxAudioUnitsOutput_MapDeviceName(constructor->name+6, &audio_device_id);
    if (BLT_FAILED(blt_result)) return blt_result;
    
    /* get the default output audio unit */
    ATX_SetMemory(&component_desc, 0, sizeof(component_desc));
    component_desc.componentType         = kAudioUnitType_Output;
    component_desc.componentSubType      = audio_device_id?kAudioUnitSubType_HALOutput:kAudioUnitSubType_DefaultOutput;
    component_desc.componentManufacturer = kAudioUnitManufacturer_Apple;
    component_desc.componentFlags        = 0;
    component_desc.componentFlagsMask    = 0;
    component = FindNextComponent(NULL, &component_desc);
    if (component == NULL) {
        ATX_LOG_WARNING("FindNextComponent failed");
        return BLT_FAILURE;
    }
    
    /* open the audio unit (we will initialize it later) */
    result = OpenAComponent(component, &audio_unit);
    if (result != noErr) {
        ATX_LOG_WARNING_1("OpenAComponent failed (%d)", (int)result);
        return BLT_FAILURE;
    }

    /* Since SnowLeopard, kAudioHardwarePropertyRunLoop points at the process's main thread.
       Since not all apps service a run loop on the main thread (like command-line apps), we
       need to set the run loop to NULL to tell the HAL to run its own thread for this.
       This is important in order for the HAL to receive events when, for example, the headphones
       are plugged in or out.
       NOTE: this was the default before SnowLeopard (10.6), so we only do this if we're 10.6 or
       after */
    {
        SInt32 major, minor;

        Gestalt(gestaltSystemVersionMajor, &major);
        Gestalt(gestaltSystemVersionMinor, &minor);
        if (major > 10 || (major == 10 && minor >= 6)) {
            ATX_LOG_INFO("configuring the HAL to use its own thread for the run loop");
            CFRunLoopRef null_loop =  NULL;
            AudioObjectPropertyAddress address = { kAudioHardwarePropertyRunLoop, 
                                                   kAudioObjectPropertyScopeGlobal, 
                                                   kAudioObjectPropertyElementMaster };
            AudioObjectSetPropertyData(kAudioObjectSystemObject, &address, 0, NULL, sizeof(CFRunLoopRef), &null_loop);
        }
    }
    
    /* allocate memory for the object */
    self = ATX_AllocateZeroMemory(sizeof(OsxAudioUnitsOutput));
    if (self == NULL) {
        *object = NULL;
        return BLT_ERROR_OUT_OF_MEMORY;
    }

    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(self, BLT_BaseMediaNode), module, core);

    /* construct the object */
    self->audio_device_id            = audio_device_id;
    self->audio_unit                 = audio_unit;
    self->media_type.sample_rate     = 0;
    self->media_type.channel_count   = 0;
    self->media_type.bits_per_sample = 0;

    /* create a lock */
    pthread_mutex_init(&self->lock, NULL);
    
    /* create the packet queue */
    {
        ATX_ListDataDestructor destructor = { NULL, OsxAudioUnitsOutput_QueueItemDestructor };
        ATX_List_CreateEx(&destructor, &self->packet_queue);
        self->max_packets_in_queue = BLT_OSX_AUDIO_UNITS_OUTPUT_DEFAULT_PACKET_QUEUE_SIZE;
    }
    
    /* setup the expected media type */
    BLT_PcmMediaType_Init(&self->expected_media_type);
    self->expected_media_type.sample_format = BLT_PCM_SAMPLE_FORMAT_SIGNED_INT_NE;

    /* setup interfaces */
    ATX_SET_INTERFACE_EX(self, OsxAudioUnitsOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(self, OsxAudioUnitsOutput, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE   (self, OsxAudioUnitsOutput, BLT_PacketConsumer);
    ATX_SET_INTERFACE   (self, OsxAudioUnitsOutput, BLT_OutputNode);
    ATX_SET_INTERFACE   (self, OsxAudioUnitsOutput, BLT_MediaPort);
    ATX_SET_INTERFACE   (self, OsxAudioUnitsOutput, BLT_VolumeControl);
    *object = &ATX_BASE_EX(self, BLT_BaseMediaNode, BLT_MediaNode);

    return BLT_SUCCESS;
}
/*----------------------------------------------------------------------
|    FileOutput_Create
+---------------------------------------------------------------------*/
static BLT_Result
FileOutput_Create(BLT_Module*              module,
                  BLT_Core*                core, 
                  BLT_ModuleParametersType parameters_type,
                  BLT_CString              parameters, 
                  BLT_MediaNode**          object)
{
    FileOutput*               self;
    BLT_MediaNodeConstructor* constructor = (BLT_MediaNodeConstructor*)parameters;
    BLT_Result                result;

    ATX_LOG_FINE("FileOutput::Create");

    /* check parameters */
    *object = NULL;
    if (parameters == NULL || 
        parameters_type != BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR) {
        return BLT_ERROR_INVALID_PARAMETERS;
    }

    /* check the name */
    if (constructor->name == NULL || ATX_StringLength(constructor->name) < 4) {
        return BLT_ERROR_INVALID_PARAMETERS;
    }
        
    /* allocate memory for the object */
    self = ATX_AllocateZeroMemory(sizeof(FileOutput));
    if (self == NULL) {
        return BLT_ERROR_OUT_OF_MEMORY;
    }

    /* construct the inherited object */
    BLT_BaseMediaNode_Construct(&ATX_BASE(self, BLT_BaseMediaNode), module, core);

    /* figure out the media type */
    if (constructor->spec.input.media_type->id == BLT_MEDIA_TYPE_ID_UNKNOWN) {
        /* unknown type, try to figure it out from the file extension */
        BLT_MediaType_Clone(&BLT_MediaType_Unknown, &self->media_type);
        result = FileOutput_DecideMediaType(self, constructor->name);
        if (BLT_FAILED(result)) {
            /* if the type is not found, assume audio/pcm */
            BLT_PcmMediaType pcm_type;
            BLT_PcmMediaType_Init(&pcm_type);
            BLT_MediaType_Clone((BLT_MediaType*)&pcm_type, &self->media_type);
        }
    } else {
        /* use the media type from the input spec */
        BLT_MediaType_Clone(constructor->spec.input.media_type,
                            &self->media_type);
    }

    /* create the output file object */
    result = ATX_File_Create(constructor->name+5, &self->file);
    if (BLT_FAILED(result)) {
        self->file = NULL;
        goto failure;
    }

    /* open the output file */
    result = ATX_File_Open(self->file,
                           ATX_FILE_OPEN_MODE_WRITE  |
                           ATX_FILE_OPEN_MODE_CREATE |
                           ATX_FILE_OPEN_MODE_TRUNCATE);
    if (ATX_FAILED(result)) goto failure;

    /* get the output stream */
    result = ATX_File_GetOutputStream(self->file, &self->stream);
    if (BLT_FAILED(result)) {
        self->stream = NULL;
        goto failure;
    }

    /* setup interfaces */
    ATX_SET_INTERFACE_EX(self, FileOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ATX_SET_INTERFACE_EX(self, FileOutput, BLT_BaseMediaNode, ATX_Referenceable);
    ATX_SET_INTERFACE(self, FileOutput, BLT_OutputStreamProvider);
    ATX_SET_INTERFACE(self, FileOutput, BLT_OutputNode);
    ATX_SET_INTERFACE(self, FileOutput, BLT_MediaPort);
    *object = &ATX_BASE_EX(self, BLT_BaseMediaNode, BLT_MediaNode);

    return BLT_SUCCESS;

 failure:
    FileOutput_Destroy(self);
    *object = NULL;
    return result;
}