summaryrefslogtreecommitdiffstats
path: root/kmix/mixer_alsa9.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmix/mixer_alsa9.cpp')
-rw-r--r--kmix/mixer_alsa9.cpp108
1 files changed, 68 insertions, 40 deletions
diff --git a/kmix/mixer_alsa9.cpp b/kmix/mixer_alsa9.cpp
index 54af7161..2a37051d 100644
--- a/kmix/mixer_alsa9.cpp
+++ b/kmix/mixer_alsa9.cpp
@@ -105,14 +105,6 @@ Mixer_ALSA::open()
bool masterChosen = false;
int err;
- snd_ctl_t *ctl_handle;
- snd_ctl_card_info_t *hw_info;
- snd_ctl_card_info_alloca(&hw_info);
-
- snd_mixer_elem_t *elem;
- snd_mixer_selem_id_t *sid;
- snd_mixer_selem_id_alloca( &sid );
-
// Card information
if ((unsigned)m_devnum > 31) m_devnum = -1;
devName = m_devnum == -1 ? "default" : TQString("hw:%1").arg(m_devnum);
@@ -122,6 +114,7 @@ Mixer_ALSA::open()
if (virginOpen)
probeMessage += "Trying ALSA Device '" + devName + "': ";
+ snd_ctl_t *ctl_handle;
if ( ( err = snd_ctl_open ( &ctl_handle, devName.latin1(), 0 ) ) < 0 )
{
kdDebug(67100) << probeMessage << "not found: snd_ctl_open err=" << snd_strerror(err) << endl;
@@ -129,23 +122,29 @@ Mixer_ALSA::open()
return Mixer::ERR_OPEN;
}
- if ( ( err = snd_ctl_card_info ( ctl_handle, hw_info ) ) < 0 )
+ snd_ctl_card_info_t *hw_info;
+ snd_ctl_card_info_malloc(&hw_info);
+ if ((err = snd_ctl_card_info(ctl_handle, hw_info)) < 0)
{
kdDebug(67100) << probeMessage << "not found: snd_ctl_card_info err=" << snd_strerror(err) << endl;
//_stateMessage = errorText( Mixer::ERR_READ );
- snd_ctl_close( ctl_handle );
+ snd_ctl_card_info_free(hw_info);
+ snd_ctl_close(ctl_handle);
return Mixer::ERR_READ;
}
// Device and mixer names
- const char* mixer_card_name = snd_ctl_card_info_get_name( hw_info );
+ const char* mixer_card_name = snd_ctl_card_info_get_name( hw_info );
//mixer_device_name = snd_ctl_card_info_get_mixername( hw_info );
// Copy the name of kmix mixer from card name (mixername is rumoured to be not that good)
m_mixerName = mixer_card_name;
if (m_devnum == -1) m_devnum = snd_card_get_index(snd_ctl_card_info_get_id(hw_info));
if (m_devnum < 0) m_devnum = -1;
- snd_ctl_close( ctl_handle );
+ // NOTE do not free hw_info here, it cause funny detections of mixers in subsequent updates.
+ // Instead free the resources later, before leaving this function.
+ // snd_ctl_card_info_free(hw_info);
+ snd_ctl_close(ctl_handle);
/* open mixer device */
@@ -155,6 +154,7 @@ Mixer_ALSA::open()
kdDebug(67100) << probeMessage << "not found: snd_mixer_open err=" << snd_strerror(err) << endl;
//errormsg( Mixer::ERR_NODEV );
_handle = 0;
+ snd_ctl_card_info_free(hw_info);
return Mixer::ERR_NODEV; // if we cannot open the mixer, we have no devices
}
//kdDebug(67100) << "OUT Mixer_ALSA snd_mixer_open()" << endl;
@@ -163,6 +163,8 @@ Mixer_ALSA::open()
{
kdDebug(67100) << probeMessage << "not found: snd_mixer_attach err=" << snd_strerror(err) << endl;
//errormsg( Mixer::ERR_PERM );
+ close();
+ snd_ctl_card_info_free(hw_info);
return Mixer::ERR_OPEN;
}
@@ -170,6 +172,8 @@ Mixer_ALSA::open()
{
kdDebug(67100) << probeMessage << "not found: snd_mixer_selem_register err=" << snd_strerror(err) << endl;
//errormsg( Mixer::ERR_READ );
+ close();
+ snd_ctl_card_info_free(hw_info);
return Mixer::ERR_READ;
}
@@ -178,27 +182,26 @@ Mixer_ALSA::open()
kdDebug(67100) << probeMessage << "not found: snd_mixer_load err=" << snd_strerror(err) << endl;
//errormsg( Mixer::ERR_READ );
close();
+ snd_ctl_card_info_free(hw_info);
return Mixer::ERR_READ;
}
kdDebug(67100) << probeMessage << "found" << endl;
unsigned int mixerIdx = 0;
- for ( elem = snd_mixer_first_elem( _handle ); elem; elem = snd_mixer_elem_next( elem ), mixerIdx++ )
+ snd_mixer_elem_t *elem;
+ for ( elem = snd_mixer_first_elem(_handle); elem; elem = snd_mixer_elem_next(elem), mixerIdx++ )
{
// If element is not active, just skip
- if ( ! snd_mixer_selem_is_active ( elem ) ) {
+ if ( !snd_mixer_selem_is_active(elem))
+ {
// ...but we still want to insert a null value into our mixer element
// list so that the list indexes match up.
- mixer_elem_list.append( 0 );
- mixer_sid_list.append( 0 );
+ mixer_elem_list.append(0);
+ mixer_sid_list.append(0);
continue;
}
-
- sid = (snd_mixer_selem_id_t*)malloc(snd_mixer_selem_id_sizeof()); // I believe *we* must malloc it for ourself
- snd_mixer_selem_get_id( elem, sid );
-
bool canPlay = false;
bool canCapture = false;
bool hasPlaySwitch = false;
@@ -209,8 +212,13 @@ Mixer_ALSA::open()
snd_mixer_selem_get_playback_volume_range( elem, &minVolumePlay, &maxVolumePlay );
snd_mixer_selem_get_capture_volume_range( elem, &minVolumeRec , &maxVolumeRec );
+
// New mix device
- MixDevice::ChannelType ct = (MixDevice::ChannelType)identify( sid );
+ snd_mixer_selem_id_t *sid;
+ snd_mixer_selem_id_malloc(&sid);
+ snd_mixer_selem_get_id(elem, sid);
+
+ MixDevice::ChannelType ct = (MixDevice::ChannelType)identify(sid);
/*
if (!masterChosen && ct==MixDevice::VOLUME) {
// Determine a nicer MasterVolume
@@ -243,7 +251,7 @@ Mixer_ALSA::open()
if ( ret == 0 ) {
TQString* enumName = new TQString(buffer);
//enumName->append(buffer);
- enumList.append( enumName);
+ enumList.append(enumName);
} // enumName could be read succesfully
} // for all enum items of this device
} // no error in reading enum list
@@ -252,7 +260,6 @@ Mixer_ALSA::open()
}
// --- get Enum names END ---
} // is an enum
-
else {
Volume::ChannelMask chn = Volume::MNONE;
Volume::ChannelMask chnTmp;
@@ -346,19 +353,23 @@ Mixer_ALSA::open()
//kdDebug(67100) << "ALSA create MDW, vol= " << *vol << endl;
delete volPlay;
delete volCapture;
- } // virginOpen
+ }
else
{
- MixDevice* md;
+ snd_mixer_selem_id_free(sid);
bool found = false;
- for ( md = m_mixDevices.first(); md != 0; md = m_mixDevices.next() ) {
- if ( md->num() == mixerIdx ) {
+ for (MixDevice *md = m_mixDevices.first(); md; md = m_mixDevices.next())
+ {
+ if (md->num() == mixerIdx)
+ {
found = true;
writeVolumeToHW( mixerIdx, md->getVolume() );
}
}
if( !found )
{
+ close();
+ snd_ctl_card_info_free(hw_info);
return Mixer::ERR_INCOMPATIBLESET;
}
} // !virginOpen
@@ -372,6 +383,8 @@ Mixer_ALSA::open()
***************************************************************************************/
if ( !validDevice )
{
+ close();
+ snd_ctl_card_info_free(hw_info);
return Mixer::ERR_NODEV;
}
@@ -385,25 +398,33 @@ Mixer_ALSA::open()
/* setup for select on stdin and the mixer fd */
if ((m_count = snd_mixer_poll_descriptors_count(_handle)) < 0) {
kdDebug(67100) << "Mixer_ALSA::poll() , snd_mixer_poll_descriptors_count() err=" << m_count << "\n";
+ close();
+ snd_ctl_card_info_free(hw_info);
return Mixer::ERR_OPEN;
}
+ // Finally release the hw_info resources here!
+ snd_ctl_card_info_free(hw_info);
+
//kdDebug(67100) << "Mixer_ALSA::prepareUpdate() 2\n";
m_fds = (struct pollfd*)calloc(m_count, sizeof(struct pollfd));
if (m_fds == NULL) {
kdDebug(67100) << "Mixer_ALSA::poll() , calloc() = null" << "\n";
- return Mixer::ERR_OPEN;
+ close();
+ return Mixer::ERR_OPEN;
}
m_fds->events = POLLIN;
if ((err = snd_mixer_poll_descriptors(_handle, m_fds, m_count)) < 0) {
kdDebug(67100) << "Mixer_ALSA::poll() , snd_mixer_poll_descriptors_count() err=" << err << "\n";
- return Mixer::ERR_OPEN;
+ close();
+ return Mixer::ERR_OPEN;
}
if (err != m_count) {
kdDebug(67100) << "Mixer_ALSA::poll() , snd_mixer_poll_descriptors_count() err=" << err << " m_count=" << m_count << "\n";
- return Mixer::ERR_OPEN;
+ close();
+ return Mixer::ERR_OPEN;
}
return 0;
@@ -442,32 +463,39 @@ Mixer_ALSA::close()
{
int ret=0;
m_isOpen = false;
- if ( _handle != 0 )
+
+ removeSignalling();
+
+ if (_handle)
{
//kdDebug(67100) << "IN Mixer_ALSA::close()" << endl;
- snd_mixer_free ( _handle );
- if ( ( ret = snd_mixer_detach ( _handle, devName.latin1() ) ) < 0 )
+ snd_mixer_free(_handle);
+ if ((ret = snd_mixer_detach(_handle, devName.latin1())) < 0)
{
kdDebug(67100) << "snd_mixer_detach err=" << snd_strerror(ret) << endl;
}
int ret2 = 0;
- if ( ( ret2 = snd_mixer_close ( _handle ) ) < 0 )
+ if ((ret2 = snd_mixer_close(_handle)) < 0)
{
kdDebug(67100) << "snd_mixer_close err=" << snd_strerror(ret2) << endl;
- if ( ret == 0 ) ret = ret2; // no error before => use current error code
+ if (ret == 0) ret = ret2; // no error before => use current error code
}
-
_handle = 0;
//kdDebug(67100) << "OUT Mixer_ALSA::close()" << endl;
-
}
+ while (!mixer_sid_list.isEmpty())
+ {
+ snd_mixer_selem_id_t *currSid = mixer_sid_list.first();
+ if (currSid)
+ {
+ snd_mixer_selem_id_free(currSid);
+ }
+ mixer_sid_list.pop_front();
+ }
mixer_elem_list.clear();
- mixer_sid_list.clear();
m_mixDevices.clear();
- removeSignalling();
-
return ret;
}