URY playd
C++ minimalist audio player
audio.cpp
Go to the documentation of this file.
1 // This file is part of playd.
2 // playd is licensed under the MIT licence: see LICENSE.txt.
3 
10 #include <algorithm>
11 #include <cassert>
12 #include <climits>
13 #include <cstdint>
14 #include <string>
15 
16 #include "../errors.hpp"
17 #include "../messages.h"
18 #include "../response.hpp"
19 #include "audio.hpp"
20 #include "audio_sink.hpp"
21 #include "audio_source.hpp"
22 #include "sample_formats.hpp"
23 
24 //
25 // NoAudio
26 //
27 
29 {
30  return Audio::State::NONE;
31 }
32 
34 {
35  return Audio::State::NONE;
36 }
37 
39 {
41 }
42 
43 void NoAudio::SetPosition(std::uint64_t)
44 {
46 }
47 
48 std::uint64_t NoAudio::Position() const
49 {
51 }
52 
53 const std::string &NoAudio::File() const
54 {
56 }
57 
58 //
59 // PipeAudio
60 //
61 
62 PipeAudio::PipeAudio(std::unique_ptr<AudioSource> src,
63  std::unique_ptr<AudioSink> sink)
64  : src(std::move(src)), sink(std::move(sink))
65 {
66  this->ClearFrame();
67 }
68 
69 const std::string &PipeAudio::File() const
70 {
71  return this->src->Path();
72 }
73 
74 void PipeAudio::SetPlaying(bool playing)
75 {
76  assert(this->sink != nullptr);
77 
78  if (playing) {
79  this->sink->Start();
80  } else {
81  this->sink->Stop();
82  }
83 }
84 
86 {
87  return this->sink->State();
88 }
89 
90 std::uint64_t PipeAudio::Position() const
91 {
92  assert(this->sink != nullptr);
93  assert(this->src != nullptr);
94 
95  return this->src->MicrosFromSamples(this->sink->Position());
96 }
97 
98 void PipeAudio::SetPosition(std::uint64_t position)
99 {
100  assert(this->sink != nullptr);
101  assert(this->src != nullptr);
102 
103  auto in_samples = this->src->SamplesFromMicros(position);
104  auto out_samples = this->src->Seek(in_samples);
105  this->sink->SetPosition(out_samples);
106 
107  // We might still have decoded samples from the old position in
108  // our frame, so clear them out.
109  this->ClearFrame();
110 }
111 
113 {
114  this->frame.clear();
115  this->frame_iterator = this->frame.end();
116 }
117 
119 {
120  assert(this->sink != nullptr);
121  assert(this->src != nullptr);
122 
123  bool more_available = this->DecodeIfFrameEmpty();
124  if (!more_available) this->sink->SourceOut();
125 
126  if (!this->FrameFinished()) this->TransferFrame();
127 
128  return this->sink->State();
129 }
130 
132 {
133  assert(!this->frame.empty());
134  assert(this->sink != nullptr);
135  assert(this->src != nullptr);
136 
137  this->sink->Transfer(this->frame_iterator, this->frame.end());
138 
139  // We empty the frame once we're done with it. This
140  // maintains FrameFinished(), as an empty frame is a finished one.
141  if (this->FrameFinished()) {
142  this->ClearFrame();
143  assert(this->FrameFinished());
144  }
145 
146  // The frame iterator should be somewhere between the beginning and
147  // end of the frame, unless the frame was emptied.
148  assert(this->frame.empty() ||
149  (this->frame.begin() <= this->frame_iterator &&
150  this->frame_iterator < this->frame.end()));
151 }
152 
154 {
155  // Either the current frame is in progress, or has been emptied.
156  // AdvanceFrameIterator() establishes this assertion by emptying a
157  // frame as soon as it finishes.
158  assert(this->frame.empty() || !this->FrameFinished());
159 
160  // If we still have a frame, don't bother decoding yet.
161  if (!this->FrameFinished()) return true;
162 
163  assert(this->src != nullptr);
164  AudioSource::DecodeResult result = this->src->Decode();
165 
166  this->frame = result.second;
167  this->frame_iterator = this->frame.begin();
168 
169  return result.first != AudioSource::DecodeState::END_OF_FILE;
170 }
171 
173 {
174  return this->frame.end() <= this->frame_iterator;
175 }
std::uint64_t Position() const override
This Audio&#39;s current position.
Definition: audio.cpp:90
Declaration of the AudioSource class.
State
Enumeration of possible states for this Audio.
Definition: audio.hpp:42
const std::string & File() const override
This Audio&#39;s current file.
Definition: audio.cpp:53
Audio::State CurrentState() const override
The state of this Audio.
Definition: audio.cpp:33
const std::string MSG_CMD_NEEDS_LOADED
Message shown when a command that works only when a file is loaded is fired when there isn&#39;t anything...
Definition: messages.h:42
void SetPosition(std::uint64_t position) override
Attempts to seek to the given position.
Definition: audio.cpp:98
Declaration of the Audio class.
bool FrameFinished() const
Returns whether the current frame has been finished.
Definition: audio.cpp:172
std::uint64_t Position() const override
This Audio&#39;s current position.
Definition: audio.cpp:48
Audio::State Update() override
Performs an update cycle on this Audio.
Definition: audio.cpp:28
void TransferFrame()
Transfers as much of the current frame as possible to the sink.
Definition: audio.cpp:131
STL namespace.
bool DecodeIfFrameEmpty()
Decodes a new frame, if the current frame is empty.
Definition: audio.cpp:153
void SetPlaying(bool playing) override
Sets whether this Audio should be playing or not.
Definition: audio.cpp:74
There is no Audio.
const std::string & File() const override
This Audio&#39;s current file.
Definition: audio.cpp:69
AudioSource::DecodeVector::iterator frame_iterator
The current position in the current decoded frame.
Definition: audio.hpp:179
The decoder has run out of things to decode.
AudioSource::DecodeVector frame
The current decoded frame.
Definition: audio.hpp:176
Audio::State Update() override
Performs an update cycle on this Audio.
Definition: audio.cpp:118
Declaration of the AudioSink class.
void SetPosition(std::uint64_t position) override
Attempts to seek to the given position.
Definition: audio.cpp:43
void SetPlaying(bool playing) override
Sets whether this Audio should be playing or not.
Definition: audio.cpp:38
Audio::State CurrentState() const override
The state of this Audio.
Definition: audio.cpp:85
PipeAudio(std::unique_ptr< AudioSource > src, std::unique_ptr< AudioSink > sink)
Constructs a PipeAudio from a source and a sink.
Definition: audio.cpp:62
std::pair< DecodeState, DecodeVector > DecodeResult
Type of the result of Decode().
void ClearFrame()
Clears the current frame and its iterator.
Definition: audio.cpp:112
The SampleFormat enumeration and related declarations.
std::unique_ptr< AudioSource > src
The source of audio data.
Definition: audio.hpp:170
An Error signifying that no audio is loaded.
Definition: errors.hpp:120
std::unique_ptr< AudioSink > sink
The sink to which audio data is sent.
Definition: audio.hpp:173