Switch to unified view

a/src/sc2mpd.cpp b/src/sc2mpd.cpp
...
...
18
 *
18
 *
19
 *   You should have received a copy of the GNU General Public License
19
 *   You should have received a copy of the GNU General Public License
20
 *   along with this program; if not, write to the
20
 *   along with this program; if not, write to the
21
 *   Free Software Foundation, Inc.,
21
 *   Free Software Foundation, Inc.,
22
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23
 *
24
 * Modified from ohSongcast/Receiver/Receiver.cpp
23
 */
25
 */
24
#include "config.h"
26
#include "config.h"
25
27
26
#include <OpenHome/OhNetTypes.h>
28
#include <OpenHome/OhNetTypes.h>
27
#include <OpenHome/Private/Ascii.h>
29
#include <OpenHome/Private/Ascii.h>
...
...
35
37
36
#include "workqueue.h"
38
#include "workqueue.h"
37
#include "rcvqueue.h"
39
#include "rcvqueue.h"
38
#include "log.h"
40
#include "log.h"
39
#include "conftree.h"
41
#include "conftree.h"
42
#include "chrono.h"
40
43
41
#include <vector>
44
#include <vector>
42
#include <stdio.h>
45
#include <stdio.h>
43
#include <iostream>
46
#include <iostream>
47
48
#include <sys/types.h>
49
#include <sys/stat.h>
50
#include <fcntl.h>
51
44
using namespace std;
52
using namespace std;
45
53
46
WorkQueue<AudioMessage*> audioqueue("audioqueue", 2);
54
WorkQueue<AudioMessage*> audioqueue("audioqueue", 2);
47
55
48
#ifdef _WIN32
56
#ifdef _WIN32
49
57
50
#pragma warning(disable:4355) // use of 'this' in ctor lists safe in this case
58
#pragma warning(disable:4355) // use of 'this' in ctor lists safe in this case
51
59
52
#define CDECL __cdecl
60
#define CDECL __cdecl
53
54
#include <conio.h>
55
61
56
int mygetch()
62
int mygetch()
57
{
63
{
58
    return (_getch());
64
    return (_getch());
59
}
65
}
...
...
105
    virtual void Process(OhmMsgAudio& aMsg);
111
    virtual void Process(OhmMsgAudio& aMsg);
106
    virtual void Process(OhmMsgTrack& aMsg);
112
    virtual void Process(OhmMsgTrack& aMsg);
107
    virtual void Process(OhmMsgMetatext& aMsg);
113
    virtual void Process(OhmMsgMetatext& aMsg);
108
114
109
private:
115
private:
116
    // Debug, stats, etc while we get to understand the Songcast streams
117
    class Observer {
118
    public:
110
    TBool iReset;
119
        TBool iReset;
111
    TUint iCount;
120
        TUint iCount;
112
    TUint iFrame;
121
        TUint iFrame;
122
        int dumpfd;
123
        Chrono chron;
124
        Observer() : iReset(true), iCount(0), iFrame(0), dumpfd(-1) {
125
#if 0
126
            dumpfd = 
127
                open("/y/av/tmp/sc2dump", O_WRONLY|O_CREAT|O_TRUNC, 0666);
128
            if (dumpfd < 0) {
129
                LOGERR("OhmReceiverDriver::Open dump file failed\n");
130
            }
131
#endif
132
        }
133
134
        void reset() {
135
            iReset = true;
136
        }
137
138
        void process(OhmMsgAudio& aMsg);
139
    };
140
    Observer obs;
113
};
141
};
114
142
115
116
OhmReceiverDriver::OhmReceiverDriver(int port)
143
OhmReceiverDriver::OhmReceiverDriver(int port)
117
{
144
{
118
    iReset = true;
119
    iCount = 0;
120
    AudioEaterContext *ctxt = new AudioEaterContext(port);
145
    AudioEaterContext *ctxt = new AudioEaterContext(port);
121
    audioqueue.start(1, &audioEater, ctxt);
146
    audioqueue.start(1, &audioEater, ctxt);
122
}
147
}
123
148
124
void OhmReceiverDriver::Add(OhmMsg& aMsg)
149
void OhmReceiverDriver::Add(OhmMsg& aMsg)
...
...
136
    LOGDEB("=== STARTED ====\n");
