14#include <libmythbase/mythconfig.h>
48 m_destinationScreen(destinationScreen),
49 m_themeScreen(themeScreen),
50 m_archiveDestination(archiveDestination)
56 LOG(VB_GENERAL, LOG_ERR,
"MythBurn: Failed to clear thumb directory");
96 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'mythburn'");
133 for (
int i = 0; i < actions.size() && !handled; i++)
135 const QString&
action = actions[i];
155 else if (
action ==
"DOWN")
167 else if (
action ==
"DELETE")
171 else if (
action ==
"INFO")
175 else if (
action ==
"TOGGLECUT")
197 uint usedSpace = size / 1024 / 1024;
210 tmpSize = QString(
"%1 Mb").arg(usedSpace);
232 item->description =
"";
233 item->bitrate = 0.0F;
239 "/MythArchive/ffmpeg_dvd_" +
241 .toLower() ==
"ntsc") ?
"ntsc" :
"pal") +
".xml";
247 "mytharchive/encoder_profiles/ffmpeg_dvd_" +
249 .toLower() ==
"ntsc") ?
"ntsc" :
"pal") +
".xml";
252 LOG(VB_GENERAL, LOG_NOTICE,
253 "MythArchive: Loading encoding profiles from " +
filename);
255 QDomDocument doc(
"mydocument");
257 if (!
file.open(QIODevice::ReadOnly))
260 if (!doc.setContent( &
file ))
267 QDomElement docElem = doc.documentElement();
268 QDomNodeList profileNodeList = doc.elementsByTagName(
"profile");
273 for (
int x = 0; x < profileNodeList.count(); x++)
275 QDomNode n = profileNodeList.item(x);
276 QDomElement e = n.toElement();
277 QDomNode n2 = e.firstChild();
280 QDomElement e2 = n2.toElement();
283 if (e2.tagName() ==
"name")
285 if (e2.tagName() ==
"description")
287 if (e2.tagName() ==
"bitrate")
291 n2 = n2.nextSibling();
297 item2->description = desc;
298 item2->bitrate = bitrate.toFloat();
320 item->
SetText(tr(
"Using Cut List"),
"cutlist");
325 item->
SetText(tr(
"Not Using Cut List"),
"cutlist");
331 item->
SetText(tr(
"No Cut List"),
"cutlist");
342 ShowOkPopup(tr(
"You need to add at least one item to archive!"));
370 if (
file.open( QIODevice::ReadOnly ))
372 QTextStream stream(&
file);
374 while ( !stream.atEnd() )
376 res = res + stream.readLine();
390 QString message = tr(
"Retrieving File Information. Please Wait...");
394 auto *busyPopup =
new
397 if (busyPopup->Create())
407 QCoreApplication::processEvents();
419 QCoreApplication::processEvents();
421 if (a->duration == 0)
424 LOG(VB_GENERAL, LOG_ERR,
425 QString(
"MythBurn: failed to get file details for: %1").arg(a->filename));
430 if (a->encoderProfile ==
nullptr)
436 item->SetData(QVariant::fromValue(a));
437 item->SetText(a->subtitle,
"subtitle");
438 item->SetText(a->startDate +
" " + a->startTime,
"date");
444 item->SetText(tr(
"Using Cut List"),
"cutlist");
445 item->DisplayState(
"using",
"cutliststatus");
449 item->SetText(tr(
"Not Using Cut List"),
"cutlist");
450 item->DisplayState(
"notusing",
"cutliststatus");
455 item->SetText(tr(
"No Cut List"),
"cutlist");
456 item->DisplayState(
"none",
"cutliststatus");
458 item->SetText(tr(
"Encoder: ") + a->encoderProfile->name,
"profile");
475 if (
type ==
"Recording")
480 query.
prepare(
"SELECT title FROM recorded WHERE basename = :FILENAME");
484 LOG(VB_GENERAL, LOG_ERR,
485 QString(
"MythArchive: Recording not found (%1)")
488 else if (
type ==
"Video")
491 query.
prepare(
"SELECT title FROM videometadata"
492 " WHERE filename = :FILENAME");
496 LOG(VB_GENERAL, LOG_ERR,
497 QString(
"MythArchive: Video not found (%1)").arg(
filename));
499 else if (
type ==
"File")
503 LOG(VB_GENERAL, LOG_ERR,
504 QString(
"MythArchive: File not found (%1)").arg(
filename));
507 LOG(VB_GENERAL, LOG_NOTICE,
"MythArchive: Archive item removed from list");
520 if (item->
videoCodec.toLower() ==
"mpeg2video (main)")
551 QString defaultProfile =
555 if (x->name == defaultProfile)
564 QDomDocument doc(
"mythburn");
566 QDomElement root = doc.createElement(
"mythburn");
567 doc.appendChild(root);
569 QDomElement job = doc.createElement(
"job");
570 job.setAttribute(
"theme",
m_theme);
571 root.appendChild(job);
573 QDomElement media = doc.createElement(
"media");
574 job.appendChild(media);
587 QDomElement
file = doc.createElement(
"file");
588 file.setAttribute(
"type", a->type.toLower() );
589 file.setAttribute(
"usecutlist",
static_cast<int>(a->useCutlist));
590 file.setAttribute(
"filename", a->filename);
591 file.setAttribute(
"encodingprofile", a->encoderProfile->name);
592 if (a->editedDetails)
594 QDomElement details = doc.createElement(
"details");
595 file.appendChild(details);
596 details.setAttribute(
"title", a->title);
597 details.setAttribute(
"subtitle", a->subtitle);
598 details.setAttribute(
"startdate", a->startDate);
599 details.setAttribute(
"starttime", a->startTime);
600 QDomText desc = doc.createTextNode(a->description);
601 details.appendChild(desc);
604 if (!a->thumbList.empty())
606 QDomElement thumbs = doc.createElement(
"thumbimages");
607 file.appendChild(thumbs);
609 for (
auto *thumbImage : std::as_const(a->thumbList))
611 QDomElement thumb = doc.createElement(
"thumb");
612 thumbs.appendChild(thumb);
613 thumb.setAttribute(
"caption", thumbImage->caption);
614 thumb.setAttribute(
"filename", thumbImage->filename);
615 thumb.setAttribute(
"frame", (
int) thumbImage->frame);
619 media.appendChild(
file);
623 QDomElement
options = doc.createElement(
"options");
634 if (!f.open(QIODevice::WriteOnly))
636 LOG(VB_GENERAL, LOG_ERR,
637 QString(
"MythBurn::createConfigFile: "
638 "Failed to open file for writing - %1") .arg(
filename));
643 t << doc.toString(4);
661 query.
prepare(
"SELECT type, title, subtitle, description, startdate, "
662 "starttime, size, filename, hascutlist, duration, "
663 "cutduration, videowidth, videoheight, filecodec, "
664 "videocodec, encoderprofile FROM archiveitems "
677 a->title = query.
value(1).toString();
678 a->subtitle = query.
value(2).toString();
679 a->description = query.
value(3).toString();
680 a->startDate = query.
value(4).toString();
681 a->startTime = query.
value(5).toString();
682 a->size = query.
value(6).toLongLong();
683 a->filename = query.
value(7).toString();
684 a->hasCutlist = (query.
value(8).toInt() == 1);
685 a->useCutlist =
false;
686 a->duration = query.
value(9).toInt();
687 a->cutDuration = query.
value(10).toInt();
688 a->videoWidth = query.
value(11).toInt();
689 a->videoHeight = query.
value(12).toInt();
690 a->fileCodec = query.
value(13).toString();
691 a->videoCodec = query.
value(14).toString();
693 a->editedDetails =
false;
701 if (x->name == profileName)
711 query.
prepare(
"DELETE FROM archiveitems;");
727 query.
prepare(
"INSERT INTO archiveitems (type, title, subtitle, "
728 "description, startdate, starttime, size, filename, "
729 "hascutlist, duration, cutduration, videowidth, "
730 "videoheight, filecodec, videocodec, encoderprofile) "
731 "VALUES(:TYPE, :TITLE, :SUBTITLE, :DESCRIPTION, :STARTDATE, "
732 ":STARTTIME, :SIZE, :FILENAME, :HASCUTLIST, :DURATION, "
733 ":CUTDURATION, :VIDEOWIDTH, :VIDEOHEIGHT, :FILECODEC, "
734 ":VIDEOCODEC, :ENCODERPROFILE);");
737 query.
bindValue(
":SUBTITLE", a->subtitle);
738 query.
bindValue(
":DESCRIPTION", a->description);
739 query.
bindValue(
":STARTDATE", a->startDate);
740 query.
bindValue(
":STARTTIME", a->startTime);
741 query.
bindValue(
":SIZE", (qint64)a->size);
742 query.
bindValue(
":FILENAME", a->filename);
743 query.
bindValue(
":HASCUTLIST", a->hasCutlist);
744 query.
bindValue(
":DURATION", a->duration);
745 query.
bindValue(
":CUTDURATION", a->cutDuration);
746 query.
bindValue(
":VIDEOWIDTH", a->videoWidth);
747 query.
bindValue(
":VIDEOHEIGHT", a->videoHeight);
748 query.
bindValue(
":FILECODEC", a->fileCodec);
749 query.
bindValue(
":VIDEOCODEC", a->videoCodec);
750 query.
bindValue(
":ENCODERPROFILE", a->encoderProfile->name);
770 auto *menuPopup =
new MythDialogBox(tr(
"Menu"), popupStack,
"actionmenu");
772 if (menuPopup->Create())
775 menuPopup->SetReturnEvent(
this,
"action");
777 if (curItem->hasCutlist)
779 if (curItem->useCutlist)
781 menuPopup->AddButton(tr(
"Don't Use Cut List"),
786 menuPopup->AddButton(tr(
"Use Cut List"),
825 if (editor->Create())
841 if (finder->Create())
849 if (ok && item && gridItem)
870 if (!profileDialog->Create())
872 delete profileDialog;
876 popupStack->
AddScreen(profileDialog,
false);
907 QString logDir = tempDir +
"logs";
908 QString configDir = tempDir +
"config";
916 QFile::remove(logDir +
"/mythburncancel.lck");
919 commandline = PYTHON_EXE;
920 commandline +=
" " +
GetShareDir() +
"mytharchive/scripts/mythburn.py";
921 commandline +=
" -j " + configDir +
"/mydata.xml";
922 commandline +=
" -l " + logDir +
"/progress.log";
923 commandline +=
" > " + logDir +
"/mythburn.log 2>&1 &";
932 ShowOkPopup(tr(
"It was not possible to create the DVD. "
933 " An error occured when running the scripts"));
955 if (selector->Create())
968 query.
prepare(
"SELECT title FROM videometadata");
985 if (selector->Create())
992 "*.mpg *.mpeg *.mov *.avi *.nuv");
1002 if (selector->Create())
1033 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'profilepopup'");
1041 item->SetData(QVariant::fromValue(x));
1094 setObjectName(
"BurnMenu");
1102 "The last run failed to create a DVD."));
1107 QString title = tr(
"Burn DVD");
1108 QString msg = tr(
"\nPlace a blank DVD in the"
1109 " drive and select an option below.");
1112 "actionmenu",
true);
1114 if (menuPopup->Create())
1117 menuPopup->SetReturnEvent(
this,
"action");
1119 menuPopup->AddButton(tr(
"Burn DVD"));
1120 menuPopup->AddButton(tr(
"Burn DVD Rewritable"));
1121 menuPopup->AddButton(tr(
"Burn DVD Rewritable (Force Erase)"));
1128 if (dce->GetId() ==
"action")
1130 doBurn(dce->GetResult());
1138 if ((mode < 0) || (mode > 2))
1146 QString logDir = tempDir +
"logs";
1147 QString commandline;
1151 QFile::remove(logDir +
"/progress.log");
1155 QFile::remove(logDir +
"/mythburncancel.lck");
1157 QString sArchiveFormat = QString::number(mode);
1158 bool bEraseDVDRW = (mode == 2);
1160 .startsWith(
"Native");
1162 commandline =
"mytharchivehelper --burndvd --mediatype " + sArchiveFormat +
1163 (bEraseDVDRW ?
" --erasedvdrw" :
"") +
1164 (bNativeFormat ?
" --nativeformat" :
"");
1167 commandline +=
" --quiet";
1168 commandline +=
" > " + logDir +
"/progress.log 2>&1 &";
1176 "mytharchivehelper to burn the DVD."));
void recalcItemSize(ArchiveItem *item)
bool getFileDetails(ArchiveItem *a)
void showWarningDialog(const QString &msg)
QString getBaseName(const QString &filename)
QString getTempDirectory(bool showError)
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
void selectorClosed(bool ok)
void toggleUseCutlist(void)
MythUIProgressBar * m_sizeBar
MythUIButton * m_prevButton
MythScreenType * m_destinationScreen
void editThumbnails(void)
MythBurn(MythScreenStack *parent, MythScreenType *destinationScreen, MythScreenType *themeScreen, const ArchiveDestination &archiveDestination, const QString &name)
EncoderProfile * getDefaultProfile(ArchiveItem *item)
void updateArchiveList(void)
MythUIButton * m_addfileButton
static bool isArchiveItemValid(const QString &type, const QString &filename)
void loadEncoderProfiles(void)
MythUIButtonList * m_archiveButtonList
MythScreenType * m_themeScreen
MythUIText * m_currentsizeErrorText
MythUIButton * m_addrecordingButton
MythUIButton * m_nextButton
MythUIText * m_nofilesText
bool Create(void) override
void loadConfiguration(void)
MythUIText * m_maxsizeText
MythUIButton * m_addvideoButton
static QString loadFile(const QString &filename)
ArchiveDestination m_archiveDestination
void handleAddVideo(void)
void handleAddRecording(void)
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
void saveConfiguration(void)
MythUIText * m_minsizeText
void profileChanged(int profileNo)
MythUIButton * m_cancelButton
EncoderProfile * getProfileFromName(const QString &profileName)
void itemClicked(MythUIButtonListItem *item)
void createConfigFile(const QString &filename)
QList< ArchiveItem * > m_archiveList
void editorClosed(bool ok, ArchiveItem *item)
void handleNextPage(void)
void handlePrevPage(void)
QList< EncoderProfile * > m_profileList
void ShowMenu(void) override
MythUIText * m_currentsizeText
void SaveSetting(const QString &key, int newValue)
QString GetSetting(const QString &key, const QString &defaultval="")
static void DBError(const QString &where, const MSqlQuery &query)
Basic menu dialog, message and a list of options.
MythScreenStack * GetMainStack()
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
MythScreenStack * GetStack(const QString &Stackname)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Screen in which all other widgets are contained and rendered.
void BuildFocusList(void)
MythUIType * GetFocusWidget(void) const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool SetFocusWidget(MythUIType *widget=nullptr)
virtual void SetText(const QString &text)
MythUIText * m_captionText
ArchiveItem * m_archiveItem
QList< EncoderProfile * > m_profileList
MythUIButton * m_okButton
void haveResult(int profile)
MythUIText * m_newSizeText
MythUIButtonList * m_profileBtnList
MythUIText * m_descriptionText
void profileChanged(MythUIButtonListItem *item)
MythUIText * m_oldSizeText
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
@ GENERIC_EXIT_OK
Exited with no error.
@ GENERIC_EXIT_RUNNING
Process is running.
bool logPropagateQuiet(void)
Check if we are propagating a "--quiet".
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
QString GetShareDir(void)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
MythMainWindow * GetMythMainWindow(void)
bool MythRemoveDirectory(QDir &aDir)
@ kMSDontBlockInputDevs
avoid blocking LIRC & Joystick Menu
@ kMSRunBackground
run child in the background
@ kMSDontDisableDrawing
avoid disabling UI drawing
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
MBASE_PUBLIC QString formatKBytes(int64_t sizeKB, int prec=1)
EncoderProfile * encoderProfile
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)