SdlAudioSink::SdlAudioSink(const AudioSource &source, int device_id)
    : bytes_per_sample(source.BytesPerSample()),
      ring_buf(RINGBUF_POWER, source.BytesPerSample()),
      position_sample_count(0),
      source_out(false),
      state(Audio::State::STOPPED)
{
	const char *name = SDL_GetAudioDeviceName(device_id, 0);
	if (name == nullptr) {
		throw ConfigError(std::string("invalid device id: ") +
		                  std::to_string(device_id));
	}

	SDL_AudioSpec want;
	SDL_zero(want);
	want.freq = source.SampleRate();
	want.format = FORMATS[static_cast<int>(source.OutputSampleFormat())];
	want.channels = source.ChannelCount();
	want.callback = &SDLCallback;
	want.userdata = (void *)this;

	SDL_AudioSpec have;
	SDL_zero(have);

	this->device = SDL_OpenAudioDevice(name, 0, &want, &have, 0);
	if (this->device == 0) {
		throw ConfigError(std::string("couldn't open device: ") +
		                  SDL_GetError());
	}
}