1 | /* ============================================================ |
---|
2 | * File : mythflix.cpp |
---|
3 | * Author: John Petrocik <john@petrocik.net> |
---|
4 | * Date : 2005-10-28 |
---|
5 | * Description : |
---|
6 | * |
---|
7 | * Copyright 2005 by John Petrocik |
---|
8 | |
---|
9 | * This program is free software; you can redistribute it |
---|
10 | * and/or modify it under the terms of the GNU General |
---|
11 | * Public License as published bythe Free Software Foundation; |
---|
12 | * either version 2, or (at your option) |
---|
13 | * any later version. |
---|
14 | * |
---|
15 | * This program is distributed in the hope that it will be useful, |
---|
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
18 | * GNU General Public License for more details. |
---|
19 | * |
---|
20 | * ============================================================ */ |
---|
21 | |
---|
22 | #include <iostream> |
---|
23 | |
---|
24 | #include <unistd.h> |
---|
25 | |
---|
26 | #include <qnetwork.h> |
---|
27 | #include <qapplication.h> |
---|
28 | #include <qdatetime.h> |
---|
29 | #include <qpainter.h> |
---|
30 | #include <qdir.h> |
---|
31 | #include <qtimer.h> |
---|
32 | #include <qregexp.h> |
---|
33 | #include <qprocess.h> |
---|
34 | |
---|
35 | #include <qurl.h> |
---|
36 | #include "mythtv/mythcontext.h" |
---|
37 | #include "mythtv/mythdbcon.h" |
---|
38 | #include "mythtv/httpcomms.h" |
---|
39 | |
---|
40 | #include "mythflixqueue.h" |
---|
41 | |
---|
42 | MythFlixQueue::MythFlixQueue(MythMainWindow *parent, const char *name ) |
---|
43 | : MythDialog(parent, name) |
---|
44 | { |
---|
45 | qInitNetworkProtocols (); |
---|
46 | |
---|
47 | // Setup cache directory |
---|
48 | |
---|
49 | QString fileprefix = MythContext::GetConfDir(); |
---|
50 | |
---|
51 | QDir dir(fileprefix); |
---|
52 | if (!dir.exists()) |
---|
53 | dir.mkdir(fileprefix); |
---|
54 | fileprefix += "/MythFlix"; |
---|
55 | dir = QDir(fileprefix); |
---|
56 | if (!dir.exists()) |
---|
57 | dir.mkdir(fileprefix); |
---|
58 | |
---|
59 | // Initialize variables |
---|
60 | zoom = QString("-z %1").arg(gContext->GetNumSetting("WebBrowserZoomLevel",200)); |
---|
61 | browser = gContext->GetSetting("WebBrowserCommand", |
---|
62 | gContext->GetInstallPrefix() + |
---|
63 | "/bin/mythbrowser"); |
---|
64 | m_UIArticles = 0; |
---|
65 | expectingPopup = false; |
---|
66 | |
---|
67 | setNoErase(); |
---|
68 | loadTheme(); |
---|
69 | |
---|
70 | // Load sites from database |
---|
71 | |
---|
72 | MSqlQuery query(MSqlQuery::InitCon()); |
---|
73 | if (QString::compare("netflix queue",name)==0) |
---|
74 | query.exec("SELECT name, url, updated FROM netflix WHERE is_queue=1 ORDER BY name"); |
---|
75 | |
---|
76 | if (QString::compare("netflix history",name)==0) |
---|
77 | query.exec("SELECT name, url, updated FROM netflix WHERE is_queue=2 ORDER BY name"); |
---|
78 | |
---|
79 | if (!query.isActive()) { |
---|
80 | VERBOSE(VB_IMPORTANT, QString("MythFlixQueue: Error in loading queue from DB")); |
---|
81 | } |
---|
82 | else { |
---|
83 | QString name; |
---|
84 | QString url; |
---|
85 | QDateTime time; |
---|
86 | while ( query.next() ) { |
---|
87 | name = QString::fromUtf8(query.value(0).toString()); |
---|
88 | url = QString::fromUtf8(query.value(1).toString()); |
---|
89 | time.setTime_t(query.value(2).toUInt()); |
---|
90 | m_NewsSites.append(new NewsSite(name,url,time)); |
---|
91 | } |
---|
92 | } |
---|
93 | |
---|
94 | NewsSite* site = (NewsSite*) m_NewsSites.first(); |
---|
95 | connect(site, SIGNAL(finished(NewsSite*)), |
---|
96 | this, SLOT(slotNewsRetrieved(NewsSite*))); |
---|
97 | |
---|
98 | |
---|
99 | slotRetrieveNews(); |
---|
100 | } |
---|
101 | |
---|
102 | MythFlixQueue::~MythFlixQueue() |
---|
103 | { |
---|
104 | delete m_Theme; |
---|
105 | } |
---|
106 | |
---|
107 | void MythFlixQueue::loadTheme() |
---|
108 | { |
---|
109 | m_Theme = new XMLParse(); |
---|
110 | m_Theme->SetWMult(wmult); |
---|
111 | m_Theme->SetHMult(hmult); |
---|
112 | |
---|
113 | QDomElement xmldata; |
---|
114 | m_Theme->LoadTheme(xmldata, "queue", "netflix-"); |
---|
115 | |
---|
116 | for (QDomNode child = xmldata.firstChild(); !child.isNull(); |
---|
117 | child = child.nextSibling()) { |
---|
118 | |
---|
119 | QDomElement e = child.toElement(); |
---|
120 | if (!e.isNull()) { |
---|
121 | |
---|
122 | if (e.tagName() == "font") { |
---|
123 | m_Theme->parseFont(e); |
---|
124 | } |
---|
125 | else if (e.tagName() == "container") { |
---|
126 | QRect area; |
---|
127 | QString name; |
---|
128 | int context; |
---|
129 | m_Theme->parseContainer(e, name, context, area); |
---|
130 | |
---|
131 | if (name.lower() == "articles") |
---|
132 | m_ArticlesRect = area; |
---|
133 | else if (name.lower() == "info") |
---|
134 | m_InfoRect = area; |
---|
135 | } |
---|
136 | else { |
---|
137 | VERBOSE(VB_IMPORTANT, QString("MythFlix: Unknown element: %1").arg(e.tagName())); |
---|
138 | exit(-1); |
---|
139 | } |
---|
140 | } |
---|
141 | } |
---|
142 | |
---|
143 | LayerSet *container = m_Theme->GetSet("articles"); |
---|
144 | if (!container) { |
---|
145 | VERBOSE(VB_IMPORTANT, QString("MythFlixQueue: Failed to get articles container.")); |
---|
146 | exit(-1); |
---|
147 | } |
---|
148 | |
---|
149 | m_UIArticles = (UIListBtnType*)container->GetType("articleslist"); |
---|
150 | if (!m_UIArticles) { |
---|
151 | VERBOSE(VB_IMPORTANT, QString("MythFlixQueue: Failed to get articles list area.")); |
---|
152 | exit(-1); |
---|
153 | } |
---|
154 | |
---|
155 | connect(m_UIArticles, SIGNAL(itemSelected(UIListBtnTypeItem*)), |
---|
156 | SLOT(slotArticleSelected(UIListBtnTypeItem*))); |
---|
157 | |
---|
158 | m_UIArticles->SetActive(true); |
---|
159 | } |
---|
160 | |
---|
161 | |
---|
162 | void MythFlixQueue::paintEvent(QPaintEvent *e) |
---|
163 | { |
---|
164 | QRect r = e->rect(); |
---|
165 | |
---|
166 | if (r.intersects(m_ArticlesRect)) |
---|
167 | updateArticlesView(); |
---|
168 | if (r.intersects(m_InfoRect)) |
---|
169 | updateInfoView(); |
---|
170 | } |
---|
171 | |
---|
172 | |
---|
173 | void MythFlixQueue::updateSitesView() |
---|
174 | { |
---|
175 | QPixmap pix(m_ArticlesRect.size()); |
---|
176 | pix.fill(this, m_ArticlesRect.topLeft()); |
---|
177 | QPainter p(&pix); |
---|
178 | |
---|
179 | LayerSet* container = m_Theme->GetSet("sites"); |
---|
180 | if (container) { |
---|
181 | container->Draw(&p, 0, 0); |
---|
182 | container->Draw(&p, 1, 0); |
---|
183 | container->Draw(&p, 2, 0); |
---|
184 | container->Draw(&p, 3, 0); |
---|
185 | container->Draw(&p, 4, 0); |
---|
186 | container->Draw(&p, 5, 0); |
---|
187 | container->Draw(&p, 6, 0); |
---|
188 | container->Draw(&p, 7, 0); |
---|
189 | container->Draw(&p, 8, 0); |
---|
190 | } |
---|
191 | p.end(); |
---|
192 | |
---|
193 | bitBlt(this, m_ArticlesRect.left(), m_ArticlesRect.top(), |
---|
194 | &pix, 0, 0, -1, -1, Qt::CopyROP); |
---|
195 | } |
---|
196 | |
---|
197 | void MythFlixQueue::updateArticlesView() |
---|
198 | { |
---|
199 | QPixmap pix(m_ArticlesRect.size()); |
---|
200 | pix.fill(this, m_ArticlesRect.topLeft()); |
---|
201 | QPainter p(&pix); |
---|
202 | |
---|
203 | LayerSet* container = m_Theme->GetSet("articles"); |
---|
204 | if (container) { |
---|
205 | container->Draw(&p, 0, 0); |
---|
206 | container->Draw(&p, 1, 0); |
---|
207 | container->Draw(&p, 2, 0); |
---|
208 | container->Draw(&p, 3, 0); |
---|
209 | container->Draw(&p, 4, 0); |
---|
210 | container->Draw(&p, 5, 0); |
---|
211 | container->Draw(&p, 6, 0); |
---|
212 | container->Draw(&p, 7, 0); |
---|
213 | container->Draw(&p, 8, 0); |
---|
214 | } |
---|
215 | p.end(); |
---|
216 | |
---|
217 | bitBlt(this, m_ArticlesRect.left(), m_ArticlesRect.top(), |
---|
218 | &pix, 0, 0, -1, -1, Qt::CopyROP); |
---|
219 | } |
---|
220 | |
---|
221 | void MythFlixQueue::updateInfoView() |
---|
222 | { |
---|
223 | QPixmap pix(m_InfoRect.size()); |
---|
224 | pix.fill(this, m_InfoRect.topLeft()); |
---|
225 | QPainter p(&pix); |
---|
226 | |
---|
227 | LayerSet* container = m_Theme->GetSet("info"); |
---|
228 | if (container) |
---|
229 | { |
---|
230 | NewsArticle *article = 0; |
---|
231 | |
---|
232 | UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent(); |
---|
233 | if (articleUIItem && articleUIItem->getData()) |
---|
234 | article = (NewsArticle*) articleUIItem->getData(); |
---|
235 | |
---|
236 | if (article) |
---|
237 | { |
---|
238 | |
---|
239 | UITextType *ttype = |
---|
240 | (UITextType *)container->GetType("status"); |
---|
241 | // if (ttype) |
---|
242 | // ttype->SetText(""); |
---|
243 | |
---|
244 | ttype = |
---|
245 | (UITextType *)container->GetType("title"); |
---|
246 | if (ttype) |
---|
247 | ttype->SetText(article->title()); |
---|
248 | |
---|
249 | ttype = |
---|
250 | (UITextType *)container->GetType("description"); |
---|
251 | if (ttype) |
---|
252 | ttype->SetText(article->description()); |
---|
253 | |
---|
254 | QString imageLoc = article->articleURL(); |
---|
255 | int index = imageLoc.find("movieid="); |
---|
256 | imageLoc = imageLoc.mid(index+8,8) + ".jpg"; |
---|
257 | |
---|
258 | QString fileprefix = MythContext::GetConfDir(); |
---|
259 | |
---|
260 | QDir dir(fileprefix); |
---|
261 | if (!dir.exists()) |
---|
262 | dir.mkdir(fileprefix); |
---|
263 | |
---|
264 | fileprefix += "/MythFlix"; |
---|
265 | |
---|
266 | dir = QDir(fileprefix); |
---|
267 | if (!dir.exists()) |
---|
268 | dir.mkdir(fileprefix); |
---|
269 | |
---|
270 | VERBOSE(VB_FILE, QString("MythFlixQueue: Boxshot File Prefix: %1").arg(fileprefix)); |
---|
271 | |
---|
272 | QString sFilename(fileprefix + "/" + imageLoc); |
---|
273 | |
---|
274 | bool exists = QFile::exists(sFilename); |
---|
275 | if (!exists) |
---|
276 | { |
---|
277 | VERBOSE(VB_NETWORK, QString("MythFlixQueue: Copying boxshot file from server (%1)").arg(imageLoc)); |
---|
278 | |
---|
279 | QString sURL("http://cdn.nflximg.com/us/boxshots/large/" + imageLoc); |
---|
280 | |
---|
281 | if (!HttpComms::getHttpFile(sFilename, sURL, 20000)) |
---|
282 | VERBOSE(VB_NETWORK, QString("MythFlix: Failed to download image from: %1").arg(sURL)); |
---|
283 | |
---|
284 | VERBOSE(VB_NETWORK, QString("MythFlixQueue: Finished copying boxshot file from server (%1)").arg(imageLoc)); |
---|
285 | } |
---|
286 | |
---|
287 | UIImageType *itype = (UIImageType *)container->GetType("boxshot"); |
---|
288 | if (itype) |
---|
289 | { |
---|
290 | itype->SetImage(sFilename); |
---|
291 | itype->LoadImage(); |
---|
292 | |
---|
293 | if (itype->isHidden()) |
---|
294 | itype->show(); |
---|
295 | } |
---|
296 | |
---|
297 | } |
---|
298 | |
---|
299 | container->Draw(&p, 0, 0); |
---|
300 | container->Draw(&p, 1, 0); |
---|
301 | container->Draw(&p, 2, 0); |
---|
302 | container->Draw(&p, 3, 0); |
---|
303 | container->Draw(&p, 4, 0); |
---|
304 | container->Draw(&p, 5, 0); |
---|
305 | container->Draw(&p, 6, 0); |
---|
306 | container->Draw(&p, 7, 0); |
---|
307 | container->Draw(&p, 8, 0); |
---|
308 | } |
---|
309 | |
---|
310 | p.end(); |
---|
311 | |
---|
312 | |
---|
313 | bitBlt(this, m_InfoRect.left(), m_InfoRect.top(), |
---|
314 | &pix, 0, 0, -1, -1, Qt::CopyROP); |
---|
315 | } |
---|
316 | |
---|
317 | void MythFlixQueue::keyPressEvent(QKeyEvent *e) |
---|
318 | { |
---|
319 | if (!e) return; |
---|
320 | |
---|
321 | bool handled = false; |
---|
322 | QStringList actions; |
---|
323 | gContext->GetMainWindow()->TranslateKeyPress("NetFlix", e, actions); |
---|
324 | |
---|
325 | for (unsigned int i = 0; i < actions.size() && !handled; i++) |
---|
326 | { |
---|
327 | QString action = actions[i]; |
---|
328 | handled = true; |
---|
329 | |
---|
330 | if (action == "UP") |
---|
331 | cursorUp(); |
---|
332 | else if (action == "PAGEUP") |
---|
333 | cursorUp(true); |
---|
334 | else if (action == "DOWN") |
---|
335 | cursorDown(); |
---|
336 | else if (action == "PAGEDOWN") |
---|
337 | cursorDown(true); |
---|
338 | else if (action == "REMOVE") |
---|
339 | slotRemoveFromQueue(); |
---|
340 | else if (action == "MOVETOTOP") |
---|
341 | slotMoveToTop(); |
---|
342 | else if (action == "SELECT") |
---|
343 | displayOptions(); |
---|
344 | else if (action == "MENU") |
---|
345 | displayOptions(); |
---|
346 | else |
---|
347 | handled = false; |
---|
348 | } |
---|
349 | |
---|
350 | if (!handled) |
---|
351 | MythDialog::keyPressEvent(e); |
---|
352 | } |
---|
353 | |
---|
354 | void MythFlixQueue::cursorUp(bool page) |
---|
355 | { |
---|
356 | UIListBtnType::MovementUnit unit = page ? UIListBtnType::MovePage : UIListBtnType::MoveItem; |
---|
357 | |
---|
358 | m_UIArticles->MoveUp(unit); |
---|
359 | } |
---|
360 | |
---|
361 | void MythFlixQueue::cursorDown(bool page) |
---|
362 | { |
---|
363 | UIListBtnType::MovementUnit unit = page ? UIListBtnType::MovePage : UIListBtnType::MoveItem; |
---|
364 | |
---|
365 | m_UIArticles->MoveDown(unit); |
---|
366 | } |
---|
367 | |
---|
368 | void MythFlixQueue::slotRetrieveNews() |
---|
369 | { |
---|
370 | if (m_NewsSites.count() == 0) |
---|
371 | return; |
---|
372 | |
---|
373 | for (NewsSite* site = m_NewsSites.first(); site; site = m_NewsSites.next()) |
---|
374 | { |
---|
375 | site->retrieve(); |
---|
376 | } |
---|
377 | } |
---|
378 | |
---|
379 | void MythFlixQueue::slotNewsRetrieved(NewsSite* site) |
---|
380 | { |
---|
381 | processAndShowNews(site); |
---|
382 | } |
---|
383 | |
---|
384 | void MythFlixQueue::processAndShowNews(NewsSite* site) |
---|
385 | { |
---|
386 | if (!site) |
---|
387 | return; |
---|
388 | |
---|
389 | site->process(); |
---|
390 | |
---|
391 | if (site) { |
---|
392 | |
---|
393 | m_UIArticles->Reset(); |
---|
394 | |
---|
395 | for (NewsArticle* article = site->articleList().first(); article; |
---|
396 | article = site->articleList().next()) { |
---|
397 | UIListBtnTypeItem* item = |
---|
398 | new UIListBtnTypeItem(m_UIArticles, article->title()); |
---|
399 | item->setData(article); |
---|
400 | } |
---|
401 | |
---|
402 | update(m_ArticlesRect); |
---|
403 | update(m_InfoRect); |
---|
404 | } |
---|
405 | } |
---|
406 | |
---|
407 | void MythFlixQueue::slotMoveToTop() |
---|
408 | { |
---|
409 | |
---|
410 | if (expectingPopup) |
---|
411 | slotCancelPopup(); |
---|
412 | |
---|
413 | UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent(); |
---|
414 | |
---|
415 | if (articleUIItem && articleUIItem->getData()) |
---|
416 | { |
---|
417 | NewsArticle *article = (NewsArticle*) articleUIItem->getData(); |
---|
418 | if(article) |
---|
419 | { |
---|
420 | |
---|
421 | QStringList args = QStringList::split(' ', |
---|
422 | gContext->GetSetting("NetFlixMoveToTopCommandLine", |
---|
423 | gContext->GetShareDir() + "mythflix/scripts/netflix.pl -1")); |
---|
424 | |
---|
425 | QString cmdUrl(article->articleURL()); |
---|
426 | cmdUrl.replace('\'', "%27"); |
---|
427 | |
---|
428 | QUrl url(cmdUrl); |
---|
429 | |
---|
430 | QString query = url.query(); |
---|
431 | QStringList getArgs = QStringList::split('&', query); |
---|
432 | |
---|
433 | for (QStringList::Iterator it = getArgs.begin();it != getArgs.end(); ++it) |
---|
434 | { |
---|
435 | QString name = (*it).section('=', 0, 0); |
---|
436 | QString vale = (*it).section('=', 1); |
---|
437 | |
---|
438 | args += vale; |
---|
439 | } |
---|
440 | // execute external command to obtain list of possible movie matches |
---|
441 | QString results = executeExternal(args, "Move To Top"); |
---|
442 | |
---|
443 | slotRetrieveNews(); |
---|
444 | |
---|
445 | } |
---|
446 | } |
---|
447 | |
---|
448 | } |
---|
449 | |
---|
450 | void MythFlixQueue::slotRemoveFromQueue() |
---|
451 | { |
---|
452 | |
---|
453 | if (expectingPopup) |
---|
454 | slotCancelPopup(); |
---|
455 | |
---|
456 | UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent(); |
---|
457 | |
---|
458 | if (articleUIItem && articleUIItem->getData()) |
---|
459 | { |
---|
460 | NewsArticle *article = (NewsArticle*) articleUIItem->getData(); |
---|
461 | if(article) |
---|
462 | { |
---|
463 | |
---|
464 | QStringList args = QStringList::split(' ', |
---|
465 | gContext->GetSetting("NetFlixRemoveFromQueueCommandLine", |
---|
466 | gContext->GetShareDir() + "mythflix/scripts/netflix.pl -R")); |
---|
467 | |
---|
468 | QString cmdUrl(article->articleURL()); |
---|
469 | cmdUrl.replace('\'', "%27"); |
---|
470 | |
---|
471 | QUrl url(cmdUrl); |
---|
472 | |
---|
473 | QString query = url.query(); |
---|
474 | QStringList getArgs = QStringList::split('&', query); |
---|
475 | |
---|
476 | for (QStringList::Iterator it = getArgs.begin();it != getArgs.end(); ++it) |
---|
477 | { |
---|
478 | QString name = (*it).section('=', 0, 0); |
---|
479 | QString vale = (*it).section('=', 1); |
---|
480 | |
---|
481 | args += vale; |
---|
482 | } |
---|
483 | // execute external command to obtain list of possible movie matches |
---|
484 | QString results = executeExternal(args, "Remove From Queue"); |
---|
485 | |
---|
486 | slotRetrieveNews(); |
---|
487 | |
---|
488 | } |
---|
489 | } |
---|
490 | |
---|
491 | } |
---|
492 | |
---|
493 | void MythFlixQueue::slotShowNetFlixPage() |
---|
494 | { |
---|
495 | if (expectingPopup) |
---|
496 | slotCancelPopup(); |
---|
497 | |
---|
498 | UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent(); |
---|
499 | if (articleUIItem && articleUIItem->getData()) |
---|
500 | { |
---|
501 | NewsArticle *article = (NewsArticle*) articleUIItem->getData(); |
---|
502 | if(article) |
---|
503 | { |
---|
504 | QString cmdUrl(article->articleURL()); |
---|
505 | cmdUrl.replace('\'', "%27"); |
---|
506 | |
---|
507 | QString cmd = QString("%1 %2 '%3'") |
---|
508 | .arg(browser) |
---|
509 | .arg(zoom) |
---|
510 | .arg(cmdUrl); |
---|
511 | VERBOSE(VB_GENERAL, QString("MythFlixQueue: Opening Neflix site: (%1)").arg(cmd)); |
---|
512 | myth_system(cmd); |
---|
513 | } |
---|
514 | } |
---|
515 | } |
---|
516 | |
---|
517 | void MythFlixQueue::slotArticleSelected(UIListBtnTypeItem*) |
---|
518 | { |
---|
519 | update(m_ArticlesRect); |
---|
520 | update(m_InfoRect); |
---|
521 | } |
---|
522 | |
---|
523 | void MythFlixQueue::displayOptions() |
---|
524 | { |
---|
525 | |
---|
526 | popup = new MythPopupBox(gContext->GetMainWindow(), "menu popup"); |
---|
527 | |
---|
528 | QLabel *label = popup->addLabel(tr("Manage Queue"), |
---|
529 | MythPopupBox::Large, false); |
---|
530 | label->setAlignment(Qt::AlignCenter | Qt::WordBreak); |
---|
531 | |
---|
532 | QButton *topButton = popup->addButton(tr("Top Of Queue"), this, |
---|
533 | SLOT(slotMoveToTop())); |
---|
534 | |
---|
535 | popup->addButton(tr("Remove From Queue"), this, |
---|
536 | SLOT(slotRemoveFromQueue())); |
---|
537 | |
---|
538 | popup->addButton(tr("Show NetFlix Page"), this, |
---|
539 | SLOT(slotShowNetFlixPage())); |
---|
540 | |
---|
541 | popup->addButton(tr("Cancel"), this, SLOT(slotCancelPopup())); |
---|
542 | |
---|
543 | popup->ShowPopup(this, SLOT(slotCancelPopup())); |
---|
544 | |
---|
545 | topButton->setFocus(); |
---|
546 | |
---|
547 | expectingPopup = true; |
---|
548 | |
---|
549 | } |
---|
550 | |
---|
551 | void MythFlixQueue::slotCancelPopup(void) |
---|
552 | { |
---|
553 | popup->hide(); |
---|
554 | expectingPopup = false; |
---|
555 | |
---|
556 | delete popup; |
---|
557 | popup = NULL; |
---|
558 | |
---|
559 | setActiveWindow(); |
---|
560 | } |
---|
561 | |
---|
562 | // Execute an external command and return results in string |
---|
563 | // probably should make this routing async vs polling like this |
---|
564 | // but it would require a lot more code restructuring |
---|
565 | QString MythFlixQueue::executeExternal(const QStringList& args, const QString& purpose) |
---|
566 | { |
---|
567 | QString ret = ""; |
---|
568 | QString err = ""; |
---|
569 | |
---|
570 | VERBOSE(VB_GENERAL, QString("%1: Executing '%2'").arg(purpose). |
---|
571 | arg(args.join(" ")).local8Bit() ); |
---|
572 | QProcess proc(args, this); |
---|
573 | |
---|
574 | QString cmd = args[0]; |
---|
575 | QFileInfo info(cmd); |
---|
576 | |
---|
577 | if (!info.exists()) |
---|
578 | { |
---|
579 | err = QString("\"%1\" failed: does not exist").arg(cmd.local8Bit()); |
---|
580 | } |
---|
581 | else if (!info.isExecutable()) |
---|
582 | { |
---|
583 | err = QString("\"%1\" failed: not executable").arg(cmd.local8Bit()); |
---|
584 | } |
---|
585 | else if (proc.start()) |
---|
586 | { |
---|
587 | while (true) |
---|
588 | { |
---|
589 | while (proc.canReadLineStdout() || proc.canReadLineStderr()) |
---|
590 | { |
---|
591 | if (proc.canReadLineStdout()) |
---|
592 | { |
---|
593 | ret += QString::fromLocal8Bit(proc.readLineStdout(),-1) + "\n"; |
---|
594 | } |
---|
595 | |
---|
596 | if (proc.canReadLineStderr()) |
---|
597 | { |
---|
598 | if (err == "") |
---|
599 | { |
---|
600 | err = cmd + ": "; |
---|
601 | } |
---|
602 | |
---|
603 | err += QString::fromLocal8Bit(proc.readLineStderr(),-1) + "\n"; |
---|
604 | } |
---|
605 | } |
---|
606 | |
---|
607 | if (proc.isRunning()) |
---|
608 | { |
---|
609 | qApp->processEvents(); |
---|
610 | usleep(10000); |
---|
611 | } |
---|
612 | else |
---|
613 | { |
---|
614 | if (!proc.normalExit()) |
---|
615 | { |
---|
616 | err = QString("\"%1\" failed: Process exited abnormally") |
---|
617 | .arg(cmd.local8Bit()); |
---|
618 | } |
---|
619 | |
---|
620 | break; |
---|
621 | } |
---|
622 | } |
---|
623 | } |
---|
624 | else |
---|
625 | { |
---|
626 | err = QString("\"%1\" failed: Could not start process") |
---|
627 | .arg(cmd.local8Bit()); |
---|
628 | } |
---|
629 | |
---|
630 | while (proc.canReadLineStdout() || proc.canReadLineStderr()) |
---|
631 | { |
---|
632 | if (proc.canReadLineStdout()) |
---|
633 | { |
---|
634 | ret += QString::fromLocal8Bit(proc.readLineStdout(),-1) + "\n"; |
---|
635 | } |
---|
636 | |
---|
637 | if (proc.canReadLineStderr()) |
---|
638 | { |
---|
639 | if (err == "") |
---|
640 | { |
---|
641 | err = cmd + ": "; |
---|
642 | } |
---|
643 | |
---|
644 | err += QString::fromLocal8Bit(proc.readLineStderr(), -1) + "\n"; |
---|
645 | } |
---|
646 | } |
---|
647 | |
---|
648 | if (err != "") |
---|
649 | { |
---|
650 | QString tempPurpose(purpose); |
---|
651 | |
---|
652 | if (tempPurpose == "") |
---|
653 | tempPurpose = "Command"; |
---|
654 | |
---|
655 | cerr << err << endl; |
---|
656 | MythPopupBox::showOkPopup(gContext->GetMainWindow(), |
---|
657 | QObject::tr(tempPurpose + " failed"), QObject::tr(err + "\n\nCheck NetFlix Settings")); |
---|
658 | ret = "#ERROR"; |
---|
659 | } |
---|
660 | |
---|
661 | VERBOSE(VB_IMPORTANT, ret); |
---|
662 | return ret; |
---|
663 | } |
---|
664 | |
---|
665 | |
---|
666 | |
---|