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