Index: libopenmpt/bindings/freebasic/libopenmpt.bi
===================================================================
--- libopenmpt/bindings/freebasic/libopenmpt.bi	(revision 16815)
+++ libopenmpt/bindings/freebasic/libopenmpt.bi	(working copy)
@@ -1076,9 +1076,18 @@
 
   \param module The module handle to work on.
   \return The current tempo in tracker units. The exact meaning of this value depends on the tempo mode being used.
+  \deprecated Please use openmpt_module_get_current_tempo2().
 '/
 Declare Function openmpt_module_get_current_tempo(ByVal module As openmpt_module Ptr) As Long
 
+/'* \brief Get the current tempo
+
+  \param module The module handle to work on.
+  \return The current tempo in tracker units. The exact meaning of this value depends on the tempo mode being used.
+  \since 0.7.0
+'/
+Declare Function openmpt_module_get_current_tempo2(ByVal module As openmpt_module Ptr) As Long
+
 /'* \brief Get the current order
 
   \param module The module handle to work on.
Index: libopenmpt/bindings/freebasic/libopenmpt_ext.bi
===================================================================
--- libopenmpt/bindings/freebasic/libopenmpt_ext.bi	(revision 16815)
+++ libopenmpt/bindings/freebasic/libopenmpt_ext.bi	(working copy)
@@ -348,6 +348,23 @@
 	get_note_finetune As Function(ByVal mod_ext As openmpt_module_ext Ptr, ByVal channel As Long) As Double
 End Type
 
+#define LIBOPENMPT_EXT_C_INTERFACE_INTERACTIVE3 "interactive3"
+
+Type openmpt_module_ext_interface_interactive3
+
+	/'* Set the current module tempo
+
+	  \param mod_ext The module handle to work on.
+	  \param tempo The new tempo in range [32, 512]. The exact meaning of the value depends on the tempo mode used by the module.
+	  \return 1 on success, 0 on failure.
+	  \remarks The tempo may be reset by pattern commands at any time. Use set_tempo_factor to apply a tempo factor that is independent of pattern commands.
+	  \sa openmpt_module_get_current_tempo2
+	  \since 0.7.0
+	'/
+	set_current_tempo As Function(ByVal mod_ext As openmpt_module_ext Ptr, ByVal tempo As Double) As Long
+
+End Type
+
 End Extern
 
 /'* \brief Construct an openmpt_module_ext
Index: libopenmpt/dox/changelog.md
===================================================================
--- libopenmpt/dox/changelog.md	(revision 16815)
+++ libopenmpt/dox/changelog.md	(working copy)
@@ -7,6 +7,9 @@
 
 ### libopenmpt 0.7.0-pre
 
+ *  [**New**] libopenmpt: New APIs for getting the current tempo as a floating
+    point value: `openmpt::module::get_current_tempo2()` (C++), and
+    `openmpt_module_get_current_tempo2()` (C).
  *  [**New**] C API: New stream callbacks for various platform extensions to the
     C stdio interface: `openmpt_stream_get_file_posix_lfs64_callbacks()` in
     `libopenmpt/libopenmpt_stream_callbacks_file_posix_lfs64.h` for explicit
@@ -37,6 +40,10 @@
     `openmpt_probe_file_header()`,
     `openmpt_probe_file_header_without_filesize()`, and
     `openmpt_probe_file_header_from_stream()` in libopenmpt 0.3.0.
+ *  [**New**] libopenmpt_ext: New interface `interactive3` adding
+    `openmpt::ext::interactive3::set_current_tempo2()` (C++) and
+    `openmpt_module_ext_interface_interactive3.set_current_tempo2()` (C) which
+    allow setting non-integer tempo values. 
  *  [**New**] `Makefile` `CONFIG=djgpp` now supports `CPU=` option to build
     optimized for a particular CPU. See `build/make/config-djgpp.mk` for all
     available options. `FLAVOURED_DIR=1` places the CPU-specific optimized
Index: libopenmpt/libopenmpt.h
===================================================================
--- libopenmpt/libopenmpt.h	(revision 16815)
+++ libopenmpt/libopenmpt.h	(working copy)
@@ -1159,8 +1159,16 @@
  *
  * \param mod The module handle to work on.
  * \return The current tempo in tracker units. The exact meaning of this value depends on the tempo mode being used.
+ * \deprecated Please use openmpt_module_get_current_tempo2().
  */
 LIBOPENMPT_API int32_t openmpt_module_get_current_tempo( openmpt_module * mod );
