~ubuntu-branches/ubuntu/trusty/0ad/trusty-backports

« back to all changes in this revision

Viewing changes to source/soundmanager/SoundManager.cpp

  • Committer: Package Import Robot
  • Author(s): Vincent Cheng
  • Date: 2013-09-17 01:08:10 UTC
  • mfrom: (5.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20130917010810-dqdu2kk39eu5jbx9
Add debian/patches/fix-arm-ftbfs.patch to fix FTBFS on armel and armhf.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2012 Wildfire Games.
 
1
        /* Copyright (C) 2013 Wildfire Games.
2
2
 * This file is part of 0 A.D.
3
3
 *
4
4
 * 0 A.D. is free software: you can redistribute it and/or modify
17
17
 
18
18
#include "precompiled.h"
19
19
 
 
20
#include "ISoundManager.h"
20
21
#include "SoundManager.h"
21
22
 
22
23
#include "soundmanager/data/SoundData.h"
23
24
#include "soundmanager/items/CSoundItem.h"
24
25
#include "soundmanager/items/CBufferItem.h"
25
26
#include "soundmanager/items/CStreamItem.h"
26
 
#include "soundmanager/js/SoundPlayer.h"
27
 
#include "soundmanager/js/AmbientSound.h"
28
 
#include "soundmanager/js/MusicSound.h"
29
 
#include "soundmanager/js/Sound.h"
30
27
#include "lib/external_libraries/libsdl.h"
31
28
#include "ps/CLogger.h"
32
29
#include "ps/CStr.h"
33
30
#include "ps/Profiler2.h"
34
31
 
35
 
CSoundManager* g_SoundManager = NULL;
 
32
ISoundManager* g_SoundManager = NULL;
36
33
 
37
34
#define         SOURCE_NUM              64
38
35
 
40
37
 
41
38
class CSoundManagerWorker
42
39
{
 
40
        NONCOPYABLE(CSoundManagerWorker);
 
41
 
43
42
public:
44
43
        CSoundManagerWorker()
45
44
        {
59
58
                delete m_DeadItems;
60
59
        }
61
60
 
62
 
        /**
63
 
         * Called by main thread, when the online reporting is enabled/disabled.
64
 
         */
65
61
        void SetEnabled(bool enabled)
66
62
        {
67
63
                CScopeLock lock(m_WorkerMutex);
71
67
                }
72
68
        }
73
69
 
74
 
        /**
75
 
         * Called by main thread to request shutdown.
76
 
         * Returns true if we've shut down successfully.
77
 
         * Returns false if shutdown is taking too long (we might be blocked on a
78
 
         * sync network operation) - you mustn't destroy this object, just leak it
79
 
         * and terminate.
80
 
         */
81
70
        bool Shutdown()
82
71
        {
83
72
                {
84
73
                        CScopeLock lock(m_WorkerMutex);
 
74
 
85
75
                        m_Shutdown = true;
86
76
                        m_Enabled = false;
87
77
 
89
79
                        while (lstr != m_Items->end())
90
80
                        {
91
81
                                delete *lstr;
92
 
                                lstr++;
 
82
                                ++lstr;
93
83
                        }
94
84
 
95
85
                }
98
88
 
99
89
                return true;
100
90
        }
 
91
 
101
92
        void addItem( ISoundItem* anItem )
102
93
        {
103
94
                CScopeLock lock(m_WorkerMutex);
112
103
                while (deadItems != m_DeadItems->end())
113
104
                {   
114
105
                        delete *deadItems;
115
 
                        deadItems++;
 
106
                        ++deadItems;
116
107
 
117
108
                        AL_CHECK
118
109
                }
132
123
 
133
124
        void Run()
134
125
        {
135
 
 
136
 
                // Wait until the main thread wakes us up
137
126
                while ( true )
138
127
                {
139
128
                        g_Profiler2.RecordRegionLeave("semaphore wait");
146
135
                        if (!GetEnabled())
147
136
                                continue;
148
137
 
149
 
                        int pauseTime = 1000;
 
138
                        int pauseTime = 500;
150
139
                        if ( g_SoundManager->InDistress() )
151
140
                                pauseTime = 50;
152
141
 
172
161
                                                CScopeLock lock(m_DeadItemsMutex);
173
162
                                                m_DeadItems->push_back(*lstr);
174
163
                                        }
175
 
                                        lstr++;
 
164
                                        ++lstr;
176
165
 
177
166
                                        AL_CHECK
178
167
                                }
207
196
        CMutex m_DeadItemsMutex;
208
197
 
209
198
        // Shared by main thread and worker thread:
210
 
        // These variables are all protected by m_WorkerMutex
 
199
        // These variables are all protected by a mutexes
211
200
        ItemsList* m_Items;
212
201
        ItemsList* m_DeadItems;
213
202
 
214
203
        bool m_Enabled;
215
204
        bool m_Shutdown;
 
205
 
 
206
        CSoundManagerWorker(ISoundManager* UNUSED(other)){};
216
207
};
217
 
