From ba9e2c48795294e3169300a27dccc0de2a09a59b Mon Sep 17 00:00:00 2001 From: Andrey Skvortsov Date: Wed, 20 Oct 2010 21:18:59 -0700 Subject: [PATCH] batch queue racing condition patch by steve.herrel 270 --- rtengine/simpleprocess.cc | 494 +++++++++++++++++----------------- rtgui/batchqueuepanel.cc | 538 +++++++++++++++++++------------------- 2 files changed, 508 insertions(+), 524 deletions(-) diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index ac1c9818b..5e1e81ee5 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1,255 +1,239 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#undef THREAD_PRIORITY_NORMAL - -Glib::Thread *batchThread = NULL; -Glib::Mutex* qMutex = NULL; - -namespace rtengine { - -IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl) { - - errorCode = 0; - - ProcessingJobImpl* job = (ProcessingJobImpl*) pjob; - - if (pl) { - pl->setProgressStr ("Processing..."); - pl->setProgress (0.0); - } - - InitialImage* ii = job->initialImage; - if (!ii) { - ii = InitialImage::load (job->fname, job->isRaw, &errorCode); - if (errorCode) { - ii->decreaseRef (); - delete job; - return NULL; - } - } - procparams::ProcParams& params = job->pparams; - - // aquire image from imagesource - ImageSource* imgsrc = ii->getImageSource (); - ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green); - if (params.wb.method=="Camera") - currWB = imgsrc->getWB (); - else if (params.wb.method=="Auto") - currWB = imgsrc->getAutoWB (); - - int tr = TR_NONE; - if (params.coarse.rotate==90) tr |= TR_R90; - if (params.coarse.rotate==180) tr |= TR_R180; - if (params.coarse.rotate==270) tr |= TR_R270; - if (params.coarse.hflip) tr |= TR_HFLIP; - if (params.coarse.vflip) tr |= TR_VFLIP; - - int fw, fh; - imgsrc->getFullSize (fw, fh, tr); - - ImProcFunctions ipf (¶ms, true); - - Image16* baseImg; - PreviewProps pp (0, 0, fw, fh, 1); - if (fabs(params.resize.scale-1.0)<1e-5) { - baseImg = new Image16 (fw, fh); - imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm); - } - else { - Image16* oorig = new Image16 (fw, fh); - imgsrc->getImage (currWB, tr, oorig, pp, params.hlrecovery, params.icm); - fw *= params.resize.scale; - fh *= params.resize.scale; - baseImg = new Image16 (fw, fh); - ipf.resize (oorig, baseImg); - delete oorig; - } - if (pl) - pl->setProgress (0.25); - - // perform first analysis - unsigned int* hist16 = new unsigned int[65536]; - ipf.firstAnalysis (baseImg, ¶ms, hist16, imgsrc->getGamma()); - - // perform transform - if (ipf.needsTransform()) { - Image16* trImg = new Image16 (fw, fh); - 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; iupdate (baseImg, (unsigned short**)buffer, shradius, ipf.lumimul, params.sh.hq); - } - // RGB processing -//!!!// auto exposure!!! - double br = params.toneCurve.expcomp; - int bl = params.toneCurve.black; - - if (params.toneCurve.autoexp) { - 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); - - LabImage* labView = new LabImage (baseImg); - ipf.rgbProc (baseImg, labView, curve, shmap); - - if (shmap) - delete shmap; - - if (pl) - pl->setProgress (0.5); - - - // luminance histogram update - memset (hist16, 0, 65536*sizeof(int)); - for (int i=0; iL[i][j]]++; - - // luminance processing - 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); - CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve, 1); - 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.chrominanceCurve (labView, labView, 1, curve, 0, fh); - - ipf.impulsedenoise (labView); - ipf.lumadenoise (labView, buffer); - ipf.sharpening (labView, (unsigned short**)buffer); - - delete [] curve; - delete [] hist16; - - // color processing - ipf.colorCurve (labView, labView); - ipf.colordenoise (labView, buffer); - ipf.dirpyrdenoise (labView); - - // wavelet equalizer - ipf.waveletEqualizer (labView, true, true); - - // directional pyramid equalizer - ipf.dirpyrequalizer (labView); - - for (int i=0; isetProgress (0.75); - - // obtain final image - Image16* readyImg; - int cx = 0, cy = 0, cw = labView->W, ch = labView->H; - if (params.crop.enabled) { - cx = params.crop.x; - cy = params.crop.y; - cw = params.crop.w; - ch = params.crop.h; - } - readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output); - - if (pl) - pl->setProgress (1.0); - - readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); - - ProfileContent pc; - if (params.icm.output.compare (0, 6, "No ICM") && params.icm.output!="") - pc = iccStore.getContent (params.icm.output); - - readyImg->setOutputProfile (pc.data, pc.length); - - delete baseImg; - - if (!job->initialImage) - ii->decreaseRef (); - - delete job; - - if (pl) { - pl->setProgress (1.0); - pl->setProgressStr ("Ready."); - } - - return readyImg; -} - -void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl) { - - if (!qMutex) - qMutex = new Glib::Mutex (); - - qMutex->lock(); - ProcessingJob* currentJob = job; - - while (currentJob) { - int errorCode; - IImage16* img = processImage (currentJob, errorCode, bpl); - if (errorCode) - bpl->error ("Can not load input image."); - currentJob = bpl->imageReady (img); - } - 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; - } - -} - -} +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef THREAD_PRIORITY_NORMAL + +namespace rtengine { + +IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* pl) { + + errorCode = 0; + + ProcessingJobImpl* job = (ProcessingJobImpl*) pjob; + + if (pl) { + pl->setProgressStr ("Processing..."); + pl->setProgress (0.0); + } + + InitialImage* ii = job->initialImage; + if (!ii) { + ii = InitialImage::load (job->fname, job->isRaw, &errorCode); + if (errorCode) { + ii->decreaseRef (); + delete job; + return NULL; + } + } + procparams::ProcParams& params = job->pparams; + + // aquire image from imagesource + ImageSource* imgsrc = ii->getImageSource (); + ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green); + if (params.wb.method=="Camera") + currWB = imgsrc->getWB (); + else if (params.wb.method=="Auto") + currWB = imgsrc->getAutoWB (); + + int tr = TR_NONE; + if (params.coarse.rotate==90) tr |= TR_R90; + if (params.coarse.rotate==180) tr |= TR_R180; + if (params.coarse.rotate==270) tr |= TR_R270; + if (params.coarse.hflip) tr |= TR_HFLIP; + if (params.coarse.vflip) tr |= TR_VFLIP; + + int fw, fh; + imgsrc->getFullSize (fw, fh, tr); + + ImProcFunctions ipf (¶ms, true); + + Image16* baseImg; + PreviewProps pp (0, 0, fw, fh, 1); + if (fabs(params.resize.scale-1.0)<1e-5) { + baseImg = new Image16 (fw, fh); + imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm); + } + else { + Image16* oorig = new Image16 (fw, fh); + imgsrc->getImage (currWB, tr, oorig, pp, params.hlrecovery, params.icm); + fw *= params.resize.scale; + fh *= params.resize.scale; + baseImg = new Image16 (fw, fh); + ipf.resize (oorig, baseImg); + delete oorig; + } + if (pl) + pl->setProgress (0.25); + + // perform first analysis + unsigned int* hist16 = new unsigned int[65536]; + ipf.firstAnalysis (baseImg, ¶ms, hist16, imgsrc->getGamma()); + + // perform transform + if (ipf.needsTransform()) { + Image16* trImg = new Image16 (fw, fh); + 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; iupdate (baseImg, (unsigned short**)buffer, shradius, ipf.lumimul, params.sh.hq); + } + // RGB processing +//!!!// auto exposure!!! + double br = params.toneCurve.expcomp; + int bl = params.toneCurve.black; + + if (params.toneCurve.autoexp) { + 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); + + LabImage* labView = new LabImage (baseImg); + ipf.rgbProc (baseImg, labView, curve, shmap); + + if (shmap) + delete shmap; + + if (pl) + pl->setProgress (0.5); + + + // luminance histogram update + memset (hist16, 0, 65536*sizeof(int)); + for (int i=0; iL[i][j]]++; + + // luminance processing + 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); + CurveFactory::complexsgnCurve (0.0, 100.0, params.labCurve.saturation, 1.0, params.labCurve.acurve, curve, 1); + 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.chrominanceCurve (labView, labView, 1, curve, 0, fh); + + ipf.impulsedenoise (labView); + ipf.lumadenoise (labView, buffer); + ipf.sharpening (labView, (unsigned short**)buffer); + + delete [] curve; + delete [] hist16; + + // color processing + ipf.colorCurve (labView, labView); + ipf.colordenoise (labView, buffer); + ipf.dirpyrdenoise (labView); + + // wavelet equalizer + ipf.waveletEqualizer (labView, true, true); + + // directional pyramid equalizer + ipf.dirpyrequalizer (labView); + + for (int i=0; isetProgress (0.75); + + // obtain final image + Image16* readyImg; + int cx = 0, cy = 0, cw = labView->W, ch = labView->H; + if (params.crop.enabled) { + cx = params.crop.x; + cy = params.crop.y; + cw = params.crop.w; + ch = params.crop.h; + } + readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output); + + if (pl) + pl->setProgress (1.0); + + readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); + + ProfileContent pc; + if (params.icm.output.compare (0, 6, "No ICM") && params.icm.output!="") + pc = iccStore.getContent (params.icm.output); + + readyImg->setOutputProfile (pc.data, pc.length); + + delete baseImg; + + if (!job->initialImage) + ii->decreaseRef (); + + delete job; + + if (pl) { + pl->setProgress (1.0); + pl->setProgressStr ("Ready."); + } + + return readyImg; +} + +void batchProcessingThread (ProcessingJob* job, BatchProcessingListener* bpl) { + + ProcessingJob* currentJob = job; + + while (currentJob) { + int errorCode; + IImage16* img = processImage (currentJob, errorCode, bpl); + if (errorCode) + bpl->error ("Can not load input image."); + currentJob = bpl->imageReady (img); + } +} + +void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl) { + + if (bpl) + Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl), 0, true, true, Glib::THREAD_PRIORITY_LOW); + +} + +} diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index 6428c34e5..e73e3853b 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -1,269 +1,269 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ -#include -#include -#include -#include -#include - -BatchQueuePanel::BatchQueuePanel () { - - batchQueue = new BatchQueue(); - - // construct batch queue panel with the extra "start" and "stop" button - Gtk::VBox* batchQueueButtonBox = Gtk::manage (new Gtk::VBox); - start = Gtk::manage (new Gtk::ToggleButton (M("FILEBROWSER_STARTPROCESSING"))); - stop = Gtk::manage (new Gtk::ToggleButton (M("FILEBROWSER_STOPPROCESSING"))); - autoStart = Gtk::manage (new Gtk::CheckButton (M("BATCHQUEUE_AUTOSTART"))); - start->set_tooltip_text (M("FILEBROWSER_STARTPROCESSINGHINT")); - stop->set_tooltip_text (M("FILEBROWSER_STOPPROCESSINGHINT")); - autoStart->set_tooltip_text (M("FILEBROWSER_TOOLTIP_STOPPROCESSING")); - start->set_active (false); - stop->set_active (true); - autoStart->set_active (options.procQueueEnabled); - - 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)); - 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)); - batchQueueButtonBox->pack_start (*start, Gtk::PACK_SHRINK, 4); - batchQueueButtonBox->pack_start (*stop, Gtk::PACK_SHRINK, 4); - batchQueueButtonBox->pack_start (*autoStart, Gtk::PACK_SHRINK, 4); - - // Output directory selection - fdir = Gtk::manage (new Gtk::Frame (M("PREFERENCES_OUTDIR"))); - Gtk::VBox* odvb = Gtk::manage (new Gtk::VBox ()); - odvb->set_border_width (4); - Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ()); - useTemplate = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRTEMPLATE")+":")); - hb2->pack_start (*useTemplate, Gtk::PACK_SHRINK,4); - outdirTemplate = Gtk::manage (new Gtk::Entry ()); - hb2->pack_start (*outdirTemplate); - odvb->pack_start (*hb2, Gtk::PACK_SHRINK, 4); - outdirTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT")); - useTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT")); - Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ()); - useFolder = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRFOLDER")+":")); - hb3->pack_start (*useFolder, Gtk::PACK_SHRINK,4); - outdirFolder = Gtk::manage (new Gtk::FileChooserButton (M("PREFERENCES_OUTDIRFOLDER"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); - hb3->pack_start (*outdirFolder); - odvb->pack_start (*hb3, Gtk::PACK_SHRINK, 4); - outdirFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT")); - useFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT")); - Gtk::RadioButton::Group g = useTemplate->get_group(); - useFolder->set_group (g); - fdir->add (*odvb); - - // Output file format selection - fformat = Gtk::manage (new Gtk::Frame (M("PREFERENCES_FILEFORMAT"))); - saveFormatPanel = Gtk::manage (new SaveFormatPanel ()); - fformat->add (*saveFormatPanel); - - saveFormatPanel->init (options.saveFormat); - outdirTemplate->set_text (options.savePathTemplate); - if (Glib::file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR)) - outdirFolder->set_filename (options.savePathFolder); - useTemplate->set_active (options.saveUsePathTemplate); - useFolder->set_active (!options.saveUsePathTemplate); - - // setup signal handlers - outdirTemplate->signal_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); - outdirFolder->signal_current_folder_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::pathFolderChanged)); - useTemplate->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); - useFolder->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); - saveFormatPanel->setListener (this); - - // setup button bar - topBox = Gtk::manage (new Gtk::HBox ()); - pack_start (*topBox, Gtk::PACK_SHRINK); - - topBox->pack_start (*batchQueueButtonBox, Gtk::PACK_SHRINK, 4); - topBox->pack_start (*fdir); - topBox->pack_start (*fformat, Gtk::PACK_SHRINK, 4); - - // add middle browser area - Gtk::HBox* hBox = Gtk::manage (new Gtk::HBox ()); - pack_start (*batchQueue); - - // lower box with thumbnail zoom - bottomBox = Gtk::manage (new Gtk::HBox ()); - pack_start (*bottomBox, Gtk::PACK_SHRINK); - - // change thumbnail arrangement button - hAlignIcon = new Gtk::Image (argv0+"/images/horizontals.png"); - vAlignIcon = new Gtk::Image (argv0+"/images/verticals.png"); - hAlignIcon->show (); - vAlignIcon->show (); - chAlign = Gtk::manage (new Gtk::Button ()); - chAlign->show (); - bottomBox->pack_end (*chAlign, Gtk::PACK_SHRINK); - chAlign->set_image (*hAlignIcon); - chAlign->set_relief (Gtk::RELIEF_NONE); - chAlign->signal_pressed().connect (sigc::mem_fun(*this, &BatchQueuePanel::arrangementButtonPressed)); - chAlign->set_tooltip_text (M("FILEBROWSER_ARRANGEMENTHINT")); - bottomBox->pack_end (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); - if (options.fbArrangement==1) - chAlign->set_image (*vAlignIcon); - else - chAlign->set_image (*hAlignIcon); - arrangementButtonPressed (); - - // thumbnail zoom - Gtk::HBox* zoomBox = Gtk::manage (new Gtk::HBox ()); - zoomBox->pack_start (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); - Gtk::Label* zoomLabel = Gtk::manage (new Gtk::Label (Glib::ustring("")+M("FILEBROWSER_THUMBSIZE")+":")); - zoomLabel->set_use_markup (true); - zoomBox->pack_start (*zoomLabel, Gtk::PACK_SHRINK, 4); - 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->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomIn)); - zoomInButton->set_relief (Gtk::RELIEF_NONE); - zoomInButton->set_tooltip_text (M("FILEBROWSER_ZOOMINHINT")); - zoomBox->pack_end (*zoomInButton, Gtk::PACK_SHRINK); - 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->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomOut)); - zoomOutButton->set_relief (Gtk::RELIEF_NONE); - zoomOutButton->set_tooltip_text (M("FILEBROWSER_ZOOMOUTHINT")); - zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK); - bottomBox->pack_end (*zoomBox, Gtk::PACK_SHRINK); - - - batchQueue->setBatchQueueListener (this); - - show_all (); -} - -void BatchQueuePanel::arrangementButtonPressed () { - - if (chAlign->get_image()==hAlignIcon) { - chAlign->set_image (*vAlignIcon); - batchQueue->setArrangement (BatchQueue::TB_Vertical); - } - else { - chAlign->set_image (*hAlignIcon); - batchQueue->setArrangement (BatchQueue::TB_Horizontal); - } -} - -void BatchQueuePanel::updateTab (int qsize) -{ - Gtk::Notebook *nb =(Gtk::Notebook *)(this->get_parent()); - Gtk::HBox* hbb = Gtk::manage (new Gtk::HBox ()); - if(!qsize ){ - hbb->pack_start (*Gtk::manage (new Gtk::Image (argv0+"/images/processing.png"))); - hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE") ))); - }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::Label (M("MAIN_FRAME_BATCHQUEUE")+" [" +Glib::ustring::format( qsize )+"]" ))); - }else{ - 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->set_spacing (2); - hbb->show_all (); - nb->set_tab_label(*this,*hbb); -} - -void BatchQueuePanel::queueSizeChanged (int qsize) -{ - updateTab ( qsize); -} - -void BatchQueuePanel::imageProcessingReady (Glib::ustring fname) { - - parent->imageDeveloped (fname); -} - -void BatchQueuePanel::startBatchProc () { - - stopConnection.block (true); - startConnection.block (true); - stop->set_active (false); - start->set_active (true); - stopConnection.block (false); - startConnection.block (false); - - if (batchQueue->hasJobs()) { - fdir->set_sensitive (false); - fformat->set_sensitive (false); - saveOptions(); - batchQueue->startProcessing (); - } - else - stopBatchProc (); - updateTab (batchQueue->getEntries().size()); -} - -void BatchQueuePanel::stopBatchProc () { - - stopConnection.block (true); - startConnection.block (true); - stop->set_active (true); - start->set_active (false); - stopConnection.block (false); - startConnection.block (false); - updateTab (batchQueue->getEntries().size()); -} - -void BatchQueuePanel::addBatchQueueJob (BatchQueueEntry* bqe, bool head) { - - batchQueue->addEntry (bqe, head); - - if (stop->get_active () && autoStart->get_active ()) - startBatchProc (); -} - -void BatchQueuePanel::queueEmpty () { - - stopBatchProc (); - fdir->set_sensitive (true); - fformat->set_sensitive (true); -} - -bool BatchQueuePanel::canStartNext () { - - if (start->get_active ()) - return true; - else { - fdir->set_sensitive (true); - fformat->set_sensitive (true); - return false; - } -} - -void BatchQueuePanel::saveOptions () { - - options.savePathTemplate = outdirTemplate->get_text(); - options.saveUsePathTemplate = useTemplate->get_active(); - options.procQueueEnabled = autoStart->get_active (); -} - -// We only want to save the following when it changes, \ -// since these settings are shared with editorpanel : -void BatchQueuePanel::pathFolderChanged () { - - options.savePathFolder = outdirFolder->get_filename(); -} - -void BatchQueuePanel::formatChanged (Glib::ustring f) { - - options.saveFormat = saveFormatPanel->getFormat (); - -} +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#include +#include +#include +#include +#include + +BatchQueuePanel::BatchQueuePanel () { + + batchQueue = new BatchQueue(); + + // construct batch queue panel with the extra "start" and "stop" button + Gtk::VBox* batchQueueButtonBox = Gtk::manage (new Gtk::VBox); + start = Gtk::manage (new Gtk::ToggleButton (M("FILEBROWSER_STARTPROCESSING"))); + stop = Gtk::manage (new Gtk::ToggleButton (M("FILEBROWSER_STOPPROCESSING"))); + autoStart = Gtk::manage (new Gtk::CheckButton (M("BATCHQUEUE_AUTOSTART"))); + start->set_tooltip_text (M("FILEBROWSER_STARTPROCESSINGHINT")); + stop->set_tooltip_text (M("FILEBROWSER_STOPPROCESSINGHINT")); + autoStart->set_tooltip_text (M("FILEBROWSER_TOOLTIP_STOPPROCESSING")); + start->set_active (false); + stop->set_active (true); + autoStart->set_active (options.procQueueEnabled); + + 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)); + 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)); + batchQueueButtonBox->pack_start (*start, Gtk::PACK_SHRINK, 4); + batchQueueButtonBox->pack_start (*stop, Gtk::PACK_SHRINK, 4); + batchQueueButtonBox->pack_start (*autoStart, Gtk::PACK_SHRINK, 4); + + // Output directory selection + fdir = Gtk::manage (new Gtk::Frame (M("PREFERENCES_OUTDIR"))); + Gtk::VBox* odvb = Gtk::manage (new Gtk::VBox ()); + odvb->set_border_width (4); + Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ()); + useTemplate = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRTEMPLATE")+":")); + hb2->pack_start (*useTemplate, Gtk::PACK_SHRINK,4); + outdirTemplate = Gtk::manage (new Gtk::Entry ()); + hb2->pack_start (*outdirTemplate); + odvb->pack_start (*hb2, Gtk::PACK_SHRINK, 4); + outdirTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT")); + useTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT")); + Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ()); + useFolder = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRFOLDER")+":")); + hb3->pack_start (*useFolder, Gtk::PACK_SHRINK,4); + outdirFolder = Gtk::manage (new Gtk::FileChooserButton (M("PREFERENCES_OUTDIRFOLDER"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER)); + hb3->pack_start (*outdirFolder); + odvb->pack_start (*hb3, Gtk::PACK_SHRINK, 4); + outdirFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT")); + useFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT")); + Gtk::RadioButton::Group g = useTemplate->get_group(); + useFolder->set_group (g); + fdir->add (*odvb); + + // Output file format selection + fformat = Gtk::manage (new Gtk::Frame (M("PREFERENCES_FILEFORMAT"))); + saveFormatPanel = Gtk::manage (new SaveFormatPanel ()); + fformat->add (*saveFormatPanel); + + saveFormatPanel->init (options.saveFormat); + outdirTemplate->set_text (options.savePathTemplate); + if (Glib::file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR)) + outdirFolder->set_current_folder (options.savePathFolder); + useTemplate->set_active (options.saveUsePathTemplate); + useFolder->set_active (!options.saveUsePathTemplate); + + // setup signal handlers + outdirTemplate->signal_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); + outdirFolder->signal_current_folder_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::pathFolderChanged)); + useTemplate->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); + useFolder->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions)); + saveFormatPanel->setListener (this); + + // setup button bar + topBox = Gtk::manage (new Gtk::HBox ()); + pack_start (*topBox, Gtk::PACK_SHRINK); + + topBox->pack_start (*batchQueueButtonBox, Gtk::PACK_SHRINK, 4); + topBox->pack_start (*fdir); + topBox->pack_start (*fformat, Gtk::PACK_SHRINK, 4); + + // add middle browser area + Gtk::HBox* hBox = Gtk::manage (new Gtk::HBox ()); + pack_start (*batchQueue); + + // lower box with thumbnail zoom + bottomBox = Gtk::manage (new Gtk::HBox ()); + pack_start (*bottomBox, Gtk::PACK_SHRINK); + + // change thumbnail arrangement button + hAlignIcon = new Gtk::Image (argv0+"/images/horizontals.png"); + vAlignIcon = new Gtk::Image (argv0+"/images/verticals.png"); + hAlignIcon->show (); + vAlignIcon->show (); + chAlign = Gtk::manage (new Gtk::Button ()); + chAlign->show (); + bottomBox->pack_end (*chAlign, Gtk::PACK_SHRINK); + chAlign->set_image (*hAlignIcon); + chAlign->set_relief (Gtk::RELIEF_NONE); + chAlign->signal_pressed().connect (sigc::mem_fun(*this, &BatchQueuePanel::arrangementButtonPressed)); + chAlign->set_tooltip_text (M("FILEBROWSER_ARRANGEMENTHINT")); + bottomBox->pack_end (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); + if (options.fbArrangement==1) + chAlign->set_image (*vAlignIcon); + else + chAlign->set_image (*hAlignIcon); + arrangementButtonPressed (); + + // thumbnail zoom + Gtk::HBox* zoomBox = Gtk::manage (new Gtk::HBox ()); + zoomBox->pack_start (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4); + Gtk::Label* zoomLabel = Gtk::manage (new Gtk::Label (Glib::ustring("")+M("FILEBROWSER_THUMBSIZE")+":")); + zoomLabel->set_use_markup (true); + zoomBox->pack_start (*zoomLabel, Gtk::PACK_SHRINK, 4); + 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->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomIn)); + zoomInButton->set_relief (Gtk::RELIEF_NONE); + zoomInButton->set_tooltip_text (M("FILEBROWSER_ZOOMINHINT")); + zoomBox->pack_end (*zoomInButton, Gtk::PACK_SHRINK); + 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->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomOut)); + zoomOutButton->set_relief (Gtk::RELIEF_NONE); + zoomOutButton->set_tooltip_text (M("FILEBROWSER_ZOOMOUTHINT")); + zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK); + bottomBox->pack_end (*zoomBox, Gtk::PACK_SHRINK); + + + batchQueue->setBatchQueueListener (this); + + show_all (); +} + +void BatchQueuePanel::arrangementButtonPressed () { + + if (chAlign->get_image()==hAlignIcon) { + chAlign->set_image (*vAlignIcon); + batchQueue->setArrangement (BatchQueue::TB_Vertical); + } + else { + chAlign->set_image (*hAlignIcon); + batchQueue->setArrangement (BatchQueue::TB_Horizontal); + } +} + +void BatchQueuePanel::updateTab (int qsize) +{ + Gtk::Notebook *nb =(Gtk::Notebook *)(this->get_parent()); + Gtk::HBox* hbb = Gtk::manage (new Gtk::HBox ()); + if(!qsize ){ + hbb->pack_start (*Gtk::manage (new Gtk::Image (argv0+"/images/processing.png"))); + hbb->pack_start (*Gtk::manage (new Gtk::Label (M("MAIN_FRAME_BATCHQUEUE") ))); + }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::Label (M("MAIN_FRAME_BATCHQUEUE")+" [" +Glib::ustring::format( qsize )+"]" ))); + }else{ + 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->set_spacing (2); + hbb->show_all (); + nb->set_tab_label(*this,*hbb); +} + +void BatchQueuePanel::queueSizeChanged (int qsize) +{ + updateTab ( qsize); +} + +void BatchQueuePanel::imageProcessingReady (Glib::ustring fname) { + + parent->imageDeveloped (fname); +} + +void BatchQueuePanel::startBatchProc () { + + stopConnection.block (true); + startConnection.block (true); + stop->set_active (false); + start->set_active (true); + stopConnection.block (false); + startConnection.block (false); + + if (batchQueue->hasJobs()) { + fdir->set_sensitive (false); + fformat->set_sensitive (false); + saveOptions(); + batchQueue->startProcessing (); + } + else + stopBatchProc (); + updateTab (batchQueue->getEntries().size()); +} + +void BatchQueuePanel::stopBatchProc () { + + stopConnection.block (true); + startConnection.block (true); + stop->set_active (true); + start->set_active (false); + stopConnection.block (false); + startConnection.block (false); + updateTab (batchQueue->getEntries().size()); +} + +void BatchQueuePanel::addBatchQueueJob (BatchQueueEntry* bqe, bool head) { + + batchQueue->addEntry (bqe, head); + + if (stop->get_active () && autoStart->get_active ()) + startBatchProc (); +} + +void BatchQueuePanel::queueEmpty () { + + stopBatchProc (); + fdir->set_sensitive (true); + fformat->set_sensitive (true); +} + +bool BatchQueuePanel::canStartNext () { + + if (start->get_active ()) + return true; + else { + fdir->set_sensitive (true); + fformat->set_sensitive (true); + return false; + } +} + +void BatchQueuePanel::saveOptions () { + + options.savePathTemplate = outdirTemplate->get_text(); + options.saveUsePathTemplate = useTemplate->get_active(); + options.procQueueEnabled = autoStart->get_active (); +} + +// We only want to save the following when it changes, \ +// since these settings are shared with editorpanel : +void BatchQueuePanel::pathFolderChanged () { + + options.savePathFolder = outdirFolder->get_current_folder(); +} + +void BatchQueuePanel::formatChanged (Glib::ustring f) { + + options.saveFormat = saveFormatPanel->getFormat (); + +}