⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pa_jack.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * $Id: pa_jack.c,v 1.5 2004/06/09 06:41:17 dmazzoni Exp $ * PortAudio Portable Real-Time Audio Library * Latest Version at: http://www.portaudio.com * JACK Implementation by Joshua Haberman * * Copyright (c) 2002 Joshua Haberman <joshua@haberman.com> * * Based on the Open Source API proposed by Ross Bencina * Copyright (c) 1999-2002 Ross Bencina, Phil Burk * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that * they can be incorporated into the canonical version. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */#include <string.h>#include <regex.h>#include <stdlib.h>#include <stdio.h>#include <jack/types.h>#include <jack/jack.h>#include "pa_util.h"#include "pa_hostapi.h"#include "pa_stream.h"#include "pa_process.h"#include "pa_allocation.h"#include "pa_cpuload.h"PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi,                           PaHostApiIndex hostApiIndex );/* * Functions that directly map to the PortAudio stream interface */static void Terminate( struct PaUtilHostApiRepresentation *hostApi );static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,                                  const PaStreamParameters *inputParameters,                                  const PaStreamParameters *outputParameters,                                  double sampleRate );static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,                           PaStream** s,                           const PaStreamParameters *inputParameters,                           const PaStreamParameters *outputParameters,                           double sampleRate,                           unsigned long framesPerBuffer,                           PaStreamFlags streamFlags,                           PaStreamCallback *streamCallback,                           void *userData );static PaError CloseStream( PaStream* stream );static PaError StartStream( PaStream *stream );static PaError StopStream( PaStream *stream );static PaError AbortStream( PaStream *stream );static PaError IsStreamStopped( PaStream *s );static PaError IsStreamActive( PaStream *stream );static PaTime GetStreamInputLatency( PaStream *stream );static PaTime GetStreamOutputLatency( PaStream *stream );static PaTime GetStreamTime( PaStream *stream );static double GetStreamCpuLoad( PaStream* stream );/*static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );static signed long GetStreamReadAvailable( PaStream* stream );static signed long GetStreamWriteAvailable( PaStream* stream );*//* * Data specific to this API */typedef struct{    PaUtilHostApiRepresentation commonHostApiRep;    PaUtilStreamInterface callbackStreamInterface;    PaUtilAllocationGroup *deviceInfoMemory;    jack_client_t *jack_client;    PaHostApiIndex hostApiIndex;}PaJackHostApiRepresentation;#define MAX_CLIENTS 100#define TRUE 1#define FALSE 0/* * Functions specific to this API */static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi );static int JackCallback( jack_nframes_t frames, void *userData );/* * * Implementation * *//* BuildDeviceList(): * * The process of determining a list of PortAudio "devices" from * JACK's client/port system is fairly involved, so it is separated * into its own routine. */static PaError BuildDeviceList( PaJackHostApiRepresentation *jackApi ){    /* Utility macros for the repetitive process of allocating memory */    /* ... MALLOC: allocate memory as part of the device list     * allocation group */#define MALLOC(size) \     (PaUtil_GroupAllocateMemory( jackApi->deviceInfoMemory, (size) ))    /* ... MEMVERIFY: make sure we didn't get NULL */#define MEMVERIFY(ptr) \    if( (ptr) == NULL ) return paInsufficientMemory;    /* JACK has no concept of a device.  To JACK, there are clients     * which have an arbitrary number of ports.  To make this     * intelligible to PortAudio clients, we will group each JACK client     * into a device, and make each port of that client a channel */    PaUtilHostApiRepresentation *commonApi = &jackApi->commonHostApiRep;    const char **jack_ports;    char *client_names[MAX_CLIENTS];    int num_clients = 0;    int port_index, client_index, i;    double *globalSampleRate;    regex_t port_regex;    /* since we are rebuilding the list of devices, free all memory     * associated with the previous list */    PaUtil_FreeAllAllocations( jackApi->deviceInfoMemory );    /* We can only retrieve the list of clients indirectly, by first     * asking for a list of all ports, then parsing the port names     * according to the client_name:port_name convention (which is     * enforced by jackd) */    jack_ports = jack_get_ports( jackApi->jack_client, "", "", 0 );    if( jack_ports == NULL )        return paUnanticipatedHostError;    /* Parse the list of ports, using a regex to grab the client names */    regcomp( &port_regex, "^[^:]*", REG_EXTENDED );    /* Build a list of clients from the list of ports */    for( port_index = 0; jack_ports[port_index] != NULL; port_index++ )    {        int client_seen;        regmatch_t match_info;        char tmp_client_name[100];        /* extract the client name from the port name, using a regex         * that parses the clientname:portname syntax */        regexec( &port_regex, jack_ports[port_index], 1, &match_info, 0 );        memcpy( tmp_client_name, &jack_ports[port_index][match_info.rm_so],                match_info.rm_eo - match_info.rm_so );        tmp_client_name[ match_info.rm_eo - match_info.rm_so ] = '\0';        /* do we know about this port's client yet? */        client_seen = FALSE;        for( i = 0; i < num_clients; i++ )            if( strcmp( tmp_client_name, client_names[i] ) == 0 )                client_seen = TRUE;        if( client_seen == FALSE )        {            client_names[num_clients] = (char*)MALLOC(strlen(tmp_client_name) + 1);            MEMVERIFY( client_names[num_clients] );            /* The alsa_pcm client should go in spot 0.  If this             * is the alsa_pcm client AND we are NOT about to put             * it in spot 0 put it in spot 0 and move whatever             * was already in spot 0 to the end. */            if( strcmp( "alsa_pcm", tmp_client_name ) == 0 && num_clients > 0 )            {                /* alsa_pcm goes in spot 0 */                strcpy( client_names[ num_clients ], client_names[0] );                strcpy( client_names[0], "alsa_pcm" );                num_clients++;            }            else            {                /* put the new client at the end of the client list */                strcpy( client_names[ num_clients ], tmp_client_name );                num_clients++;            }        }    }    free( jack_ports );    /* Now we have a list of clients, which will become the list of     * PortAudio devices. */    commonApi->info.deviceCount = num_clients;    commonApi->info.defaultInputDevice = 0;    commonApi->info.defaultOutputDevice = 0;    /* there is one global sample rate all clients must conform to */    globalSampleRate = (double*)MALLOC( sizeof(double) );    MEMVERIFY( globalSampleRate );    *globalSampleRate = jack_get_sample_rate( jackApi->jack_client );    commonApi->deviceInfos = (PaDeviceInfo**)MALLOC( sizeof(PaDeviceInfo*) *                                                     num_clients );    MEMVERIFY(commonApi->deviceInfos);    /* Create a PaDeviceInfo structure for every client */    for( client_index = 0; client_index < num_clients; client_index++ )    {        char regex_pattern[100];        PaDeviceInfo *curDevInfo;        curDevInfo = (PaDeviceInfo*)MALLOC( sizeof(PaDeviceInfo) );        MEMVERIFY( curDevInfo );        curDevInfo->name = (char*)MALLOC( strlen(client_names[client_index]) + 1 );        MEMVERIFY( curDevInfo->name );        strcpy( (char*)curDevInfo->name, client_names[client_index] );        curDevInfo->structVersion = 2;        curDevInfo->hostApi = jackApi->hostApiIndex;        /* JACK is very inflexible: there is one sample rate the whole         * system must run at, and all clients must speak IEEE float. */        curDevInfo->defaultSampleRate = *globalSampleRate;        /* To determine how many input and output channels are available,         * we re-query jackd with more specific parameters. */        sprintf( regex_pattern, "%s:.*", client_names[client_index] );        /* ... what are your output ports (that we could input to)? */        jack_ports = jack_get_ports( jackApi->jack_client, regex_pattern,                                     NULL, JackPortIsOutput);        curDevInfo->maxInputChannels = 0;        if (jack_ports) {           for( i = 0; jack_ports[i] != NULL ; i++)           {              /* The number of ports returned is the number of output channels.               * We don't care what they are, we just care how many */              curDevInfo->maxInputChannels++;           }           free(jack_ports);        }        /* ... what are your input ports (that we could output to)? */        jack_ports = jack_get_ports( jackApi->jack_client, regex_pattern,                                     NULL, JackPortIsInput);        if (jack_ports) {           curDevInfo->maxOutputChannels = 0;           for( i = 0; jack_ports[i] != NULL ; i++)           {              /* The number of ports returned is the number of input channels.               * We don't care what they are, we just care how many */              curDevInfo->maxOutputChannels++;           }           free(jack_ports);        }        curDevInfo->defaultLowInputLatency = 0.;  /* IMPLEMENT ME */        curDevInfo->defaultLowOutputLatency = 0.;  /* IMPLEMENT ME */        curDevInfo->defaultHighInputLatency = 0.;  /* IMPLEMENT ME */        curDevInfo->defaultHighOutputLatency = 0.;  /* IMPLEMENT ME */          /* Add this client to the list of devices */        commonApi->deviceInfos[client_index] = curDevInfo;    }#undef MALLOC#undef MEMVERIFY    return paNoError;}PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi,                           PaHostApiIndex hostApiIndex ){    PaError result = paNoError;    PaJackHostApiRepresentation *jackHostApi;    jackHostApi = (PaJackHostApiRepresentation*)        PaUtil_AllocateMemory( sizeof(PaJackHostApiRepresentation) );    if( !jackHostApi )    {        result = paInsufficientMemory;        goto error;    }    jackHostApi->deviceInfoMemory = NULL;    /* Try to become a client of the JACK server.  If we cannot do     * this, than this API cannot be used. */    jackHostApi->jack_client = jack_client_new( "PortAudio client" );    if( jackHostApi->jack_client == 0 )    {       /* the V19 development docs say that if an implementation        * detects that it cannot be used, it should return a NULL        * interface and paNoError */       result = paNoError;       *hostApi = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -