summaryrefslogtreecommitdiff
path: root/mixer.c
blob: bac74a1508390208630dc3e56ddf52962a371106 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
 * sndctl  -  a plugin for the Video Disk Recorder
 *        file: mixer.c
 * description: parent class for all types of mixer devices
 *
 *      author: Thomas Hildebrandt <toxym@web.de>
 *
 * inspired by and reengineered from 'avolctl'
 * thanks to Martin Prochnow <nordlichtl@martins-kabuff.de>
 */

#include "defaults.h"
#include "mixer.h"
#include "soundset.h"

/*********************************************************
 * member functions for class cMixer
 *********************************************************/

/*
 * constructor
 */
cMixer::cMixer(){
}

/*
 * destructor
 */
cMixer::~cMixer(){
  int countControls = vControls.size();
  for(int i = 0 ; i < countControls ; i++) {
    delete vControls[i];
  }
}

int cMixer::CountControls() {
  return vControls.size();
}


/*
 * returns a vector with all controls names
 */
vector<cControlId> cMixer::GetControls( void ){
  vector<cControlId> ctrls;
  int            i;

  // loop over all controls
  for( i = 0; i < vControls.size(); i++ ) {
    ctrls.push_back(cControlId(vControls[i]->soundCardId, vControls[i]->name, vControls[i]->controlNr));
  }

  return ctrls;
}

/*
 * update mixer values
 */
void cMixer::Update( cSoundSet *SoundSet ){
  int               i;
  string::size_type loc;
  string            v;

  dsyslog( "sndctl (cMixer::Update): Updating controls with sound set '%s'.", SoundSet->GetName().c_str());

  // loop over all controls
  for( i = 0; i < vControls.size(); i++ ){
    control* actualControl = vControls[i];
    v = SoundSet->Get(cControlId(actualControl->soundCardId, actualControl->name, actualControl->controlNr ));

    // get operation
    actualControl->op = v.substr( 0, 1 ).c_str()[0];

    // get value
    if(actualControl->op == SNDCTL_MIXER_NONE )
      actualControl->value = 0;
    else
      actualControl->value = atoi( v.substr( 1 ).c_str());

    // check and correct limits
    actualControl->value = actualControl->value < 0 ? 0 : actualControl->value;
    actualControl->value = actualControl->value > 999 ? 999 : actualControl->value;

    // check and set minimum volume
    actualControl->limitL = actualControl->min;
    if(( loc = v.find( ';', 0 )) != string::npos )
      actualControl->limitL = atoi( v.substr( ++loc ).c_str());

    // check and set maximum volume
    actualControl->limitU = actualControl->max;
    if(( loc != string::npos ) && (( loc = v.find( ';', loc )) != string::npos ))
      vControls[i]->limitU = atoi( v.substr( ++loc ).c_str());

    dsyslog( "sndctl (cMixer::Update): '%s' updated with %c%d;%ld;%ld", actualControl->name.c_str(), actualControl->op, actualControl->value, actualControl->limitL, actualControl->limitU );
  }
}

/*
 * sets the volume of this sound set
 */
void cMixer::Volume( int Vol ){
  int  i;
  long vol;

  dsyslog( "sndctl (cMixer::Volume): Volume goes to %d%%.", Vol );

  // loop over all controls
  for( i = 0; i < vControls.size(); i++ ){
    control* actualControl = vControls[i];
    // initial value for 'volume'
    actualControl->volume = -1;

    // calculate volume according to operation mode
    switch( actualControl->op ){
      case SNDCTL_MIXER_STATIC:
        vol = actualControl->value;
        break;

      case SNDCTL_MIXER_PLUS:
        vol = Vol + actualControl->value;
        break;

      case SNDCTL_MIXER_MINUS:
        vol = Vol - actualControl->value;
        break;

      case SNDCTL_MIXER_PERCENT:
        vol = Vol * actualControl->value / 100;
        break;

      case SNDCTL_MIXER_NONE:
      default:
        dsyslog( "sndctl (cMixer::Volume): Control '%s' stays unchanged.", actualControl->name.c_str());
        continue;
        break;
    }

    // Vol = 0 means, no matter, what happend before
    if( Vol == 0 )
      vol = 0;

    // scale volume to real values
    vol = actualControl->min + ( actualControl->max - actualControl->min ) * vol / 100;

    // check for hard limits
    if( Vol > 0 && vol < actualControl->limitL )
      vol = actualControl->limitL;
    if( vol > actualControl->limitU )
      vol = actualControl->limitU;

    dsyslog( "sndctl (cMixer::Volume): Control '%s' goes to '%ld'.", actualControl->name.c_str(), vol );

    // set volume
    actualControl->volume = vol;
  }

  // set volumes to real hardware
  Volumes();
}

cControlId::cControlId(string SoundCardId, string DisplayName, int ControlNr) {
  name = DisplayName;
  soundCardId = SoundCardId;
  controlNr = ControlNr;
}

cControlId::cControlId() : name(), soundCardId(), controlNr(0) {
}

bool cControlId::operator==(cControlId const& b) {
  return controlNr == b.controlNr && soundCardId.compare(b.soundCardId) == 0;
}

string cControlId::getDisplayName() { return name; }
int cControlId::getControlNr() { return controlNr; }
string cControlId::getSoundCardId() { return soundCardId; }