camerauis/cameraxui/cxengine/src/cxesettingsimp.cpp
branchRCL_3
changeset 54 bac7acad7cb3
parent 53 61bc0f252b2b
child 57 2c87b2808fd7
equal deleted inserted replaced
53:61bc0f252b2b 54:bac7acad7cb3
     1 /*
       
     2 * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 /*
       
    18 * Symbian specific settings handling
       
    19 */
       
    20 
       
    21 #include <QCoreApplication>
       
    22 #include <QVariant>
       
    23 #include <QList>
       
    24 #include <QMetaType>
       
    25 #include <QObject>
       
    26 
       
    27 #include "cxesettingsimp.h"
       
    28 #include "cxutils.h"
       
    29 #include "cxenamespace.h"
       
    30 #include "cxeerror.h"
       
    31 #include "cxesettingsstore.h"
       
    32 #include "cxeexception.h"
       
    33 
       
    34 #ifdef Q_OS_SYMBIAN
       
    35 #include "OstTraceDefinitions.h"
       
    36 #ifdef OST_TRACE_COMPILER_IN_USE
       
    37 #include "cxesettingsimpTraces.h"
       
    38 #endif
       
    39 #endif // Q_OS_SYMBIAN
       
    40 
       
    41 
       
    42 // signatures for setting listener slots
       
    43 const char *SETTING_LISTENER_SIGNATURE1 = "settingChanged(const QString &, const QVariant &)";
       
    44 const char *SETTING_LISTENER_SIGNATURE2 = "settingChanged(const QVariant &)";
       
    45 
       
    46 
       
    47 /*
       
    48 * CxeSettingsImp::CxeSettingsImp
       
    49 */
       
    50 CxeSettingsImp::CxeSettingsImp(CxeSettingsStore *settingStore)
       
    51 : mSettingStore(settingStore),
       
    52   mVariationSettings(),
       
    53   mSceneModeStore(),
       
    54   mCameraMode(Cxe::ImageMode)
       
    55 {
       
    56     CX_DEBUG_ENTER_FUNCTION();
       
    57     loadVariationSettings();
       
    58 
       
    59     CX_DEBUG_EXIT_FUNCTION();
       
    60 }
       
    61 
       
    62 /*
       
    63 * CxeSettingsImp::close
       
    64 */
       
    65 CxeSettingsImp::~CxeSettingsImp()
       
    66 {
       
    67     CX_DEBUG_ENTER_FUNCTION();
       
    68     delete mSettingStore;
       
    69 
       
    70     mVariationSettings.clear();
       
    71     mSettingListeners.clear();
       
    72     CX_DEBUG_EXIT_FUNCTION();
       
    73 }
       
    74 
       
    75 /*
       
    76 * Reads a value from cenrep
       
    77 * @param key   - setting key
       
    78 * @param uid   - setting UID of the component that owns the setting key
       
    79 * @param type  - the type of key cr key or P&S key (constantly monitoring value)
       
    80 * @param value - setting value read from cenrep
       
    81 */
       
    82 
       
    83 void CxeSettingsImp::get(long int uid,
       
    84                          unsigned long int key,
       
    85                          Cxe::SettingKeyType type,
       
    86                          QVariant &value) const
       
    87 {
       
    88     CX_DEBUG_ENTER_FUNCTION();
       
    89     CX_DEBUG_ASSERT(mSettingStore);
       
    90 
       
    91     mSettingStore->startMonitoring(uid, key, type, value);
       
    92 
       
    93     CX_DEBUG_EXIT_FUNCTION();
       
    94 
       
    95 }
       
    96 
       
    97 
       
    98 /*!
       
    99     Reset static settings (persistent settings)
       
   100 */
       
   101 void CxeSettingsImp::reset()
       
   102 {
       
   103     CX_DEBUG_ENTER_FUNCTION();
       
   104 
       
   105     CX_DEBUG_ASSERT(mSettingStore);
       
   106     mSettingStore->reset();
       
   107 
       
   108     CX_DEBUG_EXIT_FUNCTION();
       
   109 }
       
   110 
       
   111 /*!
       
   112 * Get the configured run-time value associated with the key.
       
   113 * @Param key - Setting key Id ( refer to CxeSettingIds in cxenums.h )
       
   114 * @Param value - contains the value associated with the key.
       
   115 * @returns CxeError::None if successful or any CxeError specific error code.
       
   116 */
       
   117 CxeError::Id CxeSettingsImp::getVariationValue(const QString &key, QVariant &value)
       
   118 {
       
   119     CX_DEBUG_ENTER_FUNCTION();
       
   120 
       
   121     CxeError::Id err = CxeError::None;
       
   122 
       
   123     // read run-time configuration value
       
   124     if ( mVariationSettings.contains(key) ) {
       
   125         value = qVariantFromValue<QVariantList > (mVariationSettings.value(key));
       
   126     } else {
       
   127         err = CxeError::NotFound;
       
   128     }
       
   129 
       
   130     CX_DEBUG_EXIT_FUNCTION();
       
   131 
       
   132     return err;
       
   133 }
       
   134 
       
   135 
       
   136 /*!
       
   137  * Add listener for changes in one setting. When the value of the setting changes, the given
       
   138  * slot is invoked on given object.
       
   139  * The validity of the settingKey is not checked.
       
   140  *
       
   141  * @param settingKey Setting to listen to
       
   142  * @param target Object that the slot will be invoked for
       
   143  * @param slot Slot that will be invoked. The slot can have either of these two signatures:
       
   144  *   slotName(const QVariant&)    only new value of setting is passed as parameter
       
   145  *   slotName(const QString&, const QVariant&) both setting key and new value are passed as parameter
       
   146  *
       
   147  * @return boolean to indicate success
       
   148  *
       
   149  */
       
   150 bool CxeSettingsImp::listenForSetting(const QString &settingKey, QObject *target, const char *slot)
       
   151 {
       
   152 
       
   153     CX_DEBUG_ENTER_FUNCTION();
       
   154     CX_DEBUG_ASSERT(target && slot);
       
   155 
       
   156     // SLOT() macro adds '1' to the beginning of string so we use slot+1 to get the name of the slot
       
   157     CX_DEBUG(("Adding listener %s::%s for key %s", target->metaObject()->className(), slot+1, settingKey.toAscii().data()));
       
   158     QByteArray normalizedSlotName = QMetaObject::normalizedSignature(slot+1);
       
   159 
       
   160     int slotIndex = target->metaObject()->indexOfSlot(normalizedSlotName);
       
   161 
       
   162     bool ok = false;
       
   163     if (slotIndex > -1) {
       
   164         CX_DEBUG(("Slot found, checking signature"));
       
   165         // verify that slot is correct type
       
   166         if (QMetaObject::checkConnectArgs(QMetaObject::normalizedSignature(SETTING_LISTENER_SIGNATURE1), normalizedSlotName) ||
       
   167             QMetaObject::checkConnectArgs(QMetaObject::normalizedSignature(SETTING_LISTENER_SIGNATURE2), normalizedSlotName)) {
       
   168 
       
   169             CX_DEBUG(("Slot signature ok, adding listener"));
       
   170 
       
   171             // check if list for given key already exists
       
   172             if (!mSettingListeners.contains(settingKey)) {
       
   173                 mSettingListeners.insert(settingKey, CxeSettingListenerList());
       
   174             }
       
   175 
       
   176             // get QMetaMethod object
       
   177             QMetaMethod method = target->metaObject()->method(slotIndex);
       
   178             // add listener to the list
       
   179             CxeSettingListenerList& list = mSettingListeners[settingKey];
       
   180             list.append(CxeSettingListener(target, method));
       
   181 
       
   182             // connect to destroyed() signal so we can remove listener if it's deleted
       
   183             connect(target, SIGNAL(destroyed(QObject*)), this, SLOT(handleListenerDestroyed(QObject*)));
       
   184 
       
   185             ok = true;
       
   186         } else {
       
   187             CX_DEBUG(("Slot signature doesn't match, can't add listener"));
       
   188         }
       
   189 
       
   190     } else {
       
   191         CX_DEBUG(("Slot not found, can't add listener"));
       
   192     }
       
   193 
       
   194     CX_DEBUG_EXIT_FUNCTION();
       
   195     return ok;
       
   196 }
       
   197 
       
   198 /*!
       
   199     Load image/video specific settings during mode change or startup
       
   200 */
       
   201 void CxeSettingsImp::loadSettings(Cxe::CameraMode mode)
       
   202 {
       
   203     CX_DEBUG_ENTER_FUNCTION();
       
   204     OstTrace0(camerax_performance, CXESETTINGSIMP_LOADSETTINGS_IN, "msg: e_CX_SETTINGS_LOADSETTINGS 1");
       
   205 
       
   206     mCameraMode = mode;
       
   207 
       
   208     // inform the settings model for the change in mode.
       
   209     if (mode == Cxe::ImageMode) {
       
   210         restoreImageSettings();
       
   211         notifyListeners(CxeSettingIds::IMAGE_SCENE_DATA, mSceneModeStore.currentScene(Cxe::ImageMode));
       
   212         notifyListeners(CxeSettingIds::IMAGE_SCENE, mSceneModeStore.currentSceneId(Cxe::ImageMode));
       
   213         emit settingValueChanged(CxeSettingIds::IMAGE_SCENE, mSceneModeStore.currentSceneId(Cxe::ImageMode));
       
   214     } else {
       
   215         restoreVideoSettings();
       
   216         notifyListeners(CxeSettingIds::VIDEO_SCENE_DATA, mSceneModeStore.currentScene(Cxe::VideoMode));
       
   217         notifyListeners(CxeSettingIds::VIDEO_SCENE, mSceneModeStore.currentSceneId(Cxe::VideoMode));
       
   218         emit settingValueChanged(CxeSettingIds::VIDEO_SCENE, mSceneModeStore.currentSceneId(Cxe::VideoMode));
       
   219     }
       
   220 
       
   221     OstTrace0(camerax_performance, CXESETTINGSIMP_LOADSETTINGS_OUT, "msg: e_CX_SETTINGS_LOADSETTINGS 0");
       
   222     CX_DEBUG_EXIT_FUNCTION();
       
   223 }
       
   224 
       
   225 /*!
       
   226 * Get setting value associated with the key.
       
   227 * @Param key - Setting key Id ( refer to CxeSettingIds in cxenums.h )
       
   228 * @Param value - contains the value associated with the key.
       
   229 * @returns CxeError::None if successful or any CxeError specific error code.
       
   230 */
       
   231 void CxeSettingsImp::getValue(const QString &key, QVariant &value) const
       
   232 {
       
   233     CX_DEBUG_ENTER_FUNCTION();
       
   234     CX_DEBUG_ASSERT(mSettingStore);
       
   235 
       
   236 
       
   237     CxeError::Id err = CxeError::None;
       
   238 
       
   239     // check if getting scene mode
       
   240     if(key == CxeSettingIds::IMAGE_SCENE_DATA) {
       
   241         value = mSceneModeStore.currentScene(Cxe::ImageMode);
       
   242     } else if(key == CxeSettingIds::VIDEO_SCENE_DATA) {
       
   243         value = mSceneModeStore.currentScene(Cxe::VideoMode);
       
   244     } else {
       
   245         // Try first to find the item from cenrep store.
       
   246         err = mSettingStore->get(key, value);
       
   247 
       
   248         // If setting is not in cenrep store, try fetching it from scene settings.
       
   249         if (!err) {
       
   250             CX_DEBUG(("Got value %s from settings store", value.toString().toAscii().data()));
       
   251         } else {
       
   252             // setting not found in setting store, try finding if its scene specific setting.
       
   253             CX_DEBUG(( "fetching value from scene settings" ));
       
   254             err = mSceneModeStore.sceneSettingValue(mCameraMode, key, value);
       
   255         }
       
   256         if (err) {
       
   257             throw CxeException(err);
       
   258         }
       
   259     }
       
   260 
       
   261     CX_DEBUG_EXIT_FUNCTION();
       
   262 
       
   263 }
       
   264 
       
   265 /*!
       
   266 * Set a value to the key.
       
   267 * @Param key - Setting key Id ( refer to CxeSettingIds in cxenums.h )
       
   268 * @Param value - contains the value associated with the key.
       
   269 * @returns CxeError::None if successful or any CxeError specific error code.
       
   270 */
       
   271 void CxeSettingsImp::setValue(const QString &key, const QVariant &newValue)
       
   272 {
       
   273     CX_DEBUG_ENTER_FUNCTION();
       
   274     CX_DEBUG_ASSERT(mSettingStore);
       
   275 
       
   276     CxeError::Id err;
       
   277     // check if setting scene mode
       
   278     if(key == CxeSettingIds::IMAGE_SCENE) {
       
   279         setImageScene(newValue.toString());
       
   280     } else if(key == CxeSettingIds::VIDEO_SCENE) {
       
   281         setVideoScene(newValue.toString());
       
   282     } else if(key == CxeSettingIds::IMAGE_SCENE_DATA || key == CxeSettingIds::VIDEO_SCENE_DATA) {
       
   283         // setting whole scene by value is not supported
       
   284         throw CxeException(CxeError::NotSupported);
       
   285     } else {
       
   286         // Try storing new value to cenrep
       
   287         err = mSettingStore->set(key, newValue);
       
   288 
       
   289         if (err) {
       
   290             CX_DEBUG(( "Key not found in cenrepstore, writing value to scene settings" ));
       
   291             err = mSceneModeStore.setSceneSettingValue(mCameraMode, key, newValue);
       
   292         }
       
   293 
       
   294         if (err) {
       
   295             throw CxeException(err);
       
   296         }
       
   297 
       
   298         // send notifications
       
   299         emit settingValueChanged(key, newValue);
       
   300         notifyListeners(key, newValue);
       
   301     }
       
   302 
       
   303     CX_DEBUG_EXIT_FUNCTION();
       
   304 
       
   305 }
       
   306 
       
   307 /*!
       
   308 * Restores image settings, during mode change or during startup.
       
   309 */
       
   310 void CxeSettingsImp::restoreImageSettings()
       
   311 {
       
   312     CX_DEBUG_ENTER_FUNCTION();
       
   313 
       
   314     QString currentSceneInUse = mSceneModeStore.currentSceneId(Cxe::ImageMode);
       
   315 
       
   316     // get the image scene value from cenrep and load the scene settings
       
   317     QString key(CxeSettingIds::IMAGE_SCENE);
       
   318     QString cenrepSceneValue = CxeSettings::get<QString>(key);
       
   319 
       
   320     bool ok2LoadSceneSettings = (cenrepSceneValue != currentSceneInUse);
       
   321 
       
   322     if (ok2LoadSceneSettings) {
       
   323         // loading scene settings
       
   324         mSceneModeStore.setCurrentScene(Cxe::ImageMode, cenrepSceneValue);
       
   325     }
       
   326 
       
   327     // Updating Flash setting from cenrep
       
   328     key = CxeSettingIds::FLASH_MODE;
       
   329     int flashMode = CxeSettings::get<int>(key);
       
   330 
       
   331     // update local datastructure with flash setting value from cenrep.
       
   332     CX_DEBUG(( "flash setting value %d", flashMode));
       
   333     mSceneModeStore.setSceneSettingValue(Cxe::ImageMode, key, flashMode);
       
   334 
       
   335     // Updating Face Tracking setting from cenrep
       
   336     key = CxeSettingIds::FACE_TRACKING;
       
   337     int faceTracking = CxeSettings::get<int>(key);
       
   338 
       
   339     // update local datastructure with flash setting value from cenrep.
       
   340     CX_DEBUG(( "Face Tracking setting value %d", faceTracking));
       
   341     mSceneModeStore.setSceneSettingValue(Cxe::ImageMode, key, faceTracking);
       
   342 
       
   343 
       
   344     CX_DEBUG_EXIT_FUNCTION();
       
   345 }
       
   346 
       
   347 
       
   348 /*!
       
   349 * Restores video settings, during mode change or during startup.
       
   350 */
       
   351 void CxeSettingsImp::restoreVideoSettings()
       
   352 {
       
   353     CX_DEBUG_ENTER_FUNCTION();
       
   354 
       
   355     QString currentSceneInUse = mSceneModeStore.currentSceneId(Cxe::VideoMode);
       
   356 
       
   357     // get the video scene value from cenrep and load the scene settings
       
   358     QString cenrepSceneValue = CxeSettings::get<QString>(CxeSettingIds::VIDEO_SCENE);
       
   359 
       
   360     bool ok2LoadSceneSettings = (cenrepSceneValue != currentSceneInUse);
       
   361 
       
   362     if (ok2LoadSceneSettings) {
       
   363         // loading video scene settings
       
   364         mSceneModeStore.setCurrentScene(Cxe::VideoMode, cenrepSceneValue);
       
   365     }
       
   366 
       
   367     CX_DEBUG_EXIT_FUNCTION();
       
   368 }
       
   369 
       
   370 /*!
       
   371 * Set new Image scene mode.
       
   372 * @returns CxeError::None if successful or any CxeError specific error code.
       
   373 */
       
   374 void CxeSettingsImp::setImageScene(const QString &newScene)
       
   375 {
       
   376     CX_DEBUG_ENTER_FUNCTION();
       
   377 
       
   378     // load scene specific settings
       
   379     mSceneModeStore.setCurrentScene(Cxe::ImageMode, newScene);
       
   380 
       
   381     // saving current image scene to cenrep
       
   382     CxeError::Id err = mSettingStore->set(CxeSettingIds::IMAGE_SCENE, newScene);
       
   383     CxeException::throwIfError(err);
       
   384 
       
   385     // saving flash value from scene to cenrep
       
   386     // call CxeSettingStore::set directly because we don't want to send notifications
       
   387     // about these changes
       
   388     QString key(CxeSettingIds::FLASH_MODE);
       
   389     err = mSettingStore->set(key, mSceneModeStore.currentScene(Cxe::ImageMode)[key].toInt());
       
   390 
       
   391     CxeException::throwIfError(err);
       
   392     // saving face tracking value from scene to cenrep
       
   393     key = CxeSettingIds::FACE_TRACKING;
       
   394     err = mSettingStore->set(key, mSceneModeStore.currentScene(Cxe::ImageMode)[key].toInt());
       
   395     CxeException::throwIfError(err);
       
   396 
       
   397     // send notifications
       
   398     emit settingValueChanged(CxeSettingIds::IMAGE_SCENE, mSceneModeStore.currentSceneId(Cxe::ImageMode));
       
   399     notifyListeners(CxeSettingIds::IMAGE_SCENE, mSceneModeStore.currentSceneId(Cxe::ImageMode));
       
   400     notifyListeners(CxeSettingIds::IMAGE_SCENE_DATA, mSceneModeStore.currentScene(Cxe::ImageMode));
       
   401 
       
   402     CX_DEBUG_EXIT_FUNCTION();
       
   403 
       
   404 }
       
   405 
       
   406 /*!
       
   407 * Set new video scene mode.
       
   408 * @returns CxeError::None if successful or any CxeError specific error code.
       
   409 */
       
   410 void CxeSettingsImp::setVideoScene(const QString &newScene)
       
   411 {
       
   412     CX_DEBUG_ENTER_FUNCTION();
       
   413 
       
   414     mSceneModeStore.setCurrentScene(Cxe::VideoMode, newScene);
       
   415 
       
   416     // video scene set successfully, store the scene value to cenrep
       
   417     CxeError::Id err = mSettingStore->set(CxeSettingIds::VIDEO_SCENE, newScene);
       
   418     CxeException::throwIfError(err);
       
   419 
       
   420     emit settingValueChanged(CxeSettingIds::VIDEO_SCENE, mSceneModeStore.currentSceneId(Cxe::VideoMode));
       
   421     notifyListeners(CxeSettingIds::VIDEO_SCENE, mSceneModeStore.currentSceneId(Cxe::VideoMode));
       
   422     notifyListeners(CxeSettingIds::VIDEO_SCENE_DATA, mSceneModeStore.currentScene(Cxe::VideoMode));
       
   423 
       
   424     CX_DEBUG_EXIT_FUNCTION();
       
   425 
       
   426 }
       
   427 
       
   428 /*!
       
   429 * Loads all run-time variation settings
       
   430 */
       
   431 void CxeSettingsImp::loadVariationSettings()
       
   432 {
       
   433     CX_DEBUG_ENTER_FUNCTION();
       
   434     CX_DEBUG_ASSERT( mSettingStore );
       
   435 
       
   436     QList<QString> variationKeys;
       
   437     // all supported runtime variation keys are fetched from here.
       
   438     variationKeys.append(CxeVariationKeys::FREE_MEMORY_LEVELS);
       
   439     variationKeys.append(CxeVariationKeys::STILL_MAX_ZOOM_LIMITS);
       
   440     variationKeys.append(CxeVariationKeys::VIDEO_MAX_ZOOM_LIMITS);
       
   441 
       
   442     // load all run-time setting values from cenrep.
       
   443     mVariationSettings = mSettingStore->loadVariationSettings(variationKeys);
       
   444 
       
   445     CX_DEBUG_EXIT_FUNCTION();
       
   446 }
       
   447 
       
   448 /*!
       
   449  * Notify setting listeners that setting has changed
       
   450  * @param settingKey Setting that has changed
       
   451  * @param newValue New value of the setting
       
   452  */
       
   453 void CxeSettingsImp::notifyListeners(const QString &settingKey, const QVariant &newValue)
       
   454 {
       
   455     CX_DEBUG_ENTER_FUNCTION();
       
   456 
       
   457     CX_DEBUG(("CxeSettingsImp::notifyListeners settingKey=%s", settingKey.toAscii().data()));
       
   458 
       
   459     if (mSettingListeners.contains(settingKey)) {
       
   460         CX_DEBUG(("Listeners found"));
       
   461         // get list of listener
       
   462         CxeSettingListenerList& list = mSettingListeners[settingKey];
       
   463 
       
   464         // iterate through the list and call all listeners
       
   465         CxeSettingListenerList::const_iterator i = list.constBegin();
       
   466         for(; i != list.constEnd(); ++i) {
       
   467 
       
   468             QObject *object = (*i).first;
       
   469             QMetaMethod slot = (*i).second;
       
   470 
       
   471             CX_DEBUG_ASSERT(object);
       
   472 
       
   473             // invoke the slot
       
   474             CX_DEBUG(("Calling slot %s::%s", object->metaObject()->className(), slot.signature()));
       
   475 
       
   476             bool ok = false;
       
   477             if (slot.parameterTypes().size() == 2) {
       
   478                 // slot has two parameters, send settingKey as well
       
   479                 ok = slot.invoke(object,
       
   480                                   Qt::AutoConnection,
       
   481                                   Q_ARG(QString, settingKey),
       
   482                                   Q_ARG(QVariant, newValue));
       
   483             } else {
       
   484                 // don't send settingKey as parameter
       
   485                 ok = slot.invoke(object,
       
   486                                  Qt::AutoConnection,
       
   487                                  Q_ARG(QVariant, newValue));
       
   488             }
       
   489 
       
   490             if (!ok) {
       
   491                 CX_DEBUG(("QMetaMethod::invoke() failed, listener not notified"))
       
   492             }
       
   493 
       
   494         }
       
   495 
       
   496     } else {
       
   497         CX_DEBUG(("NO listeners found"));
       
   498     }
       
   499 
       
   500 
       
   501 
       
   502     CX_DEBUG_EXIT_FUNCTION();
       
   503 }
       
   504 
       
   505 /*!
       
   506  * Handle deletion of registered listener.
       
   507  */
       
   508 void CxeSettingsImp::handleListenerDestroyed(QObject *object)
       
   509 {
       
   510     CX_DEBUG_ENTER_FUNCTION();
       
   511 
       
   512     QList<QString> keyList = mSettingListeners.keys();
       
   513 
       
   514     for (int i = 0; i < keyList.size(); i++) {
       
   515 
       
   516         QString key = keyList[i];
       
   517         CxeSettingListenerList& list = mSettingListeners[key];
       
   518 
       
   519         for (int j = 0; j < list.size(); j++) {
       
   520             CxeSettingListener &listener = list[j];
       
   521             if (listener.first == object) {
       
   522                 list.removeAt(j--);
       
   523             }
       
   524         }
       
   525 
       
   526         // removed last listener for this key
       
   527         if (list.size() == 0) {
       
   528             mSettingListeners.remove(key);
       
   529         }
       
   530     }
       
   531 
       
   532     CX_DEBUG_EXIT_FUNCTION();
       
   533 }
       
   534 
       
   535 // end of file