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