/*----------------------------------------------------------------------
|   DcfParser_GetPortByName
+---------------------------------------------------------------------*/
BLT_METHOD
DcfParser_GetPortByName(BLT_MediaNode*  _self,
                        BLT_CString     name,
                        BLT_MediaPort** port)
{
    DcfParser* self = ATX_SELF_EX(DcfParser, BLT_BaseMediaNode, BLT_MediaNode);

    if (ATX_StringsEqual(name, "input")) {
        *port = &ATX_BASE(&self->input, BLT_MediaPort);
        return BLT_SUCCESS;
    } else if (ATX_StringsEqual(name, "output")) {
        *port = &ATX_BASE(&self->output, BLT_MediaPort);
        return BLT_SUCCESS;
    } else {
        *port = NULL;
        return BLT_ERROR_NO_SUCH_PORT;
    }
}
Exemple #2
0
/*----------------------------------------------------------------------
|   CrossFader_GetPortByName
+---------------------------------------------------------------------*/
BLT_METHOD
CrossFader_GetPortByName(BLT_MediaNodeInstance* instance,
                         BLT_CString            name,
                         BLT_MediaPort*         port)
{
    CrossFader* fader = (CrossFader*)instance;

    if (ATX_StringsEqual(name, "input")) {
        ATX_INSTANCE(port)  = (BLT_MediaPortInstance*)fader;
        ATX_INTERFACE(port) = &CrossFaderInputPort_BLT_MediaPortInterface; 
        return BLT_SUCCESS;
    } else if (ATX_StringsEqual(name, "output")) {
        ATX_INSTANCE(port)  = (BLT_MediaPortInstance*)fader;
        ATX_INTERFACE(port) = &CrossFaderOutputPort_BLT_MediaPortInterface; 
        return BLT_SUCCESS;
    } else {
        ATX_CLEAR_OBJECT(port);
        return BLT_ERROR_NO_SUCH_PORT;
    }
}
Exemple #3
0
/*----------------------------------------------------------------------
|   ATX_HttpClient_SetOptionBool
+---------------------------------------------------------------------*/
ATX_Result
ATX_HttpClient_SetOptionBool(ATX_HttpClient* self,
                             ATX_CString     option,
                             ATX_Boolean     value)
{
    if (ATX_StringsEqual(option, ATX_HTTP_CLIENT_OPTION_FOLLOW_REDIRECT)) {
        self->options.follow_redirect = value;
    } else {
        return ATX_ERROR_NO_SUCH_ITEM;
    }

    return ATX_SUCCESS;
}
/*----------------------------------------------------------------------
|   AlsaOutput_GetPortByName
+---------------------------------------------------------------------*/
BLT_METHOD
AlsaOutput_GetPortByName(BLT_MediaNode*  _self,
                          BLT_CString     name,
                          BLT_MediaPort** port)
{
    AlsaOutput* self = ATX_SELF_EX(AlsaOutput, BLT_BaseMediaNode, BLT_MediaNode);

    if (ATX_StringsEqual(name, "input")) {
        *port = &ATX_BASE(self, BLT_MediaPort);
        return BLT_SUCCESS;
    } else {
        *port = NULL;
        return BLT_ERROR_NO_SUCH_PORT;
    }
}
Exemple #5
0
/*----------------------------------------------------------------------
|       ATX_File_Create
+---------------------------------------------------------------------*/
ATX_Result
ATX_File_Create(const char* filename, ATX_File** object)
{
    StdcFile* file;

    /* allocate a new object */
    file = (StdcFile*)ATX_AllocateZeroMemory(sizeof(StdcFile));
    if (file == NULL) {
        *object = NULL;
        return ATX_ERROR_OUT_OF_MEMORY;
    }

    /* construct the object */
    file->name = ATX_String_Create(filename);

    /* get the size */
    if (ATX_StringsEqual(filename, ATX_FILE_STANDARD_INPUT)  ||
        ATX_StringsEqual(filename, ATX_FILE_STANDARD_OUTPUT) ||
        ATX_StringsEqual(filename, ATX_FILE_STANDARD_ERROR)) {
        file->size = 0;
    } else {
        struct stat info;
        if (stat(filename, &info) == 0) {
            file->size = info.st_size;
        } else {
            file->size = 0;
        }
    }

    /* setup the interfaces */
    ATX_SET_INTERFACE(file, StdcFile, ATX_File);
    ATX_SET_INTERFACE(file, StdcFile, ATX_Destroyable);
    *object = &ATX_BASE(file, ATX_File);

    return ATX_SUCCESS;
}
/*----------------------------------------------------------------------
|   DebugOutputModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
DebugOutputModule_Probe(BLT_Module*              self, 
                        BLT_Core*                core,
                        BLT_ModuleParametersType parameters_type,
                        BLT_AnyConst             parameters,
                        BLT_Cardinal*            match)
{
    BLT_COMPILER_UNUSED(self);
    BLT_COMPILER_UNUSED(core);

    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = (BLT_MediaNodeConstructor*)parameters;

            /* the input protocol should be PACKET and the */
            /* output protocol should be NONE              */
            if ((constructor->spec.input.protocol  != BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.input.protocol  != BLT_MEDIA_PORT_PROTOCOL_PACKET) ||
                (constructor->spec.output.protocol != BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.output.protocol != BLT_MEDIA_PORT_PROTOCOL_NONE)) {
                return BLT_FAILURE;
            }

            /* the name should be 'debug' */
            if (constructor->name == NULL ||
                !ATX_StringsEqual(constructor->name, "debug")) {
                return BLT_FAILURE;
            }

            /* always an exact match, since we only respond to our name */
            *match = BLT_MODULE_PROBE_MATCH_EXACT;

            ATX_LOG_FINE_1("DebugOutputModule::Probe - Ok [%d]", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}
