f6dddcd07745a0de580032eb24aafab4f2c352c7
[groove] / playlist.cpp
1 #include "playlist.h"
2
3 playlist::playlist(QObject *parent) :
4     QAbstractTableModel(parent)
5 {
6    manager = new QNetworkAccessManager();
7    this->currentdownloaditem = -1;
8    pList = new QList<songElement *>;
9    this->currentplayingitem = -1;
10    this->currentSkeyItem = -1;
11    this->reply = NULL;
12    invalid = new QVariant();
13    icon = new QVariant(QIcon(":/groove/icons/general_forward.png"));
14 }
15
16 //Implemented model class information
17 QVariant playlist::data(const QModelIndex &index, int role) const
18 {
19
20     playlist* play = (playlist *)index.model();
21     QVariant dat = *play->invalid;
22     if(play->existAt(index.row()))
23     {
24         if (!index.isValid())
25             return *play->invalid;
26         if (role == Qt::TextAlignmentRole) {
27             return int(Qt::AlignLeft | Qt::AlignVCenter);
28         } else if (role == Qt::DecorationRole) {
29             switch(index.column())
30             {
31             case sName:
32                 if(play->currentplaying()==index.row())
33                     //dat = *play->icon;
34                     dat = *play->invalid;
35                 else
36                     dat = *play->invalid;
37                 break;
38             default:
39                 dat = *play->invalid;
40             }
41         } else if (role == Qt::ForegroundRole) {
42             switch(index.column())
43             {
44             case sName:
45                 if(!play->pList->at(index.row())->downloaded)
46                     dat = QVariant(Qt::gray);
47                 else
48                     dat = *play->invalid;
49                 break;
50             default:
51                 dat = *play->invalid;
52             }
53         } else if (role == Qt::DisplayRole) {
54             switch(index.column())
55             {
56             case sName:
57                 dat = QVariant(*play->pList->at(index.row())->name);
58                 break;
59             case sID:
60                 dat = QVariant(*play->pList->at(index.row())->songId);
61                 break;
62             case sKey:
63                 dat = QVariant(*play->pList->at(index.row())->streamkey);
64                 break;
65             case sDownloaded:
66                 dat = QVariant(play->pList->at(index.row())->downloaded);
67                 break;
68             case sReady:
69                 dat = QVariant(play->pList->at(index.row())->bufferready);
70                 break;
71             case sURL:
72                 dat = QVariant(play->pList->at(index.row())->server->toString());
73                 break;
74             case sPlayed:
75                 dat = QVariant(play->pList->at(index.row())->played);
76                 break;
77             default:
78                 dat = *play->invalid;
79             }
80         } else
81             dat = *play->invalid;
82     }
83     else
84         dat = *play->invalid;
85     return dat;
86 }
87 int playlist::rowCount(const QModelIndex &) const
88 {
89     return pList->size();
90 }
91 int playlist::columnCount(const QModelIndex &) const
92 {
93     return PLAYLISTENUMS;
94 }
95
96
97 QList<playlist::songElement *>* playlist::getList()
98 {
99     return pList;
100 }
101
102 void playlist::markPlayed(int position)
103 {
104     if(0 <= position && position < pList->size())
105     {
106         pList->at(position)->played = true;
107         this->freeMemory(position);
108     }
109 }
110 void playlist::freeMemory(int position)
111 {
112    pList->at(position)->downloaded = false;
113    pList->at(position)->bufferready = false;
114    delete pList->at(position)->buffer;
115    pList->at(position)->buffer = new QBuffer();
116 }
117 bool playlist::existAt(int position)
118 {
119     if(position < 0)
120         return false;
121     return (pList->size() > position);
122 }
123
124 int playlist::currentplaying()
125 {
126     return this->currentplayingitem;
127 }
128 bool playlist::bReady(int b)
129 {
130     if(pList->size() > b)
131         return pList->at(b)->bufferready;
132     else
133         return false;
134 }
135 void playlist::setBufferRdy(int b)
136 {
137     pList->at(b)->bufferready = true;
138 }
139 void playlist::setCurrentPlaying(int position)
140 {
141     if(this->existAt(position))
142     {
143         this->currentplayingitem = position;
144         if(!pList->at(position)->downloaded && this->currentdownloaditem != this->currentplayingitem)
145             this->beginDownload(position);
146         /*if(pList->at(position)->bufferready == false &&)
147         {
148             if(!pList->at(position)->downloaded)
149                 this->beginDownload(position);
150         }
151         else
152             emit this->bufferReady(position);
153         */
154         return;
155     }
156     else
157     {
158     if(position == -1)
159         {
160         this->currentplayingitem = -1;
161     }
162     else
163         return;
164     }
165 }
166 QIODevice * playlist::getBuffer(int position)
167 {
168     return pList->at(position)->buffer;
169 }
170
171 void playlist::beginDownload(int position)
172 {
173     this->currentdownloaditem = position;
174     qDebug() << "StartDownlaod:" << pList->at(position)->songId;
175     QNetworkRequest req;
176     req.setUrl(*pList->at(currentdownloaditem)->server);
177     qDebug() << pList->at(currentdownloaditem)->server;
178     req.setHeader(req.ContentTypeHeader,QVariant("application/x-www-form-urlencoded"));
179     if(reply)
180     {
181         reply->disconnect();
182         reply->deleteLater();
183     }
184     reply = manager->post(req,QString("streamKey=" + pList->at(this->currentdownloaditem)->streamkey->toAscii()).toAscii());
185     pList->at(this->currentdownloaditem)->buffer->open(QBuffer::ReadWrite | QBuffer::Truncate);
186     connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadSlot(qint64,qint64)));
187     connect(reply,SIGNAL(finished()),this,SLOT(networkReplyFinish()));
188     connect(this,SIGNAL(downloadComplete(int)),this,SLOT(downloadDone(int)));
189     connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(getNError(QNetworkReply::NetworkError)));
190     startStreamT = QTime::currentTime();
191 }
192 void playlist::getNError(QNetworkReply::NetworkError error)
193 {
194     qDebug() << "Network Error (if this is 99 then it will retry" << error;
195     if(error == QNetworkReply::UnknownNetworkError && this->currentdownloaditem != -1)
196         beginDownload(this->currentdownloaditem);
197
198 }
199
200 void playlist::setGscom(gscom *comm)
201 {
202     gs = comm;
203     connect(gs,SIGNAL(sKeyFound()),this,SLOT(skeyFound()));
204 }
205 void playlist::skeyFound()
206 {
207     emit this->freeze(false);
208     pList->at(this->currentSkeyItem)->streamkey = new QString(gs->streamID);
209     pList->at(this->currentSkeyItem)->server = new QUrl(gs->sku);
210     if(this->currentdownloaditem == -1)
211         this->beginDownload(this->currentSkeyItem);
212     else
213         if(this->currentplaying() == this->currentSkeyItem)
214             this->beginDownload(this->currentSkeyItem);
215     this->currentSkeyItem = -1;
216 }
217
218 int playlist::addSong(QStandardItem *item, QString name)
219 {
220     playlist::songElement *newelement = new playlist::songElement;
221     newelement->name = new QString(name);
222     newelement->buffer = new QBuffer();
223     newelement->downloaded =false;
224     newelement->songId = new QString(item->text());
225     newelement->played = false;
226     newelement->server = new QUrl();
227     newelement->streamkey = new QString("noneatm");
228     newelement->bufferready = false;
229     newelement->type = playlist::EStream;
230     pList->append(newelement);
231     gs->getSong(item->text());
232     emit this->rowsInserted(QModelIndex(),pList->size(),pList->size());
233     this->currentSkeyItem = pList->size()-1;
234     emit this->freeze(true);
235     return pList->size()-1;
236 }
237
238 void playlist::downloadDone(int position)
239 {
240     if(this->existAt(position+1) && this->currentSkeyItem == -1 && !pList->at(position+1)->downloaded && this->currentdownloaditem != position+1)
241         beginDownload(position+1);
242     else
243         this->currentdownloaditem = -1;
244     pList->at(position)->downloaded = true;
245 }
246 void playlist::networkReplyFinish()
247 {
248     qDebug() << "finish";
249     QVariant url = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
250     if(url.toUrl().isValid())
251     {
252         QNetworkRequest req;
253         req.setUrl(url.toUrl());
254         qDebug() << url;
255         if(reply)
256         {
257             reply->disconnect();
258             reply->deleteLater();
259         }
260         reply = manager->get(req);
261         startStreamT = QTime::currentTime();
262         //connect(reply,SIGNAL(finished()),this,SLOT(start()));
263         connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadSlot(qint64,qint64)));
264         connect(reply,SIGNAL(finished()),this,SLOT(networkReplyFinish()));
265         connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(getNError(QNetworkReply::NetworkError)));
266     }
267 }
268
269 void playlist::downloadSlot(qint64 b, qint64 t)
270 {
271     //qDebug() << "Download: " << b << "Total: " << t;
272     if(t != 0)
273     {
274         emit this->downloadProgress(this->currentdownloaditem,b,t);
275         if(existAt(this->currentdownloaditem))
276         {
277             pList->at(this->currentdownloaditem)->buffer->buffer().append(reply->readAll());
278             //qDebug() << !pList->at(this->currentdownloaditem)->bufferready << this->currentdownloaditem;
279             if ( b >= t*0.05 && !pList->at(this->currentdownloaditem)->bufferready)
280                 //if(!pList->at(currentdownloaditem)->bufferready && b/(startStreamT.msecsTo(QTime::currentTime()) + 1)*100/1024 >= 10)
281             {
282                 this->setBufferRdy(this->currentdownloaditem);
283                 emit this->bufferReady(this->currentdownloaditem);
284
285                 qDebug() << "Buffer Ready";
286             }
287             if (b==t)
288             {
289             emit this->downloadComplete(this->currentdownloaditem);
290             //emit this->bufferReady(this->currentdownloaditem);
291             }
292         }
293     }
294 }