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