/*----------------------------------------------------------------------
|    BLT_Decoder_SetOutput
+---------------------------------------------------------------------*/
BLT_Result
BLT_Decoder_SetOutput(BLT_Decoder* decoder, BLT_CString name, BLT_CString type)
{
    BLT_Result result;

    /* normalize the name and type */
    if (name && name[0] == '\0') name = NULL;
    if (type && type[0] == '\0') type = NULL;

    if (name == NULL) {
        /* if the name is NULL or empty, it means reset */
        BLT_Decoder_OutputChanged(decoder, NULL);
        return BLT_Stream_ResetOutput(decoder->stream);
    } else {
        if (ATX_StringsEqual(name, BLT_DECODER_DEFAULT_OUTPUT_NAME)) {
	        /* if the name is BLT_DECODER_DEFAULT_OUTPUT_NAME, use default */ 
            BLT_CString default_name;
            BLT_CString default_type;
            BLT_Builtins_GetDefaultAudioOutput(&default_name, &default_type);
            name = default_name;
            if (type == NULL) type = default_type;

  	        result = BLT_Stream_SetOutput(decoder->stream, name, type);
	    } else {
            /* set the output of the stream by name */
            result = BLT_Stream_SetOutput(decoder->stream, name, type);
	    }
    }
    
    if (BLT_SUCCEEDED(result)) {
        BLT_MediaNode* node = NULL;
        BLT_Stream_GetOutputNode(decoder->stream, &node);
        BLT_Decoder_OutputChanged(decoder, node);
        ATX_RELEASE_OBJECT(node);
    }

    return result;
}
/*----------------------------------------------------------------------
|   DcfParserModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
DcfParserModule_Probe(BLT_Module*              _self, 
                      BLT_Core*                core,
                      BLT_ModuleParametersType parameters_type,
                      BLT_AnyConst             parameters,
                      BLT_Cardinal*            match)
{
    DcfParserModule* self = ATX_SELF_EX(DcfParserModule, BLT_BaseModule, BLT_Module);
    BLT_COMPILER_UNUSED(core);

    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = 
                (BLT_MediaNodeConstructor*)parameters;

            /* we need the input protocol to be STREAM_PULL and the output */
            /* protocol to be STREAM_PULL                                  */
             if ((constructor->spec.input.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.input.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_STREAM_PULL) ||
                (constructor->spec.output.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.output.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_STREAM_PULL)) {
                return BLT_FAILURE;
            }

            /* we need the input media type to be 'application/vnd.oma.drm.content' */
            /* or 'application/vnd.oma.drm.dcf'                                     */
            if (constructor->spec.input.media_type->id != self->dcf1_type_id &&
                constructor->spec.input.media_type->id != self->dcf2_type_id) {
                return BLT_FAILURE;
            }

            /* the output type should be unknown at this point */
            if (constructor->spec.output.media_type->id != 
                BLT_MEDIA_TYPE_ID_UNKNOWN) {
                return BLT_FAILURE;
            }

            /* compute the match level */
            if (constructor->name != NULL) {
                /* we're being probed by name */
                if (ATX_StringsEqual(constructor->name, "DcfParser")) {
                    /* our name */
                    *match = BLT_MODULE_PROBE_MATCH_EXACT;
                } else {
                    /* not out name */
                    return BLT_FAILURE;
                }
            } else {
                /* we're probed by protocol/type specs only */
                *match = BLT_MODULE_PROBE_MATCH_MAX - 10;
            }

            ATX_LOG_FINE_1("DcfParserModule::Probe - Ok [%d]", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}
