git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3207 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.1
@@ -23,6 +23,10 @@ Michael Voigt | |||||
Jackdmp changes log | Jackdmp changes log | ||||
--------------------------- | --------------------------- | ||||
2008-11-16 Stephane Letz <letz@grame.fr> | |||||
* Client and library global context cleanup in case of incorrect shutdown handling (that is applications not correctly closing client after server has shutdown). | |||||
2008-11-27 Stephane Letz <letz@grame.fr> | 2008-11-27 Stephane Letz <letz@grame.fr> | ||||
* Report ringbuffer.c fixes from jack1. | * Report ringbuffer.c fixes from jack1. | ||||
@@ -259,7 +259,7 @@ static inline void WaitGraphChange() | |||||
graph change in RT context (just read the current graph state). | graph change in RT context (just read the current graph state). | ||||
*/ | */ | ||||
if (jack_tls_get(gRealTime) == NULL) { | |||||
if (jack_tls_get(JackGlobals::fRealTime) == NULL) { | |||||
JackGraphManager* manager = GetGraphManager(); | JackGraphManager* manager = GetGraphManager(); | ||||
JackEngineControl* control = GetEngineControl(); | JackEngineControl* control = GetEngineControl(); | ||||
assert(manager); | assert(manager); | ||||
@@ -283,14 +283,14 @@ EXPORT void jack_set_info_function (print_function func) | |||||
EXPORT jack_client_t* jack_client_new(const char* client_name) | EXPORT jack_client_t* jack_client_new(const char* client_name) | ||||
{ | { | ||||
assert(gOpenMutex); | |||||
gOpenMutex->Lock(); | |||||
assert(JackGlobals::fOpenMutex); | |||||
JackGlobals::fOpenMutex->Lock(); | |||||
jack_error("jack_client_new: deprecated"); | jack_error("jack_client_new: deprecated"); | ||||
int options = JackUseExactName; | int options = JackUseExactName; | ||||
if (getenv("JACK_START_SERVER") == NULL) | if (getenv("JACK_START_SERVER") == NULL) | ||||
options |= JackNoStartServer; | options |= JackNoStartServer; | ||||
jack_client_t* res = jack_client_open_aux(client_name, (jack_options_t)options, NULL, NULL); | jack_client_t* res = jack_client_open_aux(client_name, (jack_options_t)options, NULL, NULL); | ||||
gOpenMutex->Unlock(); | |||||
JackGlobals::fOpenMutex->Unlock(); | |||||
return res; | return res; | ||||
} | } | ||||
@@ -628,7 +628,7 @@ EXPORT int jack_port_set_name(jack_port_t* port, const char* name) | |||||
JackGraphManager* manager = GetGraphManager(); | JackGraphManager* manager = GetGraphManager(); | ||||
int refnum; | int refnum; | ||||
if (manager && ((refnum = manager->GetPort(myport)->GetRefNum()) > 0)) { | if (manager && ((refnum = manager->GetPort(myport)->GetRefNum()) > 0)) { | ||||
JackClient* client = JackClient::fClientTable[refnum]; | |||||
JackClient* client = JackGlobals::fClientTable[refnum]; | |||||
assert(client); | assert(client); | ||||
return client->PortRename(myport, name); | return client->PortRename(myport, name); | ||||
} else { | } else { | ||||
@@ -37,8 +37,6 @@ using namespace std; | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
JackClient* JackClient::fClientTable[CLIENT_NUM] = {}; | |||||
#define IsRealTime() ((fProcess != NULL) | (fThreadFun != NULL) | (fSync != NULL) | (fTimebase != NULL)) | #define IsRealTime() ((fProcess != NULL) | (fThreadFun != NULL) | (fSync != NULL) | (fTimebase != NULL)) | ||||
JackClient::JackClient():fThread(this) | JackClient::JackClient():fThread(this) | ||||
@@ -88,8 +86,8 @@ int JackClient::Close() | |||||
Deactivate(); | Deactivate(); | ||||
fChannel->Stop(); // Channels is stopped first to avoid receiving notifications while closing | fChannel->Stop(); // Channels is stopped first to avoid receiving notifications while closing | ||||
// Request close only is server is still running | |||||
if (GetClientControl()->fServer) { | |||||
// Request close only if server is still running | |||||
if (JackGlobals::fServerRunning) { | |||||
fChannel->ClientClose(GetClientControl()->fRefNum, &result); | fChannel->ClientClose(GetClientControl()->fRefNum, &result); | ||||
} else { | } else { | ||||
jack_log("JackClient::Close server is shutdown"); | jack_log("JackClient::Close server is shutdown"); | ||||
@@ -97,7 +95,7 @@ int JackClient::Close() | |||||
fChannel->Close(); | fChannel->Close(); | ||||
fSynchroTable[GetClientControl()->fRefNum].Disconnect(); | fSynchroTable[GetClientControl()->fRefNum].Disconnect(); | ||||
fClientTable[GetClientControl()->fRefNum] = NULL; | |||||
JackGlobals::fClientTable[GetClientControl()->fRefNum] = NULL; | |||||
return result; | return result; | ||||
} | } | ||||
@@ -359,7 +357,7 @@ int JackClient::StartThread() | |||||
*/ | */ | ||||
bool JackClient::Execute() | bool JackClient::Execute() | ||||
{ | { | ||||
if (!jack_tls_set(gRealTime, this)) | |||||
if (!jack_tls_set(JackGlobals::fRealTime, this)) | |||||
jack_error("failed to set thread realtime key"); | jack_error("failed to set thread realtime key"); | ||||
if (GetEngineControl()->fRealTime) | if (GetEngineControl()->fRealTime) | ||||
@@ -596,11 +594,7 @@ ShutDown is called: | |||||
void JackClient::ShutDown() | void JackClient::ShutDown() | ||||
{ | { | ||||
jack_log("ShutDown"); | jack_log("ShutDown"); | ||||
// Be sure client is already started | |||||
if (GetClientControl()) { | |||||
GetClientControl()->fServer = false; | |||||
} | |||||
JackGlobals::fServerRunning = false; | |||||
if (fShutdown) { | if (fShutdown) { | ||||
fShutdown(fShutdownArg); | fShutdown(fShutdownArg); | ||||
@@ -87,8 +87,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
detail::JackClientChannelInterface* fChannel; | detail::JackClientChannelInterface* fChannel; | ||||
JackSynchro* fSynchroTable; | JackSynchro* fSynchroTable; | ||||
std::list<jack_port_id_t> fPortList; | std::list<jack_port_id_t> fPortList; | ||||
bool fServerRunning; | |||||
int StartThread(); | int StartThread(); | ||||
void SetupDriverSync(bool freewheel); | void SetupDriverSync(bool freewheel); | ||||
bool IsActive(); | bool IsActive(); | ||||
@@ -98,7 +97,6 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
virtual int ClientNotifyImp(int refnum, const char* name, int notify, int sync, int value1, int value); | virtual int ClientNotifyImp(int refnum, const char* name, int notify, int sync, int value1, int value); | ||||
// Fons Adriaensen thread model | |||||
inline bool WaitFirstSync(); | inline bool WaitFirstSync(); | ||||
inline void ExecuteThread(); | inline void ExecuteThread(); | ||||
inline bool WaitSync(); | inline bool WaitSync(); | ||||
@@ -140,7 +138,6 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
virtual int PortDisconnect(jack_port_id_t src); | virtual int PortDisconnect(jack_port_id_t src); | ||||
virtual int PortIsMine(jack_port_id_t port_index); | virtual int PortIsMine(jack_port_id_t port_index); | ||||
virtual int PortRename(jack_port_id_t port_index, const char* name); | virtual int PortRename(jack_port_id_t port_index, const char* name); | ||||
// Transport | // Transport | ||||
@@ -185,9 +182,6 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
// JackRunnableInterface interface | // JackRunnableInterface interface | ||||
bool Init(); | bool Init(); | ||||
bool Execute(); | bool Execute(); | ||||
static JackClient* fClientTable[CLIENT_NUM]; | |||||
}; | }; | ||||
// Each "side" server and client will implement this to get the shared graph manager, engine control and inter-process synchro table. | // Each "side" server and client will implement this to get the shared graph manager, engine control and inter-process synchro table. | ||||
@@ -43,7 +43,6 @@ struct JackClientControl : public JackShmMemAble | |||||
int fRefNum; | int fRefNum; | ||||
int fPID; | int fPID; | ||||
bool fActive; | bool fActive; | ||||
bool fServer; | |||||
JackClientControl(const char* name, int pid, int refnum) | JackClientControl(const char* name, int pid, int refnum) | ||||
{ | { | ||||
@@ -78,7 +77,6 @@ struct JackClientControl : public JackShmMemAble | |||||
fTransportSync = false; | fTransportSync = false; | ||||
fTransportTimebase = false; | fTransportTimebase = false; | ||||
fActive = false; | fActive = false; | ||||
fServer = true; | |||||
} | } | ||||
}; | }; | ||||
@@ -27,9 +27,11 @@ | |||||
int jack_verbose = 0; | int jack_verbose = 0; | ||||
using namespace Jack; | |||||
void change_thread_log_function(jack_log_function_t log_function) | void change_thread_log_function(jack_log_function_t log_function) | ||||
{ | { | ||||
if (!jack_tls_set(g_key_log_function, (void*)log_function)) | |||||
if (!jack_tls_set(JackGlobals::fKeyLogFunction, (void*)log_function)) | |||||
{ | { | ||||
jack_error("failed to set thread log function"); | jack_error("failed to set thread log function"); | ||||
} | } | ||||
@@ -37,7 +39,7 @@ void change_thread_log_function(jack_log_function_t log_function) | |||||
SERVER_EXPORT void set_threaded_log_function() | SERVER_EXPORT void set_threaded_log_function() | ||||
{ | { | ||||
change_thread_log_function(Jack::JackMessageBufferAdd); | |||||
change_thread_log_function(JackMessageBufferAdd); | |||||
} | } | ||||
void jack_log_function(int level, const char *message) | void jack_log_function(int level, const char *message) | ||||
@@ -74,7 +76,7 @@ static void jack_format_and_log(int level, const char *prefix, const char *fmt, | |||||
vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap); | vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap); | ||||
log_function = (jack_log_function_t)jack_tls_get(g_key_log_function); | |||||
log_function = (jack_log_function_t)jack_tls_get(JackGlobals::fKeyLogFunction); | |||||
/* if log function is not overriden for thread, use default one */ | /* if log function is not overriden for thread, use default one */ | ||||
if (log_function == NULL) | if (log_function == NULL) | ||||
@@ -19,10 +19,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
#include "JackGlobals.h" | #include "JackGlobals.h" | ||||
jack_tls_key gRealTime; | |||||
static bool gKeyRealtimeInitialized = jack_tls_allocate_key(&gRealTime); | |||||
namespace Jack | |||||
{ | |||||
jack_tls_key g_key_log_function; | |||||
static bool g_key_log_function_initialized = jack_tls_allocate_key(&g_key_log_function); | |||||
jack_tls_key JackGlobals::fRealTime; | |||||
static bool gKeyRealtimeInitialized = jack_tls_allocate_key(&JackGlobals::fRealTime); | |||||
JackMutex* gOpenMutex = new JackMutex(); | |||||
jack_tls_key JackGlobals::fKeyLogFunction; | |||||
static bool fKeyLogFunctionInitialized = jack_tls_allocate_key(&JackGlobals::fKeyLogFunction); | |||||
JackMutex* JackGlobals::fOpenMutex = new JackMutex(); | |||||
bool JackGlobals::fServerRunning = false; | |||||
JackClient* JackGlobals::fClientTable[CLIENT_NUM] = {}; | |||||
} // end of namespace |
@@ -21,11 +21,24 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
#define __JackGlobals__ | #define __JackGlobals__ | ||||
#include "JackPlatformPlug.h" | #include "JackPlatformPlug.h" | ||||
#include "JackConstants.h" | |||||
#include "JackClient.h" | |||||
using namespace Jack; | |||||
namespace Jack | |||||
{ | |||||
extern jack_tls_key gRealTime; | |||||
extern jack_tls_key g_key_log_function; | |||||
extern JackMutex* gOpenMutex; | |||||
// Globals used for client management on server or libray side. | |||||
struct JackGlobals { | |||||
static jack_tls_key fRealTime; | |||||
static jack_tls_key fKeyLogFunction; | |||||
static JackMutex* fOpenMutex; | |||||
static bool fServerRunning; | |||||
static JackClient* fClientTable[]; | |||||
}; | |||||
} // end of namespace | |||||
#endif | #endif |
@@ -141,7 +141,9 @@ int JackInternalClient::Open(const char* server_name, const char* name, jack_opt | |||||
} | } | ||||
SetupDriverSync(false); | SetupDriverSync(false); | ||||
fClientTable[fClientControl.fRefNum] = this; | |||||
JackGlobals::fClientTable[fClientControl.fRefNum] = this; | |||||
JackGlobals::fServerRunning = true; | |||||
jack_log("JackInternalClient::Open name = %s refnum = %ld", name_res, fClientControl.fRefNum); | |||||
return 0; | return 0; | ||||
error: | error: | ||||
@@ -113,20 +113,20 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt | |||||
EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | ||||
{ | { | ||||
assert(gOpenMutex); | |||||
gOpenMutex->Lock(); | |||||
assert(JackGlobals::fOpenMutex); | |||||
JackGlobals::fOpenMutex->Lock(); | |||||
va_list ap; | va_list ap; | ||||
va_start(ap, status); | va_start(ap, status); | ||||
jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap); | jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap); | ||||
va_end(ap); | va_end(ap); | ||||
gOpenMutex->Unlock(); | |||||
JackGlobals::fOpenMutex->Unlock(); | |||||
return res; | return res; | ||||
} | } | ||||
EXPORT int jack_client_close(jack_client_t* ext_client) | EXPORT int jack_client_close(jack_client_t* ext_client) | ||||
{ | { | ||||
assert(gOpenMutex); | |||||
gOpenMutex->Lock(); | |||||
assert(JackGlobals::fOpenMutex); | |||||
JackGlobals::fOpenMutex->Lock(); | |||||
int res = -1; | int res = -1; | ||||
jack_log("jack_client_close"); | jack_log("jack_client_close"); | ||||
JackClient* client = (JackClient*)ext_client; | JackClient* client = (JackClient*)ext_client; | ||||
@@ -138,7 +138,7 @@ EXPORT int jack_client_close(jack_client_t* ext_client) | |||||
JackLibGlobals::Destroy(); // jack library destruction | JackLibGlobals::Destroy(); // jack library destruction | ||||
jack_log("jack_client_close res = %d", res); | jack_log("jack_client_close res = %d", res); | ||||
} | } | ||||
gOpenMutex->Unlock(); | |||||
JackGlobals::fOpenMutex->Unlock(); | |||||
return res; | return res; | ||||
} | } | ||||
@@ -70,7 +70,7 @@ JackLibClient::~JackLibClient() | |||||
int JackLibClient::Open(const char* server_name, const char* name, jack_options_t options, jack_status_t* status) | int JackLibClient::Open(const char* server_name, const char* name, jack_options_t options, jack_status_t* status) | ||||
{ | { | ||||
int shared_engine, shared_client, shared_graph, result; | int shared_engine, shared_client, shared_graph, result; | ||||
jack_log("JackLibClient::Open %s", name); | |||||
jack_log("JackLibClient::Open name = %s", name); | |||||
snprintf(fServerName, sizeof(fServerName), server_name); | snprintf(fServerName, sizeof(fServerName), server_name); | ||||
@@ -113,7 +113,8 @@ int JackLibClient::Open(const char* server_name, const char* name, jack_options_ | |||||
goto error; | goto error; | ||||
} | } | ||||
fClientTable[GetClientControl()->fRefNum] = this; | |||||
JackGlobals::fClientTable[GetClientControl()->fRefNum] = this; | |||||
JackGlobals::fServerRunning = true; | |||||
jack_log("JackLibClient::Open name = %s refnum = %ld", name_res, GetClientControl()->fRefNum); | jack_log("JackLibClient::Open name = %s refnum = %ld", name_res, GetClientControl()->fRefNum); | ||||
return 0; | return 0; | ||||
@@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
#include "JackGraphManager.h" | #include "JackGraphManager.h" | ||||
#include "JackMessageBuffer.h" | #include "JackMessageBuffer.h" | ||||
#include "JackTime.h" | #include "JackTime.h" | ||||
#include "JackClient.h" | |||||
#include "JackError.h" | #include "JackError.h" | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <signal.h> | #include <signal.h> | ||||
@@ -44,7 +45,7 @@ struct JackLibGlobals | |||||
{ | { | ||||
JackShmReadWritePtr<JackGraphManager> fGraphManager; /*! Shared memory Port manager */ | JackShmReadWritePtr<JackGraphManager> fGraphManager; /*! Shared memory Port manager */ | ||||
JackShmReadWritePtr<JackEngineControl> fEngineControl; /*! Shared engine control */ // transport engine has to be writable | JackShmReadWritePtr<JackEngineControl> fEngineControl; /*! Shared engine control */ // transport engine has to be writable | ||||
JackSynchro fSynchroTable[CLIENT_NUM]; /*! Shared synchro table */ | |||||
JackSynchro fSynchroTable[CLIENT_NUM]; /*! Shared synchro table */ | |||||
sigset_t fProcessSignals; | sigset_t fProcessSignals; | ||||
static int fClientCount; | static int fClientCount; | ||||
@@ -86,6 +87,26 @@ struct JackLibGlobals | |||||
static void Init() | static void Init() | ||||
{ | { | ||||
if (!JackGlobals::fServerRunning && fClientCount > 0) { | |||||
// Cleanup remaining clients | |||||
jack_error("Jack server was closed but clients are still allocated, cleanup..."); | |||||
for (int i = 0; i < CLIENT_NUM; i++) { | |||||
JackClient* client = JackGlobals::fClientTable[i]; | |||||
if (client) { | |||||
jack_error("Cleanup client ref = %d", i); | |||||
client->Close(); | |||||
delete client; | |||||
JackGlobals::fClientTable[CLIENT_NUM] = NULL; | |||||
} | |||||
} | |||||
// Cleanup global context | |||||
fClientCount = 0; | |||||
delete fGlobals; | |||||
fGlobals = NULL; | |||||
} | |||||
if (fClientCount++ == 0 && !fGlobals) { | if (fClientCount++ == 0 && !fGlobals) { | ||||
jack_log("JackLibGlobals Init %x", fGlobals); | jack_log("JackLibGlobals Init %x", fGlobals); | ||||
InitTime(); | InitTime(); | ||||
@@ -115,20 +115,20 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt | |||||
EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | ||||
{ | { | ||||
assert(gOpenMutex); | |||||
gOpenMutex->Lock(); | |||||
assert(JackGlobals::fOpenMutex); | |||||
JackGlobals::fOpenMutex->Lock(); | |||||
va_list ap; | va_list ap; | ||||
va_start(ap, status); | va_start(ap, status); | ||||
jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap); | jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap); | ||||
va_end(ap); | va_end(ap); | ||||
gOpenMutex->Unlock(); | |||||
JackGlobals::fOpenMutex->Unlock(); | |||||
return res; | return res; | ||||
} | } | ||||
EXPORT int jack_client_close(jack_client_t* ext_client) | EXPORT int jack_client_close(jack_client_t* ext_client) | ||||
{ | { | ||||
assert(gOpenMutex); | |||||
gOpenMutex->Lock(); | |||||
assert(JackGlobals::fOpenMutex); | |||||
JackGlobals::fOpenMutex->Lock(); | |||||
int res = -1; | int res = -1; | ||||
jack_log("jack_client_close"); | jack_log("jack_client_close"); | ||||
JackClient* client = (JackClient*)ext_client; | JackClient* client = (JackClient*)ext_client; | ||||
@@ -142,7 +142,7 @@ EXPORT int jack_client_close(jack_client_t* ext_client) | |||||
} | } | ||||
jack_log("jack_client_close res = %d", res); | jack_log("jack_client_close res = %d", res); | ||||
} | } | ||||
gOpenMutex->Unlock(); | |||||
JackGlobals::fOpenMutex->Unlock(); | |||||
return res; | return res; | ||||
} | } | ||||
@@ -27,8 +27,6 @@ | |||||
#endif /* USE_MLOCK */ | #endif /* USE_MLOCK */ | ||||
#include "JackCompilerDeps.h" | #include "JackCompilerDeps.h" | ||||
// TODO : what to do with Paul fixes done av rev 3014 (http://trac.jackaudio.org/changeset/3014) | |||||
typedef struct { | typedef struct { | ||||
char *buf; | char *buf; | ||||
size_t len; | size_t len; | ||||
@@ -75,7 +75,7 @@ ExternalMetro::ExternalMetro(int freq, double max_amp, int dur_arg, int bpm, cha | |||||
} | } | ||||
if ((client = jack_client_open (client_name, options, &status)) == 0) { | if ((client = jack_client_open (client_name, options, &status)) == 0) { | ||||
fprintf (stderr, "jack server not running?\n"); | fprintf (stderr, "jack server not running?\n"); | ||||
return; | |||||
throw -1; | |||||
} | } | ||||
jack_set_process_callback (client, process_audio, this); | jack_set_process_callback (client, process_audio, this); | ||||
@@ -184,6 +184,21 @@ int main (int argc, char *argv[]) | |||||
printf("Opening a new client....\n"); | printf("Opening a new client....\n"); | ||||
client1 = new ExternalMetro(1200, 0.4, 20, 80, "t1"); | client1 = new ExternalMetro(1200, 0.4, 20, 80, "t1"); | ||||
printf("Now quit the server, shutdown callback should be called...\n"); | |||||
printf("Type 'c' to move on...\n"); | |||||
while ((getchar() != 'c')) { | |||||
JackSleep(1); | |||||
}; | |||||
printf("Simulating client not correctly closed...\n"); | |||||
printf("Opening a new client....\n"); | |||||
try { | |||||
client1 = new ExternalMetro(1200, 0.4, 20, 80, "t1"); | |||||
} catch (int num) { | |||||
printf("Cannot open a new client since old one was not closed correctly... OK\n"); | |||||
} | |||||
printf("Type 'q' to quit...\n"); | printf("Type 'q' to quit...\n"); | ||||
while ((getchar() != 'q')) { | while ((getchar() != 'q')) { | ||||
@@ -174,7 +174,7 @@ namespace Jack | |||||
error: | error: | ||||
JackAudioDriver::Close(); | JackAudioDriver::Close(); | ||||
jack_error ( "Can't open default PortAudio device : %s", Pa_GetErrorText(err) ); | |||||
jack_error("Can't open default PortAudio device : %s", Pa_GetErrorText(err)); | |||||
return -1; | return -1; | ||||
} | } | ||||
@@ -436,8 +436,7 @@ extern "C" | |||||
case 'P': | case 'P': | ||||
playback = TRUE; | playback = TRUE; | ||||
if (strcmp(param->value.str, "none") != 0) | |||||
{ | |||||
if (strcmp(param->value.str, "none") != 0) { | |||||
playback_pcm_name = strdup(param->value.str); | playback_pcm_name = strdup(param->value.str); | ||||
} | } | ||||
break; | break; | ||||
@@ -469,8 +468,7 @@ extern "C" | |||||
} | } | ||||
// duplex is the default | // duplex is the default | ||||
if (!capture && !playback) | |||||
{ | |||||
if (!capture && !playback) { | |||||
capture = TRUE; | capture = TRUE; | ||||
playback = TRUE; | playback = TRUE; | ||||
} | } | ||||