Switch to unified view

a/src/cdplugins/tidal.cxx b/src/cdplugins/tidal.cxx
...
...
39
using namespace UPnPProvider;
39
using namespace UPnPProvider;
40
40
41
class Tidal::Internal {
41
class Tidal::Internal {
42
public:
42
public:
43
    Internal(const vector<string>& pth, const string& hp, const string& pp)
43
    Internal(const vector<string>& pth, const string& hp, const string& pp)
44
    : path(pth), httphp(hp), pathprefix(pp) { }
44
    : path(pth), httphp(hp), pathprefix(pp), lasttime(0) { }
45
45
46
    bool maybeStartCmd(const string&);
46
    bool maybeStartCmd(const string&);
47
    string get_media_url(const std::string& path);
47
    string get_media_url(const std::string& path);
48
    string get_mimetype(const std::string& path);
48
    string get_mimetype(const std::string& path);
49
    
49
    
...
...
53
    off_t seek(void *hdl, off_t offs, int whence);
53
    off_t seek(void *hdl, off_t offs, int whence);
54
    void close(void *hdl);
54
    void close(void *hdl);
55
55
56
    CmdTalk cmd;
56
    CmdTalk cmd;
57
    vector<string> path;
57
    vector<string> path;
58
    // Host and port part for the URIs we generate.
58
    string httphp;
59
    string httphp;
60
    // path prefix (this is used to redirect gets to us).
59
    string pathprefix;
61
    string pathprefix;
60
    // mimetype is a constant for a given session, depend on quality
62
    // mimetype is a constant for a given session, depend on quality
61
    // choice only. Initialized once
63
    // choice only. Initialized once
62
    string mimetype;
64
    string mimetype;
65
66
    // Cached uri translation for the vdir: we do this in getinfo()
67
    // and reuse in open()
68
    string lastpath;
69
    string lastmediaurl;
70
    time_t lasttime;
63
};
71
};
64
72
65
bool Tidal::Internal::maybeStartCmd(const string& who)
73
bool Tidal::Internal::maybeStartCmd(const string& who)
66
{
74
{
67
    LOGDEB1("Tidal::maybeStartCmd for: " << who << endl);
75
    LOGDEB1("Tidal::maybeStartCmd for: " << who << endl);
...
...
84
string Tidal::Internal::get_media_url(const std::string& path)
92
string Tidal::Internal::get_media_url(const std::string& path)
85
{
93
{
86
    if (!maybeStartCmd("get_media_url")) {
94
    if (!maybeStartCmd("get_media_url")) {
87
    return string();
95
    return string();
88
    }
96
    }
89
97
    if (lastpath.compare(path) || (time(0) - lasttime > 10)) {
90
    unordered_map<string, string> res;
98
  unordered_map<string, string> res;
91
    if (!cmd.callproc("trackuri", {{"path", path}}, res)) {
99
  if (!cmd.callproc("trackuri", {{"path", path}}, res)) {
92
    LOGERR("Tidal::get_media_url: slave failure\n");
100
        LOGERR("Tidal::get_media_url: slave failure\n");
93
    return string();
101
        return string();
94
    }
102
  }
95
103
96
    auto it = res.find("media_url");
104
  auto it = res.find("media_url");
97
    if (it == res.end()) {
105
  if (it == res.end()) {
98
    LOGERR("Tidal::get_media_url: no media url in result\n");
106
        LOGERR("Tidal::get_media_url: no media url in result\n");
99
    return string();
107
        return string();
100
    }
108
  }
101
    string& media_url = it->second;
109
  lastmediaurl = it->second;
110
  lastpath = path;
111
  lasttime = time(0);
112
    }
113
102
    LOGDEB("Tidal: got media url [" << media_url << "]\n");
114
    LOGDEB("Tidal: got media url [" << lastmediaurl << "]\n");
103
    return media_url;
115
    return lastmediaurl;
104
}
116
}
105
117
106
string Tidal::Internal::get_mimetype(const std::string& path)
118
string Tidal::Internal::get_mimetype(const std::string& path)
107
{
119
{
108
    if (!maybeStartCmd("get_mimetype")) {
120
    if (!maybeStartCmd("get_mimetype")) {
...
...
124
    LOGDEB("Tidal: got mimetype [" << mimetype << "]\n");
136
    LOGDEB("Tidal: got mimetype [" << mimetype << "]\n");
125
    }
137
    }
126
    return mimetype;
138
    return mimetype;
127
}
139
}
128
140
129
int Tidal::Internal::getinfo(const std::string& path, VirtualDir::FileInfo *inf)
130
{
131
    LOGDEB("Tidal::getinfo: " << path << endl);
132
    inf->file_length = -1;
133
    inf->last_modified = 0;
134
    inf->mime = get_mimetype(path);
135
    return 0;
136
}
137
138
class StreamHandle {
141
class StreamHandle {
139
public:
142
public:
140
    StreamHandle() : rtmp(nullptr), http_handle(nullptr) {
143
    StreamHandle() : rtmp(nullptr), http_handle(nullptr) {
141
    }
144
    }
142
    ~StreamHandle() {
145
    ~StreamHandle() {
143
    if (rtmp) {
146
    if (rtmp) {
144
        RTMP_Close(rtmp);
147
        RTMP_Close(rtmp);
145
        RTMP_Free(rtmp);
148
        RTMP_Free(rtmp);
146
    }
149
    }
147
    if (http_handle) {
150
    if (http_handle) {
151
            LOGDEB("StreamHandle:~: closing http handle\n");
148
        UpnpCloseHttpGet(http_handle);
152
        UpnpCloseHttpGet(http_handle);
153
            LOGDEB("StreamHandle:~: close done\n");
149
    }
154
    }
150
    }
155
    }
151
    
156
    
152
    RTMP *rtmp;
157
    RTMP *rtmp;
153
    void *http_handle;
158
    void *http_handle;
154
    int len;
159
    int len;
155
};
160
};
161
162
163
int Tidal::Internal::getinfo(const std::string& path, VirtualDir::FileInfo *inf)
164
{
165
    LOGDEB("Tidal::getinfo: " << path << endl);
166
    string media_url = get_media_url(path);
167
    if (media_url.empty()) {
168
  return -1;
169
    }
170
    inf->file_length = -1;
171
    inf->last_modified = 0;
172
    inf->mime = get_mimetype(path);
173
    if (media_url.find("http") == 0) {
174
  void *http_handle;
175
  char *content_type;
176
  int content_length;
177
  int httpstatus;
178
  int code = UpnpOpenHttpGet(media_url.c_str(), &http_handle,
179
                   &content_type, &content_length,
180
                   &httpstatus, 30);
181
  LOGDEB("Tidal::getinfo: UpnpOpenHttpGet: ret " << code <<
182
         " mtype " << content_type << " length " << content_length <<
183
         " HTTP status " << httpstatus << endl);
184
  if (code) {
185
      LOGERR("Tidal::getinfo: UpnpOpenHttpGet: ret " << code <<
186
         " mtype " << content_type << " length " << content_length <<
187
         " HTTP status " << httpstatus << endl);
188
  } else {
189
      inf->file_length = content_length;
190
      LOGDEB("Tidal:getinfo: got file length "<< inf->file_length <<endl);
191
  }
192
        // Doc says to free this, but it causes malloc issues
193
  //free(content_type);
194
  StreamHandle hdl;
195
  hdl.http_handle = http_handle;
196
  // Let StreamHandle clean up
197
    }
198
    LOGDEB("Tidal::getinfo: returning\n");
199
    return 0;
200
}
201
156
202
157
void *Tidal::Internal::open(const string& path)
203
void *Tidal::Internal::open(const string& path)
158
{
204
{
159
    LOGDEB("Tidal::open: " << path << endl);
205
    LOGDEB("Tidal::open: " << path << endl);
160
    string media_url = get_media_url(path);
206
    string media_url = get_media_url(path);
...
...
176
        LOGERR("Tidal::open: UpnpOpenHttpGet: ret " << code <<
222
        LOGERR("Tidal::open: UpnpOpenHttpGet: ret " << code <<
177
           " mtype " << content_type << " length " << content_length <<
223
           " mtype " << content_type << " length " << content_length <<
178
           " HTTP status " << httpstatus << endl);
224
           " HTTP status " << httpstatus << endl);
179
        return nullptr;
225
        return nullptr;
180
    }
226
    }
227
        // Doc says to free this, but it causes malloc issues
228
  //free(content_type);
181
    StreamHandle *hdl = new StreamHandle;
229
    StreamHandle *hdl = new StreamHandle;
182
    hdl->http_handle = http_handle;
230
    hdl->http_handle = http_handle;
183
    hdl->len = content_length;
231
    hdl->len = content_length;
184
    return hdl;
232
    return hdl;
185
    } else {
233
    } else {
...
...
289
337
290
static int resultToEntries(const string& encoded, int stidx, int cnt,
338
static int resultToEntries(const string& encoded, int stidx, int cnt,
291
               std::vector<UpSong>& entries)
339
               std::vector<UpSong>& entries)
292
{
340
{
293
    auto decoded = json::parse(encoded);
341
    auto decoded = json::parse(encoded);
294
    LOGDEB("Tidal::browse: got " << decoded.size() << " entries\n");
342
    LOGDEB("Tidal::results: got " << decoded.size() << " entries\n");
295
    LOGDEB1("Tidal::browse: undecoded json: " << decoded.dump() << endl);
343
    LOGDEB1("Tidal::results: undecoded json: " << decoded.dump() << endl);
296
344
297
    for (unsigned int i = stidx; i < decoded.size(); i++) {
345
    for (unsigned int i = stidx; i < decoded.size(); i++) {
298
    if (--cnt < 0) {
346
    if (--cnt < 0) {
299
        break;
347
        break;
300
    }
348
    }