+/*! \brief Get the current tempo
+ *
+ * \param mod The module handle to work on.
+ * \return The current tempo in tracker units. The exact meaning of this value depends on the tempo mode being used.
+ * \since 0.7.0
+ */
+LIBOPENMPT_API double openmpt_module_get_current_tempo2( openmpt_module * mod );
 /*! \brief Get the current order
  *
  * \param mod The module handle to work on.
Index: libopenmpt/libopenmpt.hpp
===================================================================
--- libopenmpt/libopenmpt.hpp	(revision 16815)
+++ libopenmpt/libopenmpt.hpp	(working copy)
@@ -843,8 +843,15 @@
 	//! Get the current tempo
 	/*!
 	  \return The current tempo in tracker units. The exact meaning of this value depends on the tempo mode being used.
+	  \deprecated Please use openmpt::module::get_current_tempo2().
 	*/
 	std::int32_t get_current_tempo() const;
+	//! Get the current tempo
+	/*!
+	  \return The current tempo in tracker units. The exact meaning of this value depends on the tempo mode being used.
+	  \since 0.7.0
+	*/
+	double get_current_tempo2() const;
 	//! Get the current order
 	/*!
 	  \return The current order at which the module is being played back.
Index: libopenmpt/libopenmpt_c.cpp
===================================================================
--- libopenmpt/libopenmpt_c.cpp	(revision 16815)
+++ libopenmpt/libopenmpt_c.cpp	(working copy)
@@ -967,6 +967,15 @@
 	}
 	return 0;
 }
+double openmpt_module_get_current_tempo2( openmpt_module * mod ) {
+	try {
+		openmpt::interface::check_soundfile( mod );
+		return mod->impl->get_current_tempo2();
+	} catch ( ... ) {
+		openmpt::report_exception( __func__, mod );
+	}
+	return 0;
+}
 int32_t openmpt_module_get_current_order( openmpt_module * mod ) {
 	try {
 		openmpt::interface::check_soundfile( mod );
@@ -1786,6 +1795,19 @@
 
 
 
+static int set_current_tempo2( openmpt_module_ext * mod_ext, double tempo ) {
+	try {
+		openmpt::interface::check_soundfile( mod_ext );
+		mod_ext->impl->set_current_tempo2( tempo );
+		return 1;
+	} catch ( ... ) {
+		openmpt::report_exception( __func__, mod_ext ? &mod_ext->mod : NULL );
+	}
+	return 0;
+}
+
+
+
 /* add stuff here */
 
 
@@ -1844,6 +1866,13 @@
 
 
 
+		} else if ( !std::strcmp( interface_id, LIBOPENMPT_EXT_C_INTERFACE_INTERACTIVE3 ) && ( interface_size == sizeof( openmpt_module_ext_interface_interactive3 ) ) ) {
+			openmpt_module_ext_interface_interactive3 * i = static_cast< openmpt_module_ext_interface_interactive3 * >( interface );
+			i->set_current_tempo2 = &set_current_tempo2;
+			result = 1;
+
+			
+			
 /* add stuff here */
 
 
Index: libopenmpt/libopenmpt_cxx.cpp
===================================================================
--- libopenmpt/libopenmpt_cxx.cpp	(revision 16815)
+++ libopenmpt/libopenmpt_cxx.cpp	(working copy)
@@ -312,6 +312,9 @@
 std::int32_t module::get_current_tempo() const {
 	return impl->get_current_tempo();
 }
+double module::get_current_tempo2() const {
+	return impl->get_current_tempo2();
+}
 std::int32_t module::get_current_order() const {
 	return impl->get_current_order();
 }
Index: libopenmpt/libopenmpt_ext.h
===================================================================
--- libopenmpt/libopenmpt_ext.h	(revision 16815)
+++ libopenmpt/libopenmpt_ext.h	(working copy)
@@ -389,6 +389,26 @@
 
 
 
+#ifndef LIBOPENMPT_EXT_C_INTERFACE_INTERACTIVE3
+#define LIBOPENMPT_EXT_C_INTERFACE_INTERACTIVE3 "interactive3"
+#endif
+
+typedef struct openmpt_module_ext_interface_interactive3 {
+
+	/*! Set the current module tempo
+	 *
+	 * \param mod_ext The module handle to work on.
+	 * \param tempo The new tempo in range [32, 512]. The exact meaning of the value depends on the tempo mode used by the module.
+	 * \return 1 on success, 0 on failure.
+	 * \remarks The tempo may be reset by pattern commands at any time. Use openmpt_module_ext_interface_interactive::set_tempo_factor to apply a tempo factor that is independent of pattern commands.
+	 * \sa openmpt_module_get_current_tempo2
+	 */
+	int ( * set_current_tempo2 ) ( openmpt_module_ext * mod_ext, double tempo );
+
+} openmpt_module_ext_interface_interactive3;
+
+
+
 /* add stuff here */
 
 
Index: libopenmpt/libopenmpt_ext.hpp
===================================================================
--- libopenmpt/libopenmpt_ext.hpp	(revision 16815)
+++ libopenmpt/libopenmpt_ext.hpp	(working copy)
@@ -383,9 +383,33 @@
 	*/
 	virtual double get_note_finetune( int32_t channel ) = 0;
 
-}; // class interactive
+}; // class interactive2
 
 
+#ifndef LIBOPENMPT_EXT_INTERFACE_INTERACTIVE3
+#define LIBOPENMPT_EXT_INTERFACE_INTERACTIVE3
+#endif
+
+LIBOPENMPT_DECLARE_EXT_CXX_INTERFACE(interactive3)
+
+class interactive3 {
+
+	LIBOPENMPT_EXT_CXX_INTERFACE(interactive3)
+
+	//! Set the current module tempo
+	/*!
+	  \param tempo The new tempo in range [32, 512]. The exact meaning of the value depends on the tempo mode used by the module.
+	  \throws openmpt::exception Throws an exception derived from openmpt::exception if the tempo is outside the specified range.
+	  \remarks The tempo may be reset by pattern commands at any time. Use openmpt::ext:interactive::set_tempo_factor to apply a tempo factor that is independent of pattern commands.
+	  \sa openmpt::module::get_current_tempo2
+		\since 0.7.0
+	*/
+	virtual void set_current_tempo2( double tempo ) = 0;
+
+}; // class interactive3
+
+
+
 /* add stuff here */
 
 
