Switch to unified view

a/src/cdplugins/tidal.cxx b/src/cdplugins/tidal.cxx
...
...
21
21
22
#include <string>
22
#include <string>
23
#include <vector>
23
#include <vector>
24
#include <string.h>
24
#include <string.h>
25
#include <librtmp/rtmp.h>
25
#include <librtmp/rtmp.h>
26
#include <upnp/upnp.h>
26
27
27
#include "cmdtalk.h"
28
#include "cmdtalk.h"
28
29
29
#include "pathut.h"
30
#include "pathut.h"
30
#include "smallut.h"
31
#include "smallut.h"
...
...
108
    return string();
109
    return string();
109
    }
110
    }
110
    if (mimetype.empty()) {
111
    if (mimetype.empty()) {
111
    unordered_map<string, string> res;
112
    unordered_map<string, string> res;
112
    if (!cmd.callproc("mimetype", {{"path", path}}, res)) {
113
    if (!cmd.callproc("mimetype", {{"path", path}}, res)) {
113
        LOGERR("Tidal::get_media_url: slave failure\n");
114
        LOGERR("Tidal::get_mimetype: slave failure\n");
114
        return string();
115
        return string();
115
    }
116
    }
116
117
117
    auto it = res.find("mimetype");
118
    auto it = res.find("mimetype");
118
    if (it == res.end()) {
119
    if (it == res.end()) {
...
...
132
    inf->last_modified = 0;
133
    inf->last_modified = 0;
133
    inf->mime = get_mimetype(path);
134
    inf->mime = get_mimetype(path);
134
    return 0;
135
    return 0;
135
}
136
}
136
137
138
class StreamHandle {
139
public:
140
    StreamHandle() : rtmp(nullptr), http_handle(nullptr) {
141
    }
142
    ~StreamHandle() {
143
  if (rtmp) {
144
      RTMP_Close(rtmp);
145
      RTMP_Free(rtmp);
146
  }
147
  if (http_handle) {
148
      UpnpCloseHttpGet(http_handle);
149
  }
150
    }
151
  
152
    RTMP *rtmp;
153
    void *http_handle;
154
    int len;
155
};
156
137
void *Tidal::Internal::open(const string& path)
157
void *Tidal::Internal::open(const string& path)
138
{
158
{
139
    LOGDEB("Tidal::open: " << path << endl);
159
    LOGDEB("Tidal::open: " << path << endl);
140
    string media_url = get_media_url(path);
160
    string media_url = get_media_url(path);
141
    if (media_url.empty()) {
161
    if (media_url.empty()) {
142
    return nullptr;
162
    return nullptr;
143
    }
163
    }
164
    if (media_url.find("http") == 0) {
165
  void *http_handle;
166
  char *content_type;
167
  int content_length;
168
  int httpstatus;
169
  int code = UpnpOpenHttpGet(media_url.c_str(), &http_handle,
170
                   &content_type, &content_length,
171
                   &httpstatus, 30);
172
  LOGDEB("Tidal::open: UpnpOpenHttpGet: ret " << code <<
173
         " mtype " << content_type << " length " << content_length <<
174
         " HTTP status " << httpstatus << endl);
175
  if (code) {
176
      LOGERR("Tidal::open: UpnpOpenHttpGet: ret " << code <<
177
         " mtype " << content_type << " length " << content_length <<
178
         " HTTP status " << httpstatus << endl);
179
      return nullptr;
180
  }
181
  StreamHandle *hdl = new StreamHandle;
182
  hdl->http_handle = http_handle;
183
  hdl->len = content_length;
184
  return hdl;
185
    } else {
144
    RTMP *rtmp = RTMP_Alloc();
186
  RTMP *rtmp = RTMP_Alloc();
145
    RTMP_Init(rtmp);
187
  RTMP_Init(rtmp);
146
188
147
    // Writable copy of url
189
  // Writable copy of url
148
    if (!RTMP_SetupURL(rtmp, strdup(media_url.c_str()))) {
190
  if (!RTMP_SetupURL(rtmp, strdup(media_url.c_str()))) {
149
    LOGERR("Tidal::open: RTMP_SetupURL failed for [" <<
191
        LOGERR("Tidal::open: RTMP_SetupURL failed for [" <<
150
           media_url << "]\n");
192
         media_url << "]\n");
151
    RTMP_Free(rtmp);
193
        RTMP_Free(rtmp);
152
    return nullptr;
194
        return nullptr;
153
    }
195
  }
154
    if (!RTMP_Connect(rtmp, NULL)) {
196
  if (!RTMP_Connect(rtmp, NULL)) {
155
    LOGERR("Tidal::open: RTMP_Connect failed for [" <<
197
        LOGERR("Tidal::open: RTMP_Connect failed for [" <<
156
           media_url << "]\n");
198
         media_url << "]\n");
157
    RTMP_Free(rtmp);
199
        RTMP_Free(rtmp);
158
    return nullptr;
200
        return nullptr;
159
    }
201
  }
160
    if (!RTMP_ConnectStream(rtmp, 0)) {
202
  if (!RTMP_ConnectStream(rtmp, 0)) {
161
    LOGERR("Tidal::open: RTMP_ConnectStream failed for [" <<
203
        LOGERR("Tidal::open: RTMP_ConnectStream failed for [" <<
162
           media_url << "]\n");
204
         media_url << "]\n");
163
    RTMP_Free(rtmp);
205
        RTMP_Free(rtmp);
164
    return nullptr;
206
        return nullptr;
165
    }
166
    
207
    }
167
    return rtmp;
208
  StreamHandle *hdl = new StreamHandle;
209
  hdl->rtmp = rtmp;
210
  return hdl;
211
    }
168
}
212
}
169
213
170
int Tidal::Internal::read(void *hdl, char* buf, size_t cnt)
214
int Tidal::Internal::read(void *_hdl, char* buf, size_t cnt)
171
{
215
{
172
    LOGDEB("Tidal::read: " << cnt << endl);
216
    LOGDEB("Tidal::read: " << cnt << endl);
173
    if (!hdl)
217
    if (!_hdl)
174
    return -1;
218
    return -1;
175
    RTMP *rtmp = (RTMP *)hdl;
219
220
    // The pupnp http code has a default 1MB buffer size which is much
221
    // too big for us (too slow, esp. because tidal will stall).
176
    if (cnt > 100 * 1024)
222
    if (cnt > 100 * 1024)
177
    cnt = 100 * 1024;
223
        cnt = 100 * 1024;
224
225
    StreamHandle *hdl = (StreamHandle *)_hdl;
226
227
    if (hdl->rtmp) {
228
  RTMP *rtmp = hdl->rtmp;
178
    size_t totread = 0;
229
  size_t totread = 0;
179
    while (totread < cnt) {
230
  while (totread < cnt) {
180
    int didread = RTMP_Read(rtmp, buf+totread, cnt-totread);
231
        int didread = RTMP_Read(rtmp, buf+totread, cnt-totread);
181
    //LOGDEB("Tidal::read: RTMP_Read returned: " << didread << endl);
232
        //LOGDEB("Tidal::read: RTMP_Read returned: " << didread << endl);
182
    if (didread <= 0)
233
        if (didread <= 0)
183
        break;
234
      break;
184
    totread += didread;
235
        totread += didread;
185
    }
236
  }
186
    LOGDEB("Tidal::read: total read: " << totread << endl);
237
  LOGDEB("Tidal::read: total read: " << totread << endl);
187
    return totread > 0 ? totread : -1;
238
  return totread > 0 ? totread : -1;
239
    } else if (hdl->http_handle) {
240
  int code = UpnpReadHttpGet(hdl->http_handle, buf, &cnt, 30);
241
  if (code) {
242
      LOGERR("Tidal::read: UpnpReadHttpGet returned " << code << endl);
243
      return -1;
244
  }
245
  return int(cnt);
246
    } else {
247
  LOGERR("Tidal::read: neither rtmp nor http\n");
248
  return -1;
249
    }
188
}
250
}
189
251
190
off_t Tidal::Internal::seek(void *hdl, off_t offs, int whence)
252
off_t Tidal::Internal::seek(void *hdl, off_t offs, int whence)
191
{
253
{
192
    LOGDEB("Tidal::seek\n");
254
    LOGDEB("Tidal::seek\n");
193
    return -1;
255
    return -1;
194
}
256
}
195
257
196
void Tidal::Internal::close(void *hdl)
258
void Tidal::Internal::close(void *_hdl)
197
{
259
{
198
    LOGDEB("Tidal::close\n");
260
    LOGDEB("Tidal::close\n");
199
    if (hdl) {
261
    StreamHandle *hdl = (StreamHandle *)_hdl;
200
  RTMP *rtmp = (RTMP *)hdl;
262
    delete hdl;
201
  RTMP_Close(rtmp);
202
  RTMP_Free(rtmp);
203
    }
204
}
263
}
205
264
206
265
207
VirtualDir::FileOps Tidal::getFileOps()
266
VirtualDir::FileOps Tidal::getFileOps()
208
{
267
{