summaryrefslogtreecommitdiff
path: root/src/tangara/audio/fatfs_stream_factory.cpp
blob: 9089735c7d4fc36d1dc5ef966fd53221ea8a2be8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 * Copyright 2023 jacqueline <me@jacqueline.id.au>
 *
 * SPDX-License-Identifier: GPL-3.0-only
 */

#include "audio/fatfs_stream_factory.hpp"

#include <cstdint>
#include <memory>
#include <string>

#include "esp_log.h"
#include "ff.h"
#include "freertos/portmacro.h"
#include "freertos/projdefs.h"

#include "audio/audio_source.hpp"
#include "audio/fatfs_source.hpp"
#include "codec.hpp"
#include "database/database.hpp"
#include "database/tag_parser.hpp"
#include "database/track.hpp"
#include "drivers/spi.hpp"
#include "tasks.hpp"
#include "types.hpp"

[[maybe_unused]] static const char* kTag = "SRC";

namespace audio {

FatfsStreamFactory::FatfsStreamFactory(database::Handle&& handle,
                                       database::ITagParser& parser)
    : db_(handle), tag_parser_(parser) {}

auto FatfsStreamFactory::create(database::TrackId id, uint32_t offset)
    -> std::shared_ptr<TaggedStream> {
  auto db = db_.lock();
  if (!db) {
    return {};
  }
  auto path = db->getTrackPath(id);
  if (!path) {
    return {};
  }
  return create(*path, offset);
}

auto FatfsStreamFactory::create(std::string path, uint32_t offset)
    -> std::shared_ptr<TaggedStream> {
  auto tags = tag_parser_.ReadAndParseTags(path);
  if (!tags) {
    return {};
  }

  if (!tags->title()) {
    tags->title(path);
  }

  auto stream_type = ContainerToStreamType(tags->encoding());
  if (!stream_type.has_value()) {
    ESP_LOGE(kTag, "couldn't match container to stream");
    return {};
  }

  std::unique_ptr<FIL> file = std::make_unique<FIL>();
  FRESULT res = f_open(file.get(), path.c_str(), FA_READ);
  if (res != FR_OK) {
    ESP_LOGE(kTag, "failed to open file! res: %i", res);
    return {};
  }

  return std::make_shared<TaggedStream>(
      tags, std::make_unique<FatfsSource>(stream_type.value(), std::move(file)),
      path, offset);
}

auto FatfsStreamFactory::ContainerToStreamType(database::Container enc)
    -> std::optional<codecs::StreamType> {
  switch (enc) {
    case database::Container::kMp3:
      return codecs::StreamType::kMp3;
    case database::Container::kWav:
      return codecs::StreamType::kWav;
    case database::Container::kOgg:
      return codecs::StreamType::kVorbis;
    case database::Container::kFlac:
      return codecs::StreamType::kFlac;
    case database::Container::kOpus:
      return codecs::StreamType::kOpus;
    case database::Container::kWavPack:
      return codecs::StreamType::kWavPack;
    case database::Container::kUnsupported:
    default:
      return {};
  }
}

}  // namespace audio