Index: libopenmpt/libopenmpt_ext_impl.cpp
===================================================================
--- libopenmpt/libopenmpt_ext_impl.cpp	(revision 16815)
+++ libopenmpt/libopenmpt_ext_impl.cpp	(working copy)
@@ -85,6 +85,8 @@
 			return dynamic_cast< ext::interactive * >( this );
 		} else if ( interface_id == ext::interactive2_id ) {
 			return dynamic_cast< ext::interactive2 * >( this );
+		} else if ( interface_id == ext::interactive3_id ) {
+			return dynamic_cast< ext::interactive3 * >( this );
 
 
 
@@ -344,6 +346,13 @@
 		return chn.microTuning / 32768.0;
 	}
 
+	void module_ext_impl::set_current_tempo2( double tempo ) {
+		if ( tempo < 32.0 || tempo > 512.0 ) {
+			throw openmpt::exception("invalid tempo");
+		}
+		m_sndFile->m_PlayState.m_nMusicTempo = decltype( m_sndFile->m_PlayState.m_nMusicTempo )( tempo );
+	}
+
 	/* add stuff here */
 
 
Index: libopenmpt/libopenmpt_ext_impl.hpp
===================================================================
--- libopenmpt/libopenmpt_ext_impl.hpp	(revision 16815)
+++ libopenmpt/libopenmpt_ext_impl.hpp	(working copy)
@@ -21,6 +21,7 @@
 	, public ext::pattern_vis
 	, public ext::interactive
 	, public ext::interactive2
+	, public ext::interactive3
 
 
 
@@ -112,6 +113,8 @@
 
 	double get_note_finetune( std::int32_t channel ) override;
 
+	void set_current_tempo2(double tempo) override;
+
 	/* add stuff here */
 
 }; // class module_ext_impl
Index: libopenmpt/libopenmpt_impl.cpp
===================================================================
--- libopenmpt/libopenmpt_impl.cpp	(revision 16815)
+++ libopenmpt/libopenmpt_impl.cpp	(working copy)
@@ -1316,6 +1316,9 @@
 std::int32_t module_impl::get_current_tempo() const {
 	return static_cast<std::int32_t>( m_sndFile->m_PlayState.m_nMusicTempo.GetInt() );
 }
+double module_impl::get_current_tempo2() const {
+	return m_sndFile->m_PlayState.m_nMusicTempo.ToDouble();
+}
 std::int32_t module_impl::get_current_order() const {
 	return m_sndFile->GetCurrentOrder();
 }
Index: libopenmpt/libopenmpt_impl.hpp
===================================================================
--- libopenmpt/libopenmpt_impl.hpp	(revision 16815)
+++ libopenmpt/libopenmpt_impl.hpp	(working copy)
@@ -212,6 +212,7 @@
 	double get_current_estimated_bpm() const;
 	std::int32_t get_current_speed() const;
 	std::int32_t get_current_tempo() const;
+	double get_current_tempo2() const;
 	std::int32_t get_current_order() const;
 	std::int32_t get_current_pattern() const;
 	std::int32_t get_current_row() const;
Index: openmpt123/openmpt123.cpp
===================================================================
--- openmpt123/openmpt123.cpp	(revision 16815)
+++ openmpt123/openmpt123.cpp	(working copy)
@@ -1286,7 +1286,7 @@
 					log << "   ";
 					log << "Spd:" << std::setw(2) << std::setfill(':') << mod.get_current_speed();
 					log << " ";
-					log << "Tmp:" << std::setw(3) << std::setfill(':') << mod.get_current_tempo();
+					log << "Tmp:" << std::setw(6) << std::setfill(':') << std::fixed << std::setprecision(2) << mod.get_current_tempo2();
 					log << "   ";
 					log << std::endl;
 				}
