SVN commit 1220699 by nienhueser: Voice navigation support: In route guidance mode, turn points are announced in advance using either a sound or some speaker at the user's option. There's no speaker shipped with Marble (yet), but existing TomTom ones can be converted. See http://userbase.kde.org/Marble/CustomSpeakers. REVIEW: 6469 M +2 -0 data/CMakeLists.txt A data/audio (directory) A data/audio/KDE-Sys-App-Positive.ogg M +12 -1 src/lib/routing/RoutingModel.cpp M +11 -0 src/lib/routing/RoutingModel.h A src/plugins/render/routing/AudioOutput.cpp [License: LGPL] A src/plugins/render/routing/AudioOutput.h [License: LGPL] M +2 -2 src/plugins/render/routing/CMakeLists.txt A src/plugins/render/routing/RoutingConfigDialog.ui M +68 -0 src/plugins/render/routing/RoutingPlugin.cpp M +13 -0 src/plugins/render/routing/RoutingPlugin.h --- trunk/KDE/kdeedu/marble/data/CMakeLists.txt #1220698:1220699 @@ -244,3 +244,5 @@ install (FILES icons/hi22-app-marble.png DESTINATION ${ICON_INSTALL_DIR}/hicolor/22x22/apps/ RENAME marble.png) install (FILES icons/hi16-app-marble.png DESTINATION ${ICON_INSTALL_DIR}/hicolor/16x16/apps/ RENAME marble.png) endif(NOT APPLE AND NOT WIN32 ) + +install (DIRECTORY audio DESTINATION ${MARBLE_DATA_INSTALL_PATH}) --- trunk/KDE/kdeedu/marble/src/lib/routing/RoutingModel.cpp #1220698:1220699 @@ -24,7 +24,6 @@ #include "MarbleModel.h" #include "MarbleWidget.h" #include "global.h" -#include "routing/instructions/RoutingInstruction.h" #include "GeoDataExtendedData.h" #include @@ -77,6 +76,7 @@ qreal m_nextInstructionDistance; qreal m_currentInstructionLength; QPixmap m_nextInstructionPixmap; + RoutingInstruction::TurnType m_nextTurnType; QPixmap m_followingInstructionPixmap; GeoDataCoordinates m_location; QString m_nextDescription; @@ -500,6 +500,7 @@ if( d->m_nextInstructionIndex != instructions.size() ) { d->m_location = instructions[d->m_nextInstructionIndex].position; d->m_nextDescription = instructions[d->m_nextInstructionIndex].description; + d->m_nextTurnType = instructions[d->m_nextInstructionIndex].turnType; d->m_nextInstructionPixmap = d->m_turnTypePixmaps[instructions[d->m_nextInstructionIndex].turnType]; if ( d->m_nextInstructionIndex+1 < instructions.size() ) { d->m_followingInstructionPixmap = d->m_turnTypePixmaps[instructions[d->m_nextInstructionIndex+1].turnType]; @@ -600,11 +601,21 @@ return d->m_nextInstructionPixmap; } +RoutingInstruction::TurnType RoutingModel::nextTurnType() const +{ + return d->m_nextTurnType; +} + QPixmap RoutingModel::followingInstructionPixmap() const { return d->m_followingInstructionPixmap; } +int RoutingModel::nextTurnIndex() const +{ + return d->m_nextInstructionIndex; +} + } // namespace Marble #include "RoutingModel.moc" --- trunk/KDE/kdeedu/marble/src/lib/routing/RoutingModel.h #1220698:1220699 @@ -14,6 +14,7 @@ #include "marble_export.h" #include "GeoDataLineString.h" #include "MarblePlacemarkModel.h" +#include "routing/instructions/RoutingInstruction.h" #include #include @@ -157,6 +158,16 @@ QPixmap nextInstructionPixmap() const; /** + * Returns the turn type of the next driving instruction + */ + RoutingInstruction::TurnType nextTurnType() const; + + /** + * Returns the index of the next turn point + */ + int nextTurnIndex() const; + + /** * Returns an icon indicating the turn type for the next but one driving instruction */ QPixmap followingInstructionPixmap() const; --- trunk/KDE/kdeedu/marble/src/plugins/render/routing/CMakeLists.txt #1220698:1220699 @@ -7,8 +7,8 @@ ) INCLUDE(${QT_USE_FILE}) -set( routing_SRCS RoutingPlugin.cpp ) -set( routing_UI RoutingPlugin.ui ) +set( routing_SRCS RoutingPlugin.cpp AudioOutput.cpp ) +set( routing_UI RoutingPlugin.ui RoutingConfigDialog.ui ) qt4_wrap_ui( routing_SRCS ${routing_UI} ) marble_add_plugin( RoutingPlugin ${routing_SRCS} ) --- trunk/KDE/kdeedu/marble/src/plugins/render/routing/RoutingPlugin.cpp #1220698:1220699 @@ -12,7 +12,9 @@ #include "RoutingPlugin.h" #include "ui_RoutingPlugin.h" +#include "ui_RoutingConfigDialog.h" +#include "AudioOutput.h" #include "GeoDataCoordinates.h" #include "GeoPainter.h" #include "MarbleDataFacade.h" @@ -36,6 +38,7 @@ #include #include #include +#include namespace Marble { @@ -55,6 +58,10 @@ Ui::RoutingPlugin m_widget; bool m_nearNextInstruction; bool m_guidanceModeEnabled; + AudioOutput* m_audio; + QHash m_settings; + QDialog *m_configDialog; + Ui::RoutingConfigDialog m_configUi; RoutingPluginPrivate( RoutingPlugin* parent ); @@ -84,6 +91,8 @@ QString fuzzyDistance( qreal distanceMeter ) const; + void readSettings(); + private: RoutingPlugin* m_parent; }; @@ -94,6 +103,8 @@ m_routingModel( 0 ), m_nearNextInstruction( false ), m_guidanceModeEnabled( false ), + m_audio( new AudioOutput( parent ) ), + m_configDialog( 0 ), m_parent( parent ) { // nothing to do @@ -257,6 +268,7 @@ if ( m_routingModel->rowCount() != 0 ) { qreal distanceLeft = m_routingModel->nextInstructionDistance(); + m_audio->update( m_routingModel->nextTurnIndex(), distanceLeft, m_routingModel->nextTurnType() ); m_nearNextInstruction = distanceLeft < thresholdDistance; int fontSize = 1; @@ -335,6 +347,37 @@ } } +void RoutingPluginPrivate::readSettings() +{ + bool const muted = m_settings["muted"].toBool(); + m_audio->setMuted( muted ); + bool const sound = m_settings["sound"].toBool(); + m_audio->setSoundEnabled( sound ); + QString const speaker = m_settings["speaker"].toString(); + m_audio->setSpeaker( speaker ); + + if ( m_configDialog ) { + QStringList const speakers = m_audio->speakers(); + int const index = speakers.indexOf( QRegExp( speaker ) ); + m_configUi.speakerComboBox->clear(); + m_configUi.speakerComboBox->addItems( speakers ); + m_configUi.speakerComboBox->setCurrentIndex( index ); + m_configUi.voiceNavigationCheckBox->setChecked( !muted ); + m_configUi.soundRadioButton->setChecked( sound ); + } +} + +void RoutingPlugin::writeSettings() +{ + Q_ASSERT( d->m_configDialog ); + d->m_settings["speaker"] = d->m_configUi.speakerComboBox->currentText(); + d->m_settings["muted"] = !d->m_configUi.voiceNavigationCheckBox->isChecked(); + d->m_settings["sound"] = d->m_configUi.soundRadioButton->isChecked(); + d->readSettings(); + emit settingsChanged( nameId() ); +} + + RoutingPlugin::RoutingPlugin( const QPointF &position ) : AbstractFloatItem( position ), d( new RoutingPluginPrivate( this ) ) @@ -450,8 +493,33 @@ return AbstractFloatItem::eventFilter( object, e ); } +QHash RoutingPlugin::settings() const +{ + return d->m_settings; } +void RoutingPlugin::setSettings( QHash settings ) +{ + d->m_settings = settings; + d->readSettings(); +} + +QDialog *RoutingPlugin::configDialog() +{ + if ( !d->m_configDialog ) { + d->m_configDialog = new QDialog; + d->m_configUi.setupUi( d->m_configDialog ); + d->readSettings(); + + connect( d->m_configDialog, SIGNAL( accepted() ), this, SLOT( writeSettings() ) ); + connect( d->m_configDialog, SIGNAL( rejected() ), this, SLOT( readSettings() ) ); + } + + return d->m_configDialog; +} + +} + Q_EXPORT_PLUGIN2( RoutingPlugin, Marble::RoutingPlugin ) #include "RoutingPlugin.moc" --- trunk/KDE/kdeedu/marble/src/plugins/render/routing/RoutingPlugin.h #1220698:1220699 @@ -50,6 +50,16 @@ bool eventFilter( QObject *object, QEvent *event ); + virtual QHash settings() const; + + virtual void setSettings( QHash settings ); + + QDialog *configDialog(); + +private Q_SLOTS: + /** Write settings */ + void writeSettings(); + private: /** Disable zoom buttons if needed */ Q_PRIVATE_SLOT( d, void updateZoomButtons() ) @@ -74,6 +84,9 @@ Q_PRIVATE_SLOT( d, void updateGuidanceModeButton() ); + /** Read settings */ + Q_PRIVATE_SLOT( d, void readSettings() ) + RoutingPluginPrivate* const d; };