1 /*
2  *    Copyright (C) 2017
3  *    Albrecht Lohofener (albrechtloh@gmx.de)
4  *
5  *    This file is based on SDR-J
6  *    Copyright (C) 2010, 2011, 2012, 2013
7  *    Jan van Katwijk (J.vanKatwijk@gmail.com)
8  *
9  *    This file is part of the welle.io.
10  *    Many of the ideas as implemented in welle.io are derived from
11  *    other work, made available through the GNU general Public License.
12  *    All copyrights of the original authors are recognized.
13  *
14  *    welle.io is free software; you can redistribute it and/or modify
15  *    it under the terms of the GNU General Public License as published by
16  *    the Free Software Foundation; either version 2 of the License, or
17  *    (at your option) any later version.
18  *
19  *    welle.io is distributed in the hope that it will be useful,
20  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *    GNU General Public License for more details.
23  *
24  *    You should have received a copy of the GNU General Public License
25  *    along with welle.io; if not, write to the Free Software
26  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  *
28  */
29 
30 #ifndef __VIRTUAL_INPUT
31 #define __VIRTUAL_INPUT
32 
33 #include <memory>
34 #include <fstream>
35 #include <iostream>
36 
37 #include "dab-constants.h"
38 #include "radio-controller.h"
39 #include "ringbuffer.h"
40 
41 enum class CDeviceID {
42     UNKNOWN, NULLDEVICE, AIRSPY, RAWFILE, RTL_SDR, RTL_TCP, SOAPYSDR, ANDROID_RTL_SDR, LIMESDR};
43 
44 class CVirtualInput : public InputInterface {
45 public:
~CVirtualInput()46     virtual ~CVirtualInput() {}
47     virtual CDeviceID getID(void) = 0;
48 
writeRecordBufferToFile(std::string & fileanme)49     void writeRecordBufferToFile(std::string &fileanme) {
50         if(!recordBuffer)
51             return;
52 
53         std::ofstream rawStream(fileanme, std::ios::binary);
54 
55         while (1) {
56             uint8_t data_tmp[1024];
57             const auto available = recordBuffer->GetRingBufferReadAvailable();
58 
59             if (available <= 0) {
60                 break;
61             }
62 
63             const size_t data_tmpSize = std::min(sizeof(data_tmp), (size_t)available);
64             recordBuffer->getDataFromBuffer(data_tmp, data_tmpSize);
65             rawStream.write((char*)data_tmp, data_tmpSize);
66         }
67 
68         rawStream.close();
69     }
70 
initRecordBuffer(uint32_t size)71     void initRecordBuffer(uint32_t size) {
72         // The ring buffer size has to be power of 2
73         uint32_t bitCount = ceil(log2(size));
74         uint32_t bufferSize = pow(2, bitCount);
75 
76         try {
77             recordBuffer.reset(new RingBuffer<uint8_t>(bufferSize));
78         }
79 
80         catch (const std::bad_alloc& e) {
81                 std::clog << "CVirtualInput: recordBuffer allocation failed (size " << bufferSize * sizeof(uint8_t) << " bytes) : " << e.what() << std::endl;
82         }
83     }
84 
85 protected:
putIntoRecordBuffer(uint8_t & data,uint32_t size)86     void putIntoRecordBuffer(uint8_t &data, uint32_t size) {
87         if(!recordBuffer)
88             return;
89 
90         recordBuffer->putDataIntoBuffer(&data, static_cast<int>(size));
91         //std::clog << "CVirtualInput: GetRingBufferReadAvailable() " << recordBuffer->GetRingBufferReadAvailable() << std::endl;
92     }
93 
94 private:
95     std::unique_ptr<RingBuffer<uint8_t>> recordBuffer;
96 };
97 
98 #endif
99