1 /* smplayer, GUI front-end for mplayer.
2 Copyright (C) 2006-2021 Ricardo Villalba <ricardo@smplayer.info>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #include "videopreview.h"
20 #include "videopreviewconfigdialog.h"
21 #include "playerid.h"
22 #include <QAction>
23 #include <QProcess>
24 #include <QRegExp>
25 #include <QDir>
26 #include <QTime>
27 #include <QProgressDialog>
28 #include <QWidget>
29 #include <QGridLayout>
30 #include <QLabel>
31 #include <QScrollArea>
32 #include <QDialogButtonBox>
33 #include <QPushButton>
34 #include <QPainter>
35 #include <QFileDialog>
36 #include <QMessageBox>
37 #include <QSettings>
38 #include <QApplication>
39 #include <QPixmapCache>
40 #include <QImageWriter>
41 #include <QImageReader>
42 #include <QDebug>
43
44 #include <cmath>
45
46 #ifndef NO_SMPLAYER_SUPPORT
47 #include "inforeader.h"
48 #include "images.h"
49 #endif
50
51 #define RENAME_PICTURES 0
52
53 #define N_OUTPUT_FRAMES 1
54
55 // MPlayer2 doesn't support png outdir
56 /* #define VP_USE_PNG_OUTDIR */
57
58 #define FONT_STYLE "font-family:ubuntu,verdana,arial;"
59 #define HEADER_STYLE "style=\"" FONT_STYLE " font-size:16px\""
60 #define FOOTER_STYLE HEADER_STYLE
61
VideoPreview(QString mplayer_path,QWidget * parent)62 VideoPreview::VideoPreview(QString mplayer_path, QWidget * parent) : QWidget(parent, Qt::Window)
63 {
64 setMplayerPath(mplayer_path);
65
66 set = 0; // settings
67 save_last_directory = true;
68
69 prop.input_video.clear();
70 prop.dvd_device.clear();
71 prop.n_cols = 4;
72 prop.n_rows = 4;
73 prop.initial_step = 20;
74 prop.max_width = 800;
75 prop.aspect_ratio = 0;
76 prop.display_osd = true;
77 prop.extract_format = JPEG;
78
79 output_dir = "smplayer_preview";
80 full_output_dir = QDir::tempPath() +"/"+ output_dir;
81
82 progress = new QProgressDialog(parent != 0 ? parent : this);
83 progress->setMinimumDuration(0);
84 progress->reset(); // Prevent the dialog to be shown on initialization (Qt 5.5)
85 connect( progress, SIGNAL(canceled()), this, SLOT(cancelPressed()) );
86
87 w_contents = new QWidget(this);
88 w_contents->setContentsMargins(0, 0, 0, 0);
89 QPalette p = w_contents->palette();
90 p.setColor(w_contents->backgroundRole(), Qt::white);
91 p.setColor(w_contents->foregroundRole(), Qt::black);
92 w_contents->setPalette(p);
93
94 title = new QLabel(this);
95 title->setWordWrap(true);
96
97 info = new QLabel(this);
98 info->setWordWrap(false);
99
100 foot = new QLabel(this);
101 foot->setAlignment(Qt::AlignRight);
102
103 grid_layout = new QGridLayout;
104 grid_layout->setSpacing(2);
105 grid_layout->setContentsMargins(0, 0, 0, 0);
106
107 QVBoxLayout * l = new QVBoxLayout;
108 l->setContentsMargins(4, 4, 4, 4);
109 l->setSpacing(0);
110 l->setSizeConstraint(QLayout::SetFixedSize);
111 l->addWidget(title);
112 l->addWidget(info);
113 l->addLayout(grid_layout);
114 l->addWidget(foot);
115
116 w_contents->setLayout(l);
117
118 scroll_area = new QScrollArea(this);
119 scroll_area->setWidgetResizable(true);
120 scroll_area->setAlignment(Qt::AlignCenter);
121 scroll_area->setWidget( w_contents );
122
123 button_box = new QDialogButtonBox(QDialogButtonBox::Close | QDialogButtonBox::Save, Qt::Horizontal, this);
124 connect( button_box, SIGNAL(rejected()), this, SLOT(close()) );
125 connect( button_box->button(QDialogButtonBox::Save), SIGNAL(clicked()), this, SLOT(saveImage()) );
126
127 button_box->button(QDialogButtonBox::Close)->setDefault(true);
128 button_box->button(QDialogButtonBox::Close)->setText(tr("&Close"));
129 button_box->button(QDialogButtonBox::Save)->setText(tr("&Save"));
130 #ifndef NO_SMPLAYER_SUPPORT
131 button_box->button(QDialogButtonBox::Save)->setIcon(Images::icon("save"));
132 #endif
133
134 QVBoxLayout * my_layout = new QVBoxLayout;
135 my_layout->addWidget(scroll_area);
136 my_layout->addWidget(button_box);
137 setLayout(my_layout);
138
139 retranslateStrings();
140
141 QList<QByteArray> r_formats = QImageReader::supportedImageFormats();
142 QString read_formats;
143 for (int n=0; n < r_formats.count(); n++) {
144 read_formats.append(r_formats[n]+" ");
145 }
146 qDebug("VideoPreview::VideoPreview: supported formats for reading: %s", read_formats.toUtf8().constData());
147
148 QList<QByteArray> w_formats = QImageWriter::supportedImageFormats();
149 QString write_formats;
150 for (int n=0; n < w_formats.count(); n++) {
151 write_formats.append(w_formats[n]+" ");
152 }
153 qDebug("VideoPreview::VideoPreview: supported formats for writing: %s", write_formats.toUtf8().constData());
154
155 toggleInfoAct = new QAction(this);
156 toggleInfoAct->setCheckable(true);
157 toggleInfoAct->setChecked(true);
158 toggleInfoAct->setShortcut( QKeySequence("Ctrl+H") );
159 connect( toggleInfoAct, SIGNAL(toggled(bool)), this, SLOT(showInfo(bool)) );
160 addAction(toggleInfoAct);
161 }
162
~VideoPreview()163 VideoPreview::~VideoPreview() {
164 if (set) saveSettings();
165 }
166
retranslateStrings()167 void VideoPreview::retranslateStrings() {
168 progress->setWindowTitle(tr("Thumbnail Generator"));
169 progress->setCancelButtonText( tr("Cancel") );
170
171 foot->setText("<i " FOOTER_STYLE "><b>http://smplayer.info</b></i>");
172 }
173
setMplayerPath(QString mplayer_path)174 void VideoPreview::setMplayerPath(QString mplayer_path) {
175 mplayer_bin = mplayer_path;
176 QFileInfo fi(mplayer_bin);
177 if (fi.exists() && fi.isExecutable() && !fi.isDir()) {
178 mplayer_bin = fi.absoluteFilePath();
179 }
180
181 qDebug("VideoPreview::setMplayerPath: mplayer_bin: '%s'", mplayer_bin.toUtf8().constData());
182 }
183
setSettings(QSettings * settings)184 void VideoPreview::setSettings(QSettings * settings) {
185 set = settings;
186 loadSettings();
187 }
188
clearThumbnails()189 void VideoPreview::clearThumbnails() {
190 for (int n=0; n < label_list.count(); n++) {
191 grid_layout->removeWidget( label_list[n] );
192 delete label_list[n];
193 }
194 label_list.clear();
195 info->clear();
196 }
197
framePicture()198 QString VideoPreview::framePicture() {
199 return QString("0000000%1.%2").arg(N_OUTPUT_FRAMES == 1 ? 1 : N_OUTPUT_FRAMES-1).arg(prop.extract_format == PNG ? "png" : "jpg");
200 }
201
createThumbnails()202 bool VideoPreview::createThumbnails() {
203 clearThumbnails();
204 error_message.clear();
205
206 button_box->setEnabled(false);
207
208 bool result = extractImages();
209
210 progress->close();
211
212 if ((result == false) && (!error_message.isEmpty())) {
213 QMessageBox::critical(this, tr("Error"),
214 tr("The following error has occurred while creating the thumbnails:")+"\n"+ error_message );
215 }
216
217 button_box->setEnabled(true);
218
219 // Adjust size
220 //resize( w_contents->sizeHint() );
221
222 cleanDir(full_output_dir);
223 return result;
224 }
225
extractImages()226 bool VideoPreview::extractImages() {
227 VideoInfo i = getInfo(mplayer_bin, prop.input_video);
228 int length = i.length;
229
230 if (length == 0) {
231 if (error_message.isEmpty()) error_message = tr("The length of the video is 0");
232 return false;
233 }
234
235 // Create a temporary directory
236 QDir d(QDir::tempPath());
237 if (!d.exists(output_dir)) {
238 if (!d.mkpath(output_dir)) {
239 qDebug("VideoPreview::extractImages: error: can't create '%s'", full_output_dir.toUtf8().constData());
240 error_message = tr("The temporary directory (%1) can't be created").arg(full_output_dir);
241 return false;
242 }
243 }
244
245 displayVideoInfo(i);
246
247 // Let's begin
248 run.thumbnail_width = 0;
249
250 int num_pictures = prop.n_cols * prop.n_rows;
251 length -= prop.initial_step;
252 double s_step = (double) length / num_pictures;
253
254 double current_time = prop.initial_step;
255
256 canceled = false;
257 progress->setLabelText(tr("Creating thumbnails..."));
258 progress->setRange(0, num_pictures-1);
259 progress->show();
260
261 double aspect_ratio = i.aspect;
262 if (prop.aspect_ratio != 0) aspect_ratio = prop.aspect_ratio;
263
264 for (int n = 0; n < num_pictures; n++) {
265 qDebug("VideoPreview::extractImages: getting frame %d of %d...", n+1, num_pictures);
266 progress->setValue(n);
267 qApp->processEvents();
268
269 if (canceled) return false;
270
271 if (!runPlayer(current_time, aspect_ratio)) return false;
272
273 QString frame_picture = full_output_dir + "/" + framePicture();
274 if (!QFile::exists(frame_picture)) {
275 error_message = tr("The file %1 doesn't exist").arg(frame_picture);
276 return false;
277 }
278
279 #if RENAME_PICTURES
280 QString extension = (extractFormat()==PNG) ? "png" : "jpg";
281 QString output_file = output_dir + QString("/picture_%1.%2").arg(current_time, 8, 10, QLatin1Char('0')).arg(extension);
282 d.rename(output_dir + "/" + framePicture(), output_file);
283 #else
284 QString output_file = output_dir + "/" + framePicture();
285 #endif
286
287 if (!addPicture(QDir::tempPath() +"/"+ output_file, n, current_time)) {
288 return false;
289 }
290
291 current_time += s_step;
292 }
293
294 return true;
295 }
296
297 #if defined(Q_OS_UNIX) && !defined(NO_SMPLAYER_SUPPORT)
isOptionAvailableinMPV(const QString & option)298 bool VideoPreview::isOptionAvailableinMPV(const QString & option) {
299 static QStringList option_list;
300 static QString executable;
301
302 if (option_list.isEmpty() || executable != mplayer_bin) {
303 InfoReader * ir = InfoReader::obj(mplayer_bin);
304 ir->getInfo();
305 option_list = ir->optionList();
306 executable = mplayer_bin;
307 }
308 return option_list.contains(option);
309 }
310 #endif
311
runPlayer(double seek,double aspect_ratio)312 bool VideoPreview::runPlayer(double seek, double aspect_ratio) {
313 QStringList args;
314
315 if (PlayerID::player(mplayer_bin) == PlayerID::MPV) {
316 #ifdef MPV_SUPPORT
317 bool use_new_options = true;
318 #if defined(Q_OS_UNIX) && !defined(NO_SMPLAYER_SUPPORT)
319 if (!isOptionAvailableinMPV("--vo-image-format")) use_new_options = false;
320 #endif
321
322 // MPV
323 args << "--no-config" << "--no-audio" << "--no-cache" << "--hr-seek=yes" << "--sid=no";
324 args << "--frames=" + QString::number(N_OUTPUT_FRAMES);
325 args << "--framedrop=no" << "--start=" + QString::number(seek);
326 if (aspect_ratio != 0) {
327 args << "--video-aspect=" + QString::number(aspect_ratio);
328 }
329 if (!prop.dvd_device.isEmpty()) args << "--dvd-device=" + prop.dvd_device;
330 if (!use_new_options) {
331 QString format = (prop.extract_format == PNG) ? "png:png-compression=0" : "jpg";
332 args << QString("--vo=image=format=%1:outdir=\"%2\"").arg(format).arg(full_output_dir);
333 } else {
334 QString format = (prop.extract_format == PNG) ? "png" : "jpg";
335 args << "--vo-image-format=" + format << "--vo-image-outdir=" + full_output_dir;
336 args << "--vo=image";
337 if (prop.extract_format == PNG) args << "--vo-image-png-compression=0";
338 }
339
340 /*
341 #ifdef Q_OS_WIN
342 args << "--use-text-osd=no"; // option removed in mpv 0.12
343 #endif
344 */
345 #endif // MPV_SUPPORT
346 }
347 else {
348 #ifdef MPLAYER_SUPPORT
349 // MPlayer
350 args << "-nosound" << "-nocache" << "-noframedrop" << "-noconfig" << "all";
351
352 if (prop.extract_format == PNG) {
353 args << "-vo"
354 #ifdef VP_USE_PNG_OUTDIR
355 << "png:outdir=\""+full_output_dir+"\"";
356 #else
357 << "png";
358 #endif
359 } else {
360 args << "-vo"
361 << "jpeg:outdir=\""+full_output_dir+"\"";
362 }
363
364 args << "-frames" << QString::number(N_OUTPUT_FRAMES) << "-ss" << QString::number(seek);
365
366 if (aspect_ratio != 0) {
367 args << "-aspect" << QString::number(aspect_ratio) << "-zoom";
368 }
369
370 if (!prop.dvd_device.isEmpty()) {
371 args << "-dvd-device" << prop.dvd_device;
372 }
373
374 #ifdef Q_OS_WIN
375 args << "-nofontconfig";
376 #endif
377
378 /*
379 if (display_osd) {
380 args << "-vf" << "expand=osd=1" << "-osdlevel" << "2";
381 }
382 */
383 #endif // MPLAYER_SUPPORT
384 }
385
386 args << prop.input_video;
387
388 QString command = mplayer_bin + " " + args.join(" ");
389 qDebug() << "VideoPreview::runMplayer: command:" << command;
390
391 QProcess p;
392 #ifndef VP_USE_PNG_OUTDIR
393 p.setWorkingDirectory(full_output_dir);
394 #endif
395 p.start(mplayer_bin, args);
396
397 if (!p.waitForStarted()) {
398 qDebug("VideoPreview::runMplayer: error: the process didn't start");
399 }
400
401 if (!p.waitForFinished()) {
402 qDebug("VideoPreview::runMplayer: error running process");
403 error_message = tr("The mplayer process didn't run");
404 return false;
405 }
406
407 //qDebug() << "VideoPreview::runMplayer: process output:" << p.readAll();
408
409 return true;
410 }
411
412
addPicture(const QString & filename,int num,int time)413 bool VideoPreview::addPicture(const QString & filename, int num, int time) {
414 int row = num / prop.n_cols;
415 int col = num % prop.n_cols;
416
417 qDebug("VideoPreview::addPicture: %d (row: %d col: %d) file: '%s'", num, row, col, filename.toUtf8().constData());
418
419 QPixmapCache::clear();
420 QPixmap picture;
421 if (!picture.load(filename)) {
422 qDebug("VideoPreview::addPicture: can't load file");
423 error_message = tr("The file %1 can't be loaded").arg(filename);
424 return false;
425 }
426
427 if (run.thumbnail_width == 0) {
428 qDebug("VideoPreview::addPicture: horizontalSpacing: %d", grid_layout->horizontalSpacing());
429 int spacing = grid_layout->horizontalSpacing() * (prop.n_cols-1);
430 QMargins m = w_contents->layout()->contentsMargins();
431 qDebug("VideoPreview::addPicture: contentsMargins: %d, %d", m.left(), m.right());
432 spacing += (m.left() + m.right());
433 if (spacing < 0) spacing = 0;
434 qDebug("VideoPreview::addPicture: spacing: %d", spacing);
435 run.thumbnail_width = (prop.max_width - spacing) / prop.n_cols;
436 if (run.thumbnail_width > picture.width()) run.thumbnail_width = picture.width();
437 qDebug("VideoPreview::addPicture: thumbnail_width set to %d", run.thumbnail_width);
438 }
439
440 QPixmap scaled_picture = picture.scaledToWidth(run.thumbnail_width, Qt::SmoothTransformation);
441
442 // Add current time text
443 if (prop.display_osd) {
444 QTime t(0,0);
445 QString stime = t.addSecs(time).toString("hh:mm:ss");
446 //qDebug() << "VideoPreview::addPicture: stime:" << stime << "time:" << time;
447 QFont font;
448 font.setPointSize(12);
449 font.setBold(true);
450 QPainter painter(&scaled_picture);
451 painter.setPen(Qt::white);
452 painter.setFont(font);
453 //painter.drawText(scaled_picture.rect(), Qt::AlignRight | Qt::AlignBottom, stime);
454
455 // Set background
456 QFontMetrics fm(font);
457 #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
458 int px_wide = fm.horizontalAdvance(stime);
459 #else
460 int px_wide = fm.width(stime);
461 #endif
462 int px_high = fm.height();
463 QRect rect(scaled_picture.rect());
464 rect.setX(rect.width() - px_wide);
465 rect.setY(rect.height() - px_high);
466 rect.setWidth(px_wide);
467 rect.setHeight(px_high);
468 painter.fillRect(rect, QBrush(QColor(0, 0, 0, 128)));
469
470 // Draw text
471 painter.drawText(rect, Qt::AlignCenter, stime);
472 }
473
474 QLabel * l = new QLabel(this);
475 label_list.append(l);
476 l->setPixmap(scaled_picture);
477 //l->setPixmap(picture);
478 grid_layout->addWidget(l, row, col);
479
480 return true;
481 }
482
483 #define ADD_INFO( data) \
484 { \
485 text += data; \
486 if (count++ % 3 == 0) text += "</td><td>"; else text += "<br>"; \
487 }
488
displayVideoInfo(const VideoInfo & i)489 void VideoPreview::displayVideoInfo(const VideoInfo & i) {
490 // Display info about the video
491 QTime t(0,0);
492 t = t.addSecs(i.length);
493
494 QString aspect = QString::number(i.aspect);
495 if (fabs(1.77 - i.aspect) < 0.1) aspect = "16:9";
496 else
497 if (fabs(1.33 - i.aspect) < 0.1) aspect = "4:3";
498 else
499 if (fabs(2.35 - i.aspect) < 0.1) aspect = "2.35:1";
500
501 QString no_info = tr("No info");
502
503 QString fps = (i.fps==0 || i.fps==1000) ? no_info : QString("%1").arg(i.fps);
504 QString video_bitrate = (i.video_bitrate==0) ? no_info : tr("%1 kbps").arg(i.video_bitrate/1000);
505 QString audio_bitrate = (i.audio_bitrate==0) ? no_info : tr("%1 kbps").arg(i.audio_bitrate/1000);
506 QString audio_rate = (i.audio_rate==0) ? no_info : tr("%1 Hz").arg(i.audio_rate);
507
508 title->setText("<h2 " FONT_STYLE ">" + i.filename + "</h2>");
509
510 int count = 1;
511
512 QString text =
513 "<table cellspacing=4 cellpadding=4 " HEADER_STYLE ">"
514 "<tr><td>";
515
516 ADD_INFO(tr("Size: %1 MB").arg(i.size / (1024*1024)));
517 ADD_INFO(tr("Resolution: %1x%2").arg(i.width).arg(i.height));
518 ADD_INFO(tr("Length: %1").arg(t.toString("hh:mm:ss")));
519
520 if (i.fps && i.fps != 1000) ADD_INFO(tr("FPS: %1").arg(fps));
521 if (!i.video_format.isEmpty()) ADD_INFO(tr("Video format: %1").arg(i.video_format));
522 if (!i.audio_format.isEmpty()) ADD_INFO(tr("Audio format: %1").arg(i.audio_format));
523
524 ADD_INFO(tr("Aspect ratio: %1").arg(aspect));
525
526 if (i.video_bitrate) ADD_INFO(tr("Video bitrate: %1").arg(video_bitrate));
527 if (i.audio_bitrate) ADD_INFO(tr("Audio bitrate: %1").arg(audio_bitrate));
528 if (i.audio_rate) ADD_INFO(tr("Audio rate: %1").arg(audio_rate));
529
530 text += "</td></tr></table>";
531
532 //qDebug() << "VideoPreview::displayVideoInfo: text:" << text;
533
534 info->setText(text);
535 setWindowTitle( tr("Video preview") + " - " + i.filename );
536 }
537
cleanDir(QString directory)538 void VideoPreview::cleanDir(QString directory) {
539 QStringList filter;
540 if (prop.extract_format == PNG) {
541 filter.append("*.png");
542 } else {
543 filter.append("*.jpg");
544 }
545
546 QDir d(directory);
547 QStringList l = d.entryList( filter, QDir::Files, QDir::Unsorted);
548
549 for (int n = 0; n < l.count(); n++) {
550 qDebug("VideoPreview::cleanDir: deleting '%s'", l[n].toUtf8().constData());
551 d.remove(l[n]);
552 }
553 qDebug("VideoPreview::cleanDir: removing directory '%s'", directory.toUtf8().constData());
554 d.rmpath(directory);
555 }
556
getInfo(const QString & mplayer_path,const QString & filename)557 VideoInfo VideoPreview::getInfo(const QString & mplayer_path, const QString & filename) {
558 VideoInfo i;
559
560 if (filename.isEmpty()) {
561 error_message = tr("No filename");
562 return i;
563 }
564
565 QFileInfo fi(filename);
566 if (fi.exists()) {
567 i.filename = fi.fileName();
568 i.size = fi.size();
569 }
570
571 QRegExp rx("^ID_(.*)=(.*)");
572
573 QProcess p;
574 p.setProcessChannelMode( QProcess::MergedChannels );
575
576 QStringList args;
577
578 if (PlayerID::player(mplayer_path) == PlayerID::MPV) {
579 #ifdef MPV_SUPPORT
580 // MPV
581 args << "--term-playing-msg="
582 "ID_LENGTH=${=duration:${=length}}\n"
583 "ID_VIDEO_WIDTH=${=width}\n"
584 "ID_VIDEO_HEIGHT=${=height}\n"
585 "ID_VIDEO_FPS=${=container-fps:${=fps}}\n"
586 "ID_VIDEO_ASPECT=${=video-aspect}\n"
587 "ID_VIDEO_BITRATE=${=video-bitrate}\n"
588 "ID_AUDIO_BITRATE=${=audio-bitrate}\n"
589 "ID_AUDIO_RATE=${audio-params/samplerate:${=audio-samplerate}}\n"
590 "ID_VIDEO_FORMAT=${video-format}\n"
591 "ID_AUDIO_FORMAT=${audio-codec-name}\n";
592
593 args << "--vo=null" << "-ao=null" << "--frames=1" << "--no-quiet" << "--no-cache" << "--no-config";
594 if (!prop.dvd_device.isEmpty()) args << "--dvd-device=" + prop.dvd_device;
595 args << filename;
596 #endif // MPV_SUPPORT
597 }
598 else {
599 #ifdef MPLAYER_SUPPORT
600 // MPlayer
601 args << "-vo" << "null" << "-ao" << "null" << "-frames" << "1" << "-identify" << "-nocache" << "-noquiet" << "-noconfig" << "all";
602 if (!prop.dvd_device.isEmpty()) args << "-dvd-device" << prop.dvd_device;
603
604 #ifdef Q_OS_WIN
605 args << "-nofontconfig";
606 #endif
607
608 args << filename;
609 #endif // MPLAYER_SUPPORT
610 }
611
612 QString command = mplayer_path + " " + args.join(" ").replace("\n", "\\n");//.replace("$", "\\$");
613 qDebug() << "VideoPreview::getInfo: command:" << command;
614
615 p.start(mplayer_path, args);
616
617 if (p.waitForFinished()) {
618 QByteArray line;
619 while (p.canReadLine()) {
620 line = p.readLine().trimmed();
621 qDebug("VideoPreview::getInfo: '%s'", line.constData());
622 if (rx.indexIn(line) > -1) {
623 QString tag = rx.cap(1);
624 QString value = rx.cap(2);
625 qDebug("VideoPreview::getInfo: tag: '%s', value: '%s'", tag.toUtf8().constData(), value.toUtf8().constData());
626
627 if (tag == "LENGTH") i.length = (int) value.toDouble();
628 else
629 if (tag == "VIDEO_WIDTH") i.width = value.toInt();
630 else
631 if (tag == "VIDEO_HEIGHT") i.height = value.toInt();
632 else
633 if (tag == "VIDEO_FPS") i.fps = value.toDouble();
634 else
635 if (tag == "VIDEO_ASPECT") {
636 i.aspect = value.toDouble();
637 if ((i.aspect == 0) && (i.width != 0) && (i.height != 0)) {
638 i.aspect = (double) i.width / i.height;
639 }
640 }
641 else
642 if (tag == "VIDEO_BITRATE") i.video_bitrate = value.toInt();
643 else
644 if (tag == "AUDIO_BITRATE") i.audio_bitrate = value.toInt();
645 else
646 if (tag == "AUDIO_RATE") i.audio_rate = value.toInt();
647 else
648 if (tag == "VIDEO_FORMAT") i.video_format = value;
649 else
650 if (tag == "AUDIO_FORMAT") i.audio_format = value;
651 }
652 }
653 } else {
654 qDebug("VideoPreview::getInfo: error: process didn't start");
655 error_message = tr("The mplayer process didn't start while trying to get info about the video");
656 }
657
658 qDebug("VideoPreview::getInfo: filename: '%s'", i.filename.toUtf8().constData());
659 qDebug("VideoPreview::getInfo: resolution: '%d x %d'", i.width, i.height);
660 qDebug("VideoPreview::getInfo: length: '%d'", i.length);
661 qDebug("VideoPreview::getInfo: size: '%d'", (int) i.size);
662
663 return i;
664 }
665
showInfo(bool visible)666 void VideoPreview::showInfo(bool visible) {
667 qDebug("VideoPreview::showInfo: %d", visible);
668 info->setVisible(visible);
669 foot->setVisible(visible);
670 }
671
saveImage()672 void VideoPreview::saveImage() {
673 qDebug("VideoPreview::saveImage");
674
675 // Proposed name
676 QString proposed_name = "";
677 if (save_last_directory) proposed_name = last_directory;
678
679 QFileInfo fi(prop.input_video);
680 if (fi.exists()) {
681 if (!save_last_directory) proposed_name = fi.absolutePath();
682 QString extension = (extractFormat()==PNG) ? "png" : "jpg";
683 proposed_name += "/"+ fi.completeBaseName() +"_preview."+ extension;
684 }
685
686 // Formats
687 QList<QByteArray> w_formats = QImageWriter::supportedImageFormats();
688 QString write_formats;
689 for (int n=0; n < w_formats.count(); n++) {
690 write_formats.append("*."+w_formats[n]+" ");
691 }
692 if (write_formats.isEmpty()) {
693 // Shouldn't happen!
694 write_formats = "*.png *.jpg";
695 }
696
697 QString filename = QFileDialog::getSaveFileName(this, tr("Save file"),
698 proposed_name, tr("Images") +" ("+ write_formats +")");
699
700 if (!filename.isEmpty()) {
701 #if QT_VERSION >= 0x050000
702 QPixmap image = w_contents->grab();
703 #else
704 QPixmap image = QPixmap::grabWidget(w_contents);
705 #endif
706 qDebug("VideoPreview::saveImage: size: %d %d", image.size().width(), image.size().height());
707 if (image.size().width() > prop.max_width) {
708 image = image.scaledToWidth(prop.max_width, Qt::SmoothTransformation);
709 qDebug("VideoPreview::saveImage: image scaled to : %d %d", image.size().width(), image.size().height());
710 }
711 if (!image.save(filename)) {
712 // Failed!!!
713 qDebug("VideoPreview::saveImage: error saving '%s'", filename.toUtf8().constData());
714 QMessageBox::warning(this, tr("Error saving file"),
715 tr("The file couldn't be saved") );
716 } else {
717 last_directory = QFileInfo(filename).absolutePath();
718 }
719 }
720 }
721
showConfigDialog(QWidget * parent)722 bool VideoPreview::showConfigDialog(QWidget * parent) {
723 VideoPreviewConfigDialog d(parent);
724
725 d.setVideoFile( videoFile() );
726 d.setDVDDevice( DVDDevice() );
727 d.setCols( cols() );
728 d.setRows( rows() );
729 d.setInitialStep( initialStep() );
730 d.setMaxWidth( maxWidth() );
731 d.setDisplayOSD( displayOSD() );
732 d.setAspectRatio( aspectRatio() );
733 d.setFormat( extractFormat() );
734 d.setSaveLastDirectory( save_last_directory );
735
736 if (d.exec() == QDialog::Accepted) {
737 setVideoFile( d.videoFile() );
738 setDVDDevice( d.DVDDevice() );
739 setCols( d.cols() );
740 setRows( d.rows() );
741 setInitialStep( d.initialStep() );
742 setMaxWidth( d.maxWidth() );
743 setDisplayOSD( d.displayOSD() );
744 setAspectRatio( d.aspectRatio() );
745 setExtractFormat(d.format() );
746 save_last_directory = d.saveLastDirectory();
747
748 return true;
749 }
750
751 return false;
752 }
753
saveSettings()754 void VideoPreview::saveSettings() {
755 qDebug("VideoPreview::saveSettings");
756
757 set->beginGroup("videopreview");
758
759 set->setValue("columns", cols());
760 set->setValue("rows", rows());
761 set->setValue("initial_step", initialStep());
762 set->setValue("max_width", maxWidth());
763 set->setValue("osd", displayOSD());
764 set->setValue("format", extractFormat());
765 set->setValue("save_last_directory", save_last_directory);
766
767 if (save_last_directory) {
768 set->setValue("last_directory", last_directory);
769 }
770
771 set->setValue("filename", videoFile());
772 set->setValue("dvd_device", DVDDevice());
773
774 set->setValue("show_info", toggleInfoAct->isChecked());
775
776 set->endGroup();
777 }
778
loadSettings()779 void VideoPreview::loadSettings() {
780 qDebug("VideoPreview::loadSettings");
781
782 set->beginGroup("videopreview");
783
784 setCols( set->value("columns", cols()).toInt() );
785 setRows( set->value("rows", rows()).toInt() );
786 setInitialStep( set->value("initial_step", initialStep()).toInt() );
787 setMaxWidth( set->value("max_width", maxWidth()).toInt() );
788 setDisplayOSD( set->value("osd", displayOSD()).toBool() );
789 setExtractFormat( (ExtractFormat) set->value("format", extractFormat()).toInt() );
790 save_last_directory = set->value("save_last_directory", save_last_directory).toBool();
791 last_directory = set->value("last_directory", last_directory).toString();
792
793 setVideoFile( set->value("filename", videoFile()).toString() );
794 setDVDDevice( set->value("dvd_device", DVDDevice()).toString() );
795
796 toggleInfoAct->setChecked(set->value("show_info", true).toBool());
797
798 set->endGroup();
799 }
800
adjustWindowSize()801 void VideoPreview::adjustWindowSize() {
802 qDebug("VideoPreview::adjustWindowSize: window size: %d %d", width(), height());
803 qDebug("VideoPreview::adjustWindowSize: scroll_area size: %d %d", scroll_area->width(), scroll_area->height());
804
805 int diff_width = width() - scroll_area->maximumViewportSize().width();
806 int diff_height = height() - scroll_area->maximumViewportSize().height();
807
808 qDebug("VideoPreview::adjustWindowSize: diff_width: %d diff_height: %d", diff_width, diff_height);
809
810 QSize new_size = w_contents->size() + QSize( diff_width, diff_height);
811
812 qDebug("VideoPreview::adjustWindowSize: new_size: %d %d", new_size.width(), new_size.height());
813
814 resize(new_size);
815 }
816
cancelPressed()817 void VideoPreview::cancelPressed() {
818 canceled = true;
819 }
820
821 // Language change stuff
changeEvent(QEvent * e)822 void VideoPreview::changeEvent(QEvent *e) {
823 if (e->type() == QEvent::LanguageChange) {
824 retranslateStrings();
825 } else {
826 QWidget::changeEvent(e);
827 }
828 }
829
830 #include "moc_videopreview.cpp"
831
832