summaryrefslogtreecommitdiff
path: root/utils/hlfaceposer/wavebrowser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/hlfaceposer/wavebrowser.cpp')
-rw-r--r--utils/hlfaceposer/wavebrowser.cpp1182
1 files changed, 1182 insertions, 0 deletions
diff --git a/utils/hlfaceposer/wavebrowser.cpp b/utils/hlfaceposer/wavebrowser.cpp
new file mode 100644
index 0000000..c961369
--- /dev/null
+++ b/utils/hlfaceposer/wavebrowser.cpp
@@ -0,0 +1,1182 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#include "cbase.h"
+#include <windows.h>
+#include "resource.h"
+#include "wavefile.h"
+#include "wavebrowser.h"
+#include "SoundEmitterSystem/isoundemittersystembase.h"
+#include "ifaceposersound.h"
+#include "snd_wave_source.h"
+#include "filesystem.h"
+#include "tabwindow.h"
+#include "inputproperties.h"
+#include "choreowidgetdrawhelper.h"
+#include "ifileloader.h"
+#include "tier2/riff.h"
+#include "UtlBuffer.h"
+#include "ChoreoEvent.h"
+
+CWaveBrowser *g_pWaveBrowser = NULL;
+
+//-----------------------------------------------------------------------------
+// Purpose: Implements the RIFF i/o interface on stdio
+//-----------------------------------------------------------------------------
+class StdIOReadBinary : public IFileReadBinary
+{
+public:
+ int open( const char *pFileName )
+ {
+ return (int)filesystem->Open( pFileName, "rb" );
+ }
+
+ int read( void *pOutput, int size, int file )
+ {
+ if ( !file )
+ return 0;
+
+ return filesystem->Read( pOutput, size, (FileHandle_t)file );
+ }
+
+ void seek( int file, int pos )
+ {
+ if ( !file )
+ return;
+
+ filesystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD );
+ }
+
+ unsigned int tell( int file )
+ {
+ if ( !file )
+ return 0;
+
+ return filesystem->Tell( (FileHandle_t)file );
+ }
+
+ unsigned int size( int file )
+ {
+ if ( !file )
+ return 0;
+
+ return filesystem->Size( (FileHandle_t)file );
+ }
+
+ void close( int file )
+ {
+ if ( !file )
+ return;
+
+ filesystem->Close( (FileHandle_t)file );
+ }
+};
+
+class StdIOWriteBinary : public IFileWriteBinary
+{
+public:
+ int create( const char *pFileName )
+ {
+ return (int)filesystem->Open( pFileName, "wb" );
+ }
+
+ int write( void *pData, int size, int file )
+ {
+ return filesystem->Write( pData, size, (FileHandle_t)file );
+ }
+
+ void close( int file )
+ {
+ filesystem->Close( (FileHandle_t)file );
+ }
+
+ void seek( int file, int pos )
+ {
+ filesystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD );
+ }
+
+ unsigned int tell( int file )
+ {
+ return filesystem->Tell( (FileHandle_t)file );
+ }
+};
+
+static StdIOReadBinary io_in;
+static StdIOWriteBinary io_out;
+
+#define RIFF_WAVE MAKEID('W','A','V','E')
+#define WAVE_FMT MAKEID('f','m','t',' ')
+#define WAVE_DATA MAKEID('d','a','t','a')
+#define WAVE_FACT MAKEID('f','a','c','t')
+#define WAVE_CUE MAKEID('c','u','e',' ')
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &walk -
+//-----------------------------------------------------------------------------
+static void SceneManager_ParseSentence( CSentence& sentence, IterateRIFF &walk )
+{
+ CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
+
+ buf.EnsureCapacity( walk.ChunkSize() );
+ walk.ChunkRead( buf.Base() );
+ buf.SeekPut( CUtlBuffer::SEEK_HEAD, walk.ChunkSize() );
+
+ sentence.InitFromDataChunk( buf.Base(), buf.TellPut() );
+}
+
+bool SceneManager_LoadSentenceFromWavFileUsingIO( char const *wavfile, CSentence& sentence, IFileReadBinary& io )
+{
+ sentence.Reset();
+
+ InFileRIFF riff( wavfile, io );
+
+ // UNDONE: Don't use printf to handle errors
+ if ( riff.RIFFName() != RIFF_WAVE )
+ {
+ return false;
+ }
+
+ // set up the iterator for the whole file (root RIFF is a chunk)
+ IterateRIFF walk( riff, riff.RIFFSize() );
+
+ // This chunk must be first as it contains the wave's format
+ // break out when we've parsed it
+ bool found = false;
+ while ( walk.ChunkAvailable() && !found )
+ {
+ switch( walk.ChunkName() )
+ {
+ case WAVE_VALVEDATA:
+ {
+ found = true;
+ SceneManager_ParseSentence( sentence, walk );
+ }
+ break;
+ }
+ walk.ChunkNext();
+ }
+
+ return true;
+}
+
+bool SceneManager_LoadSentenceFromWavFile( char const *wavfile, CSentence& sentence )
+{
+ return SceneManager_LoadSentenceFromWavFileUsingIO( wavfile, sentence, io_in );
+}
+
+enum
+{
+ // Controls
+ IDC_SB_LISTVIEW = 101,
+ IDC_SB_FILETREE,
+
+ // Messages
+ IDC_SB_PLAY = 1000,
+};
+
+enum
+{
+ COL_WAV = 0,
+ COL_DUCKED,
+ COL_PHONEMES,
+ COL_SENTENCE
+};
+
+class CWaveList : public mxListView
+{
+public:
+ CWaveList( mxWindow *parent, int id = 0 )
+ : mxListView( parent, 0, 0, 0, 0, id )
+ {
+ // Add column headers
+ insertTextColumn( COL_WAV, 300, "WAV" );
+ insertTextColumn( COL_DUCKED, 50, "Ducked" );
+ insertTextColumn( COL_PHONEMES, 120, "Words [ Phonemes ]" );
+ insertTextColumn( COL_SENTENCE, 300, "Sentence Text" );
+ }
+};
+
+class CWaveFileTree : public mxTreeView
+{
+public:
+ CWaveFileTree( mxWindow *parent, int id = 0 ) : mxTreeView( parent, 0, 0, 0, 0, id ),
+ m_Paths( 0, 0, FileTreeLessFunc )
+ {
+ }
+
+ void Clear()
+ {
+ removeAll();
+ m_Paths.RemoveAll();
+ }
+
+ void FindOrAddSubdirectory( char const *subdir )
+ {
+ FileTreePath fp;
+ Q_strcpy( fp.path, subdir );
+
+ if ( m_Paths.Find( fp ) != m_Paths.InvalidIndex() )
+ return;
+
+ m_Paths.Insert( fp );
+ }
+
+ mxTreeViewItem *FindOrAddChildItem( mxTreeViewItem *parent, char const *child )
+ {
+ mxTreeViewItem *p = getFirstChild( parent );
+ if ( !p )
+ {
+ return add( parent, child );
+ }
+
+ while ( p )
+ {
+ if ( !Q_stricmp( getLabel( p ), child ) )
+ return p;
+
+ p = getNextChild( p );
+ }
+
+ return add( parent, child );
+ }
+
+ void _PopulateTree( int pathId, char const *path )
+ {
+ char sz[ 512 ];
+ Q_strcpy( sz, path );
+ char *p = sz;
+
+ // Start at root
+ mxTreeViewItem *cur = NULL;
+
+ // Tokenize path
+ while ( p && p[0] )
+ {
+ char *slash = Q_strstr( p, "/" );
+ if ( !slash )
+ {
+ slash = Q_strstr( p, "\\" );
+ }
+
+ char *check = p;
+
+ if ( slash )
+ {
+ *slash = 0;
+
+ // see if a child of current already exists with this name
+ p = slash + 1;
+ }
+ else
+ {
+ p = NULL;
+ }
+
+ Assert( check );
+
+ cur = FindOrAddChildItem( cur, check );
+ }
+
+ setUserData( cur, (void *)pathId );
+ }
+
+ char const *GetSelectedPath( void )
+ {
+ mxTreeViewItem *tvi = getSelectedItem();
+ unsigned int id = (unsigned int)getUserData( tvi );
+
+ if ( id < 0 || id >= m_Paths.Count() )
+ {
+ Assert( 0 );
+ return "";
+ }
+ return m_Paths[ id ].path;
+ }
+
+ void PopulateTree()
+ {
+ int i;
+ for ( i = m_Paths.FirstInorder(); i != m_Paths.InvalidIndex(); i = m_Paths.NextInorder( i ) )
+ {
+ _PopulateTree( i, m_Paths[ i ].path );
+ }
+
+ mxTreeViewItem *p = getFirstChild( NULL );
+ setOpen( p, true );
+ }
+
+ struct FileTreePath
+ {
+ char path[ MAX_PATH ];
+ };
+
+ static bool FileTreeLessFunc( const FileTreePath &lhs, const FileTreePath &rhs )
+ {
+ return Q_stricmp( lhs.path, rhs.path ) < 0;
+ }
+
+ CUtlRBTree< FileTreePath, int > m_Paths;
+};
+#pragma optimize( "", off )
+class CWaveOptionsWindow : public mxWindow
+{
+typedef mxWindow BaseClass;
+public:
+ enum
+ {
+ IDC_PLAYSOUND = 1000,
+ IDC_STOP_SOUNDS,
+ IDC_SEARCH,
+ IDC_CANCELSEARCH,
+ };
+
+ CWaveOptionsWindow( CWaveBrowser *browser ) : BaseClass( browser, 0, 0, 0, 0 ), m_pBrowser( browser )
+ {
+ FacePoser_AddWindowStyle( this, WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
+
+ m_szSearchString[0]=0;
+
+ m_pPlay = new mxButton( this, 0, 0, 0, 0, "Play", IDC_PLAYSOUND );
+
+ m_pStopSounds = new mxButton( this, 0, 0, 0, 0, "Stop Sounds", IDC_STOP_SOUNDS );
+
+ m_pSearch = new mxLineEdit( this, 0, 0, 0, 0, "", IDC_SEARCH );
+
+ m_pCancelSearch = new mxButton( this, 0, 0, 0, 0, "Cancel", IDC_CANCELSEARCH );
+ }
+
+ bool PaintBackground( void )
+ {
+ redraw();
+ return false;
+ }
+
+
+ virtual void redraw()
+ {
+ CChoreoWidgetDrawHelper drawHelper( this, GetSysColor( COLOR_BTNFACE ) );
+ }
+ virtual int handleEvent( mxEvent *event )
+ {
+ int iret = 0;
+ switch ( event->event )
+ {
+ default:
+ break;
+ case mxEvent::Size:
+ {
+ iret = 1;
+
+ int split = 120;
+
+ int x = 1;
+
+ m_pPlay->setBounds( x, 1, split, h2() - 2 );
+
+ x += split + 10;
+
+ m_pStopSounds->setBounds( x, 1, split, h2()-2 );
+
+ x += split + 10;
+
+ m_pCancelSearch->setBounds( x, 1, split, h2() - 2 );
+
+ x += split + 10;
+
+ m_pSearch->setBounds( x, 0, split * 3, h2() - 1 );
+
+ x += split * 3 + 10;
+ }
+ break;
+ case mxEvent::KeyDown:
+ switch ( event->action )
+ {
+ default:
+ break;
+ case IDC_SEARCH:
+ {
+ if ( event->event == mxEvent::KeyDown )
+ {
+ OnSearch();
+ }
+ iret = 1;
+ };
+ break;
+ }
+ break;
+ case mxEvent::Action:
+ {
+ switch ( event->action )
+ {
+ case IDC_STOP_SOUNDS:
+ {
+ iret = 1;
+ sound->StopAll();
+ }
+ break;
+ case IDC_SEARCH:
+ iret = 1;
+ break;
+ case IDC_PLAYSOUND:
+ {
+ iret = 1;
+ m_pBrowser->OnPlay();
+ }
+ break;
+ case IDC_CANCELSEARCH:
+ {
+ iret = 1;
+ OnCancelSearch();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ }
+
+ return iret;
+ }
+
+ char const *GetSearchString()
+ {
+ return m_szSearchString;
+ }
+
+ void OnSearch()
+ {
+ m_pSearch->getText( m_szSearchString, sizeof( m_szSearchString ) );
+
+ m_pBrowser->OnSearch();
+ }
+
+ void OnCancelSearch()
+ {
+ m_szSearchString[ 0 ] = 0;
+ m_pSearch->clear();
+
+ m_pBrowser->OnCancelSearch();
+ }
+
+private:
+
+ mxButton *m_pStopSounds;
+ mxButton *m_pPlay;
+ mxLineEdit *m_pSearch;
+ mxButton *m_pCancelSearch;
+
+ CWaveBrowser *m_pBrowser;
+
+ char m_szSearchString[ 256 ];
+};
+
+#pragma optimize( "", on )
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *parent -
+//-----------------------------------------------------------------------------
+CWaveBrowser::CWaveBrowser( mxWindow *parent )
+ : IFacePoserToolWindow( "WaveBrowser", "Waves" ), mxWindow( parent, 0, 0, 0, 0 )
+{
+ SetAutoProcess( false );
+
+ m_bTextSearch = false;
+ m_nPrevProcessed = -1;
+
+ m_pListView = new CWaveList( this, IDC_SB_LISTVIEW );
+ m_pOptions = new CWaveOptionsWindow( this );
+ m_pFileTree = new CWaveFileTree( this, IDC_SB_FILETREE );
+
+ //HIMAGELIST list = CreateImageList();
+
+ // Associate the image list with the tree-view control.
+ //m_pListView->setImageList( (void *)list );
+
+ LoadAllSounds();
+
+ PopulateTree( NULL );
+}
+
+#define CX_ICON 16
+#define CY_ICON 16
+
+HIMAGELIST CWaveBrowser::CreateImageList()
+{
+ HIMAGELIST list;
+
+ list = ImageList_Create( CX_ICON, CY_ICON,
+ FALSE, NUM_IMAGES, 0 );
+
+ // Load the icon resources, and add the icons to the image list.
+ HICON hicon;
+ int slot;
+#if defined( DBGFLAG_ASSERT )
+ int c = 0;
+#endif
+
+ /*
+ hicon = LoadIcon( GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WORKSPACE));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+
+ hicon = LoadIcon( GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WORKSPACE_CHECKEDOUT));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+
+ hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_PROJECT));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+
+ hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_PROJECT_CHECKEDOUT));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+
+ hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SCENE));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+ */
+
+// hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SCENE_CHECKEDOUT));
+// slot = ImageList_AddIcon(list, hicon);
+// Assert( slot == c++ );
+// DeleteObject( hicon );
+
+ /*
+ hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_VCD));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+
+ hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_VCD_CHECKEDOUT ));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+ */
+
+ hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WAV));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+
+ /*
+ hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_WAV_CHECKEDOUT));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+
+ hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SPEAK));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+
+ hicon = LoadIcon(GetModuleHandle( 0 ), MAKEINTRESOURCE(IDI_SPEAK_CHECKEDOUT));
+ slot = ImageList_AddIcon(list, hicon);
+ Assert( slot == c++ );
+ DeleteObject( hicon );
+ */
+
+ return list;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWaveBrowser::OnDelete()
+{
+ RemoveAllSounds();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *event -
+// Output : int
+//-----------------------------------------------------------------------------
+int CWaveBrowser::handleEvent( mxEvent *event )
+{
+ int iret = 0;
+
+ if ( HandleToolEvent( event ) )
+ {
+ return iret;
+ }
+
+ switch ( event->event )
+ {
+ default:
+ break;
+ case mxEvent::Action:
+ {
+ iret = 1;
+ switch ( event->action )
+ {
+ default:
+ {
+ iret = 0;
+ }
+ break;
+ case IDC_SB_LISTVIEW:
+ {
+ SetActiveTool( this );
+
+ bool rightmouse = ( event->flags == mxEvent::RightClicked ) ? true : false;
+ bool doubleclicked = ( event->flags == mxEvent::DoubleClicked ) ? true : false;
+
+ if ( rightmouse )
+ {
+ ShowContextMenu();
+ }
+ else if ( doubleclicked )
+ {
+ if ( m_pListView->getNumSelected() == 1 )
+ {
+ int index = m_pListView->getNextSelectedItem( -1 );
+ if ( index >= 0 )
+ {
+ CWaveFile *wav = (CWaveFile *)m_pListView->getUserData( index, 0 );
+ if ( wav )
+ {
+ wav->Play();
+ }
+ }
+ }
+ }
+ }
+ break;
+ case IDC_SB_FILETREE:
+ {
+ SetActiveTool( this );
+
+ PopulateTree( m_pFileTree->GetSelectedPath() );
+ }
+ break;
+ case IDC_SB_PLAY:
+ {
+ OnPlay();
+ }
+ break;
+ }
+ }
+ break;
+ case mxEvent::Size:
+ {
+ int optionsh = 20;
+
+ m_pOptions->setBounds( 0, 0, w2(), optionsh );
+
+ int filetreewidth = 175;
+
+ m_pFileTree->setBounds( 0, optionsh, filetreewidth, h2() - optionsh );
+ m_pListView->setBounds( filetreewidth, optionsh, w2() - filetreewidth, h2() - optionsh );
+
+ iret = 1;
+ }
+ break;
+ case mxEvent::Close:
+ {
+ iret = 1;
+ }
+ break;
+ }
+
+ return iret;
+}
+
+static bool NameLessFunc( CWaveFile *const& name1, CWaveFile *const& name2 )
+{
+ if ( Q_stricmp( name1->GetName(), name2->GetName() ) < 0 )
+ return true;
+ return false;
+}
+
+#define SOUND_PREFIX_LEN 6
+//-----------------------------------------------------------------------------
+// Finds all .wav files in a particular directory
+//-----------------------------------------------------------------------------
+bool CWaveBrowser::LoadWaveFilesInDirectory( CUtlDict< CWaveFile *, int >& soundlist, char const* pDirectoryName, int nDirectoryNameLen )
+{
+ Assert( Q_strnicmp( pDirectoryName, "sound", 5 ) == 0 );
+
+ char *pWildCard;
+ pWildCard = ( char * )stackalloc( nDirectoryNameLen + 7 );
+ Q_snprintf( pWildCard, nDirectoryNameLen + 7, "%s/*.wav", pDirectoryName );
+
+ if ( !filesystem )
+ {
+ return false;
+ }
+
+ FileFindHandle_t findHandle;
+ const char *pFileName = filesystem->FindFirst( pWildCard, &findHandle );
+ while( pFileName )
+ {
+ if( !filesystem->FindIsDirectory( findHandle ) )
+ {
+ // Strip off the 'sound/' part of the name.
+ char *pFileNameWithPath;
+ int nAllocSize = nDirectoryNameLen + Q_strlen(pFileName) + 2;
+ pFileNameWithPath = (char *)stackalloc( nAllocSize );
+ Q_snprintf( pFileNameWithPath, nAllocSize, "%s/%s", &pDirectoryName[SOUND_PREFIX_LEN], pFileName );
+ Q_strnlwr( pFileNameWithPath, nAllocSize );
+
+ CWaveFile *wav = new CWaveFile( pFileNameWithPath );
+ soundlist.Insert( pFileNameWithPath, wav );
+
+ /*
+ if ( !(soundlist.Count() % 500 ) )
+ {
+ Con_Printf( "CWaveBrowser: loaded %i sounds\n", soundlist.Count() );
+ }
+ */
+ }
+ pFileName = filesystem->FindNext( findHandle );
+ }
+
+ m_pFileTree->FindOrAddSubdirectory( &pDirectoryName[ SOUND_PREFIX_LEN ] );
+
+ filesystem->FindClose( findHandle );
+ return true;
+}
+
+bool CWaveBrowser::InitDirectoryRecursive( CUtlDict< CWaveFile *, int >& soundlist, char const* pDirectoryName )
+{
+ // Compute directory name length
+ int nDirectoryNameLen = Q_strlen( pDirectoryName );
+
+ if (!LoadWaveFilesInDirectory( soundlist, pDirectoryName, nDirectoryNameLen ) )
+ return false;
+
+ char *pWildCard = ( char * )stackalloc( nDirectoryNameLen + 4 );
+ strcpy(pWildCard, pDirectoryName);
+ strcat(pWildCard, "/*.");
+ int nPathStrLen = nDirectoryNameLen + 1;
+
+ FileFindHandle_t findHandle;
+ const char *pFileName = filesystem->FindFirst( pWildCard, &findHandle );
+ while( pFileName )
+ {
+ if ((pFileName[0] != '.') || (pFileName[1] != '.' && pFileName[1] != 0))
+ {
+ if( filesystem->FindIsDirectory( findHandle ) )
+ {
+ int fileNameStrLen = Q_strlen( pFileName );
+ char *pFileNameWithPath = ( char * )stackalloc( nPathStrLen + fileNameStrLen + 1 );
+ memcpy( pFileNameWithPath, pWildCard, nPathStrLen );
+ pFileNameWithPath[nPathStrLen] = '\0';
+ strcat( pFileNameWithPath, pFileName );
+
+ if (!InitDirectoryRecursive( soundlist, pFileNameWithPath ))
+ return false;
+ }
+ }
+ pFileName = filesystem->FindNext( findHandle );
+ }
+
+ return true;
+}
+
+void CWaveBrowser::LoadAllSounds()
+{
+ RemoveAllSounds();
+
+ Con_Printf( "Building list of all .wavs in sound/ folder\n" );
+
+ InitDirectoryRecursive( m_AllSounds, "sound" );
+
+ m_pFileTree->PopulateTree();
+}
+
+void CWaveBrowser::RemoveAllSounds()
+{
+ int c = m_AllSounds.Count();
+ for ( int i = 0; i < c; i++ )
+ {
+ CWaveFile *wav = m_AllSounds[ i ];
+ delete wav;
+ }
+
+ m_AllSounds.RemoveAll();
+ m_Scripts.RemoveAll();
+ m_CurrentSelection.RemoveAll();
+
+ m_pFileTree->Clear();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWaveBrowser::PopulateTree( char const *subdirectory )
+{
+ int i;
+
+ CUtlRBTree< CWaveFile *, int > m_Sorted( 0, 0, NameLessFunc );
+
+ bool check_load_sentence_data = false;
+
+ char const *texttofind = NULL;
+
+ if ( m_bTextSearch )
+ {
+ subdirectory = NULL;
+ texttofind = GetSearchString();
+ }
+
+ int len = 0;
+ if ( subdirectory )
+ {
+ len = Q_strlen( subdirectory );
+ check_load_sentence_data = ( Q_strstr( subdirectory, "/" ) || subdirectory[0] ) ? true : false;
+ }
+
+ int c = m_AllSounds.Count();
+ for ( i = 0; i < c; i++ )
+ {
+ CWaveFile *wav = m_AllSounds[ i ];
+ char const *name = wav->GetName();
+
+ if ( subdirectory )
+ {
+ if ( Q_strnicmp( subdirectory, wav->GetName(), len ) )
+ continue;
+ }
+
+ if ( m_bTextSearch && texttofind )
+ {
+ if ( !Q_stristr( name, texttofind ) )
+ continue;
+ }
+
+ m_Sorted.Insert( wav );
+ }
+
+ char prevSelectedName[ 512 ];
+ prevSelectedName[ 0 ] = 0;
+ if ( m_pListView->getNumSelected() == 1 )
+ {
+ int selectedItem = m_pListView->getNextSelectedItem( 0 );
+ if ( selectedItem >= 0 )
+ {
+ // Grab wave name of previously selected item
+ Q_strcpy( prevSelectedName, m_pListView->getLabel( selectedItem, 0 ) );
+ }
+ }
+
+// Repopulate tree
+ m_pListView->removeAll();
+
+ int loadcount = 0;
+
+ m_pListView->setDrawingEnabled( false );
+
+ int selectedSlot = -1;
+
+ CUtlVector< CWaveFile * > list;
+
+
+ for ( i = m_Sorted.FirstInorder(); i != m_Sorted.InvalidIndex(); i = m_Sorted.NextInorder( i ) )
+ {
+ CWaveFile *wav = m_Sorted[ i ];
+ char const *name = wav->GetName();
+
+ int slot = m_pListView->add( name );
+
+ if ( !Q_stricmp( prevSelectedName, name ) )
+ {
+ selectedSlot = slot;
+ }
+
+ if ( ( check_load_sentence_data || m_bTextSearch ) &&
+ !wav->HasLoadedSentenceInfo() && !wav->IsAsyncLoading() )
+ {
+ wav->SetAsyncLoading( true );
+ list.AddToTail( wav );
+ }
+
+ // m_pListView->setImage( slot, COL_WAV, wav->GetIconIndex() );
+ m_pListView->setUserData( slot, COL_WAV, (void *)wav );
+
+ if ( wav->HasLoadedSentenceInfo() )
+ {
+ m_pListView->setLabel( slot, COL_DUCKED, wav->GetVoiceDuck() ? "yes" : "no" );
+ m_pListView->setLabel( slot, COL_PHONEMES, wav->GetPhonemeCount() || wav->GetWordCount() ? va( "%i [ %i ]", wav->GetWordCount(), wav->GetPhonemeCount() ) : "" );
+ m_pListView->setLabel( slot, COL_SENTENCE, wav->GetSentenceText() );
+ }
+ else
+ {
+ m_pListView->setLabel( slot, COL_SENTENCE, "(loading...)" );
+ }
+
+ ++loadcount;
+ }
+
+ m_pListView->setDrawingEnabled( true );
+
+ if ( selectedSlot != -1 )
+ {
+ m_pListView->setSelected( selectedSlot, true );
+ m_pListView->scrollToItem( selectedSlot );
+ }
+
+ if ( list.Count() > 0 )
+ {
+ fileloader->AddWaveFilesToThread( list );
+ }
+
+ // Con_Printf( "CWaveBrowser: selected %i sounds\n", loadcount );
+}
+
+void CWaveBrowser::RepopulateTree()
+{
+ PopulateTree( m_pFileTree->GetSelectedPath() );
+}
+
+void CWaveBrowser::BuildSelectionList( CUtlVector< CWaveFile * >& selected )
+{
+ selected.RemoveAll();
+
+ int idx = -1;
+ do
+ {
+ idx = m_pListView->getNextSelectedItem( idx );
+ if ( idx != -1 )
+ {
+ CWaveFile *wav = (CWaveFile *)m_pListView->getUserData( idx, 0 );
+ if ( wav )
+ {
+ selected.AddToTail( wav );
+ }
+ }
+ } while ( idx != -1 );
+
+}
+
+void CWaveBrowser::ShowContextMenu( void )
+{
+ SetActiveTool( this );
+
+ BuildSelectionList( m_CurrentSelection );
+ if ( m_CurrentSelection.Count() <= 0 )
+ return;
+
+ POINT pt;
+ GetCursorPos( &pt );
+ ScreenToClient( (HWND)getHandle(), &pt );
+
+ // New scene, edit comments
+ mxPopupMenu *pop = new mxPopupMenu();
+
+ if ( m_CurrentSelection.Count() == 1 )
+ {
+ pop->add ("&Play", IDC_SB_PLAY );
+// pop->addSeparator();
+ }
+
+// pop->add( "Import Sentence Data", IDC_SB_IMPORTSENTENCE );
+// pop->add( "Export Sentence Data", IDC_SB_EXPORTSENTENCE );
+
+ pop->popup( this, pt.x, pt.y );
+}
+
+void CWaveBrowser::OnPlay()
+{
+ SetActiveTool( this );
+
+ BuildSelectionList( m_CurrentSelection );
+ if ( m_CurrentSelection.Count() == 1 )
+ {
+ CWaveFile *wav = m_CurrentSelection[ 0 ];
+ if ( wav )
+ {
+ wav->Play();
+ }
+ }
+}
+
+static void SplitFileName( char const *in, char *path, int maxpath, char *filename, int maxfilename )
+{
+ char drive[_MAX_DRIVE];
+ char dir[_MAX_DIR];
+ char fname[_MAX_FNAME];
+ char ext[_MAX_EXT];
+
+ _splitpath( in, drive, dir, fname, ext );
+
+ if ( dir[0] )
+ {
+ Q_snprintf( path, maxpath, "\\%s", dir );
+ }
+ else
+ {
+ path[0] = 0;
+ }
+ Q_snprintf( filename, maxfilename, "%s%s", fname, ext );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *se -
+//-----------------------------------------------------------------------------
+void CWaveBrowser::JumpToItem( CWaveFile *wav )
+{
+
+ SetActiveTool( this );
+
+ char path[ 256 ];
+ char filename[ 256 ];
+
+ SplitFileName( wav->GetFileName(), path, sizeof( path ), filename, sizeof( filename ) );
+
+ char *usepath = path + Q_strlen( "/sound/" );
+ PopulateTree( usepath );
+
+ int idx = 0;
+ int c = m_pListView->getItemCount();
+ for ( ; idx < c; idx++ )
+ {
+ CWaveFile *item = (CWaveFile *)m_pListView->getUserData( idx, 0 );
+ if ( !Q_stricmp( item->GetFileName(), wav->GetFileName() ) )
+ {
+ break;
+ }
+ }
+
+ if ( idx < c )
+ {
+ m_pListView->scrollToItem( idx );
+ }
+}
+
+CWaveFile *CWaveBrowser::FindEntry( char const *wavname, bool jump /*= false*/ )
+{
+ int idx = m_AllSounds.Find( wavname );
+ if ( idx != m_AllSounds.InvalidIndex() )
+ {
+ CWaveFile *wav = m_AllSounds[ idx ];
+ if ( jump )
+ {
+ JumpToItem( wav );
+ }
+
+ return wav;
+ }
+
+ return NULL;
+}
+
+int CWaveBrowser::GetSoundCount() const
+{
+ return m_AllSounds.Count();
+}
+
+CWaveFile *CWaveBrowser::GetSound( int index )
+{
+ if ( index < 0 || index >= (int)m_AllSounds.Count() )
+ return NULL;
+
+ return m_AllSounds[ index ];
+}
+
+
+void CWaveBrowser::OnSearch()
+{
+ SetActiveTool( this );
+
+ m_bTextSearch = true;
+
+ PopulateTree( GetSearchString());
+}
+
+void CWaveBrowser::OnCancelSearch()
+{
+ SetActiveTool( this );
+
+ m_bTextSearch = false;
+
+ PopulateTree( m_pFileTree->GetSelectedPath() );
+}
+
+char const *CWaveBrowser::GetSearchString()
+{
+ return m_pOptions->GetSearchString();
+}
+
+void CWaveBrowser::Think( float dt )
+{
+ int pending = fileloader->GetPendingLoadCount();
+ if ( pending != m_nPrevProcessed )
+ {
+ m_nPrevProcessed = pending;
+
+ // Put into suffix of window title
+ if ( pending == 0 )
+ {
+ SetSuffix( "" );
+ }
+ else
+ {
+ SetSuffix( va( " - %i", pending ) );
+ }
+ }
+
+ int c = fileloader->ProcessCompleted();
+ if ( c > 0 )
+ {
+ RepopulateTree();
+ }
+}
+
+void CWaveBrowser::SetEvent( CChoreoEvent *event )
+{
+ if ( event->GetType() != CChoreoEvent::SPEAK )
+ return;
+
+ SetCurrent( FacePoser_TranslateSoundName( event->GetParameters() ) );
+}
+
+void CWaveBrowser::SetCurrent( char const *filename )
+{
+// Get sound name and look up .wav from it
+ char const *p = filename;
+ if ( p &&
+ ( !Q_strnicmp( p, "sound/", 6 ) || !Q_strnicmp( p, "sound\\", 6 ) ) )
+ {
+ p += 6;
+ }
+
+ char fn[ 512 ];
+ Q_strncpy( fn, p, sizeof( fn ) );
+ Q_FixSlashes( fn );
+
+ int i;
+ int c = m_pListView->getItemCount();
+
+ for ( i = 0; i < c; ++i )
+ {
+ CWaveFile *wav = reinterpret_cast< CWaveFile * >( m_pListView->getUserData( i, COL_WAV ) );
+ if ( !wav )
+ continue;
+
+ char fixed[ 512 ];
+ Q_strncpy( fixed, wav->GetName(), sizeof( fixed ) );
+ Q_FixSlashes( fixed );
+
+ if ( !Q_stricmp( fixed, fn ) )
+ {
+ m_pListView->scrollToItem( i );
+ m_pListView->setSelected( i, true );
+ }
+ else
+ {
+ m_pListView->setSelected( i, false );
+ }
+ }
+}