Game Development Community

TGEA 1.7.0 Bug: crash when adjusting audio volume in gui

by Jeff Faust · in Torque Game Engine Advanced · 04/07/2008 (9:07 am) · 7 replies

Adjusting audio volume in the Audio panel of the Options popup crashes the program. This does not happen when changing the master volume, but does happen when adjusting "sim" of "shell" volume.

I've reproduced this crash on all stock demos that have an audio options panel.

A debug compile suggests the problem has to do with a bad removeNotify() call that occurs when an SFXSource is deleted.

About the author

Jeff Faust creates special effects indie middleware and games for Faust Logic. --- Blog: Effectronica.com --- Twitter: @FaustLogic


#1
04/11/2008 (8:56 pm)
Master Volume slider function is not right, otherwise it would crash also.

In OptAudioUpdateMasterVolume(%volume):

$AudioTestHandle = sfxPlayOnce( "AudioChannel" @ %channel

should be:

$AudioTestHandle = sfxPlayOnce( "AudioChannel0"


Then it will crash :p
#2
05/02/2008 (4:55 pm)
Confirmed. Found. Fixed.
#3
05/04/2008 (1:00 pm)
Can you post the fix for this?

Since theres no "live" updates of any kind, the fixes getting posted as they're fixed, based on forum posts, is next best thing.
#4
05/04/2008 (3:12 pm)
The reason I did not post a fix is that it's all going to end up in your hands anyway (and probably in very reasonable time). Posting fixes for each and every issue that gets resolved is very tedious (especially since not all fixes are trivial) and consumes time that is better spent doing some more fixing.

However, I realize that this was my own fault as really no one could infer from my post above that the respective fix would be available.

So, since I'm the one to blame, here's the fix:

engine/source/sfx/sfxSystem.cpp

@@ -563,17 +563,19 @@
    }
    else if ( description )
    {
-      SFXProfile tempProfile( description, StringTable->insert( argv[2] ) );
+      SFXProfile* tempProfile = new SFXProfile( description, StringTable->insert( argv[2] ), true );
       if ( argc == 3 )
       {
-         source = SFX->createSource( &tempProfile );
+         source = SFX->createSource( tempProfile );
       }
       else
       {
          MatrixF transform;
          transform.set(EulerF(0,0,0), Point3F( dAtof(argv[3]),dAtof(argv[4]),dAtof(argv[5]) ));
-         source = SFX->createSource( &tempProfile, &transform );
+         source = SFX->createSource( tempProfile, &transform );
       }
+
+      tempProfile->setAutoDelete( true );
    }
 
    if ( source )
@@ -599,7 +601,7 @@
       description = dynamic_cast<SFXDescription*>( Sim::findObject( argv[1] ) );
       if ( !description )
       {
-         Con::printf( "Unable to locate sound profile/description '%s'", argv[1] );
+         Con::errorf( "sfxPlayOnce - Unable to locate sound profile/description '%s'", argv[1] );
          return 0;
       }
    }
@@ -620,15 +622,25 @@
 
    else if ( description )
    {
-      SFXProfile tempProfile( description, StringTable->insert( argv[2] ) );
-      if ( argc == 3 )
-         source = SFX->playOnce( &tempProfile );
+      SFXProfile* tempProfile = new SFXProfile( description, StringTable->insert( argv[2] ), true );
+      if( !tempProfile->registerObject() )
+      {
+         Con::errorf( "sfxPlayOnce - unable to create profile" );
+         delete tempProfile;
+      }
       else
       {
-         MatrixF transform;
-         transform.set(EulerF(0,0,0), Point3F( dAtof(argv[3]),dAtof(argv[4]),dAtof(argv[5]) ));
-         source = SFX->playOnce( &tempProfile, &transform );
+         if ( argc == 3 )
+            source = SFX->playOnce( tempProfile );
+         else
+         {
+            MatrixF transform;
+            transform.set(EulerF(0,0,0), Point3F( dAtof(argv[3]),dAtof(argv[4]),dAtof(argv[5]) ));
+            source = SFX->playOnce( tempProfile, &transform );
+         }
       }
+
+      tempProfile->setAutoDelete( true );
    }
 
    if ( source )

engine/source/console/simObject.h

@@ -221,7 +221,8 @@
       Selected  = BIT(4),   ///< This object has been marked as selected. (in editor)
       Expanded  = BIT(5),   ///< This object has been marked as expanded. (in editor)
       ModStaticFields  = BIT(6),    ///< The object allows you to read/modify static fields
-      ModDynamicFields = BIT(7)     ///< The object allows you to read/modify dynamic fields
+      ModDynamicFields = BIT(7),    ///< The object allows you to read/modify dynamic fields
+      AutoDelete = BIT( 8 ),        ///< Delete this object when the last ObjectRef is gone.
    };
 public:
    /// @name Notification
@@ -664,6 +665,7 @@
    void setExpanded(bool exp) { if(exp) mFlags.set(Expanded); else mFlags.clear(Expanded); }
    void setModDynamicFields(bool dyn) { if(dyn) mFlags.set(ModDynamicFields); else mFlags.clear(ModDynamicFields); }
    void setModStaticFields(bool sta) { if(sta) mFlags.set(ModStaticFields); else mFlags.clear(ModStaticFields); }
+   void setAutoDelete( bool val ) { if( val ) mFlags.set( AutoDelete ); else mFlags.clear( AutoDelete ); }
 
    /// @}

engine/source/console/simObject.cpp

@@ -762,7 +762,18 @@
 {
    Notify *note = removeNotify((void *) ptr, Notify::ObjectRef);
    if(note)
+   {
       freeNotify(note);
+
+      if( mFlags.test( AutoDelete ) )
+      {
+         for( Notify* n = mNotifyList; n != NULL; n = n->next )
+            if( n->type == Notify::ObjectRef )
+               return;
+
+         deleteObject();
+      }
+   }
 }
 
 void SimObject::clearNotify(SimObject* obj)
#5
05/04/2008 (3:19 pm)
Actually, I just noticed two errors in my fix.

a) The profile isn't registered in sfxCreateSource.
b) In both sfxCreateSource and sfxPlayOnce, the setAutoDelete must be moved into the else branch.
#6
05/06/2008 (7:40 pm)
"The reason I did not post a fix is that it's all going to end up in your hands anyway (and probably in very reasonable time). Posting fixes for each and every issue that gets resolved is very tedious (especially since not all fixes are trivial) and consumes time that is better spent doing some more fixing."



No offense, but thats why most engine companies still offer consistent code drops or ways to get "live" code, even if it might very well be broken or not working 100%.

I realize not all fixes can be posted that easily, but when bugs are reported in forums, if there is a fix made, then there needs to be either a separate place to find the fix or a real ETA on the fix being available. Especially with something as severe as this crash, since its a bit sketchy as its all mostly new code with the new SFX changes, and anybody who is using 1.7 will run into this crash quickly.


Thanks for posting the fix
#7
05/07/2008 (10:36 am)
No offense taken and you absolutely have a very valid point there.