MixerControl.cxx 2.93 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2014 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14 15 16 17
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 19
 */

20
#include "config.h"
21 22
#include "MixerControl.hxx"
#include "MixerInternal.hxx"
23
#include "util/Error.hxx"
24

25
#include <assert.h>
26

27
Mixer *
28
mixer_new(EventLoop &event_loop,
29
	  const MixerPlugin &plugin, AudioOutput &ao,
30
	  MixerListener &listener,
31
	  const config_param &param,
32
	  Error &error)
33
{
34
	Mixer *mixer = plugin.init(event_loop, ao, listener, param, error);
35

36
	assert(mixer == nullptr || mixer->IsPlugin(plugin));
37 38 39 40 41

	return mixer;
}

void
42
mixer_free(Mixer *mixer)
43
{
44
	assert(mixer != nullptr);
45

46 47 48 49
	/* mixers with the "global" flag set might still be open at
	   this point (see mixer_auto_close()) */
	mixer_close(mixer);

50
	delete mixer;
51 52 53
}

bool
54
mixer_open(Mixer *mixer, Error &error)
55
{
56 57
	bool success;

58
	assert(mixer != nullptr);
59

60
	const ScopeLock protect(mixer->mutex);
61

62
	success = mixer->open || (mixer->open = mixer->Open(error));
63

64 65
	mixer->failed = !success;

66
	return success;
67 68
}

69
static void
70
mixer_close_internal(Mixer *mixer)
71
{
72
	assert(mixer != nullptr);
73 74
	assert(mixer->open);

75
	mixer->Close();
76 77 78
	mixer->open = false;
}

79
void
80
mixer_close(Mixer *mixer)
81
{
82
	assert(mixer != nullptr);
83

84
	const ScopeLock protect(mixer->mutex);
85

86 87
	if (mixer->open)
		mixer_close_internal(mixer);
88 89
}

90
void
91
mixer_auto_close(Mixer *mixer)
92
{
93
	if (!mixer->plugin.global)
94 95 96
		mixer_close(mixer);
}

97 98 99 100 101
/*
 * Close the mixer due to failure.  The mutex must be locked before
 * calling this function.
 */
static void
102
mixer_failed(Mixer *mixer)
103 104 105
{
	assert(mixer->open);

106
	mixer_close_internal(mixer);
107 108

	mixer->failed = true;
109 110
}

111
int
112
mixer_get_volume(Mixer *mixer, Error &error)
113
{
114 115
	int volume;

116
	assert(mixer != nullptr);
117

118
	if (mixer->plugin.global && !mixer->failed &&
119
	    !mixer_open(mixer, error))
120 121
		return -1;

122
	const ScopeLock protect(mixer->mutex);
123 124

	if (mixer->open) {
125
		volume = mixer->GetVolume(error);
126
		if (volume < 0 && error.IsDefined())
127
			mixer_failed(mixer);
128 129 130
	} else
		volume = -1;

131
	return volume;
132 133 134
}

bool
135
mixer_set_volume(Mixer *mixer, unsigned volume, Error &error)
136
{
137
	assert(mixer != nullptr);
138
	assert(volume <= 100);
139

140
	if (mixer->plugin.global && !mixer->failed &&
141
	    !mixer_open(mixer, error))
142 143
		return false;

144
	const ScopeLock protect(mixer->mutex);
145

146
	return mixer->open && mixer->SetVolume(volume, error);
147
}