batch queue racing condition patch by steve.herrel 270

This commit is contained in:
Andrey Skvortsov
2010-10-20 21:18:59 -07:00
parent 75c4f12ee8
commit ba9e2c4879
2 changed files with 508 additions and 524 deletions

View File

@@ -1,255 +1,239 @@
/* /*
* This file is part of RawTherapee. * This file is part of RawTherapee.
* *
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com> * Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
* *
* RawTherapee is free software: you can redistribute it and/or modify * RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* RawTherapee is distributed in the hope that it will be useful, * RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>. * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <rtengine.h> #include <rtengine.h>
#include <colortemp.h> #include <colortemp.h>
#include <imagesource.h> #include <imagesource.h>
#include <improcfun.h> #include <improcfun.h>
#include <curves.h> #include <curves.h>
#include <iccstore.h> #include <iccstore.h>
#include <processingjob.h> #include <processingjob.h>
#include <glibmm.h> #include <glibmm.h>
#include <iostream> #include <iostream>
#undef THREAD_PRIORITY_NORMAL #undef THREAD_PRIORITY_NORMAL
Glib::Thread *batchThread = NULL; namespace rtengine {
Glib::Mutex* qMutex = NULL;
IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl) {
namespace rtengine {
errorCode = 0;
IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl) {
ProcessingJobImpl* job = (ProcessingJobImpl*) pjob;
errorCode = 0;
if (pl) {
ProcessingJobImpl* job = (ProcessingJobImpl*) pjob; pl->setProgressStr ("Processing...");
pl->setProgress (0.0);
if (pl) { }
pl->setProgressStr ("Processing...");
pl->setProgress (0.0); InitialImage* ii = job->initialImage;
} if (!ii) {
ii = InitialImage::load (job->fname, job->isRaw, &errorCode);
InitialImage* ii = job->initialImage; if (errorCode) {
if (!ii) { ii->decreaseRef ();
ii = InitialImage::load (job->fname, job->isRaw, &errorCode); delete job;
if (errorCode) { return NULL;
ii->decreaseRef (); }
delete job; }
return NULL; procparams::ProcParams& params = job->pparams;
}
} // aquire image from imagesource
procparams::ProcParams& params = job->pparams; ImageSource* imgsrc = ii->getImageSource ();
ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green);
// aquire image from imagesource if (params.wb.method=="Camera")
ImageSource* imgsrc = ii->getImageSource (); currWB = imgsrc->getWB ();
ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green); else if (params.wb.method=="Auto")
if (params.wb.method=="Camera") currWB = imgsrc->getAutoWB ();
currWB = imgsrc->getWB ();
else if (params.wb.method=="Auto") int tr = TR_NONE;
currWB = imgsrc->getAutoWB (); if (params.coarse.rotate==90) tr |= TR_R90;
if (params.coarse.rotate==180) tr |= TR_R180;
int tr = TR_NONE; if (params.coarse.rotate==270) tr |= TR_R270;
if (params.coarse.rotate==90) tr |= TR_R90; if (params.coarse.hflip) tr |= TR_HFLIP;
if (params.coarse.rotate==180) tr |= TR_R180; if (params.coarse.vflip) tr |= TR_VFLIP;
if (params.coarse.rotate==270) tr |= TR_R270;
if (params.coarse.hflip) tr |= TR_HFLIP; int fw, fh;
if (params.coarse.vflip) tr |= TR_VFLIP; imgsrc->getFullSize (fw, fh, tr);
int fw, fh; ImProcFunctions ipf (&params, true);
imgsrc->getFullSize (fw, fh, tr);
Image16* baseImg;
ImProcFunctions ipf (&params, true); PreviewProps pp (0, 0, fw, fh, 1);
if (fabs(params.resize.scale-1.0)<1e-5) {
Image16* baseImg; baseImg = new Image16 (fw, fh);
PreviewProps pp (0, 0, fw, fh, 1); imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm);
if (fabs(params.resize.scale-1.0)<1e-5) { }
baseImg = new Image16 (fw, fh); else {
imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm); Image16* oorig = new Image16 (fw, fh);
} imgsrc->getImage (currWB, tr, oorig, pp, params.hlrecovery, params.icm);
else { fw *= params.resize.scale;
Image16* oorig = new Image16 (fw, fh); fh *= params.resize.scale;
imgsrc->getImage (currWB, tr, oorig, pp, params.hlrecovery, params.icm); baseImg = new Image16 (fw, fh);
fw *= params.resize.scale; ipf.resize (oorig, baseImg);
fh *= params.resize.scale; delete oorig;
baseImg = new Image16 (fw, fh); }
ipf.resize (oorig, baseImg); if (pl)
delete oorig; pl->setProgress (0.25);
}
if (pl) // perform first analysis
pl->setProgress (0.25); unsigned int* hist16 = new unsigned int[65536];
ipf.firstAnalysis (baseImg, &params, hist16, imgsrc->getGamma());
// perform first analysis
unsigned int* hist16 = new unsigned int[65536]; // perform transform
ipf.firstAnalysis (baseImg, &params, hist16, imgsrc->getGamma()); if (ipf.needsTransform()) {
Image16* trImg = new Image16 (fw, fh);
// perform transform ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh);
if (ipf.needsTransform()) { delete baseImg;
Image16* trImg = new Image16 (fw, fh); baseImg = trImg;
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh); }
delete baseImg;
baseImg = trImg; // update blurmap
} int** buffer = new int*[fh];
for (int i=0; i<fh; i++)
// update blurmap buffer[i] = new int[fw];
int** buffer = new int*[fh];
for (int i=0; i<fh; i++) SHMap* shmap = NULL;
buffer[i] = new int[fw]; if (params.sh.enabled) {
shmap = new SHMap (fw, fh, true);
SHMap* shmap = NULL; double radius = sqrt (double(fw*fw+fh*fh)) / 2.0;
if (params.sh.enabled) { double shradius = radius / 1800.0 * params.sh.radius;
shmap = new SHMap (fw, fh, true); shmap->update (baseImg, (unsigned short**)buffer, shradius, ipf.lumimul, params.sh.hq);
double radius = sqrt (double(fw*fw+fh*fh)) / 2.0; }
double shradius = radius / 1800.0 * params.sh.radius; // RGB processing
shmap->update (baseImg, (unsigned short**)buffer, shradius, ipf.lumimul, params.sh.hq); //!!!// auto exposure!!!
} double br = params.toneCurve.expcomp;
// RGB processing int bl = params.toneCurve.black;
//!!!// auto exposure!!!
double br = params.toneCurve.expcomp; if (params.toneCurve.autoexp) {
int bl = params.toneCurve.black; unsigned int aehist[65536]; int aehistcompr;
imgsrc->getAEHistogram (aehist, aehistcompr);
if (params.toneCurve.autoexp) { ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, br, bl);
unsigned int aehist[65536]; int aehistcompr; }
imgsrc->getAEHistogram (aehist, aehistcompr);
ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, br, bl); int* curve = new int [65536];
}
CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getDefGain(), imgsrc->getGamma(), true, params.toneCurve.curve, hist16, curve, NULL);
int* curve = new int [65536];
LabImage* labView = new LabImage (baseImg);
CurveFactory::complexCurve (br, bl/65535.0, params.toneCurve.hlcompr, params.toneCurve.shcompr, params.toneCurve.brightness, params.toneCurve.contrast, imgsrc->getDefGain(), imgsrc->getGamma(), true, params.toneCurve.curve, hist16, curve, NULL); ipf.rgbProc (baseImg, labView, curve, shmap);
LabImage* labView = new LabImage (baseImg); if (shmap)
ipf.rgbProc (baseImg, labView, curve, shmap); delete shmap;
if (shmap) if (pl)
delete shmap; pl->setProgress (0.5);
if (pl)
pl->setProgress (0.5); // luminance histogram update
memset (hist16, 0, 65536*sizeof(int));
for (int i=0; i<fh; i++)
// luminance histogram update for (int j=0; j<fw; j++)
memset (hist16, 0, 65536*sizeof(int)); hist16[labView->L[i][j]]++;
for (int i=0; i<fh; i++)
for (int j=0; j<fw; j++) // luminance processing
hist16[labView->L[i][j]]++; CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, params.labCurve.brightness, params.labCurve.contrast, 0.0, 0.0, false, params.labCurve.lcurve, hist16, curve, NULL);
ipf.luminanceCurve (labView, labView, curve, 0, fh);
// luminance processing CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve, 1);
CurveFactory::complexCurve (0.0, 0.0, 0.0, 0.0, params.labCurve.brightness, params.labCurve.contrast, 0.0, 0.0, false, params.labCurve.lcurve, hist16, curve, NULL); ipf.chrominanceCurve (labView, labView, 0, curve, 0, fh);
ipf.luminanceCurve (labView, labView, curve, 0, fh); CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, curve, 1);
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve, 1); ipf.chrominanceCurve (labView, labView, 1, curve, 0, fh);
ipf.chrominanceCurve (labView, labView, 0, curve, 0, fh);
CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.bcurve, curve, 1); ipf.impulsedenoise (labView);
ipf.chrominanceCurve (labView, labView, 1, curve, 0, fh); ipf.lumadenoise (labView, buffer);
ipf.sharpening (labView, (unsigned short**)buffer);
ipf.impulsedenoise (labView);
ipf.lumadenoise (labView, buffer); delete [] curve;
ipf.sharpening (labView, (unsigned short**)buffer); delete [] hist16;
delete [] curve; // color processing
delete [] hist16; ipf.colorCurve (labView, labView);
ipf.colordenoise (labView, buffer);
// color processing ipf.dirpyrdenoise (labView);
ipf.colorCurve (labView, labView);
ipf.colordenoise (labView, buffer); // wavelet equalizer
ipf.dirpyrdenoise (labView); ipf.waveletEqualizer (labView, true, true);
// wavelet equalizer // directional pyramid equalizer
ipf.waveletEqualizer (labView, true, true); ipf.dirpyrequalizer (labView);
// directional pyramid equalizer for (int i=0; i<fh; i++)
ipf.dirpyrequalizer (labView); delete [] buffer[i];
delete [] buffer;
for (int i=0; i<fh; i++)
delete [] buffer[i]; if (pl)
delete [] buffer; pl->setProgress (0.75);
if (pl) // obtain final image
pl->setProgress (0.75); Image16* readyImg;
int cx = 0, cy = 0, cw = labView->W, ch = labView->H;
// obtain final image if (params.crop.enabled) {
Image16* readyImg; cx = params.crop.x;
int cx = 0, cy = 0, cw = labView->W, ch = labView->H; cy = params.crop.y;
if (params.crop.enabled) { cw = params.crop.w;
cx = params.crop.x; ch = params.crop.h;
cy = params.crop.y; }
cw = params.crop.w; readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output);
ch = params.crop.h;
} if (pl)
readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output); pl->setProgress (1.0);
if (pl) readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc);
pl->setProgress (1.0);
ProfileContent pc;
readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); if (params.icm.output.compare (0, 6, "No ICM") && params.icm.output!="")
pc = iccStore.getContent (params.icm.output);
ProfileContent pc;
if (params.icm.output.compare (0, 6, "No ICM") && params.icm.output!="") readyImg->setOutputProfile (pc.data, pc.length);
pc = iccStore.getContent (params.icm.output);
delete baseImg;
readyImg->setOutputProfile (pc.data, pc.length);
if (!job->initialImage)
delete baseImg; ii->decreaseRef ();
if (!job->initialImage) delete job;
ii->decreaseRef ();
if (pl) {
delete job; pl->setProgress (1.0);
pl->setProgressStr ("Ready.");
if (pl) { }
pl->setProgress (1.0);
pl->setProgressStr ("Ready."); return readyImg;
} }
return readyImg; void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl) {
}
ProcessingJob* currentJob = job;
void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl) {
while (currentJob) {
if (!qMutex) int errorCode;
qMutex = new Glib::Mutex (); IImage16* img = processImage (currentJob, errorCode, bpl);
if (errorCode)
qMutex->lock(); bpl->error ("Can not load input image.");
ProcessingJob* currentJob = job; currentJob = bpl->imageReady (img);
}
while (currentJob) { }
int errorCode;
IImage16* img = processImage (currentJob, errorCode, bpl); void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl) {
if (errorCode)
bpl->error ("Can not load input image."); if (bpl)
currentJob = bpl->imageReady (img); Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl), 0, true, true, Glib::THREAD_PRIORITY_LOW);
}
qMutex->unlock(); }
}
}
void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl) {
if (bpl)
batchThread = Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl), 0, true, true, Glib::THREAD_PRIORITY_LOW);
if(qMutex)
{
delete qMutex;
qMutex = NULL;
}
}
}

View File

@@ -1,269 +1,269 @@
/* /*
* This file is part of RawTherapee. * This file is part of RawTherapee.
* *
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com> * Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
* *
* RawTherapee is free software: you can redistribute it and/or modify * RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* RawTherapee is distributed in the hope that it will be useful, * RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>. * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <batchqueuepanel.h> #include <batchqueuepanel.h>
#include <options.h> #include <options.h>
#include <preferences.h> #include <preferences.h>
#include <multilangmgr.h> #include <multilangmgr.h>
#include <rtwindow.h> #include <rtwindow.h>
BatchQueuePanel::BatchQueuePanel () { BatchQueuePanel::BatchQueuePanel () {
batchQueue = new BatchQueue(); batchQueue = new BatchQueue();
// construct batch queue panel with the extra "start" and "stop" button // construct batch queue panel with the extra "start" and "stop" button
Gtk::VBox* batchQueueButtonBox = Gtk::manage (new Gtk::VBox); Gtk::VBox* batchQueueButtonBox = Gtk::manage (new Gtk::VBox);
start = Gtk::manage (new Gtk::ToggleButton (M("FILEBROWSER_STARTPROCESSING"))); start = Gtk::manage (new Gtk::ToggleButton (M("FILEBROWSER_STARTPROCESSING")));
stop = Gtk::manage (new Gtk::ToggleButton (M("FILEBROWSER_STOPPROCESSING"))); stop = Gtk::manage (new Gtk::ToggleButton (M("FILEBROWSER_STOPPROCESSING")));
autoStart = Gtk::manage (new Gtk::CheckButton (M("BATCHQUEUE_AUTOSTART"))); autoStart = Gtk::manage (new Gtk::CheckButton (M("BATCHQUEUE_AUTOSTART")));
start->set_tooltip_text (M("FILEBROWSER_STARTPROCESSINGHINT")); start->set_tooltip_text (M("FILEBROWSER_STARTPROCESSINGHINT"));
stop->set_tooltip_text (M("FILEBROWSER_STOPPROCESSINGHINT")); stop->set_tooltip_text (M("FILEBROWSER_STOPPROCESSINGHINT"));
autoStart->set_tooltip_text (M("FILEBROWSER_TOOLTIP_STOPPROCESSING")); autoStart->set_tooltip_text (M("FILEBROWSER_TOOLTIP_STOPPROCESSING"));
start->set_active (false); start->set_active (false);
stop->set_active (true); stop->set_active (true);
autoStart->set_active (options.procQueueEnabled); autoStart->set_active (options.procQueueEnabled);
start->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-media-play"), Gtk::ICON_SIZE_BUTTON))); start->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-media-play"), Gtk::ICON_SIZE_BUTTON)));
startConnection = start->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::startBatchProc)); startConnection = start->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::startBatchProc));
stop->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-media-stop"), Gtk::ICON_SIZE_BUTTON))); stop->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-media-stop"), Gtk::ICON_SIZE_BUTTON)));
stopConnection = stop->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::stopBatchProc)); stopConnection = stop->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::stopBatchProc));
batchQueueButtonBox->pack_start (*start, Gtk::PACK_SHRINK, 4); batchQueueButtonBox->pack_start (*start, Gtk::PACK_SHRINK, 4);
batchQueueButtonBox->pack_start (*stop, Gtk::PACK_SHRINK, 4); batchQueueButtonBox->pack_start (*stop, Gtk::PACK_SHRINK, 4);
batchQueueButtonBox->pack_start (*autoStart, Gtk::PACK_SHRINK, 4); batchQueueButtonBox->pack_start (*autoStart, Gtk::PACK_SHRINK, 4);
// Output directory selection // Output directory selection
fdir = Gtk::manage (new Gtk::Frame (M("PREFERENCES_OUTDIR"))); fdir = Gtk::manage (new Gtk::Frame (M("PREFERENCES_OUTDIR")));
Gtk::VBox* odvb = Gtk::manage (new Gtk::VBox ()); Gtk::VBox* odvb = Gtk::manage (new Gtk::VBox ());
odvb->set_border_width (4); odvb->set_border_width (4);
Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ()); Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ());
useTemplate = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRTEMPLATE")+":")); useTemplate = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRTEMPLATE")+":"));
hb2->pack_start (*useTemplate, Gtk::PACK_SHRINK,4); hb2->pack_start (*useTemplate, Gtk::PACK_SHRINK,4);
outdirTemplate = Gtk::manage (new Gtk::Entry ()); outdirTemplate = Gtk::manage (new Gtk::Entry ());
hb2->pack_start (*outdirTemplate); hb2->pack_start (*outdirTemplate);
odvb->pack_start (*hb2, Gtk::PACK_SHRINK, 4); odvb->pack_start (*hb2, Gtk::PACK_SHRINK, 4);
outdirTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT")); outdirTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT"));
useTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT")); useTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT"));
Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ()); Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ());
useFolder = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRFOLDER")+":")); useFolder = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRFOLDER")+":"));
hb3->pack_start (*useFolder, Gtk::PACK_SHRINK,4); hb3->pack_start (*useFolder, Gtk::PACK_SHRINK,4);
outdirFolder = Gtk::manage (new Gtk::FileChooserButton (M("PREFERENCES_OUTDIRFOLDER"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); outdirFolder = Gtk::manage (new Gtk::FileChooserButton (M("PREFERENCES_OUTDIRFOLDER"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER));
hb3->pack_start (*outdirFolder); hb3->pack_start (*outdirFolder);
odvb->pack_start (*hb3, Gtk::PACK_SHRINK, 4); odvb->pack_start (*hb3, Gtk::PACK_SHRINK, 4);
outdirFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT")); outdirFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT"));
useFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT")); useFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT"));
Gtk::RadioButton::Group g = useTemplate->get_group(); Gtk::RadioButton::Group g = useTemplate->get_group();
useFolder->set_group (g); useFolder->set_group (g);
fdir->add (*odvb); fdir->add (*odvb);
// Output file format selection // Output file format selection
fformat = Gtk::manage (new Gtk::Frame (M("PREFERENCES_FILEFORMAT"))); fformat = Gtk::manage (new Gtk::Frame (M("PREFERENCES_FILEFORMAT")));
saveFormatPanel = Gtk::manage (new SaveFormatPanel ()); saveFormatPanel = Gtk::manage (new SaveFormatPanel ());
fformat->add (*saveFormatPanel); fformat->add (*saveFormatPanel);
saveFormatPanel->init (options.saveFormat); saveFormatPanel->init (options.saveFormat);
outdirTemplate->set_text (options.savePathTemplate); outdirTemplate->set_text (options.savePathTemplate);
if (Glib::file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR)) if (Glib::file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR))
outdirFolder->set_filename (options.savePathFolder); outdirFolder->set_current_folder (options.savePathFolder);
useTemplate->set_active (options.saveUsePathTemplate); useTemplate->set_active (options.saveUsePathTemplate);
useFolder->set_active (!options.saveUsePathTemplate); useFolder->set_active (!options.saveUsePathTemplate);
// setup signal handlers // setup signal handlers
outdirTemplate->signal_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); outdirTemplate->signal_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions));
outdirFolder->signal_current_folder_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::pathFolderChanged)); outdirFolder->signal_current_folder_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::pathFolderChanged));
useTemplate->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); useTemplate->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions));
useFolder->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); useFolder->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions));
saveFormatPanel->setListener (this); saveFormatPanel->setListener (this);
// setup button bar // setup button bar
topBox = Gtk::manage (new Gtk::HBox ()); topBox = Gtk::manage (new Gtk::HBox ());
pack_start (*topBox, Gtk::PACK_SHRINK); pack_start (*topBox, Gtk::PACK_SHRINK);
topBox->pack_start (*batchQueueButtonBox, Gtk::PACK_SHRINK, 4); topBox->pack_start (*batchQueueButtonBox, Gtk::PACK_SHRINK, 4);
topBox->pack_start (*fdir); topBox->pack_start (*fdir);
topBox->pack_start (*fformat, Gtk::PACK_SHRINK, 4); topBox->pack_start (*fformat, Gtk::PACK_SHRINK, 4);
// add middle browser area // add middle browser area
Gtk::HBox* hBox = Gtk::manage (new Gtk::HBox ()); Gtk::HBox* hBox = Gtk::manage (new Gtk::HBox ());
pack_start (*batchQueue); pack_start (*batchQueue);
// lower box with thumbnail zoom // lower box with thumbnail zoom
bottomBox = Gtk::manage (new Gtk::HBox ()); bottomBox = Gtk::manage (new Gtk::HBox ());
pack_start (*bottomBox, Gtk::PACK_SHRINK); pack_start (*bottomBox, Gtk::PACK_SHRINK);
// change thumbnail arrangement button // change thumbnail arrangement button
hAlignIcon = new Gtk::Image (argv0+"/images/horizontals.png"); hAlignIcon = new Gtk::Image (argv0+"/images/horizontals.png");
vAlignIcon = new Gtk::Image (argv0+"/images/verticals.png"); vAlignIcon = new Gtk::Image (argv0+"/images/verticals.png");
hAlignIcon->show (); hAlignIcon->show ();
vAlignIcon->show (); vAlignIcon->show ();
chAlign = Gtk::manage (new Gtk::Button ()); chAlign = Gtk::manage (new Gtk::Button ());
chAlign->show (); chAlign->show ();
bottomBox->pack_end (*chAlign, Gtk::PACK_SHRINK); bottomBox->pack_end (*chAlign, Gtk::PACK_SHRINK);
chAlign->set_image (*hAlignIcon); chAlign->set_image (*hAlignIcon);
chAlign->set_relief (Gtk::RELIEF_NONE); chAlign->set_relief (Gtk::RELIEF_NONE);
chAlign->signal_pressed().connect (sigc::mem_fun(*this, &BatchQueuePanel::arrangementButtonPressed)); chAlign->signal_pressed().connect (sigc::mem_fun(*this, &BatchQueuePanel::arrangementButtonPressed));
chAlign->set_tooltip_text (M("FILEBROWSER_ARRANGEMENTHINT")); chAlign->set_tooltip_text (M("FILEBROWSER_ARRANGEMENTHINT"));
bottomBox->pack_end (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); bottomBox->pack_end (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4);
if (options.fbArrangement==1) if (options.fbArrangement==1)
chAlign->set_image (*vAlignIcon); chAlign->set_image (*vAlignIcon);
else else
chAlign->set_image (*hAlignIcon); chAlign->set_image (*hAlignIcon);
arrangementButtonPressed (); arrangementButtonPressed ();
// thumbnail zoom // thumbnail zoom
Gtk::HBox* zoomBox = Gtk::manage (new Gtk::HBox ()); Gtk::HBox* zoomBox = Gtk::manage (new Gtk::HBox ());
zoomBox->pack_start (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); zoomBox->pack_start (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4);
Gtk::Label* zoomLabel = Gtk::manage (new Gtk::Label (Glib::ustring("<b>")+M("FILEBROWSER_THUMBSIZE")+":</b>")); Gtk::Label* zoomLabel = Gtk::manage (new Gtk::Label (Glib::ustring("<b>")+M("FILEBROWSER_THUMBSIZE")+":</b>"));
zoomLabel->set_use_markup (true); zoomLabel->set_use_markup (true);
zoomBox->pack_start (*zoomLabel, Gtk::PACK_SHRINK, 4); zoomBox->pack_start (*zoomLabel, Gtk::PACK_SHRINK, 4);
zoomInButton = Gtk::manage (new Gtk::Button ()); zoomInButton = Gtk::manage (new Gtk::Button ());
zoomInButton->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-zoom-in"), Gtk::ICON_SIZE_SMALL_TOOLBAR))); zoomInButton->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-zoom-in"), Gtk::ICON_SIZE_SMALL_TOOLBAR)));
zoomInButton->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomIn)); zoomInButton->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomIn));
zoomInButton->set_relief (Gtk::RELIEF_NONE); zoomInButton->set_relief (Gtk::RELIEF_NONE);
zoomInButton->set_tooltip_text (M("FILEBROWSER_ZOOMINHINT")); zoomInButton->set_tooltip_text (M("FILEBROWSER_ZOOMINHINT"));
zoomBox->pack_end (*zoomInButton, Gtk::PACK_SHRINK); zoomBox->pack_end (*zoomInButton, Gtk::PACK_SHRINK);
zoomOutButton = Gtk::manage (new Gtk::Button ()); zoomOutButton = Gtk::manage (new Gtk::Button ());
zoomOutButton->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-zoom-out"), Gtk::ICON_SIZE_SMALL_TOOLBAR))); zoomOutButton->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-zoom-out"), Gtk::ICON_SIZE_SMALL_TOOLBAR)));
zoomOutButton->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomOut)); zoomOutButton->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomOut));
zoomOutButton->set_relief (Gtk::RELIEF_NONE); zoomOutButton->set_relief (Gtk::RELIEF_NONE);
zoomOutButton->set_tooltip_text (M("FILEBROWSER_ZOOMOUTHINT")); zoomOutButton->set_tooltip_text (M("FILEBROWSER_ZOOMOUTHINT"));
zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK); zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK);
bottomBox->pack_end (*zoomBox, Gtk::PACK_SHRINK); bottomBox->pack_end (*zoomBox, Gtk::PACK_SHRINK);
batchQueue->setBatchQueueListener (this); batchQueue->setBatchQueueListener (this);
show_all (); show_all ();
} }
void BatchQueuePanel::arrangementButtonPressed () { void BatchQueuePanel::arrangementButtonPressed () {
if (chAlign->get_image()==hAlignIcon) { if (chAlign->get_image()==hAlignIcon) {
chAlign->set_image (*vAlignIcon); chAlign->set_image (*vAlignIcon);
batchQueue->setArrangement (BatchQueue::TB_Vertical); batchQueue->setArrangement (BatchQueue::TB_Vertical);
} }
else { else {
chAlign->set_image (*hAlignIcon); chAlign->set_image (*hAlignIcon);
batchQueue->setArrangement (BatchQueue::TB_Horizontal); batchQueue->setArrangement (BatchQueue::TB_Horizontal);
} }
} }
void BatchQueuePanel::updateTab (int qsize) void BatchQueuePanel::updateTab (int qsize)
{ {
Gtk::Notebook *nb =(Gtk::Notebook *)(this->get_parent()); Gtk::Notebook *nb =(Gtk::Notebook *)(this->get_parent());
Gtk::HBox* hbb = Gtk::manage (new Gtk::HBox ()); Gtk::HBox* hbb = Gtk::manage (new Gtk::HBox ());
if(!qsize ){ if(!qsize ){
hbb->pack_start (*Gtk::manage (new Gtk::Image (argv0+"/images/processing.png"))); hbb->pack_start (*Gtk::manage (new Gtk::Image (argv0+"/images/processing.png")));
hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE") ))); hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE") )));
}else if( start->get_active () ){ }else if( start->get_active () ){
hbb->pack_start (*Gtk::manage (new Gtk::Image (argv0+"/images/processing-play.png"))); hbb->pack_start (*Gtk::manage (new Gtk::Image (argv0+"/images/processing-play.png")));
hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE")+" [" +Glib::ustring::format( qsize )+"]" ))); hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE")+" [" +Glib::ustring::format( qsize )+"]" )));
}else{ }else{
hbb->pack_start (*Gtk::manage (new Gtk::Image (argv0+"/images/processing-pause.png"))); hbb->pack_start (*Gtk::manage (new Gtk::Image (argv0+"/images/processing-pause.png")));
hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE")+" [" +Glib::ustring::format( qsize )+"]" ))); hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE")+" [" +Glib::ustring::format( qsize )+"]" )));
} }
hbb->set_spacing (2); hbb->set_spacing (2);
hbb->show_all (); hbb->show_all ();
nb->set_tab_label(*this,*hbb); nb->set_tab_label(*this,*hbb);
} }
void BatchQueuePanel::queueSizeChanged (int qsize) void BatchQueuePanel::queueSizeChanged (int qsize)
{ {
updateTab ( qsize); updateTab ( qsize);
} }
void BatchQueuePanel::imageProcessingReady (Glib::ustring fname) { void BatchQueuePanel::imageProcessingReady (Glib::ustring fname) {
parent->imageDeveloped (fname); parent->imageDeveloped (fname);
} }
void BatchQueuePanel::startBatchProc () { void BatchQueuePanel::startBatchProc () {
stopConnection.block (true); stopConnection.block (true);
startConnection.block (true); startConnection.block (true);
stop->set_active (false); stop->set_active (false);
start->set_active (true); start->set_active (true);
stopConnection.block (false); stopConnection.block (false);
startConnection.block (false); startConnection.block (false);
if (batchQueue->hasJobs()) { if (batchQueue->hasJobs()) {
fdir->set_sensitive (false); fdir->set_sensitive (false);
fformat->set_sensitive (false); fformat->set_sensitive (false);
saveOptions(); saveOptions();
batchQueue->startProcessing (); batchQueue->startProcessing ();
} }
else else
stopBatchProc (); stopBatchProc ();
updateTab (batchQueue->getEntries().size()); updateTab (batchQueue->getEntries().size());
} }
void BatchQueuePanel::stopBatchProc () { void BatchQueuePanel::stopBatchProc () {
stopConnection.block (true); stopConnection.block (true);
startConnection.block (true); startConnection.block (true);
stop->set_active (true); stop->set_active (true);
start->set_active (false); start->set_active (false);
stopConnection.block (false); stopConnection.block (false);
startConnection.block (false); startConnection.block (false);
updateTab (batchQueue->getEntries().size()); updateTab (batchQueue->getEntries().size());
} }
void BatchQueuePanel::addBatchQueueJob (BatchQueueEntry* bqe, bool head) { void BatchQueuePanel::addBatchQueueJob (BatchQueueEntry* bqe, bool head) {
batchQueue->addEntry (bqe, head); batchQueue->addEntry (bqe, head);
if (stop->get_active () && autoStart->get_active ()) if (stop->get_active () && autoStart->get_active ())
startBatchProc (); startBatchProc ();
} }
void BatchQueuePanel::queueEmpty () { void BatchQueuePanel::queueEmpty () {
stopBatchProc (); stopBatchProc ();
fdir->set_sensitive (true); fdir->set_sensitive (true);
fformat->set_sensitive (true); fformat->set_sensitive (true);
} }
bool BatchQueuePanel::canStartNext () { bool BatchQueuePanel::canStartNext () {
if (start->get_active ()) if (start->get_active ())
return true; return true;
else { else {
fdir->set_sensitive (true); fdir->set_sensitive (true);
fformat->set_sensitive (true); fformat->set_sensitive (true);
return false; return false;
} }
} }
void BatchQueuePanel::saveOptions () { void BatchQueuePanel::saveOptions () {
options.savePathTemplate = outdirTemplate->get_text(); options.savePathTemplate = outdirTemplate->get_text();
options.saveUsePathTemplate = useTemplate->get_active(); options.saveUsePathTemplate = useTemplate->get_active();
options.procQueueEnabled = autoStart->get_active (); options.procQueueEnabled = autoStart->get_active ();
} }
// We only want to save the following when it changes, \ // We only want to save the following when it changes, \
// since these settings are shared with editorpanel : // since these settings are shared with editorpanel :
void BatchQueuePanel::pathFolderChanged () { void BatchQueuePanel::pathFolderChanged () {
options.savePathFolder = outdirFolder->get_filename(); options.savePathFolder = outdirFolder->get_current_folder();
} }
void BatchQueuePanel::formatChanged (Glib::ustring f) { void BatchQueuePanel::formatChanged (Glib::ustring f) {
options.saveFormat = saveFormatPanel->getFormat (); options.saveFormat = saveFormatPanel->getFormat ();
} }