00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <iostream>
00023 #include <cstdlib>
00024
00025 #include <unistd.h>
00026
00027 #include <qnetwork.h>
00028 #include <qapplication.h>
00029 #include <qdatetime.h>
00030 #include <qpainter.h>
00031 #include <qdir.h>
00032 #include <qtimer.h>
00033 #include <qregexp.h>
00034 #include <qprocess.h>
00035
00036 #include <qurl.h>
00037 #include "mythtv/mythcontext.h"
00038 #include "mythtv/mythdbcon.h"
00039 #include "mythtv/httpcomms.h"
00040
00041 #include "mythflixqueue.h"
00042 #include "flixutil.h"
00043
00044 MythFlixQueue::MythFlixQueue(MythMainWindow *parent, const char *name,
00045 QString queueName)
00046 : MythDialog(parent, name)
00047 {
00048 qInitNetworkProtocols ();
00049
00050
00051
00052 QString fileprefix = MythContext::GetConfDir();
00053
00054 QDir dir(fileprefix);
00055 if (!dir.exists())
00056 dir.mkdir(fileprefix);
00057 fileprefix += "/MythFlix";
00058 dir = QDir(fileprefix);
00059 if (!dir.exists())
00060 dir.mkdir(fileprefix);
00061
00062
00063 zoom = QString("-z %1")
00064 .arg(gContext->GetNumSetting("WebBrowserZoomLevel",200));
00065 browser = gContext->GetSetting("WebBrowserCommand",
00066 gContext->GetInstallPrefix() +
00067 "/bin/mythbrowser");
00068 m_UIArticles = 0;
00069 expectingPopup = false;
00070 m_queueName = queueName;
00071
00072 setNoErase();
00073 loadTheme();
00074
00075 updateBackground();
00076
00077
00078
00079 MSqlQuery query(MSqlQuery::InitCon());
00080
00081 query.prepare("SELECT name, url, updated "
00082 "FROM netflix "
00083 "WHERE is_queue = :ISQUEUE "
00084 "AND queue = :QUEUENAME "
00085 "ORDER BY name");
00086
00087 if (QString::compare("netflix history",name)==0)
00088 query.bindValue(":ISQUEUE", 2);
00089 else if (QString::compare("netflix queue",name)==0)
00090 query.bindValue(":ISQUEUE", 1);
00091 else
00092 query.bindValue(":ISQUEUE", 1);
00093
00094 query.bindValue(":QUEUENAME", m_queueName);
00095 query.exec();
00096
00097 if (!query.isActive()) {
00098 VERBOSE(VB_IMPORTANT,
00099 QString("MythFlixQueue: Error in loading queue from DB"));
00100 }
00101 else {
00102 QString name;
00103 QString url;
00104 QDateTime time;
00105 while ( query.next() ) {
00106 name = QString::fromUtf8(query.value(0).toString());
00107 url = QString::fromUtf8(query.value(1).toString());
00108 time.setTime_t(query.value(2).toUInt());
00109 m_NewsSites.append(new NewsSite(name,url,time));
00110 }
00111 }
00112
00113 NewsSite* site = (NewsSite*) m_NewsSites.first();
00114 connect(site, SIGNAL(finished(NewsSite*)),
00115 this, SLOT(slotNewsRetrieved(NewsSite*)));
00116
00117 slotRetrieveNews();
00118 }
00119
00120 MythFlixQueue::~MythFlixQueue()
00121 {
00122 delete m_Theme;
00123 }
00124
00125 void MythFlixQueue::loadTheme()
00126 {
00127 m_Theme = new XMLParse();
00128 m_Theme->SetWMult(wmult);
00129 m_Theme->SetHMult(hmult);
00130
00131 QDomElement xmldata;
00132 m_Theme->LoadTheme(xmldata, "queue", "netflix-");
00133
00134 for (QDomNode child = xmldata.firstChild(); !child.isNull();
00135 child = child.nextSibling()) {
00136
00137 QDomElement e = child.toElement();
00138 if (!e.isNull()) {
00139
00140 if (e.tagName() == "font") {
00141 m_Theme->parseFont(e);
00142 }
00143 else if (e.tagName() == "container") {
00144 QRect area;
00145 QString name;
00146 int context;
00147 m_Theme->parseContainer(e, name, context, area);
00148
00149 if (name.lower() == "articles")
00150 m_ArticlesRect = area;
00151 else if (name.lower() == "info")
00152 m_InfoRect = area;
00153 }
00154 else {
00155 VERBOSE(VB_IMPORTANT, QString("MythFlix: Unknown element: %1").arg(e.tagName()));
00156 exit(-1);
00157 }
00158 }
00159 }
00160
00161 LayerSet *container = m_Theme->GetSet("articles");
00162 if (!container) {
00163 VERBOSE(VB_IMPORTANT, QString("MythFlixQueue: Failed to get articles container."));
00164 exit(-1);
00165 }
00166
00167 UITextType *ttype = (UITextType *)container->GetType("queuename");
00168 if (ttype)
00169 {
00170 QString myQueue = m_queueName != "" ? m_queueName : tr("Default");
00171 if (QString::compare("netflix history",name())==0)
00172 ttype->SetText(tr("History for Queue: ") + m_queueName);
00173 else
00174 ttype->SetText(tr("Items in Queue: ") + m_queueName);
00175 }
00176
00177 m_UIArticles = (UIListBtnType*)container->GetType("articleslist");
00178 if (!m_UIArticles) {
00179 VERBOSE(VB_IMPORTANT, QString("MythFlixQueue: Failed to get articles list area."));
00180 exit(-1);
00181 }
00182
00183 connect(m_UIArticles, SIGNAL(itemSelected(UIListBtnTypeItem*)),
00184 SLOT(slotArticleSelected(UIListBtnTypeItem*)));
00185
00186 m_UIArticles->SetActive(true);
00187 }
00188
00189
00190 void MythFlixQueue::paintEvent(QPaintEvent *e)
00191 {
00192 QRect r = e->rect();
00193
00194 if (r.intersects(m_ArticlesRect))
00195 updateArticlesView();
00196 if (r.intersects(m_InfoRect))
00197 updateInfoView();
00198 }
00199
00200 void MythFlixQueue::updateBackground(void)
00201 {
00202 QPixmap bground(size());
00203 bground.fill(this, 0, 0);
00204
00205 QPainter tmp(&bground);
00206
00207 LayerSet *container = m_Theme->GetSet("background");
00208 if (container)
00209 {
00210 container->Draw(&tmp, 0, 0);
00211 }
00212
00213 tmp.end();
00214 m_background = bground;
00215
00216 setPaletteBackgroundPixmap(m_background);
00217 }
00218
00219 void MythFlixQueue::updateSitesView()
00220 {
00221 QPixmap pix(m_ArticlesRect.size());
00222 pix.fill(this, m_ArticlesRect.topLeft());
00223 QPainter p(&pix);
00224
00225 LayerSet* container = m_Theme->GetSet("sites");
00226 if (container) {
00227 container->Draw(&p, 0, 0);
00228 container->Draw(&p, 1, 0);
00229 container->Draw(&p, 2, 0);
00230 container->Draw(&p, 3, 0);
00231 container->Draw(&p, 4, 0);
00232 container->Draw(&p, 5, 0);
00233 container->Draw(&p, 6, 0);
00234 container->Draw(&p, 7, 0);
00235 container->Draw(&p, 8, 0);
00236 }
00237 p.end();
00238
00239 bitBlt(this, m_ArticlesRect.left(), m_ArticlesRect.top(),
00240 &pix, 0, 0, -1, -1, Qt::CopyROP);
00241 }
00242
00243 void MythFlixQueue::updateArticlesView()
00244 {
00245 QPixmap pix(m_ArticlesRect.size());
00246 pix.fill(this, m_ArticlesRect.topLeft());
00247 QPainter p(&pix);
00248
00249 LayerSet* container = m_Theme->GetSet("articles");
00250 if (container) {
00251 container->Draw(&p, 0, 0);
00252 container->Draw(&p, 1, 0);
00253 container->Draw(&p, 2, 0);
00254 container->Draw(&p, 3, 0);
00255 container->Draw(&p, 4, 0);
00256 container->Draw(&p, 5, 0);
00257 container->Draw(&p, 6, 0);
00258 container->Draw(&p, 7, 0);
00259 container->Draw(&p, 8, 0);
00260 }
00261 p.end();
00262
00263 bitBlt(this, m_ArticlesRect.left(), m_ArticlesRect.top(),
00264 &pix, 0, 0, -1, -1, Qt::CopyROP);
00265 }
00266
00267 void MythFlixQueue::updateInfoView()
00268 {
00269 QPixmap pix(m_InfoRect.size());
00270 pix.fill(this, m_InfoRect.topLeft());
00271 QPainter p(&pix);
00272
00273 LayerSet* container = m_Theme->GetSet("info");
00274 if (container)
00275 {
00276 NewsArticle *article = 0;
00277
00278 UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent();
00279 if (articleUIItem && articleUIItem->getData())
00280 article = (NewsArticle*) articleUIItem->getData();
00281
00282 if (article)
00283 {
00284
00285 UITextType *ttype =
00286 (UITextType *)container->GetType("status");
00287
00288
00289
00290 ttype =
00291 (UITextType *)container->GetType("title");
00292 if (ttype)
00293 ttype->SetText(article->title());
00294
00295 ttype =
00296 (UITextType *)container->GetType("description");
00297 if (ttype)
00298 ttype->SetText(article->description());
00299
00300
00301 {
00302 QString artText = article->description();
00303
00304 if( artText.find(QRegExp("</(p|P)>")) )
00305 {
00306 artText.replace( QRegExp("<(p|P)>"), "");
00307 artText.replace( QRegExp("</(p|P)>"), "\n\n");
00308 }
00309 else
00310 {
00311 artText.replace( QRegExp("<(p|P)>"), "\n\n");
00312 artText.replace( QRegExp("</(p|P)>"), "");
00313 }
00314 artText.replace( QRegExp("<(br|BR|)/>"), "\n");
00315 artText.replace( QRegExp("<(br|BR|)>"), "\n");
00316
00317
00318
00319 artText.replace( QRegExp("\t"), "");
00320
00321 artText.replace( QRegExp(" "), "");
00322
00323 artText.replace( QRegExp("\n "), "\n");
00324
00325 QRegExp removeHTML(QRegExp("</?.+>"));
00326 removeHTML.setMinimal(true);
00327 artText.remove((const QRegExp&) removeHTML);
00328 artText = artText.stripWhiteSpace();
00329 ttype->SetText(artText);
00330 }
00331
00332 QString imageLoc = article->articleURL();
00333 int length = imageLoc.length();
00334 int index = imageLoc.findRev("/");
00335 imageLoc = imageLoc.mid(index,length) + ".jpg";
00336
00337 QString fileprefix = MythContext::GetConfDir();
00338
00339 QDir dir(fileprefix);
00340 if (!dir.exists())
00341 dir.mkdir(fileprefix);
00342
00343 fileprefix += "/MythFlix";
00344
00345 dir = QDir(fileprefix);
00346 if (!dir.exists())
00347 dir.mkdir(fileprefix);
00348
00349 VERBOSE(VB_FILE, QString("MythFlixQueue: Boxshot File Prefix: %1").arg(fileprefix));
00350
00351 QString sFilename(fileprefix + "/" + imageLoc);
00352
00353 bool exists = QFile::exists(sFilename);
00354 if (!exists)
00355 {
00356 VERBOSE(VB_NETWORK, QString("MythFlixQueue: Copying boxshot file from server (%1)").arg(imageLoc));
00357
00358 QString sURL("http://cdn.nflximg.com/us/boxshots/large/" + imageLoc);
00359
00360 if (!HttpComms::getHttpFile(sFilename, sURL, 20000))
00361 VERBOSE(VB_NETWORK, QString("MythFlix: Failed to download image from: %1").arg(sURL));
00362
00363 VERBOSE(VB_NETWORK, QString("MythFlixQueue: Finished copying boxshot file from server (%1)").arg(imageLoc));
00364 }
00365
00366 UIImageType *itype = (UIImageType *)container->GetType("boxshot");
00367 if (itype)
00368 {
00369 itype->SetImage(sFilename);
00370 itype->LoadImage();
00371
00372 if (itype->isHidden())
00373 itype->show();
00374 }
00375
00376 }
00377
00378 container->Draw(&p, 0, 0);
00379 container->Draw(&p, 1, 0);
00380 container->Draw(&p, 2, 0);
00381 container->Draw(&p, 3, 0);
00382 container->Draw(&p, 4, 0);
00383 container->Draw(&p, 5, 0);
00384 container->Draw(&p, 6, 0);
00385 container->Draw(&p, 7, 0);
00386 container->Draw(&p, 8, 0);
00387 }
00388
00389 p.end();
00390
00391
00392 bitBlt(this, m_InfoRect.left(), m_InfoRect.top(),
00393 &pix, 0, 0, -1, -1, Qt::CopyROP);
00394 }
00395
00396 void MythFlixQueue::keyPressEvent(QKeyEvent *e)
00397 {
00398 if (!e) return;
00399
00400 bool handled = false;
00401 QStringList actions;
00402 gContext->GetMainWindow()->TranslateKeyPress("NetFlix", e, actions);
00403
00404 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00405 {
00406 QString action = actions[i];
00407 handled = true;
00408
00409 if (action == "UP")
00410 cursorUp();
00411 else if (action == "PAGEUP")
00412 cursorUp(true);
00413 else if (action == "DOWN")
00414 cursorDown();
00415 else if (action == "PAGEDOWN")
00416 cursorDown(true);
00417 else if (action == "REMOVE")
00418 slotRemoveFromQueue();
00419 else if (action == "MOVETOTOP")
00420 slotMoveToTop();
00421 else if (action == "SELECT")
00422 displayOptions();
00423 else if (action == "MENU")
00424 displayOptions();
00425 else
00426 handled = false;
00427 }
00428
00429 if (!handled)
00430 MythDialog::keyPressEvent(e);
00431 }
00432
00433 void MythFlixQueue::cursorUp(bool page)
00434 {
00435 UIListBtnType::MovementUnit unit = page ? UIListBtnType::MovePage : UIListBtnType::MoveItem;
00436
00437 m_UIArticles->MoveUp(unit);
00438 }
00439
00440 void MythFlixQueue::cursorDown(bool page)
00441 {
00442 UIListBtnType::MovementUnit unit = page ? UIListBtnType::MovePage : UIListBtnType::MoveItem;
00443
00444 m_UIArticles->MoveDown(unit);
00445 }
00446
00447 void MythFlixQueue::slotRetrieveNews()
00448 {
00449 if (m_NewsSites.count() == 0)
00450 return;
00451
00452 for (NewsSite* site = m_NewsSites.first(); site; site = m_NewsSites.next())
00453 {
00454 site->retrieve();
00455 }
00456 }
00457
00458 void MythFlixQueue::slotNewsRetrieved(NewsSite* site)
00459 {
00460 processAndShowNews(site);
00461 }
00462
00463 void MythFlixQueue::processAndShowNews(NewsSite* site)
00464 {
00465 if (!site)
00466 return;
00467
00468 site->process();
00469
00470 if (site) {
00471
00472 m_UIArticles->Reset();
00473
00474 for (NewsArticle* article = site->articleList().first(); article;
00475 article = site->articleList().next()) {
00476 UIListBtnTypeItem* item =
00477 new UIListBtnTypeItem(m_UIArticles, article->title());
00478 item->setData(article);
00479 }
00480
00481 update(m_ArticlesRect);
00482 update(m_InfoRect);
00483 }
00484 }
00485
00486 void MythFlixQueue::slotMoveToTop()
00487 {
00488
00489 if (expectingPopup)
00490 slotCancelPopup();
00491
00492 UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent();
00493
00494 if (articleUIItem && articleUIItem->getData())
00495 {
00496 NewsArticle *article = (NewsArticle*) articleUIItem->getData();
00497 if(article)
00498 {
00499
00500 QStringList args =
00501 gContext->GetShareDir() + "mythflix/scripts/netflix.pl";
00502
00503 QString movieID(article->articleURL());
00504 int length = movieID.length();
00505 int index = movieID.findRev("/");
00506 movieID = movieID.mid(index+1,length);
00507
00508 if (m_queueName != "")
00509 {
00510 args += "-q";
00511 args += m_queueName;
00512 }
00513
00514 args += "-1";
00515 args += movieID;
00516
00517
00518 QString results = executeExternal(args, "Move To Top");
00519
00520 slotRetrieveNews();
00521
00522 }
00523 }
00524
00525 }
00526
00527 void MythFlixQueue::slotRemoveFromQueue()
00528 {
00529
00530 if (expectingPopup)
00531 slotCancelPopup();
00532
00533 UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent();
00534
00535 if (articleUIItem && articleUIItem->getData())
00536 {
00537 NewsArticle *article = (NewsArticle*) articleUIItem->getData();
00538 if(article)
00539 {
00540
00541 QStringList args =
00542 gContext->GetShareDir() + "mythflix/scripts/netflix.pl";
00543
00544 QString movieID(article->articleURL());
00545 int length = movieID.length();
00546 int index = movieID.findRev("/");
00547 movieID = movieID.mid(index+1,length);
00548
00549 if (m_queueName != "")
00550 {
00551 args += "-q";
00552 args += m_queueName;
00553 }
00554
00555 args += "-R";
00556 args += movieID;
00557
00558
00559 QString results = executeExternal(args, "Remove From Queue");
00560
00561 slotRetrieveNews();
00562
00563 }
00564 }
00565
00566 }
00567
00568 void MythFlixQueue::slotMoveToQueue()
00569 {
00570 if (expectingPopup)
00571 slotCancelPopup();
00572
00573 UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent();
00574
00575 if (articleUIItem && articleUIItem->getData())
00576 {
00577 NewsArticle *article = (NewsArticle*) articleUIItem->getData();
00578 if(article)
00579 {
00580
00581 QString newQueue = chooseQueue(m_queueName);
00582
00583 if (newQueue == "__NONE__")
00584 {
00585 MythPopupBox::showOkPopup(
00586 gContext->GetMainWindow(), tr("Move Canceled"),
00587 tr("Item not moved."));
00588 return;
00589 }
00590
00591 QStringList base =
00592 gContext->GetShareDir() + "mythflix/scripts/netflix.pl";
00593
00594 QString movieID(article->articleURL());
00595 int length = movieID.length();
00596 int index = movieID.findRev("/");
00597 movieID = movieID.mid(index+1,length);
00598
00599 QStringList args = base;
00600 QString results;
00601
00602 if (newQueue != "")
00603 {
00604 args += "-q";
00605 args += newQueue;
00606 }
00607
00608 args += "-A";
00609 args += movieID;
00610
00611 results = executeExternal(args, "Add To Queue");
00612
00613 args = base;
00614
00615 if (m_queueName != "")
00616 {
00617 args += "-q";
00618 args += m_queueName;
00619 }
00620
00621 args += "-R";
00622 args += movieID;
00623
00624 results = executeExternal(args, "Remove From Queue");
00625
00626 slotRetrieveNews();
00627 }
00628 }
00629 }
00630
00631 void MythFlixQueue::slotShowNetFlixPage()
00632 {
00633 if (expectingPopup)
00634 slotCancelPopup();
00635
00636 UIListBtnTypeItem *articleUIItem = m_UIArticles->GetItemCurrent();
00637 if (articleUIItem && articleUIItem->getData())
00638 {
00639 NewsArticle *article = (NewsArticle*) articleUIItem->getData();
00640 if(article)
00641 {
00642 QString cmdUrl(article->articleURL());
00643 cmdUrl.replace('\'', "%27");
00644
00645 QString cmd = QString("%1 %2 '%3'")
00646 .arg(browser).arg(zoom).arg(cmdUrl);
00647 VERBOSE(VB_GENERAL,
00648 QString("MythFlixQueue: Opening Neflix site: (%1)").arg(cmd));
00649 myth_system(cmd);
00650 }
00651 }
00652 }
00653
00654 void MythFlixQueue::slotArticleSelected(UIListBtnTypeItem*)
00655 {
00656 update(m_ArticlesRect);
00657 update(m_InfoRect);
00658 }
00659
00660 void MythFlixQueue::displayOptions()
00661 {
00662
00663 popup = new MythPopupBox(gContext->GetMainWindow(), "menu popup");
00664
00665 QLabel *label = popup->addLabel(tr("Manage Queue"),
00666 MythPopupBox::Large, false);
00667 label->setAlignment(Qt::AlignCenter | Qt::WordBreak);
00668
00669 QButton *topButton = popup->addButton(tr("Top Of Queue"), this,
00670 SLOT(slotMoveToTop()));
00671
00672 popup->addButton(tr("Remove From Queue"), this,
00673 SLOT(slotRemoveFromQueue()));
00674
00675 if (m_queueName != "")
00676 popup->addButton(tr("Move To Another Queue"), this,
00677 SLOT(slotMoveToQueue()));
00678
00679 popup->addButton(tr("Show NetFlix Page"), this,
00680 SLOT(slotShowNetFlixPage()));
00681
00682 popup->addButton(tr("Cancel"), this, SLOT(slotCancelPopup()));
00683
00684 popup->ShowPopup(this, SLOT(slotCancelPopup()));
00685
00686 topButton->setFocus();
00687
00688 expectingPopup = true;
00689
00690 }
00691
00692 void MythFlixQueue::slotCancelPopup(void)
00693 {
00694 popup->hide();
00695 expectingPopup = false;
00696
00697 popup->deleteLater();
00698 popup = NULL;
00699
00700 setActiveWindow();
00701 }
00702
00703
00704
00705
00706 QString MythFlixQueue::executeExternal(const QStringList& args, const QString& purpose)
00707 {
00708 QString ret = "";
00709 QString err = "";
00710
00711 VERBOSE(VB_GENERAL, QString("%1: Executing '%2'").arg(purpose).
00712 arg(args.join(" ")).local8Bit() );
00713 QProcess proc(args, this);
00714
00715 QString cmd = args[0];
00716 QFileInfo info(cmd);
00717
00718 if (!info.exists())
00719 {
00720 err = QString("\"%1\" failed: does not exist").arg(cmd.local8Bit());
00721 }
00722 else if (!info.isExecutable())
00723 {
00724 err = QString("\"%1\" failed: not executable").arg(cmd.local8Bit());
00725 }
00726 else if (proc.start())
00727 {
00728 while (true)
00729 {
00730 while (proc.canReadLineStdout() || proc.canReadLineStderr())
00731 {
00732 if (proc.canReadLineStdout())
00733 {
00734 ret += QString::fromLocal8Bit(proc.readLineStdout(),-1) + "\n";
00735 }
00736
00737 if (proc.canReadLineStderr())
00738 {
00739 if (err == "")
00740 {
00741 err = cmd + ": ";
00742 }
00743
00744 err += QString::fromLocal8Bit(proc.readLineStderr(),-1) + "\n";
00745 }
00746 }
00747
00748 if (proc.isRunning())
00749 {
00750 qApp->processEvents();
00751 usleep(10000);
00752 }
00753 else
00754 {
00755 if (!proc.normalExit())
00756 {
00757 err = QString("\"%1\" failed: Process exited abnormally")
00758 .arg(cmd.local8Bit());
00759 }
00760
00761 break;
00762 }
00763 }
00764 }
00765 else
00766 {
00767 err = QString("\"%1\" failed: Could not start process")
00768 .arg(cmd.local8Bit());
00769 }
00770
00771 while (proc.canReadLineStdout() || proc.canReadLineStderr())
00772 {
00773 if (proc.canReadLineStdout())
00774 {
00775 ret += QString::fromLocal8Bit(proc.readLineStdout(),-1) + "\n";
00776 }
00777
00778 if (proc.canReadLineStderr())
00779 {
00780 if (err == "")
00781 {
00782 err = cmd + ": ";
00783 }
00784
00785 err += QString::fromLocal8Bit(proc.readLineStderr(), -1) + "\n";
00786 }
00787 }
00788
00789 if (err != "")
00790 {
00791 QString tempPurpose(purpose);
00792
00793 if (tempPurpose == "")
00794 tempPurpose = "Command";
00795
00796 VERBOSE(VB_IMPORTANT, QString("%1").arg(err));
00797 MythPopupBox::showOkPopup(gContext->GetMainWindow(),
00798 QObject::tr(tempPurpose + " failed"), QObject::tr(err + "\n\nCheck NetFlix Settings"));
00799 ret = "#ERROR";
00800 }
00801
00802 VERBOSE(VB_IMPORTANT, ret);
00803 return ret;
00804 }
00805
00806