161
    LOGDEB("=== STARTED ====\n");
137
}
162
}
138
163
139
void OhmReceiverDriver::Connected()
164
void OhmReceiverDriver::Connected()
140
{
165
{
141
    iReset = true;
166
    obs.reset();
142
    LOGDEB("=== CONNECTED ====\n");
167
    LOGDEB("=== CONNECTED ====\n");
143
}
168
}
144
169
145
void OhmReceiverDriver::Playing()
170
void OhmReceiverDriver::Playing()
146
{
171
{
...
...
157
void OhmReceiverDriver::Stopped()
182
void OhmReceiverDriver::Stopped()
158
{
183
{
159
    LOGDEB("=== STOPPED ====\n");
184
    LOGDEB("=== STOPPED ====\n");
160
}
185
}
161
186
162
void OhmReceiverDriver::Process(OhmMsgAudio& aMsg)
187
void OhmReceiverDriver::Observer::process(OhmMsgAudio& aMsg)
163
{
188
{
164
    if (++iCount == 400 || aMsg.Halt()) {
189
    if (++iCount == 400 || aMsg.Halt()) {
190
        static unsigned long long last_timestamp;
191
        unsigned long long timestamp = aMsg.MediaTimestamp();
165
        LOGDEB("OhmRcvDrv::Process:audio: samplerate " << aMsg.SampleRate() <<
192
        LOGDEB("OhmRcvDrv::Process:audio: samplerate " << aMsg.SampleRate() <<
166
               " bitdepth " << aMsg.BitDepth() << " channels " <<
193
               " bitdepth " << aMsg.BitDepth() << " channels " <<
167
               aMsg.Channels() << " samples " << aMsg.Samples() << 
194
               aMsg.Channels() << " samples " << aMsg.Samples() << 
168
               " Halted ? " << aMsg.Halt() << endl);
195
               " Halted ? " << aMsg.Halt() << endl);
196
197
        if (last_timestamp) {
198
            long long intervalus = 
199
                ((timestamp - last_timestamp) * 1000000) / (256*48000);
200
            long long atsus = 
201
                ((timestamp) * 1000000) / (256*48000);
202
            long long absus = chron.amicros() - 1430477861905884LL;
203
            LOGDEB("Computed-uS: " << intervalus  << 
204
                   " Elapsed-uS: " << chron.urestart() << 
205
                   " Timestamp-uS: " << atsus <<
206
                   " Abs-uS: " << absus << 
207
                   " Diff-mS " << (absus - atsus) / 1000 <<
208
                   endl);
209
        }
210
        last_timestamp = timestamp;
211
212
        if (!aMsg.Halt()) {
213
            unsigned int bytes = 
214
                aMsg.Samples() * (aMsg.BitDepth() / 8) * aMsg.Channels();
215
216
            if (bytes != aMsg.Audio().Bytes()) {
217
                LOGERR("OhmRcvDrv::Process:audio: computed bytes " << bytes << 
218
                       " !=  bufer's " << aMsg.Audio().Bytes() << endl);
219
                bytes = aMsg.Audio().Bytes();
220
            }
221
            const unsigned char *icp = 
222
                (const unsigned char *)aMsg.Audio().Ptr();
223
            bool silence = true;
224
            for (unsigned int i = 0; i < bytes; i++) {
225
                if (icp[i]) {
226
                    silence = false;
227
                    break;
228
                }
229
            }
230
            if (silence) {
231
                LOGDEB("OhmRcvDrv::Process:audio: silence buffer" << endl);
232
            }
233
            if (dumpfd >= 0) {
234
                if (write(dumpfd, icp, bytes) != int(bytes)) {
235
                    ;
236
                }
237
            }
238
        }
239
169
        iCount = 0;
240
        iCount = 0;
170
    }
241
    }
171
242
172
    if (iReset) {
243
    if (iReset) {
173
        iFrame = aMsg.Frame();
244
        iFrame = aMsg.Frame();
...
...
177
            LOGINF("Missed frames between " << iFrame << " and " << 
248
            LOGINF("Missed frames between " << iFrame << " and " << 
178
                    aMsg.Frame());
249
                    aMsg.Frame());
179
        }
250
        }
180
        iFrame = aMsg.Frame();
251
        iFrame = aMsg.Frame();
181
    }
252
    }
253
}
182
254
255
void OhmReceiverDriver::Process(OhmMsgAudio& aMsg)
256
{
257
183
    if (aMsg.Audio().Bytes() == 0)
258
    if (aMsg.Audio().Bytes() == 0) {
259
        LOGDEB("OhmReceiverDriver::Process: empty message\n");
184
        return;
260
        return;
261
    }
185
262
186
    unsigned int bytes = 
187
        aMsg.Samples() * (aMsg.BitDepth() / 8) * aMsg.Channels();
188
189
    if (bytes != aMsg.Audio().Bytes()) {
190
        LOGERR("OhmRcvDrv::Process:audio: computed bytes " << bytes << 
191
               " !=  bufer's " << aMsg.Audio().Bytes() << endl);
192
        bytes = aMsg.Audio().Bytes();
263
    unsigned int bytes = aMsg.Audio().Bytes();
193
    }
194
195
    char *buf = (char *)malloc(bytes);
264
    char *buf = (char *)malloc(bytes);
265
    if (buf == 0) {
266
        LOGERR("OhmReceiverDriver::Process: can't allocate " << 
267
               bytes << " bytes\n");
268
        return;
269
    }
270
271
#ifdef WORDS_BIGENDIAN
272
    memcpy(buf, aMsg.Audio().Ptr(), bytes);
273
#else
196
    if (aMsg.BitDepth() == 16) {
274
    if (aMsg.BitDepth() == 16) {
197
        swab(aMsg.Audio().Ptr(), buf, bytes);
275
        swab(aMsg.Audio().Ptr(), buf, bytes);
198
    } else if (aMsg.BitDepth() == 24) {
276
    } else if (aMsg.BitDepth() == 24) {
199
        unsigned char *ocp = (unsigned char *)buf;
277
        unsigned char *ocp = (unsigned char *)buf;
200
        const unsigned char *icp = (const unsigned char *)aMsg.Audio().Ptr();
278
        const unsigned char *icp = (const unsigned char *)aMsg.Audio().Ptr();
...
...
204
            *ocp++ = icp[1];
282
            *ocp++ = icp[1];
205
            *ocp++ = *icp;
283
            *ocp++ = *icp;
206
            icp += 3;
284
            icp += 3;
207
        }
285
        }
208
    } else if (aMsg.BitDepth() == 32) {
286
    } else if (aMsg.BitDepth() == 32) {
287
        // Never seen this but whatever...
288
        unsigned char *ocp = (unsigned char *)buf;
289
        const unsigned char *icp = (const unsigned char *)aMsg.Audio().Ptr();
290
        const unsigned char *icp0 = icp;
291
        while (icp - icp0 <= int(bytes) - 4) {
292
            *ocp++ = icp[3];
293
            *ocp++ = icp[2];
294
            *ocp++ = icp[1];
295
            *ocp++ = *icp;
296
            icp += 4;
209
    }
297
        }
298
    }
299
#endif
210
300
211
    AudioMessage *ap = new 
301
    AudioMessage *ap = new 
212
        AudioMessage(aMsg.BitDepth(), aMsg.Channels(), aMsg.Samples(),
302
        AudioMessage(aMsg.BitDepth(), aMsg.Channels(), aMsg.Samples(),
213
                     aMsg.SampleRate(), buf);
303
                     aMsg.SampleRate(), buf);
214
304