diff --git a/client/player/alsa_player.cpp b/client/player/alsa_player.cpp index 93d518f0..66bb8192 100644 --- a/client/player/alsa_player.cpp +++ b/client/player/alsa_player.cpp @@ -225,7 +225,7 @@ void AlsaPlayer::worker() adjustVolume(buff_, frames_); if ((pcm = snd_pcm_writei(handle_, buff_, frames_)) == -EPIPE) { - LOG(ERROR) << "XRUN\n"; + LOG(ERROR) << "XRUN: " << snd_strerror(pcm) << "\n"; snd_pcm_prepare(handle_); } else if (pcm < 0) diff --git a/common/time_defs.hpp b/common/time_defs.hpp index de97c889..f94ef568 100644 --- a/common/time_defs.hpp +++ b/common/time_defs.hpp @@ -51,6 +51,20 @@ inline static void systemtimeofday(struct timeval* tv) // timeofday(tv); } +template +inline ToDuration diff(const timeval& tv1, const timeval& tv2) +{ + auto sec = tv1.tv_sec - tv2.tv_sec; + auto usec = tv1.tv_usec - tv2.tv_usec; + while (usec < 0) + { + sec -= 1; + usec += 1000000; + } + return std::chrono::duration_cast(std::chrono::seconds(sec) + std::chrono::microseconds(usec)); +} + + inline static void addUs(timeval& tv, int us) { if (us < 0) @@ -115,7 +129,7 @@ inline void usleep(const int32_t& microseconds) return; sleep(usec(microseconds)); } -} +} // namespace chronos #endif diff --git a/common/utils/string_utils.hpp b/common/utils/string_utils.hpp index 55d0baf1..91b86308 100644 --- a/common/utils/string_utils.hpp +++ b/common/utils/string_utils.hpp @@ -95,6 +95,22 @@ static std::string uriDecode(const std::string& src) } +static void split_left(const std::string& s, char delim, std::string& left, std::string& right) +{ + auto pos = s.find(delim); + if (pos != std::string::npos) + { + left = s.substr(0, pos); + right = s.substr(pos + 1); + } + else + { + left = s; + right = ""; + } +} + + static std::vector& split(const std::string& s, char delim, std::vector& elems) { diff --git a/server/streamreader/asio_stream.hpp b/server/streamreader/asio_stream.hpp index 7cf6bbe9..fbfb6fe1 100644 --- a/server/streamreader/asio_stream.hpp +++ b/server/streamreader/asio_stream.hpp @@ -138,12 +138,14 @@ void AsioStream::do_read() // First read after connect. Set the initial read timestamp // the timestamp will be incremented after encoding, // since we do not know how much the encoder actually encoded + + timeval now; chronos::systemtimeofday(&now); - size_t stream2systime_diff = abs(now.tv_sec - tvEncodedChunk_.tv_sec); - if (stream2systime_diff > 5 + pcmReadMs_ / 1000) + auto stream2systime_diff = chronos::diff(now, tvEncodedChunk_); + if (stream2systime_diff > chronos::sec(5) + chronos::msec(pcmReadMs_)) { - LOG(WARNING) << "Stream and system time out of sync: " << stream2systime_diff << "s, resetting stream time.\n"; + LOG(WARNING) << "Stream and system time out of sync: " << stream2systime_diff.count() << "ms, resetting stream time.\n"; first_ = true; } if (first_)