Exemple #9
0
/*----------------------------------------------------------------------
|   CrossFaderModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
CrossFaderModule_Probe(BLT_ModuleInstance*      instance, 
                       BLT_Core*                core,
                       BLT_ModuleParametersType parameters_type,
                       BLT_AnyConst             parameters,
                       BLT_Cardinal*            match)
{
    BLT_COMPILER_UNUSED(core);
    BLT_COMPILER_UNUSED(instance);

    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = 
                (BLT_MediaNodeConstructor*)parameters;

            /* we need a name */
            if (constructor->name == NULL ||
                !ATX_StringsEqual(constructor->name, "CrossFader")) {
                return BLT_FAILURE;
            }

            /* the input and output protocols should be PACKET */
            if ((constructor->spec.input.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.input.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_PACKET) ||
                (constructor->spec.output.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.output.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_PACKET)) {
                return BLT_FAILURE;
            }

            /* the input type should be unspecified, or audio/pcm */
            if (!(constructor->spec.input.media_type->id == 
                  BLT_MEDIA_TYPE_ID_AUDIO_PCM) &&
                !(constructor->spec.input.media_type->id ==
                  BLT_MEDIA_TYPE_ID_UNKNOWN)) {
                return BLT_FAILURE;
            }

            /* the output type should be unspecified, or audio/pcm */
            if (!(constructor->spec.output.media_type->id == 
                  BLT_MEDIA_TYPE_ID_AUDIO_PCM) &&
                !(constructor->spec.output.media_type->id ==
                  BLT_MEDIA_TYPE_ID_UNKNOWN)) {
                return BLT_FAILURE;
            }

            /* match level is always exact */
            *match = BLT_MODULE_PROBE_MATCH_EXACT;

            ATX_LOG_FINE_1("CrossFaderModule::Probe - Ok [%d]", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}
Exemple #10
0
/*----------------------------------------------------------------------
|   PcmAdapterModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
PcmAdapterModule_Probe(BLT_Module*              self,  
                       BLT_Core*                core,
                       BLT_ModuleParametersType parameters_type,
                       BLT_AnyConst             parameters,
                       BLT_Cardinal*            match)
{
    BLT_COMPILER_UNUSED(self);
    BLT_COMPILER_UNUSED(core);

    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = 
                (BLT_MediaNodeConstructor*)parameters;

            /* compute match based on specified name */
            if (constructor->name == NULL) {
                *match = BLT_MODULE_PROBE_MATCH_DEFAULT;

                /* the input protocol should be PACKET */
                if (constructor->spec.input.protocol != 
                    BLT_MEDIA_PORT_PROTOCOL_PACKET) {
                    return BLT_FAILURE;
                }

                /* output protocol should be PACKET */
                if (constructor->spec.output.protocol != 
                    BLT_MEDIA_PORT_PROTOCOL_PACKET) {
                    return BLT_FAILURE;
                }

                /* check that the in and out formats are supported */
                if (!BLT_Pcm_CanConvert(constructor->spec.input.media_type, 
                                        constructor->spec.output.media_type)) {
                    return BLT_FAILURE;
                }
            } else {
                /* if a name is specified, it needs to match exactly */
                if (!ATX_StringsEqual(constructor->name, "PcmAdapter")) {
                    return BLT_FAILURE;
                } else {
                    *match = BLT_MODULE_PROBE_MATCH_EXACT;
                }

                /* the input protocol should be PACKET or ANY */
                if (constructor->spec.input.protocol !=
                    BLT_MEDIA_PORT_PROTOCOL_ANY &&
                    constructor->spec.input.protocol != 
                    BLT_MEDIA_PORT_PROTOCOL_PACKET) {
                    return BLT_FAILURE;
                }

                /* output protocol should be PACKET or ANY */
                if ((constructor->spec.output.protocol !=
                    BLT_MEDIA_PORT_PROTOCOL_ANY &&
                    constructor->spec.output.protocol != 
                    BLT_MEDIA_PORT_PROTOCOL_PACKET)) {
                    return BLT_FAILURE;
                }

                /* check that the in and out formats are supported */
                if (!BLT_Pcm_CanConvert(constructor->spec.input.media_type, 
                                        constructor->spec.output.media_type)) {
                    return BLT_FAILURE;
                }
            }

            ATX_LOG_FINE_1("PcmAdapterModule::Probe - Ok [%d]", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}