#endif
218
 
 
219
 
void CSoundManager::ScriptingInit()
220
 
{
221
 
        JAmbientSound::ScriptingInit();
222
 
        JMusicSound::ScriptingInit();
223
 
        JSound::ScriptingInit();
224
 
        JSoundPlayer::ScriptingInit();
225
 
}
226
 
 
227
 
 
228
 
#if CONFIG2_AUDIO
229
 
 
230
 
 
231
 
void CSoundManager::CreateSoundManager()
 
208
 
 
209
void ISoundManager::CreateSoundManager()
232
210
{
233
211
        g_SoundManager = new CSoundManager();
234
212
}
235
213
 
236
 
void CSoundManager::SetEnabled(bool doEnable)
 
214
void ISoundManager::SetEnabled(bool doEnable)
237
215
{
238
216
        if ( g_SoundManager && !doEnable ) 
239
217
        {
241
219
        }
242
220
        else if ( ! g_SoundManager && doEnable ) 
243
221
        {
244
 
                CSoundManager::CreateSoundManager();
 
222
                ISoundManager::CreateSoundManager();
245
223
        }
246
224
}
 
225
void ISoundManager::CloseGame()
 
226
{
 
227
        if ( CSoundManager* aSndMgr = (CSoundManager*)g_SoundManager )
 
228
                aSndMgr->SetAmbientItem( NULL );
 
229
}
247
230
 
