Ticket #756: queueManagement.patch
File queueManagement.patch, 16.9 KB (added by , 18 years ago) |
---|
-
mythflix/mythflix.cpp
22 22 #include <iostream> 23 23 24 24 #include <qnetwork.h> 25 #include <qapplication.h> 25 26 #include <qdatetime.h> 26 27 #include <qpainter.h> 27 28 #include <qdir.h> 28 29 #include <qtimer.h> 29 30 #include <qregexp.h> 31 #include <qprocess.h> 30 32 31 33 #include <qurl.h> 32 34 #include "mythtv/mythcontext.h" … … 95 97 this, SLOT(slotNewsRetrieved(NewsSite*))); 96 98 97 99 slotRetrieveNews(); 98 99 netflixShopperId = gContext->GetSetting("NetflixShopperId");100 VERBOSE(VB_GENERAL, QString("MythFlix: Using NetflixShopperId %1").arg(netflixShopperId));101 100 } 102 101 103 102 MythFlix::~MythFlix() … … 533 532 if(article) 534 533 { 535 534 536 // updateAddingView(); 535 QStringList args = QStringList::split(' ', 536 gContext->GetSetting("NetFlixAddQueueCommandLine", 537 gContext->GetShareDir() + "mythflix/scripts/netflix.pl -A")); 537 538 538 539 QString cmdUrl(article->articleURL()); 539 540 cmdUrl.replace('\'', "%27"); … … 541 542 QUrl url(cmdUrl); 542 543 543 544 QString query = url.query(); 545 QStringList getArgs = QStringList::split('&', query); 544 546 545 QString get("/AddToQueue?"); 546 get.append(query); 547 for (QStringList::Iterator it = getArgs.begin();it != getArgs.end(); ++it) 548 { 549 QString name = (*it).section('=', 0, 0); 550 QString vale = (*it).section('=', 1); 547 551 548 http = new QHttp(); 549 connect(http, SIGNAL(responseHeaderReceived (const QHttpResponseHeader&)), this, SLOT(slotMovieAdded(const QHttpResponseHeader&))); 550 //connect(http, SIGNAL(done (const QHttpResponseHeader&)), this, SLOT(slotMovieAdded(const QHttpResponseHeader&))); 551 552 QHttpRequestHeader header( "GET", get ); 553 header.setValue( "Cookie", "validReEntryCookie=Y; validReEntryConfirmed=Y; NetflixShopperId=" + netflixShopperId + ";" ); 554 header.setValue( "Host", "www.netflix.com" ); 555 556 http->setHost( "www.netflix.com" ); 557 http->request( header ); 552 args += vale; 553 } 554 555 // execute external command to obtain list of possible movie matches 556 QString results = executeExternal(args, "Add Movie"); 557 558 558 } 559 559 } 560 560 } 561 561 562 void MythFlix::slotMovieAdded(const QHttpResponseHeader &resp) 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 MythFlix::executeExternal(const QStringList& args, const QString& purpose) 563 566 { 564 QString location = resp.value(QString("Location")); 567 QString ret = ""; 568 QString err = ""; 565 569 566 if (location) 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()) 567 578 { 568 //How do you clean up http objects 569 //do you listen for signal done 570 //delete http; 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 } 571 629 572 VERBOSE(VB_NETWORK, QString("MythFlix: Redirecting to (%1)").arg(location)); 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 } 573 647 574 http = new QHttp(); 575 connect(http, SIGNAL(responseHeaderReceived (const QHttpResponseHeader&)), this, SLOT(slotMovieAdded(const QHttpResponseHeader&))); 648 if (err != "") 649 { 650 QString tempPurpose(purpose); 651 652 if (tempPurpose == "") 653 tempPurpose = "Command"; 576 654 577 QHttpRequestHeader header( "GET", location ); 578 header.setValue( "Cookie", "validReEntryCookie=Y; validReEntryConfirmed=Y; NetflixShopperId=" + netflixShopperId + ";" ); 579 header.setValue( "Host", "www.netflix.com" ); 580 http->setHost( "www.netflix.com" ); 581 http->request( header ); 655 cerr << err << endl; 656 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 657 QObject::tr(tempPurpose + " failed"), QObject::tr(err + "\n\nCheck NetFlix Settings")); 658 ret = "#ERROR"; 582 659 } 660 661 VERBOSE(VB_ALL, ret); 662 return ret; 583 663 } 664 665 -
mythflix/mythflixqueue.cpp
22 22 #include <iostream> 23 23 24 24 #include <qnetwork.h> 25 #include <qapplication.h> 25 26 #include <qdatetime.h> 26 27 #include <qpainter.h> 27 28 #include <qdir.h> 28 29 #include <qtimer.h> 29 30 #include <qregexp.h> 31 #include <qprocess.h> 30 32 31 33 #include <qurl.h> 32 34 #include "mythtv/mythcontext.h" … … 327 329 cursorDown(); 328 330 else if (action == "PAGEDOWN") 329 331 cursorDown(true); 332 else if (action == "REMOVE") 333 removeFromQueue(); 334 else if (action == "MOVETOTOP") 335 moveToTop(); 330 336 else 331 337 handled = false; 332 338 } … … 388 394 } 389 395 } 390 396 397 void MythFlixQueue::moveToTop() 398 { 399 UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent(); 400 401 if (articleUIItem && articleUIItem->getData()) 402 { 403 NewsArticle *article = (NewsArticle*) articleUIItem->getData(); 404 if(article) 405 { 406 407 QStringList args = QStringList::split(' ', 408 gContext->GetSetting("NetFlixMoveToTopCommandLine", 409 gContext->GetShareDir() + "mythflix/scripts/netflix.pl -1")); 410 411 QString cmdUrl(article->articleURL()); 412 cmdUrl.replace('\'', "%27"); 413 414 QUrl url(cmdUrl); 415 416 QString query = url.query(); 417 QStringList getArgs = QStringList::split('&', query); 418 419 for (QStringList::Iterator it = getArgs.begin();it != getArgs.end(); ++it) 420 { 421 QString name = (*it).section('=', 0, 0); 422 QString vale = (*it).section('=', 1); 423 424 args += vale; 425 } 426 // execute external command to obtain list of possible movie matches 427 QString results = executeExternal(args, "Move To Top"); 428 429 slotRetrieveNews(); 430 431 } 432 } 433 434 } 435 436 void MythFlixQueue::removeFromQueue() 437 { 438 UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent(); 439 440 if (articleUIItem && articleUIItem->getData()) 441 { 442 NewsArticle *article = (NewsArticle*) articleUIItem->getData(); 443 if(article) 444 { 445 446 QStringList args = QStringList::split(' ', 447 gContext->GetSetting("NetFlixRemoveFromQueueCommandLine", 448 gContext->GetShareDir() + "mythflix/scripts/netflix.pl -R")); 449 450 QString cmdUrl(article->articleURL()); 451 cmdUrl.replace('\'', "%27"); 452 453 QUrl url(cmdUrl); 454 455 QString query = url.query(); 456 QStringList getArgs = QStringList::split('&', query); 457 458 for (QStringList::Iterator it = getArgs.begin();it != getArgs.end(); ++it) 459 { 460 QString name = (*it).section('=', 0, 0); 461 QString vale = (*it).section('=', 1); 462 463 args += vale; 464 } 465 // execute external command to obtain list of possible movie matches 466 QString results = executeExternal(args, "Remove From Queue"); 467 468 slotRetrieveNews(); 469 470 } 471 } 472 473 } 474 391 475 void MythFlixQueue::slotArticleSelected(UIListBtnTypeItem*) 392 476 { 393 477 update(m_ArticlesRect); 394 478 update(m_InfoRect); 395 479 } 396 480 481 // Execute an external command and return results in string 482 // probably should make this routing async vs polling like this 483 // but it would require a lot more code restructuring 484 QString MythFlixQueue::executeExternal(const QStringList& args, const QString& purpose) 485 { 486 QString ret = ""; 487 QString err = ""; 488 489 VERBOSE(VB_GENERAL, QString("%1: Executing '%2'").arg(purpose). 490 arg(args.join(" ")).local8Bit() ); 491 QProcess proc(args, this); 492 493 QString cmd = args[0]; 494 QFileInfo info(cmd); 495 496 if (!info.exists()) 497 { 498 err = QString("\"%1\" failed: does not exist").arg(cmd.local8Bit()); 499 } 500 else if (!info.isExecutable()) 501 { 502 err = QString("\"%1\" failed: not executable").arg(cmd.local8Bit()); 503 } 504 else if (proc.start()) 505 { 506 while (true) 507 { 508 while (proc.canReadLineStdout() || proc.canReadLineStderr()) 509 { 510 if (proc.canReadLineStdout()) 511 { 512 ret += QString::fromLocal8Bit(proc.readLineStdout(),-1) + "\n"; 513 } 514 515 if (proc.canReadLineStderr()) 516 { 517 if (err == "") 518 { 519 err = cmd + ": "; 520 } 521 522 err += QString::fromLocal8Bit(proc.readLineStderr(),-1) + "\n"; 523 } 524 } 525 526 if (proc.isRunning()) 527 { 528 qApp->processEvents(); 529 usleep(10000); 530 } 531 else 532 { 533 if (!proc.normalExit()) 534 { 535 err = QString("\"%1\" failed: Process exited abnormally") 536 .arg(cmd.local8Bit()); 537 } 538 539 break; 540 } 541 } 542 } 543 else 544 { 545 err = QString("\"%1\" failed: Could not start process") 546 .arg(cmd.local8Bit()); 547 } 548 549 while (proc.canReadLineStdout() || proc.canReadLineStderr()) 550 { 551 if (proc.canReadLineStdout()) 552 { 553 ret += QString::fromLocal8Bit(proc.readLineStdout(),-1) + "\n"; 554 } 555 556 if (proc.canReadLineStderr()) 557 { 558 if (err == "") 559 { 560 err = cmd + ": "; 561 } 562 563 err += QString::fromLocal8Bit(proc.readLineStderr(), -1) + "\n"; 564 } 565 } 566 567 if (err != "") 568 { 569 QString tempPurpose(purpose); 570 571 if (tempPurpose == "") 572 tempPurpose = "Command"; 573 574 cerr << err << endl; 575 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 576 QObject::tr(tempPurpose + " failed"), QObject::tr(err + "\n\nCheck NetFlix Settings")); 577 ret = "#ERROR"; 578 } 579 580 VERBOSE(VB_ALL, ret); 581 return ret; 582 } 583 584 585 -
mythflix/mythflix.h
62 62 void cancelRetrieve(); 63 63 void processAndShowNews(NewsSite *site); 64 64 65 QString executeExternal(const QStringList& args, const QString& purpose); 66 65 67 XMLParse *m_Theme; 66 68 67 69 UIListBtnType *m_UISites; … … 73 75 74 76 NewsSite::List m_NewsSites; 75 77 76 QHttp *http;77 78 QString netflixShopperId;79 80 78 private slots: 81 79 void slotViewArticle(); 82 80 void slotRetrieveNews(); … … 85 83 void slotSiteSelected(UIListBtnTypeItem *item); 86 84 void slotArticleSelected(UIListBtnTypeItem *item); 87 85 88 void slotMovieAdded(const QHttpResponseHeader &resp);89 86 }; 90 87 91 88 #endif /* MYTHFLIX_H */ -
mythflix/mythflixqueue.h
60 60 void cancelRetrieve(); 61 61 void processAndShowNews(NewsSite *site); 62 62 63 void moveToTop(); 64 void removeFromQueue(); 65 QString executeExternal(const QStringList& args, const QString& purpose); 66 63 67 XMLParse *m_Theme; 64 68 65 69 UIListBtnType *m_UIArticles; -
mythflix/mythflix.pro
15 15 installfiles.files = netflix-rss.xml 16 16 installimages.path = $${PREFIX}/share/mythtv/themes/default 17 17 installimages.files = images/*.png 18 installscripts.path = $${PREFIX}/share/mythtv/mythflix/scripts 19 installscripts.files = scripts/*.pl 18 20 19 INSTALLS += installfiles installimages installmenus uifiles21 INSTALLS += installfiles installimages installmenus installscripts uifiles 20 22 21 23 # Input 22 24 HEADERS += mythflixqueue.h mythflix.h mythflixconfig.h newsengine.h -
mythflix/main.cpp
105 105 { 106 106 REG_JUMP("Browse", "", "", browse); 107 107 108 REG_KEY("NetFlix", "RETRIEVENEWS", "Update news items", "I"); 109 REG_KEY("NetFlix", "FORCERETRIEVE", "Force update news items", "M"); 110 REG_KEY("NetFlix", "CANCEL", "Cancel news item updating", "C"); 108 REG_KEY("NetFlix", "MOVETOTOP", "Moves movie to top of queue", "1"); 109 REG_KEY("NetFlix", "REMOVE", "Removes movie from queue", "D"); 111 110 112 111 //REG_JUMP("MythFlix", "NetFlix", "", runNews); 113 112 -
README
23 23 /usr/local/share/mythtv/mythflix directory 24 24 - image files and ui file go to /usr/local/share/mythtv/themes/default 25 25 26 Mythtv menu needs to be modified to support MythFlix plugin. Patches for the menu27 xml files are provided. Apply each patch: patch -p0 < xxxx.patch. When prompted for28 which file to patch:29 - main_settings.xml.patch -> /usr/local/share/mythtv/main_settings.xml30 - info_menu.xml.patch -> /usr/local/share/mythtv/info_menu.xml31 - info_settings.xml.patch -> /usr/local/share/mythtv/info_settings.xml32 - theme.xml.patch -> /usr/local/share/mythtv/themes/G.A.N.T./theme.xml33 34 Insert you Netflix ShopperId in the database. Your Netflix shopperId can be found in35 your browser's cookie. For KDE Konqueuer users, your cookie file is .kde/share/apps//kcookiejar/cookies36 look for cookie key NetflixShopperId. The cookie value should look like something like P23421493824908329048090329837 38 insert settings values ('NetflixShopperId','[NetflixShooperId]', null);39 40 26 Run mythfrontend and setup the Netflix RSS feeds to include when you browse for movies. 41 27 You MUST run the mythfrontend first to give the plugin a chance to intial the database 42 28 before continuing. See CONFIGURATION/USAGE. 43 29 30 Currenty, MythFlix plugin lacks a more rebust configuration UI. So your netflix account settings need to be initilized manually. 31 To do this run the following command. For some reason to properly intialized the netflix cookie you must run script twice. 32 33 /usr/local/share/mythtv/mythflix/scripts/netflix.pl -L <userid> <passwd> 34 /usr/local/share/mythtv/mythflix/scripts/netflix.pl -L <userid> <passwd> 35 44 36 FINAL INSTALLATION 45 37 --------------------------------------------------------------------- 46 38