~ubuntu-branches/ubuntu/natty/kdemultimedia/natty-updates

« back to all changes in this revision

Viewing changes to .pc/kubuntu_03_kmix_pulseaudio_fixes.diff/kmix/core/mixdevice.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-04-19 16:01:21 UTC
  • Revision ID: james.westby@ubuntu.com-20110419160121-jw7ffrspt26u3kt2
Tags: 4:4.6.2-0ubuntu2
* Add kubuntu_03_kmix_pulseaudio_fixes.diff: Cherry-pick several PulseAudio
  related KMix fixes that will be part of KDE 4.6.3.
  - Fixes very high CPU usage. (LP: #720882)
  - Fixes memory leaks. (LP: #676780)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * KMix -- KDE's full featured mini mixer
 
3
 *
 
4
 *
 
5
 * Copyright (C) 1996-2004 Christian Esken <esken@kde.org>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Library General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Library General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Library General Public
 
18
 * License along with this program; if not, write to the Free
 
19
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
20
 */
 
21
 
 
22
#include <kdebug.h>
 
23
#include <klocale.h>
 
24
 
 
25
#include "core/mixdevice.h"
 
26
#include "gui/guiprofile.h"
 
27
#include "core/volume.h"
 
28
 
 
29
static const QString channelTypeToIconName( MixDevice::ChannelType type )
 
30
{
 
31
    switch (type) {
 
32
        case MixDevice::AUDIO:
 
33
            return "mixer-pcm";
 
34
        case MixDevice::BASS:
 
35
        case MixDevice::SURROUND_LFE: // "LFE" SHOULD have an own icon
 
36
            return "mixer-lfe";
 
37
        case MixDevice::CD:
 
38
            return "mixer-cd";
 
39
        case MixDevice::EXTERNAL:
 
40
            return "mixer-line";
 
41
        case MixDevice::MICROPHONE:
 
42
            return "mixer-microphone";
 
43
        case MixDevice::MIDI:
 
44
            return "mixer-midi";
 
45
        case MixDevice::RECMONITOR:
 
46
            return "mixer-capture";
 
47
        case MixDevice::TREBLE:
 
48
            return "mixer-pcm-default";
 
49
        case MixDevice::UNKNOWN:
 
50
            return "mixer-front";
 
51
        case MixDevice::VOLUME:
 
52
            return "mixer-master";
 
53
        case MixDevice::VIDEO:
 
54
            return "mixer-video";
 
55
        case MixDevice::SURROUND:
 
56
        case MixDevice::SURROUND_BACK:
 
57
            return "mixer-surround";
 
58
        case MixDevice::SURROUND_CENTERFRONT:
 
59
        case MixDevice::SURROUND_CENTERBACK:
 
60
            return "mixer-surround-center";
 
61
        case MixDevice::HEADPHONE:
 
62
            return "mixer-headset";
 
63
        case MixDevice::DIGITAL:
 
64
            return "mixer-digital";
 
65
        case MixDevice::AC97:
 
66
            return "mixer-ac97";
 
67
        case MixDevice::SPEAKER:
 
68
            return "mixer-pc-speaker";
 
69
        case MixDevice::MICROPHONE_BOOST:
 
70
            return "mixer-microphone-boost";
 
71
        case MixDevice::MICROPHONE_FRONT_BOOST:
 
72
            return "mixer-microphone-front-boost";
 
73
        case MixDevice::MICROPHONE_FRONT:
 
74
            return "mixer-microphone-front";
 
75
        case MixDevice::KMIX_COMPOSITE:
 
76
            return "mixer-line";
 
77
    }
 
78
    return "mixer-front";
 
79
}
 
80
 
 
81
 
 
82
/**
 
83
 * Constructs a MixDevice. A MixDevice represents one channel or control of
 
84
 * the mixer hardware. A MixDevice has a type (e.g. PCM), a descriptive name
 
85
 * (for example "Master" or "Headphone" or "IEC 958 Output"),
 
86
 * can have a volume level (2 when stereo), can be recordable and muted.
 
87
 * The category tells which kind of control the MixDevice is.
 
88
 *
 
89
 * Hints: Meaning of "category" has changed. In future the MixDevice might contain two
 
90
 * Volume objects, one for Output (Playback volume) and one for Input (Record volume).
 
91
 */
 
92
MixDevice::MixDevice(  Mixer* mixer, const QString& id, const QString& name, ChannelType type )
 
93
{
 
94
    init(mixer, id, name, channelTypeToIconName(type), (MixSet*)0);
 
95
}
 
96
 
 
97
MixDevice::MixDevice(  Mixer* mixer, const QString& id, const QString& name, const QString& iconName, MixSet* moveDestinationMixSet )
 
98
{
 
99
    // doNotRestore is superseded by the more generic concepts isEthereal(), isArtificial()
 
100
    init(mixer, id, name, iconName, moveDestinationMixSet);
 
101
}
 
102
 
 
103
void MixDevice::init(  Mixer* mixer, const QString& id, const QString& name, const QString& iconName, MixSet* moveDestinationMixSet )
 
104
{
 
105
    _artificial = false;
 
106
    _ethereal   = false;
 
107
    _mixer = mixer;
 
108
    _id = id;
 
109
    if( name.isEmpty() )
 
110
        _name = i18n("unknown");
 
111
    else
 
112
        _name = name;
 
113
    if ( iconName.isEmpty() )
 
114
        _iconName = "mixer-front";
 
115
    else
 
116
        _iconName = iconName;
 
117
    _moveDestinationMixSet = moveDestinationMixSet;
 
118
    if ( _id.contains(' ') ) {
 
119
        // The key is used in the config file. It MUST NOT contain spaces
 
120
        kError(67100) << "MixDevice::setId(\"" << id << "\") . Invalid key - it might not contain spaces" << endl;
 
121
        _id.replace(' ', '_');
 
122
    }
 
123
}
 
124
 
 
125
void MixDevice::addPlaybackVolume(Volume &playbackVol)
 
126
{
 
127
   // Hint: "_playbackVolume" gets COPIED from "playbackVol", because the copy-constructor actually copies the volume levels.
 
128
   _playbackVolume = playbackVol;
 
129
   _playbackVolume.setSwitchType(Volume::PlaybackSwitch);
 
130
}
 
131
 
 
132
void MixDevice::addCaptureVolume (Volume &captureVol)
 
133
{
 
134
   _captureVolume = captureVol;
 
135
   _captureVolume.setSwitchType(Volume::CaptureSwitch);
 
136
}
 
137
 
 
138
void MixDevice::addEnums(QList<QString*>& ref_enumList)
 
139
{
 
140
   if ( ref_enumList.count() > 0 ) {
 
141
      int maxEnumId = ref_enumList.count();
 
142
      for (int i=0; i<maxEnumId; i++ ) {
 
143
            // we have an enum. Lets set the names of the enum items in the MixDevice
 
144
            // the enum names are assumed to be static!
 
145
            _enumValues.append( *(ref_enumList.at(i)) );
 
146
      }
 
147
   }
 
148
}
 
149
 
 
150
 
 
151
MixDevice::~MixDevice() {
 
152
    _enumValues.clear(); // The QString's inside will be auto-deleted, as they get unref'ed
 
153
}
 
154
 
 
155
Volume& MixDevice::playbackVolume()
 
156
{
 
157
    return _playbackVolume;
 
158
}
 
159
 
 
160
Volume& MixDevice::captureVolume()
 
161
{
 
162
    return _captureVolume;
 
163
}
 
164
 
 
165
 
 
166
void MixDevice::setEnumId(int enumId)
 
167
{
 
168
   if ( enumId < _enumValues.count() ) {
 
169
      _enumCurrentId = enumId;
 
170
   }
 
171
}
 
172
 
 
173
unsigned int MixDevice::enumId()
 
174
{
 
175
   return _enumCurrentId;
 
176
}
 
177
 
 
178
QList<QString>& MixDevice::enumValues() {
 
179
   return _enumValues;
 
180
}
 
181
 
 
182
 
 
183
const QString& MixDevice::id() const {
 
184
   return _id;
 
185
}
 
186
 
 
187
 
 
188
bool MixDevice::isMuted()                  { return ( _playbackVolume.hasSwitch() && ! _playbackVolume.isSwitchActivated() ); }
 
189
void MixDevice::setMuted(bool value)       { _playbackVolume.setSwitch( ! value ); }
 
190
bool MixDevice::isRecSource()              { return ( _captureVolume.hasSwitch() && _captureVolume.isSwitchActivated() ); }
 
191
void MixDevice::setRecSource(bool value)   { _captureVolume.setSwitch( value ); }
 
192
bool MixDevice::isEnum()                   { return ( ! _enumValues.empty() ); }
 
193
 
 
194
 
 
195
 
 
196
bool MixDevice::operator==(const MixDevice& other) const
 
197
{
 
198
   return ( _id == other._id );
 
199
}
 
200
 
 
201
void MixDevice::setControlProfile(ProfControl* control)
 
202
{
 
203
    _profControl = control;
 
204
}
 
205
 
 
206
ProfControl* MixDevice::controlProfile() {
 
207
    return _profControl;
 
208
}
 
209
 
 
210
/**
 
211
 * This method is currently only called on "kmixctrl --restore"
 
212
 *
 
213
 * Normally we have a working _volume object already, which is very important,
 
214
 * because we need to read the minimum and maximum volume levels.
 
215
 * (Another solution would be to "equip" volFromConfig with maxInt and minInt values).
 
216
 */
 
217
void MixDevice::read( KConfig *config, const QString& grp )
 
218
{
 
219
    if ( isEthereal() || isArtificial() ) {
 
220
        kDebug(67100) << "MixDevice::read(): This MixDevice does not permit volume restoration (i.e. because it is handled lower down in the audio stack). Ignoring.";
 
221
    } else {
 
222
        QString devgrp;
 
223
        devgrp.sprintf( "%s.Dev%s", grp.toAscii().data(), _id.toAscii().data() );
 
224
        KConfigGroup cg = config->group( devgrp );
 
225
        //kDebug(67100) << "MixDevice::read() of group devgrp=" << devgrp;
 
226
 
 
227
        readPlaybackOrCapture(cg, false);
 
228
        readPlaybackOrCapture(cg, true );
 
229
 
 
230
        bool mute = cg.readEntry("is_muted", false);
 
231
        setMuted( mute );
 
232
 
 
233
        bool recsrc = cg.readEntry("is_recsrc", false);
 
234
        setRecSource( recsrc );
 
235
 
 
236
        int enumId = cg.readEntry("enum_id", -1);
 
237
        if ( enumId != -1 ) {
 
238
            setEnumId( enumId );
 
239
        }
 
240
    }
 
241
}
 
242
 
 
243
void MixDevice::readPlaybackOrCapture(const KConfigGroup& config, bool capture)
 
244
{
 
245
    //Volume::ChannelMask chMask = Volume::MNONE;
 
246
    
 
247
    Volume& volume = capture ? captureVolume() : playbackVolume();
 
248
 
 
249
    for ( int i=0; i<= Volume::CHIDMAX; i++ ) {
 
250
       Volume::ChannelID chid = (Volume::ChannelID)i;
 
251
       QString volstr (Volume::ChannelNameForPersistence[ chid ]);
 
252
       if ( capture ) volstr += "Capture";
 
253
       if ( config.hasKey(volstr) ) {
 
254
          long volCfg = config.readEntry(volstr, 0);
 
255
          //chMask |= _channelMaskEnum[i];
 
256
 
 
257
          volume.setVolume(chid, volCfg);
 
258
       } // if saved channel exists
 
259
    } // for all channels    
 
260
}
 
261
 
 
262
/**
 
263
 *  called on "kmixctrl --save" and from the GUI's (currently only on exit)
 
264
 */
 
265
void MixDevice::write( KConfig *config, const QString& grp )
 
266
{
 
267
    if (isEthereal() || isArtificial()) {
 
268
        kDebug(67100) << "MixDevice::write(): This MixDevice does not permit volume saving (i.e. because it is handled lower down in the audio stack). Ignoring.";
 
269
    } else {
 
270
        QString devgrp;
 
271
        devgrp.sprintf( "%s.Dev%s", grp.toAscii().data(), _id.toAscii().data() );
 
272
        KConfigGroup cg = config->group(devgrp);
 
273
        // kDebug(67100) << "MixDevice::write() of group devgrp=" << devgrp;
 
274
 
 
275
        writePlaybackOrCapture(cg, false);
 
276
        writePlaybackOrCapture(cg, true );
 
277
 
 
278
        cg.writeEntry("is_muted" , isMuted() );
 
279
        cg.writeEntry("is_recsrc", isRecSource() );
 
280
        cg.writeEntry("name", _name);
 
281
        if ( isEnum() ) {
 
282
            cg.writeEntry("enum_id", enumId() );
 
283
        }
 
284
    }
 
285
}
 
286
 
 
287
void MixDevice::writePlaybackOrCapture(KConfigGroup& config, bool capture)
 
288
{
 
289
    Volume& volume = capture ? captureVolume() : playbackVolume();
 
290
 
 
291
    for ( int i=0; i<= Volume::CHIDMAX; i++ ) {
 
292
       if ( volume._chmask & Volume::_channelMaskEnum[i] ) {
 
293
           Volume::ChannelID chid = (Volume::ChannelID)i;
 
294
 
 
295
           volume.getVolume( chid );
 
296
           QString volstr (Volume::ChannelNameForPersistence[ chid ]);
 
297
           if ( capture ) volstr += "Capture";
 
298
           config.writeEntry(volstr , (int)volume.getVolume( chid ) );
 
299
       } // if supported channel
 
300
    } // for all channels
 
301
 
 
302
}
 
303
 
 
304
 
 
305
#include "mixdevice.moc"
 
306