/*----------------------------------------------------------------------
|   Mp4ParserModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
Mp4ParserModule_Probe(BLT_Module*              _self, 
                      BLT_Core*                core,
                      BLT_ModuleParametersType parameters_type,
                      BLT_AnyConst             parameters,
                      BLT_Cardinal*            match)
{
    Mp4ParserModule* self = ATX_SELF_EX(Mp4ParserModule, BLT_BaseModule, BLT_Module);
    BLT_COMPILER_UNUSED(core);

    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = (BLT_MediaNodeConstructor*)parameters;

            /* check if we're being probed by name */
            if (constructor->name != NULL) {
                /* we're being probed by name */
                if (ATX_StringsEqual(constructor->name, "com.bluetune.parsers.mp4")) {
                    /* our name */
                    *match = BLT_MODULE_PROBE_MATCH_EXACT;
                    return BLT_SUCCESS;
                } else {
                    /* not out name */
                    *match = 0;
                    return BLT_FAILURE;
                }
            }
            
            /* we need the input protocol to be STREAM_PULL and the output */
            /* protocol to be PACKET                                       */
             if ((constructor->spec.input.protocol  != BLT_MEDIA_PORT_PROTOCOL_ANY &&
                  constructor->spec.input.protocol  != BLT_MEDIA_PORT_PROTOCOL_STREAM_PULL) ||
                 (constructor->spec.output.protocol != BLT_MEDIA_PORT_PROTOCOL_ANY &&
                  constructor->spec.output.protocol != BLT_MEDIA_PORT_PROTOCOL_PACKET)) {
                return BLT_FAILURE;
            }

            /* we need the input media type to be 'audio/mp4' or 'video/mp4' */
            if (constructor->spec.input.media_type->id != self->mp4_audio_type_id &&
                constructor->spec.input.media_type->id != self->mp4_video_type_id) {
                return BLT_FAILURE;
            }

            /* the output type should be unknown at this point */
            if (constructor->spec.output.media_type->id != BLT_MEDIA_TYPE_ID_UNKNOWN) {
                return BLT_FAILURE;
            }

            /* set the match level */
            *match = BLT_MODULE_PROBE_MATCH_MAX - 10;

            ATX_LOG_FINE_1("match %d", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}
