Version 4.42 of MUSHclient introduces a new feature - the ability to play sounds already loaded into memory.
The reason for this is to make it easier for plugin authors to distribute a plugin with a batch of sound effects associated with it. Instead of having to install dozens of sounds, you can now simply distribute a SQLite database, and the plugin can then extract out sounds, as required, from the database.
Below I show how you can do this.
This feature is only available to Lua scripting, as Lua supports strings which are 8-bit "clean", in other words with any value including 0x00.
First, an example of creating such a database:
The code above creates or opens a database in the MUSHclient application directory called sounds.db.
Inside that is created a table (obviously you only do this once), which has the sound name as a text field, and the sound data as a blob (binary large object).
Next we read into memory a sound from the default sounds directory ("door_opening.wav").
To make it easy to insert this data into the database, which may contain binary zeroes, or quote symbols, we use bind_names to bind the data to the name "sound". This simplifies the INSERT INTO statement.
The step does the actual insert, putting the row into the database. If you wanted to add more rows, you would then re-execute the stmt:bind_names, stmt:step and stmt:reset for each additional sound.
The code above would be done by the plugin author to create the sound effects database.
Now, in the plugin, we can extract out sounds like this:
The code above assumes it is running in a plugin, so it opens the sounds.db database in the same directory that the plugin is loaded into (a reasonable place to put the database). Then it find the "open door" sound in the database, loads that into memory, and plays it from there.
Also see http://www.gammon.com.au/forum/?id=9567 which describes loading images from memory. Obviously you could store the sound effects and the images in the same database, which means you still only have one extra file to distribute (apart from the plugin itself).
The reason for this is to make it easier for plugin authors to distribute a plugin with a batch of sound effects associated with it. Instead of having to install dozens of sounds, you can now simply distribute a SQLite database, and the plugin can then extract out sounds, as required, from the database.
Below I show how you can do this.
This feature is only available to Lua scripting, as Lua supports strings which are 8-bit "clean", in other words with any value including 0x00.
First, an example of creating such a database:
-- open database on disk (in MUSHclient application directory)
db = assert (sqlite3.open (GetInfo (66) .. "sounds.db"))
-- create a table
assert (db:execute[[
DROP TABLE IF EXISTS sound_effects;
CREATE TABLE sound_effects (
name text,
sound blob,
PRIMARY KEY (name)
);
]])
local f = assert (io.open (GetInfo (74) .. "door_opening.wav", "rb"))
local s = f:read ("*a") -- read all of it
f:close () -- close it
local stmt = db:prepare ("INSERT INTO sound_effects VALUES (:name, :sound)")
stmt:bind_names {name = "open_door", sound = s}
stmt:step()
stmt:reset()
stmt:finalize()
-- close database
db:close()
The code above creates or opens a database in the MUSHclient application directory called sounds.db.
Inside that is created a table (obviously you only do this once), which has the sound name as a text field, and the sound data as a blob (binary large object).
Next we read into memory a sound from the default sounds directory ("door_opening.wav").
To make it easy to insert this data into the database, which may contain binary zeroes, or quote symbols, we use bind_names to bind the data to the name "sound". This simplifies the INSERT INTO statement.
The step does the actual insert, putting the row into the database. If you wanted to add more rows, you would then re-execute the stmt:bind_names, stmt:step and stmt:reset for each additional sound.
The code above would be done by the plugin author to create the sound effects database.
Now, in the plugin, we can extract out sounds like this:
-- open database on disk
db = assert (sqlite3.open (GetPluginInfo (20) .. "sounds.db")) -- open in plugins directory
for a in db:nrows([[SELECT * FROM sound_effects WHERE name = 'open_door']]) do
PlaySoundMemory (0, a.sound)
end
-- close database
db:close()
The code above assumes it is running in a plugin, so it opens the sounds.db database in the same directory that the plugin is loaded into (a reasonable place to put the database). Then it find the "open door" sound in the database, loads that into memory, and plays it from there.
Also see http://www.gammon.com.au/forum/?id=9567 which describes loading images from memory. Obviously you could store the sound effects and the images in the same database, which means you still only have one extra file to distribute (apart from the plugin itself).