1 /* 2 * Copyright (C) 2020 3 * Matthias P. Braendli (matthias.braendli@mpb.li) 4 * 5 * This file is part of the welle.io. 6 * Many of the ideas as implemented in welle.io are derived from 7 * other work, made available through the GNU general Public License. 8 * All copyrights of the original authors are recognized. 9 * 10 * welle.io is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * welle.io is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with welle.io; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * 24 */ 25 #pragma once 26 27 #include <atomic> 28 #include <thread> 29 #include <utility> 30 #include <chrono> 31 #include <condition_variable> 32 #include <deque> 33 #include <list> 34 #include <map> 35 #include <memory> 36 #include <mutex> 37 #include <vector> 38 #include <string> 39 #include <cstdint> 40 #include <cstddef> 41 #include "backend/dab-constants.h" 42 #include "backend/radio-controller.h" 43 #include "various/fft.h" 44 #include "various/Socket.h" 45 #include "various/channels.h" 46 #include "webprogrammehandler.h" 47 #include "radio-receiver-options.h" 48 49 class CVirtualInput; // from input/virtual_input.h 50 class RadioReceiver; // from backend/radio_receiver.h 51 52 class WebRadioInterface : public RadioControllerInterface { 53 public: 54 enum class DecodeStrategy { 55 /* Decode services only on-demand */ 56 OnDemand, 57 58 /* Decode all services simultaneously */ 59 All, 60 61 /* Decode all services one by one, for 10s */ 62 Carousel10, 63 64 /* Decode all services one by one, switch when 65 * DLS and slide were decoded, stay at most 80s on one service. */ 66 CarouselPAD 67 }; 68 69 struct DecodeSettings { 70 DecodeStrategy strategy = DecodeStrategy::OnDemand; 71 int num_decoders_in_carousel = 0; 72 }; 73 74 WebRadioInterface( 75 CVirtualInput& in, 76 int port, 77 DecodeSettings cs, 78 RadioReceiverOptions rro); 79 ~WebRadioInterface(); 80 WebRadioInterface(const WebRadioInterface&) = delete; 81 WebRadioInterface& operator=(const WebRadioInterface&) = delete; 82 83 void serve(); 84 85 virtual void onSNR(float snr) override; 86 virtual void onFrequencyCorrectorChange(int fine, int coarse) override; 87 virtual void onSyncChange(char isSync) override; 88 virtual void onSignalPresence(bool isSignal) override; 89 virtual void onServiceDetected(uint32_t sId) override; 90 virtual void onNewEnsemble(uint16_t eId) override; 91 virtual void onSetEnsembleLabel(DabLabel& label) override; 92 virtual void onDateTimeUpdate(const dab_date_time_t& dateTime) override; 93 virtual void onFIBDecodeSuccess(bool crcCheckOk, const uint8_t* fib) override; 94 virtual void onNewImpulseResponse(std::vector<float>&& data) override; 95 virtual void onNewNullSymbol(std::vector<DSPCOMPLEX>&& data) override; 96 virtual void onConstellationPoints(std::vector<DSPCOMPLEX>&& data) override; 97 virtual void onMessage(message_level_t level, const std::string& text, const std::string& text2 = std::string()) override; 98 virtual void onTIIMeasurement(tii_measurement_t&& m) override; 99 virtual void onInputFailure() override; 100 101 private: 102 std::mutex retune_mut; 103 void retune(const std::string& channel); 104 105 bool dispatch_client(Socket&& client); 106 // Send a file 107 bool send_file(Socket& s, 108 const std::string& filename, 109 const std::string& content_type); 110 111 // Generate and send the mux.json 112 bool send_mux_json(Socket& s); 113 114 // Send an mp3 stream containing the selected programme. 115 // stream is a service id, either in hex with 0x prefix or 116 // in decimal 117 bool send_mp3(Socket& s, const std::string& stream); 118 119 // Send the slide for the selected programme. 120 // stream is a service id, either in hex with 0x prefix or 121 // in decimal 122 bool send_slide(Socket& s, const std::string& stream); 123 124 // Send the Fast Information Channel as a stream. 125 // Every FIB is 32 bytes long, there three FIBs per 24ms interval, 126 // which gives 32000 bits/s 127 bool send_fic(Socket& s); 128 129 // Send the impulse response, in dB, as a sequence of float values. 130 bool send_impulseresponse(Socket& s); 131 132 // Send the signal spectrum, in dB, as a sequence of float values. 133 bool send_spectrum(Socket& s); 134 bool send_null_spectrum(Socket& s); 135 136 // Send the constellation points, a sequence of phases between -180 and 180 . 137 bool send_constellation(Socket& s); 138 139 // Send the currently tuned channel 140 bool send_channel(Socket& s); 141 142 // Handle a POSTs 143 bool handle_fft_window_placement_post(Socket& s, const std::string& request); 144 bool handle_coarse_corrector_post(Socket& s, const std::string& request); 145 146 // Handle a POST to /channel that will tune the receiver 147 bool handle_channel_post(Socket& s, const std::string& request); 148 149 void handle_phs(); 150 void check_decoders_required(); 151 std::list<tii_measurement_t> getTiiStats(); 152 153 std::thread programme_handler_thread; 154 std::atomic<bool> running = ATOMIC_VAR_INIT(true); 155 156 Channels channels; 157 DABParams dabparams; 158 CVirtualInput& input; 159 fft::Forward spectrum_fft_handler; 160 161 RadioReceiverOptions rro; 162 DecodeSettings decode_settings; 163 164 mutable std::mutex data_mut; 165 bool synced = 0; 166 int last_snr = 0; 167 int last_fine_correction = 0; 168 int last_coarse_correction = 0; 169 dab_date_time_t last_dateTime; 170 171 struct pending_message_t { 172 message_level_t level; 173 std::string text; 174 std::chrono::time_point<std::chrono::system_clock> timestamp; 175 }; 176 177 std::deque<pending_message_t> pending_messages; 178 179 mutable std::mutex plotdata_mut; 180 std::vector<float> last_CIR; 181 std::vector<DSPCOMPLEX> last_NULL; 182 std::vector<DSPCOMPLEX> last_constellation; 183 184 mutable std::mutex fib_mut; 185 size_t num_fic_crc_errors = 0; 186 std::condition_variable new_fib_block_available; 187 std::deque<std::vector<uint8_t> > fib_blocks; 188 189 using comb_pattern_t = std::pair<int, int>; 190 191 std::chrono::time_point<std::chrono::steady_clock> time_last_tiis_clean; 192 std::map<comb_pattern_t, std::list<tii_measurement_t> > tiis; 193 194 Socket serverSocket; 195 196 mutable std::mutex rx_mut; 197 std::chrono::time_point<std::chrono::system_clock> time_rx_created; 198 std::unique_ptr<RadioReceiver> rx; 199 200 using SId_t = uint32_t; 201 std::map<SId_t, WebProgrammeHandler> phs; 202 std::map<SId_t, bool> programmes_being_decoded; 203 std::condition_variable phs_changed; 204 205 std::list<SId_t> carousel_services_available; 206 struct ActiveCarouselService { ActiveCarouselServiceActiveCarouselService207 explicit ActiveCarouselService(SId_t sid) : sid(sid) { 208 time_change = std::chrono::steady_clock::now(); 209 } 210 SId_t sid; 211 std::chrono::time_point<std::chrono::steady_clock> time_change; 212 }; 213 std::list<ActiveCarouselService> carousel_services_active; 214 }; 215