/*----------------------------------------------------------------------
|   AacDecoderModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
AacDecoderModule_Probe(BLT_Module*              _self, 
                       BLT_Core*                core,
                       BLT_ModuleParametersType parameters_type,
                       BLT_AnyConst             parameters,
                       BLT_Cardinal*            match)
{
    AacDecoderModule* self = ATX_SELF_EX(AacDecoderModule, BLT_BaseModule, BLT_Module);
    BLT_COMPILER_UNUSED(core);
    
    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = 
                (BLT_MediaNodeConstructor*)parameters;

            /* the input and output protocols should be PACKET */
            if ((constructor->spec.input.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.input.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_PACKET) ||
                (constructor->spec.output.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.output.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_PACKET)) {
                return BLT_FAILURE;
            }

            /* the input type should be BLT_MP4_ES_MIME_TYPE */
            if (constructor->spec.input.media_type->id != 
                self->mp4es_type_id) {
                return BLT_FAILURE;
            } else {
                /* check the object type id */
                BLT_Mp4AudioMediaType* media_type = (BLT_Mp4AudioMediaType*)constructor->spec.input.media_type;
                if (media_type->base.stream_type != BLT_MP4_STREAM_TYPE_AUDIO) return BLT_FAILURE;
                if (media_type->base.format_or_object_type_id != BLT_AAC_OBJECT_TYPE_ID_MPEG2_AAC_LC &&
                    media_type->base.format_or_object_type_id != BLT_AAC_OBJECT_TYPE_ID_MPEG4_AUDIO) {
                    return BLT_FAILURE;
                }
                if (media_type->base.format_or_object_type_id == BLT_AAC_OBJECT_TYPE_ID_MPEG4_AUDIO) {
                    /* check that this is AAC LC */
                    AacDecoderConfig decoder_config;
                    if (BLT_FAILED(AacDecoderConfig_Parse(media_type->decoder_info, media_type->decoder_info_length, &decoder_config))) {
                        return BLT_FAILURE;
                    }
                    if (decoder_config.object_type != BLT_AAC_OBJECT_TYPE_AAC_LC &&
                        decoder_config.object_type != BLT_AAC_OBJECT_TYPE_SBR) {
                        return BLT_FAILURE;
                    }
                }
            }

            /* the output type should be unspecified, or audio/pcm */
            if (!(constructor->spec.output.media_type->id == 
                  BLT_MEDIA_TYPE_ID_AUDIO_PCM) &&
                !(constructor->spec.output.media_type->id ==
                  BLT_MEDIA_TYPE_ID_UNKNOWN)) {
                return BLT_FAILURE;
            }

            /* compute the match level */
            if (constructor->name != NULL) {
                /* we're being probed by name */
                if (ATX_StringsEqual(constructor->name, "AacDecoder")) {
                    /* our name */
                    *match = BLT_MODULE_PROBE_MATCH_EXACT;
                } else {
                    /* not our name */
                    return BLT_FAILURE;
                }
            } else {
                /* we're probed by protocol/type specs only */
                *match = BLT_MODULE_PROBE_MATCH_MAX - 10;
            }

            ATX_LOG_FINE_1("AacDecoderModule::Probe - Ok [%d]", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}
