| Chris@136 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| Chris@136 | 2 | 
| Chris@136 | 3 /* | 
| Chris@136 | 4     Sonic Visualiser | 
| Chris@136 | 5     An audio file viewer and annotation editor. | 
| Chris@136 | 6     Centre for Digital Music, Queen Mary, University of London. | 
| Chris@202 | 7     This file copyright 2006 Chris Cannam and QMUL. | 
| Chris@136 | 8 | 
| Chris@136 | 9     This program is free software; you can redistribute it and/or | 
| Chris@136 | 10     modify it under the terms of the GNU General Public License as | 
| Chris@136 | 11     published by the Free Software Foundation; either version 2 of the | 
| Chris@136 | 12     License, or (at your option) any later version.  See the file | 
| Chris@136 | 13     COPYING included with this distribution for more information. | 
| Chris@136 | 14 */ | 
| Chris@136 | 15 | 
| Chris@136 | 16 #include "Preferences.h" | 
| Chris@136 | 17 | 
| Chris@145 | 18 #include "Exceptions.h" | 
| Chris@145 | 19 | 
| Chris@145 | 20 #include "TempDirectory.h" | 
| Chris@145 | 21 | 
| Chris@145 | 22 #include <QDir> | 
| Chris@145 | 23 #include <QFileInfo> | 
| Chris@156 | 24 #include <QMutex> | 
| Chris@156 | 25 #include <QSettings> | 
| Chris@145 | 26 | 
| Chris@136 | 27 Preferences * | 
| Chris@156 | 28 Preferences::m_instance = 0; | 
| Chris@156 | 29 | 
| Chris@156 | 30 Preferences * | 
| Chris@156 | 31 Preferences::getInstance() | 
| Chris@156 | 32 { | 
| Chris@156 | 33     if (!m_instance) m_instance = new Preferences(); | 
| Chris@156 | 34     return m_instance; | 
| Chris@156 | 35 } | 
| Chris@136 | 36 | 
| Chris@136 | 37 Preferences::Preferences() : | 
| Chris@246 | 38     m_spectrogramSmoothing(SpectrogramZeroPadded), | 
| Chris@140 | 39     m_tuningFrequency(440), | 
| Chris@140 | 40     m_propertyBoxLayout(VerticallyStacked), | 
| Chris@164 | 41     m_windowType(HanningWindow), | 
| Chris@164 | 42     m_resampleQuality(1) | 
| Chris@136 | 43 { | 
| Chris@156 | 44     QSettings settings; | 
| Chris@156 | 45     settings.beginGroup("Preferences"); | 
| Chris@246 | 46     m_spectrogramSmoothing = SpectrogramSmoothing | 
| Chris@246 | 47         (settings.value("spectrogram-smoothing", int(m_spectrogramSmoothing)).toInt()); | 
| Chris@156 | 48     m_tuningFrequency = settings.value("tuning-frequency", 440.f).toDouble(); | 
| Chris@145 | 49     m_propertyBoxLayout = PropertyBoxLayout | 
| Chris@156 | 50         (settings.value("property-box-layout", int(VerticallyStacked)).toInt()); | 
| Chris@145 | 51     m_windowType = WindowType | 
| Chris@156 | 52         (settings.value("window-type", int(HanningWindow)).toInt()); | 
| Chris@164 | 53     m_resampleQuality = settings.value("resample-quality", 1).toInt(); | 
| Chris@156 | 54     settings.endGroup(); | 
| Chris@145 | 55 } | 
| Chris@145 | 56 | 
| Chris@145 | 57 Preferences::~Preferences() | 
| Chris@145 | 58 { | 
| Chris@136 | 59 } | 
| Chris@136 | 60 | 
| Chris@136 | 61 Preferences::PropertyList | 
| Chris@136 | 62 Preferences::getProperties() const | 
| Chris@136 | 63 { | 
| Chris@136 | 64     PropertyList props; | 
| Chris@246 | 65     props.push_back("Spectrogram Smoothing"); | 
| Chris@136 | 66     props.push_back("Tuning Frequency"); | 
| Chris@138 | 67     props.push_back("Property Box Layout"); | 
| Chris@140 | 68     props.push_back("Window Type"); | 
| Chris@164 | 69     props.push_back("Resample Quality"); | 
| Chris@136 | 70     return props; | 
| Chris@136 | 71 } | 
| Chris@136 | 72 | 
| Chris@136 | 73 QString | 
| Chris@136 | 74 Preferences::getPropertyLabel(const PropertyName &name) const | 
| Chris@136 | 75 { | 
| Chris@246 | 76     if (name == "Spectrogram Smoothing") { | 
| Chris@246 | 77         return tr("Spectrogram y-axis smoothing:"); | 
| Chris@136 | 78     } | 
| Chris@136 | 79     if (name == "Tuning Frequency") { | 
| Chris@141 | 80         return tr("Frequency of concert A"); | 
| Chris@136 | 81     } | 
| Chris@138 | 82     if (name == "Property Box Layout") { | 
| Chris@141 | 83         return tr("Property box layout"); | 
| Chris@138 | 84     } | 
| Chris@140 | 85     if (name == "Window Type") { | 
| Chris@141 | 86         return tr("Spectral analysis window shape"); | 
| Chris@140 | 87     } | 
| Chris@164 | 88     if (name == "Resample Quality") { | 
| Chris@165 | 89         return tr("Playback resampler type"); | 
| Chris@164 | 90     } | 
| Chris@136 | 91     return name; | 
| Chris@136 | 92 } | 
| Chris@136 | 93 | 
| Chris@136 | 94 Preferences::PropertyType | 
| Chris@136 | 95 Preferences::getPropertyType(const PropertyName &name) const | 
| Chris@136 | 96 { | 
| Chris@246 | 97     if (name == "Spectrogram Smoothing") { | 
| Chris@246 | 98         return ValueProperty; | 
| Chris@136 | 99     } | 
| Chris@136 | 100     if (name == "Tuning Frequency") { | 
| Chris@136 | 101         return RangeProperty; | 
| Chris@136 | 102     } | 
| Chris@138 | 103     if (name == "Property Box Layout") { | 
| Chris@138 | 104         return ValueProperty; | 
| Chris@138 | 105     } | 
| Chris@140 | 106     if (name == "Window Type") { | 
| Chris@140 | 107         return ValueProperty; | 
| Chris@140 | 108     } | 
| Chris@164 | 109     if (name == "Resample Quality") { | 
| Chris@164 | 110         return ValueProperty; | 
| Chris@164 | 111     } | 
| Chris@136 | 112     return InvalidProperty; | 
| Chris@136 | 113 } | 
| Chris@136 | 114 | 
| Chris@136 | 115 int | 
| Chris@136 | 116 Preferences::getPropertyRangeAndValue(const PropertyName &name, | 
| Chris@245 | 117                                       int *min, int *max, int *deflt) const | 
| Chris@136 | 118 { | 
| Chris@246 | 119     if (name == "Spectrogram Smoothing") { | 
| Chris@136 | 120         if (min) *min = 0; | 
| Chris@246 | 121         if (max) *max = 2; | 
| Chris@246 | 122         if (deflt) *deflt = int(SpectrogramZeroPadded); | 
| Chris@246 | 123         return int(m_spectrogramSmoothing); | 
| Chris@136 | 124     } | 
| Chris@136 | 125 | 
| Chris@136 | 126     //!!! freq mapping | 
| Chris@136 | 127 | 
| Chris@138 | 128     if (name == "Property Box Layout") { | 
| Chris@138 | 129         if (min) *min = 0; | 
| Chris@138 | 130         if (max) *max = 1; | 
| Chris@245 | 131         if (deflt) *deflt = 0; | 
| Chris@138 | 132         return m_propertyBoxLayout == Layered ? 1 : 0; | 
| Chris@138 | 133     } | 
| Chris@138 | 134 | 
| Chris@140 | 135     if (name == "Window Type") { | 
| Chris@140 | 136         if (min) *min = int(RectangularWindow); | 
| Chris@142 | 137         if (max) *max = int(BlackmanHarrisWindow); | 
| Chris@245 | 138         if (deflt) *deflt = int(HanningWindow); | 
| Chris@140 | 139         return int(m_windowType); | 
| Chris@140 | 140     } | 
| Chris@140 | 141 | 
| Chris@164 | 142     if (name == "Resample Quality") { | 
| Chris@164 | 143         if (min) *min = 0; | 
| Chris@164 | 144         if (max) *max = 2; | 
| Chris@245 | 145         if (deflt) *deflt = 1; | 
| Chris@164 | 146         return m_resampleQuality; | 
| Chris@164 | 147     } | 
| Chris@164 | 148 | 
| Chris@136 | 149     return 0; | 
| Chris@136 | 150 } | 
| Chris@136 | 151 | 
| Chris@136 | 152 QString | 
| Chris@136 | 153 Preferences::getPropertyValueLabel(const PropertyName &name, | 
| Chris@136 | 154                                    int value) const | 
| Chris@136 | 155 { | 
| Chris@138 | 156     if (name == "Property Box Layout") { | 
| Chris@141 | 157         if (value == 0) return tr("Show boxes for all panes"); | 
| Chris@141 | 158         else return tr("Show box for current pane only"); | 
| Chris@138 | 159     } | 
| Chris@140 | 160     if (name == "Window Type") { | 
| Chris@140 | 161         switch (WindowType(value)) { | 
| Chris@140 | 162         case RectangularWindow: return tr("Rectangular"); | 
| Chris@141 | 163         case BartlettWindow: return tr("Triangular"); | 
| Chris@140 | 164         case HammingWindow: return tr("Hamming"); | 
| Chris@140 | 165         case HanningWindow: return tr("Hanning"); | 
| Chris@140 | 166         case BlackmanWindow: return tr("Blackman"); | 
| Chris@140 | 167         case GaussianWindow: return tr("Gaussian"); | 
| Chris@140 | 168         case ParzenWindow: return tr("Parzen"); | 
| Chris@142 | 169         case NuttallWindow: return tr("Nuttall"); | 
| Chris@142 | 170         case BlackmanHarrisWindow: return tr("Blackman-Harris"); | 
| Chris@140 | 171         } | 
| Chris@140 | 172     } | 
| Chris@164 | 173     if (name == "Resample Quality") { | 
| Chris@164 | 174         switch (value) { | 
| Chris@164 | 175         case 0: return tr("Fastest"); | 
| Chris@165 | 176         case 1: return tr("Standard"); | 
| Chris@164 | 177         case 2: return tr("Highest quality"); | 
| Chris@164 | 178         } | 
| Chris@164 | 179     } | 
| Chris@246 | 180     if (name == "Spectrogram Smoothing") { | 
| Chris@246 | 181         switch (value) { | 
| Chris@246 | 182         case NoSpectrogramSmoothing: return tr("None - blocky but accurate"); | 
| Chris@246 | 183         case SpectrogramInterpolated: return tr("Interpolate - fast but fuzzy"); | 
| Chris@246 | 184         case SpectrogramZeroPadded: return tr("Zero pad FFT - slow but clear"); | 
| Chris@246 | 185         } | 
| Chris@246 | 186     } | 
| Chris@246 | 187 | 
| Chris@136 | 188     return ""; | 
| Chris@136 | 189 } | 
| Chris@136 | 190 | 
| Chris@136 | 191 QString | 
| Chris@136 | 192 Preferences::getPropertyContainerName() const | 
| Chris@136 | 193 { | 
| Chris@136 | 194     return tr("Preferences"); | 
| Chris@136 | 195 } | 
| Chris@136 | 196 | 
| Chris@136 | 197 QString | 
| Chris@136 | 198 Preferences::getPropertyContainerIconName() const | 
| Chris@136 | 199 { | 
| Chris@136 | 200     return "preferences"; | 
| Chris@136 | 201 } | 
| Chris@136 | 202 | 
| Chris@136 | 203 void | 
| Chris@136 | 204 Preferences::setProperty(const PropertyName &name, int value) | 
| Chris@136 | 205 { | 
| Chris@246 | 206     if (name == "Spectrogram Smoothing") { | 
| Chris@246 | 207         setSpectrogramSmoothing(SpectrogramSmoothing(value)); | 
| Chris@136 | 208     } else if (name == "Tuning Frequency") { | 
| Chris@136 | 209         //!!! | 
| Chris@138 | 210     } else if (name == "Property Box Layout") { | 
| Chris@138 | 211         setPropertyBoxLayout(value == 0 ? VerticallyStacked : Layered); | 
| Chris@140 | 212     } else if (name == "Window Type") { | 
| Chris@140 | 213         setWindowType(WindowType(value)); | 
| Chris@164 | 214     } else if (name == "Resample Quality") { | 
| Chris@164 | 215         setResampleQuality(value); | 
| Chris@136 | 216     } | 
| Chris@136 | 217 } | 
| Chris@136 | 218 | 
| Chris@136 | 219 void | 
| Chris@246 | 220 Preferences::setSpectrogramSmoothing(SpectrogramSmoothing smoothing) | 
| Chris@136 | 221 { | 
| Chris@246 | 222     if (m_spectrogramSmoothing != smoothing) { | 
| Chris@246 | 223 | 
| Chris@246 | 224         // "smoothing" is one of those words that looks increasingly | 
| Chris@246 | 225         // ridiculous the more you see it.  Smoothing smoothing smoothing. | 
| Chris@246 | 226         m_spectrogramSmoothing = smoothing; | 
| Chris@246 | 227 | 
| Chris@156 | 228         QSettings settings; | 
| Chris@156 | 229         settings.beginGroup("Preferences"); | 
| Chris@246 | 230         settings.setValue("spectrogram-smoothing", int(smoothing)); | 
| Chris@156 | 231         settings.endGroup(); | 
| Chris@246 | 232         emit propertyChanged("Spectrogram Smoothing"); | 
| Chris@138 | 233     } | 
| Chris@136 | 234 } | 
| Chris@136 | 235 | 
| Chris@136 | 236 void | 
| Chris@136 | 237 Preferences::setTuningFrequency(float freq) | 
| Chris@136 | 238 { | 
| Chris@138 | 239     if (m_tuningFrequency != freq) { | 
| Chris@138 | 240         m_tuningFrequency = freq; | 
| Chris@156 | 241         QSettings settings; | 
| Chris@156 | 242         settings.beginGroup("Preferences"); | 
| Chris@156 | 243         settings.setValue("tuning-frequency", freq); | 
| Chris@156 | 244         settings.endGroup(); | 
| Chris@141 | 245         emit propertyChanged("Tuning Frequency"); | 
| Chris@138 | 246     } | 
| Chris@136 | 247 } | 
| Chris@136 | 248 | 
| Chris@138 | 249 void | 
| Chris@138 | 250 Preferences::setPropertyBoxLayout(PropertyBoxLayout layout) | 
| Chris@138 | 251 { | 
| Chris@138 | 252     if (m_propertyBoxLayout != layout) { | 
| Chris@138 | 253         m_propertyBoxLayout = layout; | 
| Chris@156 | 254         QSettings settings; | 
| Chris@156 | 255         settings.beginGroup("Preferences"); | 
| Chris@156 | 256         settings.setValue("property-box-layout", int(layout)); | 
| Chris@156 | 257         settings.endGroup(); | 
| Chris@141 | 258         emit propertyChanged("Property Box Layout"); | 
| Chris@138 | 259     } | 
| Chris@138 | 260 } | 
| Chris@138 | 261 | 
| Chris@140 | 262 void | 
| Chris@140 | 263 Preferences::setWindowType(WindowType type) | 
| Chris@140 | 264 { | 
| Chris@140 | 265     if (m_windowType != type) { | 
| Chris@140 | 266         m_windowType = type; | 
| Chris@156 | 267         QSettings settings; | 
| Chris@156 | 268         settings.beginGroup("Preferences"); | 
| Chris@156 | 269         settings.setValue("window-type", int(type)); | 
| Chris@156 | 270         settings.endGroup(); | 
| Chris@141 | 271         emit propertyChanged("Window Type"); | 
| Chris@140 | 272     } | 
| Chris@140 | 273 } | 
| Chris@140 | 274 | 
| Chris@164 | 275 void | 
| Chris@164 | 276 Preferences::setResampleQuality(int q) | 
| Chris@164 | 277 { | 
| Chris@164 | 278     if (m_resampleQuality != q) { | 
| Chris@164 | 279         m_resampleQuality = q; | 
| Chris@164 | 280         QSettings settings; | 
| Chris@164 | 281         settings.beginGroup("Preferences"); | 
| Chris@164 | 282         settings.setValue("resample-quality", q); | 
| Chris@164 | 283         settings.endGroup(); | 
| Chris@164 | 284         emit propertyChanged("Resample Quality"); | 
| Chris@164 | 285     } | 
| Chris@164 | 286 } |