From eba8825d9f4df93e3f89010a4349c72046faa16a Mon Sep 17 00:00:00 2001
From: Tursiae <git@tursiae.org>
Date: Tue, 18 Feb 2025 23:39:48 +1100
Subject: [PATCH] Gate playback on the existence of /.tangara-tts/.

Also, clang-format previous changes in provider.hpp.
---
 src/tangara/tts/player.cpp   |  6 +++++-
 src/tangara/tts/provider.cpp | 33 +++++++++++++++++++++++++++++++++
 src/tangara/tts/provider.hpp |  4 +++-
 3 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/src/tangara/tts/player.cpp b/src/tangara/tts/player.cpp
index 9cc7a1f7..1b1e0bcf 100644
--- a/src/tangara/tts/player.cpp
+++ b/src/tangara/tts/player.cpp
@@ -44,7 +44,11 @@ auto Player::playFile(const std::string& text, const std::string& file)
       stream_playing_ = true;
     }
 
-    openAndDecode(text, file);
+    // Only attempt playback if the card contains samples.
+    // We gate this on directory existence to avoid spamming the logs.
+    if (Provider::SamplesOnSDCard()) {
+      openAndDecode(text, file);
+    }
 
     if (!stream_cancelled_) {
       events::Audio().Dispatch(audio::TtsPlaybackChanged{.is_playing = false});
diff --git a/src/tangara/tts/provider.cpp b/src/tangara/tts/provider.cpp
index 2fb6c426..c101dbb1 100644
--- a/src/tangara/tts/provider.cpp
+++ b/src/tangara/tts/provider.cpp
@@ -75,4 +75,37 @@ auto Provider::feed(const Event& e) -> void {
   }
 }
 
+bool Provider::SamplesOnSDCard() {
+  // Does the /.tangara-tts/ path exist on the SD card?
+  FILINFO fi;
+  FRESULT status = f_stat(kTtsPath, &fi);
+
+  switch (status) {
+    case FR_NO_PATH:
+    case FR_NO_FILE:
+    case FR_NO_FILESYSTEM:
+      // If the SD card isn't mounted, or no matching file, then no samples.
+      return false;
+
+    case FR_OK:
+      // If /.tangara-tts exists, let's check it out first.
+      break;
+
+    default:
+      // If things look odd, then assume samples aren't present.
+      ESP_LOGW(kTag, "got unexpected %d status from f_stat(\"%s\")", status,
+               kTtsPath);
+      return false;
+  }
+
+  // If /.tangara-tts exists and is a directory, it probably contains samples.
+  if (fi.fattrib & AM_DIR)
+    return true;
+
+  // Otherwise, for example, if it's a file, assume no samples present.
+  ESP_LOGW(kTag, "got unexpected file attributes for %s: %d", kTtsPath,
+           fi.fattrib);
+  return false;
+}
+
 }  // namespace tts
diff --git a/src/tangara/tts/provider.hpp b/src/tangara/tts/provider.hpp
index 3a16d5a9..e46950ce 100644
--- a/src/tangara/tts/provider.hpp
+++ b/src/tangara/tts/provider.hpp
@@ -11,9 +11,9 @@
 #include <string>
 #include <variant>
 
+#include "drivers/nvs.hpp"
 #include "tts/events.hpp"
 #include "tts/player.hpp"
-#include "drivers/nvs.hpp"
 
 namespace tts {
 
@@ -34,6 +34,8 @@ class Provider {
   Provider(const Provider&) = delete;
   Provider& operator=(const Provider&) = delete;
 
+  static bool SamplesOnSDCard();
+
  private:
   drivers::NvsStorage& nvs_;
   std::unique_ptr<Player> player_;