/*----------------------------------------------------------------------
|   OsxAudioUnitsOutput_MapDeviceIndex
+---------------------------------------------------------------------*/
static BLT_Result
OsxAudioUnitsOutput_MapDeviceName(const char* name, AudioDeviceID* device_id)
{
    OSStatus       err;
    BLT_Result     result = BLT_ERROR_NO_SUCH_DEVICE;
    UInt32         prop_size = 0;
    AudioDeviceID* devices = NULL;
    unsigned int   device_count = 0;
    ATX_UInt32     device_index = 0;
    unsigned int   device_selector = 1;
    char*          device_name = NULL;
    unsigned int   i;
    
    /* setup a default value */
    *device_id = 0;
    
    /* check the parameters */
    if (name[0] == '\0') return BLT_ERROR_NO_SUCH_DEVICE;
    
    /* parse the name */
    if (name[0] == '#') {
        ++name;
        ATX_LOG_FINE_1("device name = %s", name);
    } else {
        if (BLT_FAILED(ATX_ParseInteger32U(name, &device_index, ATX_FALSE))) {
            return BLT_ERROR_NO_SUCH_DEVICE;
        }
        ATX_LOG_FINE_1("device index = %d", device_index);
        name = NULL;
        
        /* 0 means default */
        if (device_index == 0) {
            /* look at the device's streams */
            AudioDeviceID default_device_id = 0;
            prop_size = sizeof(AudioDeviceID);
            err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &prop_size, &default_device_id);
            if (err == noErr) {
                prop_size = 0;
                err = AudioDeviceGetPropertyInfo(default_device_id, 0, FALSE, kAudioDevicePropertyStreams, &prop_size, NULL);
                if (err == noErr) {
                    ATX_LOG_FINE_1("device has %d streams", (int)prop_size/4);
                }
            }
            return BLT_SUCCESS;
        }
    }
    
    /* ask how many devices exist */
    err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &prop_size, NULL);
    if (err != noErr) {
        ATX_LOG_FINE_1("AudioHardwareGetPropertyInfo failed (%d)", (int)err);
        return 0;
    }
    device_count = prop_size/sizeof(AudioDeviceID);
    ATX_LOG_FINE_1("found %d devices", device_count);
    
    /* allocate memory for the array */
    devices = (AudioDeviceID*)ATX_AllocateZeroMemory(sizeof(AudioDeviceID) * device_count);
    if (devices == NULL) return 0;
    
    /* retrieve the list of device IDs */
    err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &prop_size, devices);
    if (err != noErr) {
        ATX_LOG_FINE_1("AudioHardwareGetProperty(kAudioHardwarePropertyDevices) failed (%d)", (int)err);
        return 0;
    }
    
    /* find the device ID we want */
    for (i=0; i<device_count; i++) {
        /* get the device name */
        err = AudioDeviceGetPropertyInfo(devices[i], 0, false,
                                         kAudioDevicePropertyDeviceName,
                                         &prop_size, NULL);
        if (err == noErr) {
            if (device_name) ATX_FreeMemory(device_name);
            device_name = (char*)ATX_AllocateZeroMemory(prop_size+1);
            err = AudioDeviceGetProperty(devices[i], 0, false,
                                         kAudioDevicePropertyDeviceName,
                                         &prop_size, device_name);
            if (err == noErr) {
                ATX_LOG_FINE_2("device name [%d] = %s", i, device_name);
            }
            /* cleanup the string */
            device_name[prop_size] = '\0'; /* NULL-terminate the string */
            if (prop_size > 0) {
                unsigned int x;
                for (x=prop_size-1; x; x--) {
                    if (device_name[x] == ' ') {
                        device_name[x] = '\0';
                    } else if (device_name[x]) {
                        break;
                    }
                }
            }
        } else {
            continue;
        }
        
        /* look at the device's streams */
        prop_size = 0;
        err = AudioDeviceGetPropertyInfo(devices[i], 0, FALSE, kAudioDevicePropertyStreams, &prop_size, NULL);
        if (err != noErr || prop_size == 0) {
            ATX_LOG_FINE("skipping device (not an output)");
            continue;
        }

        if (name) {
            /* look for a match by name */
            if (ATX_StringsEqual(device_name, name)) {
                *device_id = devices[i];
                ATX_LOG_FINE("device selected as output");
                result = BLT_SUCCESS;
                break;
            }
        } else {
            /* look for a match by index */
            if (device_selector++ == device_index) {
                *device_id = devices[i];
                ATX_LOG_FINE("device selected as output");
                result = BLT_SUCCESS;
                break;
            }
        }
    }
    
    if (device_name) ATX_FreeMemory(device_name);
    if (devices)     ATX_FreeMemory(devices);
    
    return result;
}
/*----------------------------------------------------------------------
|   WaveFormatterModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
WaveFormatterModule_Probe(BLT_Module*              _self, 
                          BLT_Core*                core,
                          BLT_ModuleParametersType parameters_type,
                          BLT_AnyConst             parameters,
                          BLT_Cardinal*            match)
{
    WaveFormatterModule* self = ATX_SELF_EX(WaveFormatterModule, BLT_BaseModule, BLT_Module);
    BLT_COMPILER_UNUSED(core);

    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = 
                (BLT_MediaNodeConstructor*)parameters;

            /* the input protocol should be STREAM_PUSH and the */
            /* output protocol should be STREAM_PUSH            */
            if ((constructor->spec.input.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.input.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_STREAM_PUSH) ||
                (constructor->spec.output.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.output.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_STREAM_PUSH)) {
                return BLT_FAILURE;
            }

            /* the input type should be audio/pcm */
            if (constructor->spec.input.media_type->id !=
                BLT_MEDIA_TYPE_ID_AUDIO_PCM) {
                return BLT_FAILURE;
            }

            /* compute the match level */
            if (constructor->name != NULL) {
                /* we're being probed by name */
                if (ATX_StringsEqual(constructor->name, "WaveFormatter")) {
                    /* our name */
                    *match = BLT_MODULE_PROBE_MATCH_EXACT;
                } else {
                    /* not our name */
                    return BLT_FAILURE;
                }
            } else {
                /* we're probed by protocol/type specs only */

                /* the output type should be audio/wav */
                if (constructor->spec.output.media_type->id !=
                    self->wav_type_id) {
                    return BLT_FAILURE;
                }

                *match = BLT_MODULE_PROBE_MATCH_MAX - 10;
            }

            ATX_LOG_FINE_1("WaveFormatterModule::Probe - Ok [%d]", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}