I'm writing an android app using Firemonkey.
For this reason I cannot use MMSystem's function sndPlaySound to play from the resource file, because that is Windows only.
The media player works and resources are supported under Firemonkey. But the media player cannot use resource files directly.
How do I play a sound from resource using TMediaPlayer?
Playing media that is not in a file
TMediaPlayer does not natively implement any non-filesystem data sources, so you will have to implement your own custom codec/media classes to access (and play) the resource data however you want. TMediaPlayer itself does not care if its FileName exists on a filesystem or not. It simply asks the TMediaCodecManager class to retreive a suitable TMedia object to access and play the data from whatever source the FileName refers to.
Create a custom class that derives from FMX.Media.TMedia and implement its abstract methods as needed (DoPlay(), DoStop(), GetDuration(), etc). This class accesses and plays the actual media data, so you can pass the desired FileName to it and have it load/access your resource stream as needed. Look at the default TMedia implementations for examples (FMX.Media.Win.TWindowsMedia, FMX.Media.Mac.TQTMedia, etc).
Create a custom class that derives from FMX.Media.TCustomMediaCodec and implement its abstract CreateFromFile() method to return an instance of your custom TMedia class. You can then register this class at program startup using FMX.Media.TMediaCodecManager.RegisterMediaCodecClass(). The trick is that you have to register the class using a file extension, so pick something that is unique and cannot be confused for a real file.
For example:
unit PlayMediaFromResource;
uses
..., FMX.Media;
type
TMyResourceMedia = class(TMedia)
...
protected
function GetDuration: TMediaTime; override;
function GetCurrent: TMediaTime; override;
procedure SetCurrent(const Value: TMediaTime); override;
function GetVideoSize: TPointF; override;
function GetMediaState: TMediaState; override;
function GetVolume: Single; override;
procedure SetVolume(const Value: Single); override;
procedure UpdateMediaFromControl; override;
procedure DoPlay; override;
procedure DoStop; override;
public
constructor Create(const AFileName: string); override;
destructor Destroy; override;
end;
TMyResourceMediaCodec = class(TCustomMediaCodec)
public
function CreateFromFile(const AFileName: string): TMedia; override;
end;
function TMyResourceMediaCodec.CreateFromFile(const AFileName: string): TMedia;
begin
Result := TMyResourceMedia.Create(AFileName);
end;
constructor TMyResourceMedia.Create(const AFileName: string);
var
ResName: string;
begin
ResName := ChangeFileExt(AFileName, ''); // strip off '.myres' file extension
// load resource identified by ResName as needed...
end;
....
initialization
TMediaCodecManager.RegisterMediaCodecClass('.myres', 'My Resource Stream',
TMediaType.Audio, TMyResourceMediaCodec);
Then you can do this:
MediaPlayer1.FileName := 'MyResourceName.myres';
MediaPlayer1.Play;
end;
--
Or you can just save the resource to a file
If you can somehow save the resource to a file and play it from there then everything is much easier. You can just use the stock TMediaPlayer.
Don't forget to delete the file when you're done playing otherwise you'll fill up the disk.