248
231
void CSoundManager::al_ReportError(ALenum err, const char* caller, int line)
249
232
{
261
244
{
262
245
        m_CurrentEnvirons       = 0;
263
246
        m_ALSourceBuffer        = NULL;
 
247
        m_Device        = NULL;
 
248
        m_Context       = NULL;
 
249
        m_Worker        = NULL;
 
250
        m_PlayListItems = NULL;
264
251
        m_CurrentTune           = 0;
265
 
        m_SourceCOunt           = 0;
266
252
        m_Gain                          = 1;
267
253
        m_MusicGain                     = 1;
268
254
        m_AmbientGain           = 1;
269
255
        m_ActionGain            = 1;
 
256
        m_UIGain = 1;
270
257
        m_BufferCount           = 50;
271
 
        m_BufferSize            = 65536;
 
258
        m_BufferSize            = 98304;
 
259
        m_SoundEnabled          = true;
272
260
        m_MusicEnabled          = true;
 
261
        m_MusicPaused     = false;
 
262
        m_AmbientPaused   = false;
 
263
        m_ActionPaused     = false;
 
264
 
273
265
        m_DistressTime  = 0;
274
266
        m_DistressErrCount = 0;
275
267
 
276
 
        m_Enabled                       = AlcInit() == INFO::OK;
277
 
        m_ItemsMap                      = new ItemsMap;
278
 
        InitListener();
279
 
 
280
 
        m_Worker = new CSoundManagerWorker();
281
 
        m_Worker->SetEnabled( true );
 
268
        m_PlayingPlaylist = false;
 
269
        m_LoopingPlaylist = false;
 
270
        m_RunningPlaylist = false;
 
271
        m_PlaylistGap      = 0;
 
272
 
 
273
        m_Enabled = false;
 
274
        AlcInit();
 
275
 
 
276
        if ( m_Enabled )
 
277
        {
 
278
                InitListener();
 
279
 
 
280
                m_PlayListItems = new PlayList;
 
281
 
 
282
                m_Worker = new CSoundManagerWorker();
 
283
                m_Worker->SetEnabled( true );
 
284
        }
282
285
}
283
286
 
284
287
CSoundManager::~CSoundManager()
285
 
{       
286
 
        if (m_Worker->Shutdown())
 
288
{
 
289
        if (m_Worker )
 
290
        {
 
291
                AL_CHECK
 
292
                m_Worker->Shutdown();
 
293
                AL_CHECK
 
294
                m_Worker->CleanupItems();
 
295
                AL_CHECK
 
296
 
287
297
                delete m_Worker;
288
 
 
289
 
        delete m_ItemsMap;
290
 
        
 
298
        }
 
299
        AL_CHECK
 
300
 
 
301
        for (std::map<std::wstring, CSoundGroup*>::iterator it = m_SoundGroups.begin(); it != m_SoundGroups.end(); ++it)
 
302
                delete it->second;
 
303
        m_SoundGroups.clear();
 
304
 
 
305
        if ( m_PlayListItems )
 
306
                delete m_PlayListItems;
 
307
 
291
308
        if ( m_ALSourceBuffer != NULL )
292
309
                delete[] m_ALSourceBuffer;
293
310
 
294
 
        alcDestroyContext(m_Context);
295
 
        alcCloseDevice(m_Device);
 
311
        if ( m_Context )
 
312
                alcDestroyContext(m_Context);
 
313
        
 
314
        if ( m_Device )
 
315
                alcCloseDevice(m_Device);
296
316
}
297
317
 
298
318
 
302
322
        Status ret = INFO::OK;
303
323
 
304
324
        m_Device = alcOpenDevice(NULL);
305
 
        if(m_Device)
 
325
        if (m_Device)
306
326
        {
307
327
                ALCint attribs[] = {ALC_STEREO_SOURCES, 16, 0};
308
328
                m_Context = alcCreateContext(m_Device, &attribs[0]);
309
329
 
310
 
                if(m_Context)
 
330
                if (m_Context)
311
331
                {
312
332
                        alcMakeContextCurrent(m_Context);
313
333
                        m_ALSourceBuffer = new ALSourceHolder[SOURCE_NUM];
325
345
                                        m_ALSourceBuffer[x].SourceItem  = NULL;
326
346
 
327
347
                                }
 
348
                                m_Enabled = true;
328
349
                        }
329
350
                        else
330
351
                        {
403
424
        {
404
425
                if ( ! m_ALSourceBuffer[x].SourceItem )
405
426
                {
406
 
                        m_SourceCOunt++;
407
427
                        m_ALSourceBuffer[x].SourceItem = anItem;
408
428
                        return m_ALSourceBuffer[x].ALSource;
409
429
                }
418
438
        {
419
439
                if ( m_ALSourceBuffer[x].ALSource == theSource )
420
440
                {
421
 
                        m_SourceCOunt--;
422
441
                        m_ALSourceBuffer[x].SourceItem = NULL;
423
442
                        return;
424
443
                }
425
444
        }
426
445
}
427
446
 
428
 
void CSoundManager::SetMemoryUsage(long bufferSize, int bufferCount)
429
 
{
430
 
        m_BufferCount = bufferCount;
431
 
        m_BufferSize = bufferSize;
432
 
}
433
447
long CSoundManager::GetBufferCount()
434
448
{
435
449
        return m_BufferCount;
439
453
        return m_BufferSize;
440
454
}
441
455
 
 
456
void CSoundManager::AddPlayListItem( const VfsPath* itemPath)
 
457
{
 
458
  m_PlayListItems->push_back( *itemPath );
 
459
}
 
460
 
 
461
void CSoundManager::ClearPlayListItems()
 
462
{
 
463
  if ( m_PlayingPlaylist )
 
464
    SetMusicItem( NULL );
 
465
 
 
466
  m_PlayingPlaylist = false;
 
467
  m_LoopingPlaylist = false;
 
468
  m_RunningPlaylist = false;
 
469
 
 
470
  m_PlayListItems->clear();
 
471
}
 
472
 
 
473
void CSoundManager::StartPlayList( bool doLoop )
 
474
{
 
475
        if ( m_MusicEnabled )
 
476
        {
 
477
          if ( m_PlayListItems->size() > 0 )
 
478
          {
 
479
            m_PlayingPlaylist = true;
 
480
            m_LoopingPlaylist = doLoop;
 
481
            m_RunningPlaylist = false;
 
482
            
 
483
            ISoundItem* aSnd = LoadItem( (m_PlayListItems->at( 0 )) );
 
484
            if ( aSnd )
 
485
              SetMusicItem( aSnd );
 
486
            else
 
487
            {
 
488
              SetMusicItem( NULL );
 
489
            }
 
490
          }
 
491
        }
 
492
}
 
493
 
442
494
void CSoundManager::SetMasterGain(float gain)
443
495
{
444
 
        m_Gain = gain;
445
 
        alListenerf( AL_GAIN, m_Gain);
446
 
        AL_CHECK
 
496
        if ( m_Enabled )
 
497
        {
 
498
                m_Gain = gain;
 
499
                alListenerf( AL_GAIN, m_Gain);
 
500
                AL_CHECK
 
501
        }
447
502
}
448
503
 
449
504
void CSoundManager::SetMusicGain(float gain)
458
513
{
459
514
        m_ActionGain = gain;
460
515
}
 
516
void CSoundManager::SetUIGain(float gain)
 
517
{
 
518
        m_UIGain = gain;
 
519
}
461
520
 
462
521
 
463
522
ISoundItem* CSoundManager::LoadItem(const VfsPath& itemPath)
464
523
{       
465
524
        AL_CHECK
466
525
 
467
 
        CSoundData* itemData = CSoundData::SoundDataFromFile(itemPath);
 
526
        if ( m_Enabled )
 
527
        {
 
528
                CSoundData* itemData = CSoundData::SoundDataFromFile(itemPath);
468
529
 
469
 
        AL_CHECK
470
 
        if ( itemData )
471
 
                return CSoundManager::ItemForData( itemData );
 
530
                AL_CHECK
 
531
                if ( itemData )
 
532
                        return CSoundManager::ItemForData( itemData );
 
533
        }
472
534
 
473
535
        return NULL;
474
536
}
480
542
 
481
543
        AL_CHECK
482
544
        
483
 
        if (itemData != NULL)
 
545
        if ( m_Enabled && (itemData != NULL) )
484
546
        {
485
547
                if (itemData->IsOneShot())
486
548
                {
504
566
 
505
567
void CSoundManager::IdleTask()
506
568
{
507
 
        AL_CHECK
508
 
        if (m_CurrentTune)
509
 
                m_CurrentTune->EnsurePlay();
510
 
        AL_CHECK
511
 
        if (m_CurrentEnvirons)
512
 
                m_CurrentEnvirons->EnsurePlay();
513
 
        AL_CHECK
514
 
        if (m_Worker)
515
 
                m_Worker->CleanupItems();
516
 
        AL_CHECK
517
 
}
518
 
 
519
 
ISoundItem*     CSoundManager::ItemForEntity( entity_id_t source, CSoundData* sndData)
520
 
{
521
 
        ISoundItem*             currentItem = NULL;
522
 
        if ( false ) 
 
569
        if ( m_Enabled )
523
570
        {
524
 
                ItemsMap::iterator              itemFound = m_ItemsMap->find( source );
525
 
                if ( itemFound != m_ItemsMap->end() )
 
571
                if (m_CurrentTune)
526
572
                {
527
 
                        currentItem = itemFound->second;
528
 
                        if ( currentItem->CanAttach( sndData ) )
529
 
                        {
530
 
                                currentItem->Attach( sndData );
531
 
                                LOGERROR(L"did REUSE items source = %d", m_SourceCOunt);
532
 
                        }
533
 
                        else
534
 
                        {
535
 
                                m_ItemsMap->erase( itemFound );
536
 
                                currentItem->StopAndDelete();
537
 
                                LOGERROR(L"item UNREUSABLE for data = %d", m_SourceCOunt);
538
 
                                currentItem = NULL;
 
573
                        m_CurrentTune->EnsurePlay();
 
574
                        if ( m_PlayingPlaylist && m_RunningPlaylist )
 
575
                        {
 
576
                                if ( m_CurrentTune->Finished() )
 
577
                                {
 
578
                                        if ( m_PlaylistGap == 0 )
 
579
                                        {
 
580
                                                m_PlaylistGap = timer_Time() + 15;
 
581
                                        }
 
582
                                        else if ( m_PlaylistGap < timer_Time() )
 
583
                                        {
 
584
                                                m_PlaylistGap = 0;
 
585
                                                PlayList::iterator it = find (m_PlayListItems->begin(), m_PlayListItems->end(), *(m_CurrentTune->GetName()) );
 
586
                                                if ( it != m_PlayListItems->end() )
 
587
                                                {
 
588
                                                        ++it;
 
589
 
 
590
                                                        Path nextPath;
 
591
                                                        if ( it == m_PlayListItems->end() )
 
592
                                                                nextPath = m_PlayListItems->at( 0 );
 
593
                                                        else
 
594
                                                                nextPath = *it;
 
595
 
 
596
                                                        ISoundItem* aSnd = LoadItem( nextPath );
 
597
                                                        if ( aSnd )
 
598
                                                                SetMusicItem( aSnd );
 
599
                                                }
 
600
                                        }
 
601
                                }
539
602
                        }
540
603
                }
 
604
 
 
605
                if (m_CurrentEnvirons)
 
606
                        m_CurrentEnvirons->EnsurePlay();
 
607
 
 
608
                if (m_Worker)
 
609
                        m_Worker->CleanupItems();
 
610
 
541
611
        }
542
 
        if ( currentItem == NULL )
543
 
        {
 
612
}
 
613
 
 
614
ISoundItem*     CSoundManager::ItemForEntity( entity_id_t UNUSED(source), CSoundData* sndData)
 
615
{
 
616
        ISoundItem* currentItem = NULL;
 
617
 
 
618
        if ( m_Enabled )
544
619
                currentItem = ItemForData( sndData );
545
 
                if ( currentItem )
546
 
                        m_ItemsMap->insert(std::make_pair( source, currentItem));               
547
 
        }
548
620
 
549
621
        return currentItem;
550
622
}
563
635
        alDistanceModel(AL_LINEAR_DISTANCE);
564
636
}
565
637
 
566
 
void CSoundManager::PlayActionItem(ISoundItem* anItem)
567
 
{
568
 
        if (anItem)
569
 
        {
570
 
                if (m_Enabled && (m_ActionGain > 0))
571
 
                {
572
 
                        anItem->SetGain( m_ActionGain );
573
 
                        anItem->Play();
574
 
                        AL_CHECK
575
 
                }
576
 
        }
577
 
}
578
638
void CSoundManager::PlayGroupItem(ISoundItem* anItem, ALfloat groupGain )
579
639
{
580
640
        if (anItem)
597
657
        m_MusicEnabled = isEnabled;
598
658
}
599
659
 
 
660
void CSoundManager::PlayAsGroup(const VfsPath& groupPath, CVector3D sourcePos, entity_id_t source, bool ownedSound)
 
661
{
 
662
        // Make sure the sound group is loaded
 
663
        CSoundGroup* group;
 
664
        if (m_SoundGroups.find(groupPath.string()) == m_SoundGroups.end())
 
665
        {
 
666
                group = new CSoundGroup();
 
667
                if (!group->LoadSoundGroup(L"audio/" + groupPath.string() ))
 
668
                {
 
669
                        LOGERROR(L"Failed to load sound group '%ls'", groupPath.string().c_str());
 
670
                        delete group;
 
671
                        group = NULL;
 
672
                }
 
673
                // Cache the sound group (or the null, if it failed)
 
674
                m_SoundGroups[groupPath.string()] = group;
 
675
        }
 
676
        else
 
677
        {
 
678
                group = m_SoundGroups[groupPath.string()];
 
679
        }
 
680
 
 
681
        // Failed to load group -> do nothing
 
682
        if ( group && ( ownedSound || !group->TestFlag( eOwnerOnly ) ) )
 
683
                group->PlayNext(sourcePos, source);
 
684
}
 
685
 
 
686
void CSoundManager::PlayAsMusic( const VfsPath& itemPath, bool looping )
 
687
{
 
688
                UNUSED2( looping );
 
689
 
 
690
    ISoundItem* aSnd = LoadItem(itemPath);
 
691
    if (aSnd != NULL)
 
692
      SetMusicItem( aSnd );
 
693
}
 
694
 
 
695
void CSoundManager::PlayAsAmbient( const VfsPath& itemPath, bool looping )
 
696
{
 
697
                UNUSED2( looping );
 
698
    ISoundItem* aSnd = LoadItem(itemPath);
 
699
    if (aSnd != NULL)
 
700
      SetAmbientItem( aSnd );
 
701
}
 
702
 
 
703
 
 
704
void CSoundManager::PlayAsUI(const VfsPath& itemPath, bool looping)
 
705
{
 
706
        IdleTask();
 
707
        
 
708
  if ( ISoundItem* anItem = LoadItem(itemPath) )
 
709
        {
 
710
                if (m_Enabled && (m_UIGain > 0))
 
711
                {
 
712
                        anItem->SetGain(m_UIGain);
 
713
                        anItem->SetLooping( looping );
 
714
                        anItem->PlayAndDelete();
 
715
                }
 
716
        }
 
717
        AL_CHECK
 
718
}
 
719
 
 
720
 
 
721
void CSoundManager::Pause(bool pauseIt)
 
722
{
 
723
  PauseMusic(pauseIt);
 
724
  PauseAmbient(pauseIt);
 
725
  PauseAction(pauseIt);
 
726
}
 
727
 
 
728
void CSoundManager::PauseMusic (bool pauseIt)
 
729
{
 
730
        if (m_CurrentTune && pauseIt && !m_MusicPaused )
 
731
        {
 
732
                m_CurrentTune->FadeAndPause( 1.0 );
 
733
        }
 
734
        else if ( m_CurrentTune && m_MusicPaused && !pauseIt && m_MusicEnabled )
 
735
        {
 
736
                m_CurrentTune->SetGain(0);
 
737
                m_CurrentTune->Resume();
 
738
                m_CurrentTune->FadeToIn( m_MusicGain, 1.0);
 
739
        }
 
740
        m_MusicPaused = pauseIt;
 
741
}
 
742
 
 
743
void CSoundManager::PauseAmbient (bool pauseIt)
 
744
{
 
745
  if (m_CurrentEnvirons && pauseIt)
 
746
    m_CurrentEnvirons->Pause();
 
747
  else if ( m_CurrentEnvirons )
 
748
    m_CurrentEnvirons->Resume();
 
749
 
 
750
  m_AmbientPaused = pauseIt;
 
751
}
 
752
 
 
753
void CSoundManager::PauseAction (bool pauseIt)
 
754
{
 
755
  m_ActionPaused = pauseIt;
 
756
}
 
757
 
600
758
void CSoundManager::SetMusicItem(ISoundItem* anItem)
601
759
{
602
760
        AL_CHECK
613
771
                if (m_MusicEnabled && m_Enabled)
614
772
                {
615
773
                        m_CurrentTune = anItem;
616
 
                        m_CurrentTune->SetIsManaged( true );
617
774
                        m_CurrentTune->SetGain(0);
618
 
                        m_CurrentTune->PlayLoop();
 
775
 
 
776
                        if ( m_PlayingPlaylist )
 
777
                        {
 
778
                                m_RunningPlaylist = true;
 
779
                                m_CurrentTune->Play();
 
780
                        }
 
781
                        else
 
782
                                m_CurrentTune->PlayLoop();
 
783
 
619
784
                        m_CurrentTune->FadeToIn( m_MusicGain, 1.00);
620
785
                }
621
786
                else
640
805
                if (m_Enabled && (m_AmbientGain > 0))
641
806
                {
642
807
                        m_CurrentEnvirons = anItem;
643
 
                        m_CurrentEnvirons->SetIsManaged( true );
644
808
                        m_CurrentEnvirons->SetGain(0);
645
809
                        m_CurrentEnvirons->PlayLoop();
646
810
                        m_CurrentEnvirons->FadeToIn( m_AmbientGain, 2.00);
648
812
        }
649
813
        AL_CHECK
650
814
}
 
815
#else // CONFIG2_AUDIO
 
816
 
 
817
void ISoundManager::CreateSoundManager(){}
 
818
void ISoundManager::SetEnabled(bool UNUSED(doEnable)){}
 
819
void ISoundManager::CloseGame(){}
651
820
 
652
821
#endif // CONFIG2_AUDIO
653
822