diff --git a/src/include/sound.h b/src/include/sound.h index 402a179d..5c3d2f9d 100644 --- a/src/include/sound.h +++ b/src/include/sound.h @@ -100,7 +100,7 @@ public: virtual size_t Write_stereo(double *, double *, size_t) = 0; virtual size_t Read(float *, size_t) = 0; virtual void flush(unsigned dir = UINT_MAX) = 0; - virtual bool must_close(void) = 0; + virtual bool must_close(int dir = 0) = 0; #if USE_SNDFILE void get_file_params(const char* def_fname, const char** fname, int* format); int Capture(bool val); @@ -150,7 +150,7 @@ public: size_t Write(double *, size_t); size_t Write_stereo(double *, double *, size_t); size_t Read(float *, size_t); - bool must_close(void) { return true; } + bool must_close(int dir = 0) { return true; } void flush(unsigned dir = UINT_MAX) { wait_till_finished(); } private: @@ -193,13 +193,14 @@ public: size_t Write(double *buf, size_t count); size_t Write_stereo(double *bufleft, double *bufright, size_t count); size_t Read(float *buf, size_t count); - bool must_close(void); + bool must_close(int dir = 0); void flush(unsigned dir = UINT_MAX); private: void src_data_reset(unsigned dir); static long src_read_cb(void* arg, float** data); size_t resample_write(float* buf, size_t count); + device_iterator name_to_device(const std::string& name); void init_stream(unsigned dir); void start_stream(unsigned dir); void pause_stream(unsigned dir); @@ -276,7 +277,7 @@ public: size_t Write(double* buf, size_t count); size_t Write_stereo(double* bufleft, double* bufright, size_t count); size_t Read(float *buf, size_t count); - bool must_close(void) { return false; } + bool must_close(int dir = 0) { return false; } void flush(unsigned dir = UINT_MAX); private: @@ -323,7 +324,7 @@ public: size_t Write(double* buf, size_t count); size_t Write_stereo(double* bufleft, double* bufright, size_t count); size_t Read(float *buf, size_t count); - bool must_close(void) { return false; } + bool must_close(int dir = 0) { return false; } void flush(unsigned) { } }; diff --git a/src/soundcard/sound.cxx b/src/soundcard/sound.cxx index 9d0ab959..ef0438c0 100644 --- a/src/soundcard/sound.cxx +++ b/src/soundcard/sound.cxx @@ -860,7 +860,19 @@ int SoundPort::Open(int mode, int freq) // do we need to (re)initialise the streams? int ret = 0; int sr[2] = { progdefaults.in_sample_rate, progdefaults.out_sample_rate }; - for (size_t i = 0; i < 2; i++) { + + // initialize stream if it is a JACK device, regardless of mode + device_iterator idev; + if (mode == O_WRONLY && (idev = name_to_device(sd[0].device)) != devs.end() && + Pa_GetHostApiInfo((*idev)->hostApi)->type == paJACK) + mode = O_RDWR; + if (mode == O_RDONLY && (idev = name_to_device(sd[1].device)) != devs.end() && + Pa_GetHostApiInfo((*idev)->hostApi)->type == paJACK) + mode = O_RDWR; + + size_t start = (mode == O_RDONLY || mode == O_RDWR) ? 0 : 1, + end = (mode == O_WRONLY || mode == O_RDWR) ? 1 : 0; + for (size_t i = start; i <= end; i++) { if ( !(stream_active(i) && (Pa_GetHostApiInfo((*sd[i].idev)->hostApi)->type == paJACK || old_sample_rate == freq || sr[i] != SAMPLE_RATE_AUTO)) ) { @@ -1243,6 +1255,15 @@ long SoundPort::src_read_cb(void* arg, float** data) return vec[0].len / sd[0].params.channelCount; } +SoundPort::device_iterator SoundPort::name_to_device(const string& name) +{ + device_iterator i; + for (i = devs.begin(); i != devs.end(); ++i) + if (name == (*i)->name) + break; + return i; +} + void SoundPort::init_stream(unsigned dir) { const char* dir_str[2] = { "input", "output" }; @@ -1250,12 +1271,8 @@ void SoundPort::init_stream(unsigned dir) LOG_DEBUG("looking for device \"%s\"", sd[dir].device.c_str()); - for (sd[dir].idev = devs.begin(); sd[dir].idev != devs.end(); ++sd[dir].idev) { - if (sd[dir].device == (*sd[dir].idev)->name) { - idx = sd[dir].idev - devs.begin(); // save this device index - break; - } - } + if ((sd[dir].idev = name_to_device(sd[dir].device)) != devs.end()) + idx = sd[dir].idev - devs.begin(); if (idx == paNoDevice) { // no match LOG_ERROR("Could not find device \"%s\", using default device", sd[dir].device.c_str()); PaDeviceIndex def = (dir == 0 ? Pa_GetDefaultInputDevice() : Pa_GetDefaultOutputDevice()); @@ -1450,9 +1467,9 @@ bool SoundPort::full_duplex_device(const PaDeviceInfo* dev) return dev->maxInputChannels > 0 && dev->maxOutputChannels > 0; } -bool SoundPort::must_close(void) +bool SoundPort::must_close(int dir) { - return false; + return Pa_GetHostApiInfo((*sd[dir].idev)->hostApi)->type != paJACK; } // Determine the sample rate that we will use. We try the modem's rate diff --git a/src/trx/trx.cxx b/src/trx/trx.cxx index 7a859d96..829bde1a 100644 --- a/src/trx/trx.cxx +++ b/src/trx/trx.cxx @@ -170,6 +170,8 @@ void trx_trx_receive_loop() active_modem->HistoryON(false); } } + if (scard->must_close(O_RDONLY)) + scard->Close(O_RDONLY); } @@ -218,8 +220,9 @@ void trx_trx_transmit_loop() ReedSolomon->send(false); scard->flush(); - if (scard->must_close()) - scard->Close(); + if (scard->must_close(O_WRONLY)) + scard->Close(O_WRONLY); + } else MilliSleep(10); @@ -269,8 +272,9 @@ void trx_tune_loop() return; } scard->flush(); - if (scard->must_close()) - scard->Close(); + if (scard->must_close(O_WRONLY)) + scard->Close(O_WRONLY); + _trx_tune = 0; } else MilliSleep(10);