1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "bladerunner/audio_cache.h"
24 
25 #include "common/stream.h"
26 
27 namespace BladeRunner {
28 
AudioCache()29 AudioCache::AudioCache() :
30 	_totalSize(0),
31 	_maxSize(2457600),
32 	_accessCounter(0) {}
33 
~AudioCache()34 AudioCache::~AudioCache() {
35 	for (uint i = 0; i != _cacheItems.size(); ++i) {
36 		free(_cacheItems[i].data);
37 	}
38 }
39 
canAllocate(uint32 size) const40 bool AudioCache::canAllocate(uint32 size) const {
41 	Common::StackLock lock(_mutex);
42 
43 	return _maxSize - _totalSize >= size;
44 }
45 
dropOldest()46 bool AudioCache::dropOldest() {
47 	Common::StackLock lock(_mutex);
48 
49 	if (_cacheItems.size() == 0)
50 		return false;
51 
52 	int oldest = -1;
53 	for (uint i = 1; i != _cacheItems.size(); ++i) {
54 		if (_cacheItems[i].refs == 0) {
55 			if (oldest == -1 || _cacheItems[i].lastAccess < _cacheItems[oldest].lastAccess) {
56 				oldest = i;
57 			}
58 		}
59 	}
60 
61 	if (oldest == -1) {
62 		return false;
63 	}
64 
65 	memset(_cacheItems[oldest].data, 0x00, _cacheItems[oldest].size);
66 	free(_cacheItems[oldest].data);
67 	_totalSize -= _cacheItems[oldest].size;
68 	_cacheItems.remove_at(oldest);
69 	return true;
70 }
71 
findByHash(int32 hash)72 byte *AudioCache::findByHash(int32 hash) {
73 	Common::StackLock lock(_mutex);
74 
75 	for (uint i = 0; i != _cacheItems.size(); ++i) {
76 		if (_cacheItems[i].hash == hash) {
77 			_cacheItems[i].lastAccess = _accessCounter++;
78 			return _cacheItems[i].data;
79 		}
80 	}
81 
82 	return nullptr;
83 }
84 
storeByHash(int32 hash,Common::SeekableReadStream * stream)85 void  AudioCache::storeByHash(int32 hash, Common::SeekableReadStream *stream) {
86 	Common::StackLock lock(_mutex);
87 
88 	uint32 size = stream->size();
89 	byte *data = (byte *)malloc(size);
90 	stream->read(data, size);
91 
92 	cacheItem item = {
93 		hash,
94 		0,
95 		_accessCounter++,
96 		data,
97 		size
98 	};
99 
100 	_cacheItems.push_back(item);
101 	_totalSize += size;
102 }
103 
incRef(int32 hash)104 void AudioCache::incRef(int32 hash) {
105 	Common::StackLock lock(_mutex);
106 
107 	for (uint i = 0; i != _cacheItems.size(); ++i) {
108 		if (_cacheItems[i].hash == hash) {
109 			++(_cacheItems[i].refs);
110 			return;
111 		}
112 	}
113 	assert(false && "AudioCache::incRef: hash not found");
114 }
115 
decRef(int32 hash)116 void AudioCache::decRef(int32 hash) {
117 	Common::StackLock lock(_mutex);
118 
119 	for (uint i = 0; i != _cacheItems.size(); ++i) {
120 		if (_cacheItems[i].hash == hash) {
121 			assert(_cacheItems[i].refs > 0);
122 			--(_cacheItems[i].refs);
123 			return;
124 		}
125 	}
126 	assert(false && "AudioCache::decRef: hash not found");
127 }
128 
129 } // End of namespace BladeRunner
130