svcore  1.9
Preferences.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "Preferences.h"
00017 
00018 #include "Exceptions.h"
00019 
00020 #include "TempDirectory.h"
00021 
00022 #include <QDir>
00023 #include <QFileInfo>
00024 #include <QMutex>
00025 #include <QSettings>
00026 
00027 Preferences *
00028 Preferences::m_instance = 0;
00029 
00030 Preferences *
00031 Preferences::getInstance()
00032 {
00033     if (!m_instance) m_instance = new Preferences();
00034     return m_instance;
00035 }
00036 
00037 Preferences::Preferences() :
00038     m_spectrogramSmoothing(SpectrogramInterpolated),
00039     m_spectrogramXSmoothing(SpectrogramXInterpolated),
00040     m_tuningFrequency(440),
00041     m_propertyBoxLayout(VerticallyStacked),
00042     m_windowType(HanningWindow),
00043     m_resampleQuality(1),
00044     m_omitRecentTemps(true),
00045     m_tempDirRoot(""),
00046     m_fixedSampleRate(0),
00047     m_resampleOnLoad(false),
00048     m_normaliseAudio(false),
00049     m_viewFontSize(10),
00050     m_backgroundMode(BackgroundFromTheme),
00051     m_timeToTextMode(TimeToTextMs),
00052     m_octave(4),
00053     m_showSplash(true)
00054 {
00055     QSettings settings;
00056     settings.beginGroup("Preferences");
00057     m_spectrogramSmoothing = SpectrogramSmoothing
00058         (settings.value("spectrogram-y-smoothing", int(m_spectrogramSmoothing)).toInt());
00059     m_spectrogramXSmoothing = SpectrogramXSmoothing
00060         (settings.value("spectrogram-x-smoothing", int(m_spectrogramXSmoothing)).toInt());
00061     m_tuningFrequency = settings.value("tuning-frequency", 440.f).toDouble();
00062     m_propertyBoxLayout = PropertyBoxLayout
00063         (settings.value("property-box-layout", int(VerticallyStacked)).toInt());
00064     m_windowType = WindowType
00065         (settings.value("window-type", int(HanningWindow)).toInt());
00066     m_resampleQuality = settings.value("resample-quality", 1).toInt();
00067     m_fixedSampleRate = settings.value("fixed-sample-rate", 0).toInt();
00068     m_resampleOnLoad = settings.value("resample-on-load", false).toBool();
00069     m_normaliseAudio = settings.value("normalise-audio", false).toBool();
00070     m_backgroundMode = BackgroundMode
00071         (settings.value("background-mode", int(BackgroundFromTheme)).toInt());
00072     m_timeToTextMode = TimeToTextMode
00073         (settings.value("time-to-text-mode", int(TimeToTextMs)).toInt());
00074     m_octave = (settings.value("octave-of-middle-c", 4)).toInt();
00075     m_viewFontSize = settings.value("view-font-size", 10).toInt();
00076     m_showSplash = settings.value("show-splash", true).toBool();
00077     settings.endGroup();
00078 
00079     settings.beginGroup("TempDirectory");
00080     m_tempDirRoot = settings.value("create-in", "$HOME").toString();
00081     settings.endGroup();
00082 }
00083 
00084 Preferences::~Preferences()
00085 {
00086 }
00087 
00088 Preferences::PropertyList
00089 Preferences::getProperties() const
00090 {
00091     PropertyList props;
00092     props.push_back("Spectrogram Y Smoothing");
00093     props.push_back("Spectrogram X Smoothing");
00094     props.push_back("Tuning Frequency");
00095     props.push_back("Property Box Layout");
00096     props.push_back("Window Type");
00097     props.push_back("Resample Quality");
00098     props.push_back("Omit Temporaries from Recent Files");
00099     props.push_back("Resample On Load");
00100     props.push_back("Normalise Audio");
00101     props.push_back("Fixed Sample Rate");
00102     props.push_back("Temporary Directory Root");
00103     props.push_back("Background Mode");
00104     props.push_back("Time To Text Mode");
00105     props.push_back("Octave Numbering System");
00106     props.push_back("View Font Size");
00107     props.push_back("Show Splash Screen");
00108     return props;
00109 }
00110 
00111 QString
00112 Preferences::getPropertyLabel(const PropertyName &name) const
00113 {
00114     if (name == "Spectrogram Y Smoothing") {
00115         return tr("Spectrogram y-axis interpolation:");
00116     }
00117     if (name == "Spectrogram X Smoothing") {
00118         return tr("Spectrogram x-axis interpolation:");
00119     }
00120     if (name == "Tuning Frequency") {
00121         return tr("Frequency of concert A");
00122     }
00123     if (name == "Property Box Layout") {
00124         return tr("Property box layout");
00125     }
00126     if (name == "Window Type") {
00127         return tr("Spectral analysis window shape");
00128     }
00129     if (name == "Resample Quality") {
00130         return tr("Playback resampler type");
00131     }
00132     if (name == "Normalise Audio") {
00133         return tr("Normalise audio signal when reading from audio file");
00134     }
00135     if (name == "Omit Temporaries from Recent Files") {
00136         return tr("Omit temporaries from Recent Files menu");
00137     }
00138     if (name == "Resample On Load") {
00139         return tr("Resample mismatching files on import");
00140     }
00141     if (name == "Fixed Sample Rate") {
00142         return tr("Single fixed sample rate to resample all files to");
00143     }
00144     if (name == "Temporary Directory Root") {
00145         return tr("Location for cache file directory");
00146     }
00147     if (name == "Background Mode") {
00148         return tr("Background colour preference");
00149     }
00150     if (name == "Time To Text Mode") {
00151         return tr("Time display format");
00152     }
00153     if (name == "Octave Numbering System") {
00154         return tr("Label middle C as");
00155     }
00156     if (name == "View Font Size") {
00157         return tr("Font size for text overlays");
00158     }
00159     if (name == "Show Splash Screen") {
00160         return tr("Show splash screen on startup");
00161     }
00162     return name;
00163 }
00164 
00165 Preferences::PropertyType
00166 Preferences::getPropertyType(const PropertyName &name) const
00167 {
00168     if (name == "Spectrogram Y Smoothing") {
00169         return ValueProperty;
00170     }
00171     if (name == "Spectrogram X Smoothing") {
00172         return ValueProperty;
00173     }
00174     if (name == "Tuning Frequency") {
00175         return RangeProperty;
00176     }
00177     if (name == "Property Box Layout") {
00178         return ValueProperty;
00179     }
00180     if (name == "Window Type") {
00181         return ValueProperty;
00182     }
00183     if (name == "Resample Quality") {
00184         return ValueProperty;
00185     }
00186     if (name == "Normalise Audio") {
00187         return ToggleProperty;
00188     }
00189     if (name == "Omit Temporaries from Recent Files") {
00190         return ToggleProperty;
00191     }
00192     if (name == "Resample On Load") {
00193         return ToggleProperty;
00194     }
00195     if (name == "Fixed Sample Rate") {
00196         return ValueProperty;
00197     }
00198     if (name == "Temporary Directory Root") {
00199         // It's an arbitrary string, we don't have a set of values for this
00200         return InvalidProperty;
00201     }
00202     if (name == "Background Mode") {
00203         return ValueProperty;
00204     }
00205     if (name == "Time To Text Mode") {
00206         return ValueProperty;
00207     }
00208     if (name == "Octave Numbering System") {
00209         return ValueProperty;
00210     }
00211     if (name == "View Font Size") {
00212         return RangeProperty;
00213     }
00214     if (name == "Show Splash Screen") {
00215         return ToggleProperty;
00216     }
00217     return InvalidProperty;
00218 }
00219 
00220 int
00221 Preferences::getPropertyRangeAndValue(const PropertyName &name,
00222                                       int *min, int *max, int *deflt) const
00223 {
00224     if (name == "Spectrogram Y Smoothing") {
00225         if (min) *min = 0;
00226         if (max) *max = 3;
00227         if (deflt) *deflt = int(SpectrogramInterpolated);
00228         return int(m_spectrogramSmoothing);
00229     }
00230     if (name == "Spectrogram X Smoothing") {
00231         if (min) *min = 0;
00232         if (max) *max = 1;
00233         if (deflt) *deflt = int(SpectrogramXInterpolated);
00234         return int(m_spectrogramXSmoothing);
00235     }
00236 
00238 
00239     if (name == "Property Box Layout") {
00240         if (min) *min = 0;
00241         if (max) *max = 1;
00242         if (deflt) *deflt = 0;
00243         return m_propertyBoxLayout == Layered ? 1 : 0;
00244     }        
00245 
00246     if (name == "Window Type") {
00247         if (min) *min = int(RectangularWindow);
00248         if (max) *max = int(BlackmanHarrisWindow);
00249         if (deflt) *deflt = int(HanningWindow);
00250         return int(m_windowType);
00251     }
00252 
00253     if (name == "Resample Quality") {
00254         if (min) *min = 0;
00255         if (max) *max = 2;
00256         if (deflt) *deflt = 1;
00257         return m_resampleQuality;
00258     }
00259 
00260     if (name == "Omit Temporaries from Recent Files") {
00261         if (deflt) *deflt = 1;
00262     }
00263 
00264     if (name == "Background Mode") {
00265         if (min) *min = 0;
00266         if (max) *max = 2;
00267         if (deflt) *deflt = 0;
00268         return int(m_backgroundMode);
00269     }        
00270 
00271     if (name == "Time To Text Mode") {
00272         if (min) *min = 0;
00273         if (max) *max = 6;
00274         if (deflt) *deflt = 0;
00275         return int(m_timeToTextMode);
00276     }        
00277 
00278     if (name == "Octave Numbering System") {
00279         // we don't support arbitrary octaves in the gui, because we
00280         // want to be able to label what the octave system comes
00281         // from. so we support 0, 3, 4 and 5.
00282         if (min) *min = 0;
00283         if (max) *max = 3;
00284         if (deflt) *deflt = 2;
00285         return int(getSystemWithMiddleCInOctave(m_octave));
00286     }
00287 
00288     if (name == "View Font Size") {
00289         if (min) *min = 3;
00290         if (max) *max = 48;
00291         if (deflt) *deflt = 10;
00292         return int(m_viewFontSize);
00293     }
00294 
00295     if (name == "Show Splash Screen") {
00296         if (deflt) *deflt = 1;
00297     }
00298 
00299     return 0;
00300 }
00301 
00302 QString
00303 Preferences::getPropertyValueLabel(const PropertyName &name,
00304                                    int value) const
00305 {
00306     if (name == "Property Box Layout") {
00307         if (value == 0) return tr("Show boxes for all panes");
00308         else return tr("Show box for current pane only");
00309     }
00310     if (name == "Window Type") {
00311         switch (WindowType(value)) {
00312         case RectangularWindow: return tr("Rectangular");
00313         case BartlettWindow: return tr("Triangular");
00314         case HammingWindow: return tr("Hamming");
00315         case HanningWindow: return tr("Hann");
00316         case BlackmanWindow: return tr("Blackman");
00317         case GaussianWindow: return tr("Gaussian");
00318         case ParzenWindow: return tr("Parzen");
00319         case NuttallWindow: return tr("Nuttall");
00320         case BlackmanHarrisWindow: return tr("Blackman-Harris");
00321         }
00322     }
00323     if (name == "Resample Quality") {
00324         switch (value) {
00325         case 0: return tr("Fastest");
00326         case 1: return tr("Standard");
00327         case 2: return tr("Highest quality");
00328         }
00329     }
00330     if (name == "Spectrogram Y Smoothing") {
00331         switch (value) {
00332         case NoSpectrogramSmoothing: return tr("None");
00333         case SpectrogramInterpolated: return tr("Linear interpolation");
00334         case SpectrogramZeroPadded: return tr("4 x Oversampling");
00335         case SpectrogramZeroPaddedAndInterpolated: return tr("4 x Oversampling with interpolation");
00336         }
00337     }
00338     if (name == "Spectrogram X Smoothing") {
00339         switch (value) {
00340         case NoSpectrogramXSmoothing: return tr("None");
00341         case SpectrogramXInterpolated: return tr("Linear interpolation");
00342         }
00343     }
00344     if (name == "Background Mode") {
00345         switch (value) {
00346         case BackgroundFromTheme: return tr("Follow desktop theme");
00347         case DarkBackground: return tr("Dark background");
00348         case LightBackground: return tr("Light background");
00349         }
00350     }
00351     if (name == "Time To Text Mode") {
00352         switch (value) {
00353         case TimeToTextMs: return tr("Standard (to millisecond)");
00354         case TimeToTextUs: return tr("High resolution (to microsecond)");
00355         case TimeToText24Frame: return tr("24 FPS");
00356         case TimeToText25Frame: return tr("25 FPS");
00357         case TimeToText30Frame: return tr("30 FPS");
00358         case TimeToText50Frame: return tr("50 FPS");
00359         case TimeToText60Frame: return tr("60 FPS");
00360         }
00361     }
00362     if (name == "Octave Numbering System") {
00363         switch (value) {
00364         case C0_Centre: return tr("C0 - middle of octave scale");
00365         case C3_Logic: return tr("C3 - common MIDI sequencer convention");
00366         case C4_ASA: return tr("C4 - ASA American standard");
00367         case C5_Sonar: return tr("C5 - used in Cakewalk and others");
00368         }
00369     }
00370             
00371     return "";
00372 }
00373 
00374 QString
00375 Preferences::getPropertyContainerName() const
00376 {
00377     return tr("Preferences");
00378 }
00379 
00380 QString
00381 Preferences::getPropertyContainerIconName() const
00382 {
00383     return "preferences";
00384 }
00385 
00386 void
00387 Preferences::setProperty(const PropertyName &name, int value) 
00388 {
00389     if (name == "Spectrogram Y Smoothing") {
00390         setSpectrogramSmoothing(SpectrogramSmoothing(value));
00391     } else if (name == "Spectrogram X Smoothing") {
00392         setSpectrogramXSmoothing(SpectrogramXSmoothing(value));
00393     } else if (name == "Tuning Frequency") {
00395     } else if (name == "Property Box Layout") {
00396         setPropertyBoxLayout(value == 0 ? VerticallyStacked : Layered);
00397     } else if (name == "Window Type") {
00398         setWindowType(WindowType(value));
00399     } else if (name == "Resample Quality") {
00400         setResampleQuality(value);
00401     } else if (name == "Omit Temporaries from Recent Files") {
00402         setOmitTempsFromRecentFiles(value ? true : false);
00403     } else if (name == "Background Mode") {
00404         setBackgroundMode(BackgroundMode(value));
00405     } else if (name == "Time To Text Mode") {
00406         setTimeToTextMode(TimeToTextMode(value));
00407     } else if (name == "Octave Numbering System") {
00408         setOctaveOfMiddleC(getOctaveOfMiddleCInSystem
00409                            (OctaveNumberingSystem(value)));
00410     } else if (name == "View Font Size") {
00411         setViewFontSize(value);
00412     } else if (name == "Show Splash Screen") {
00413         setShowSplash(value ? true : false);
00414     }
00415 }
00416 
00417 void
00418 Preferences::setSpectrogramSmoothing(SpectrogramSmoothing smoothing)
00419 {
00420     if (m_spectrogramSmoothing != smoothing) {
00421 
00422         // "smoothing" is one of those words that looks increasingly
00423         // ridiculous the more you see it.  Smoothing smoothing smoothing.
00424         m_spectrogramSmoothing = smoothing;
00425 
00426         QSettings settings;
00427         settings.beginGroup("Preferences");
00428         settings.setValue("spectrogram-y-smoothing", int(smoothing));
00429         settings.endGroup();
00430         emit propertyChanged("Spectrogram Y Smoothing");
00431     }
00432 }
00433 
00434 void
00435 Preferences::setSpectrogramXSmoothing(SpectrogramXSmoothing smoothing)
00436 {
00437     if (m_spectrogramXSmoothing != smoothing) {
00438 
00439         // "smoothing" is one of those words that looks increasingly
00440         // ridiculous the more you see it.  Smoothing smoothing smoothing.
00441         m_spectrogramXSmoothing = smoothing;
00442 
00443         QSettings settings;
00444         settings.beginGroup("Preferences");
00445         settings.setValue("spectrogram-x-smoothing", int(smoothing));
00446         settings.endGroup();
00447         emit propertyChanged("Spectrogram X Smoothing");
00448     }
00449 }
00450 
00451 void
00452 Preferences::setTuningFrequency(float freq)
00453 {
00454     if (m_tuningFrequency != freq) {
00455         m_tuningFrequency = freq;
00456         QSettings settings;
00457         settings.beginGroup("Preferences");
00458         settings.setValue("tuning-frequency", freq);
00459         settings.endGroup();
00460         emit propertyChanged("Tuning Frequency");
00461     }
00462 }
00463 
00464 void
00465 Preferences::setPropertyBoxLayout(PropertyBoxLayout layout)
00466 {
00467     if (m_propertyBoxLayout != layout) {
00468         m_propertyBoxLayout = layout;
00469         QSettings settings;
00470         settings.beginGroup("Preferences");
00471         settings.setValue("property-box-layout", int(layout));
00472         settings.endGroup();
00473         emit propertyChanged("Property Box Layout");
00474     }
00475 }
00476 
00477 void
00478 Preferences::setWindowType(WindowType type)
00479 {
00480     if (m_windowType != type) {
00481         m_windowType = type;
00482         QSettings settings;
00483         settings.beginGroup("Preferences");
00484         settings.setValue("window-type", int(type));
00485         settings.endGroup();
00486         emit propertyChanged("Window Type");
00487     }
00488 }
00489 
00490 void
00491 Preferences::setResampleQuality(int q)
00492 {
00493     if (m_resampleQuality != q) {
00494         m_resampleQuality = q;
00495         QSettings settings;
00496         settings.beginGroup("Preferences");
00497         settings.setValue("resample-quality", q);
00498         settings.endGroup();
00499         emit propertyChanged("Resample Quality");
00500     }
00501 }
00502 
00503 void
00504 Preferences::setOmitTempsFromRecentFiles(bool omit)
00505 {
00506     if (m_omitRecentTemps != omit) {
00507         m_omitRecentTemps = omit;
00508         QSettings settings;
00509         settings.beginGroup("Preferences");
00510         settings.setValue("omit-recent-temporaries", omit);
00511         settings.endGroup();
00512         emit propertyChanged("Omit Temporaries from Recent Files");
00513     }
00514 }
00515 
00516 void
00517 Preferences::setTemporaryDirectoryRoot(QString root)
00518 {
00519     if (root == QDir::home().absolutePath()) {
00520         root = "$HOME";
00521     }
00522     if (m_tempDirRoot != root) {
00523         m_tempDirRoot = root;
00524         QSettings settings;
00525         settings.beginGroup("TempDirectory");
00526         settings.setValue("create-in", root);
00527         settings.endGroup();
00528         emit propertyChanged("Temporary Directory Root");
00529     }
00530 }
00531 
00532 void
00533 Preferences::setResampleOnLoad(bool resample)
00534 {
00535     if (m_resampleOnLoad != resample) {
00536         m_resampleOnLoad = resample;
00537         QSettings settings;
00538         settings.beginGroup("Preferences");
00539         settings.setValue("resample-on-load", resample);
00540         settings.endGroup();
00541         emit propertyChanged("Resample On Load");
00542     }
00543 }
00544 
00545 void
00546 Preferences::setFixedSampleRate(int rate)
00547 {
00548     if (m_fixedSampleRate != rate) {
00549         m_fixedSampleRate = rate;
00550         QSettings settings;
00551         settings.beginGroup("Preferences");
00552         settings.setValue("fixed-sample-rate", rate);
00553         settings.endGroup();
00554         emit propertyChanged("Fixed Sample Rate");
00555     }
00556 }
00557 
00558 void
00559 Preferences::setNormaliseAudio(bool norm)
00560 {
00561     if (m_normaliseAudio != norm) {
00562         m_normaliseAudio = norm;
00563         QSettings settings;
00564         settings.beginGroup("Preferences");
00565         settings.setValue("normalise-audio", norm);
00566         settings.endGroup();
00567         emit propertyChanged("Normalise Audio");
00568     }
00569 }
00570 
00571 void
00572 Preferences::setBackgroundMode(BackgroundMode mode)
00573 {
00574     if (m_backgroundMode != mode) {
00575 
00576         m_backgroundMode = mode;
00577 
00578         QSettings settings;
00579         settings.beginGroup("Preferences");
00580         settings.setValue("background-mode", int(mode));
00581         settings.endGroup();
00582         emit propertyChanged("Background Mode");
00583     }
00584 }
00585 
00586 void
00587 Preferences::setTimeToTextMode(TimeToTextMode mode)
00588 {
00589     if (m_timeToTextMode != mode) {
00590 
00591         m_timeToTextMode = mode;
00592 
00593         QSettings settings;
00594         settings.beginGroup("Preferences");
00595         settings.setValue("time-to-text-mode", int(mode));
00596         settings.endGroup();
00597         emit propertyChanged("Time To Text Mode");
00598     }
00599 }
00600 
00601 void
00602 Preferences::setOctaveOfMiddleC(int oct)
00603 {
00604     if (m_octave != oct) {
00605 
00606         m_octave = oct;
00607 
00608         QSettings settings;
00609         settings.beginGroup("Preferences");
00610         settings.setValue("octave-of-middle-c", int(oct));
00611         settings.endGroup();
00612         emit propertyChanged("Octave Numbering System");
00613     }
00614 }
00615 
00616 int
00617 Preferences::getOctaveOfMiddleCInSystem(OctaveNumberingSystem s)
00618 {
00619     switch (s) {
00620     case C0_Centre: return 0;
00621     case C3_Logic: return 3;
00622     case C4_ASA: return 4;
00623     case C5_Sonar: return 5;
00624     default: return 4;
00625     }
00626 }
00627 
00628 Preferences::OctaveNumberingSystem
00629 Preferences::getSystemWithMiddleCInOctave(int o)
00630 {
00631     switch (o) {
00632     case 0: return C0_Centre;
00633     case 3: return C3_Logic;
00634     case 4: return C4_ASA;
00635     case 5: return C5_Sonar;
00636     default: return C4_ASA;
00637     }
00638 }
00639 
00640 void
00641 Preferences::setViewFontSize(int size)
00642 {
00643     if (m_viewFontSize != size) {
00644 
00645         m_viewFontSize = size;
00646 
00647         QSettings settings;
00648         settings.beginGroup("Preferences");
00649         settings.setValue("view-font-size", size);
00650         settings.endGroup();
00651         emit propertyChanged("View Font Size");
00652     }
00653 }
00654 
00655 void
00656 Preferences::setShowSplash(bool show) 
00657 {
00658     if (m_showSplash != show) {
00659 
00660         m_showSplash = show;
00661 
00662         QSettings settings;
00663         settings.beginGroup("Preferences");
00664         settings.setValue("show-splash", show);
00665         settings.endGroup();
00666         emit propertyChanged("Show Splash Screen");
00667     }
00668 }
00669