Can I house an audio file on the form? - delphi

If I have an image file that I want to save to a stream, I can do so by placing an TImage on the form and using it as a container, like so:
Image1.Bitmap.LoadFromFile('ExampleFile.png');
Image1.Bitmap.SaveToStream(mybytestream);
Is there an equivalent for audio content, some object I can place on the form to house an audio file? If not, how do I use SaveToStream with audio?

begin
var myaudio := TByteStream.Create;
myaudio.LoadFromFile( 'myaudiofile.mp3' );
// do something with myaudio data
myaudio.SaveToFile( 'myaudiofile2.mp3' );
myaudio.Free;
end;
Is this what you're looking for? The example you gave does not "house" the image loaded on the form, so it's hard to decipher your question vs. your example.
Audio files are usually VERY LARGE and you'd want to store a compressed version as a resource in the app. But you'd want to use an audio player that can play a compressed file in the specified format saved in a run-time buffer like a TStream.
Yes, you can use a TImageList to save small images to your form, and it's loaded up when the program starts executing. You could create something like that to hold short audio samples like dings and chimes, but I wouldn't do it for something like an audiobook.
(People often ask how to attach a video to a PDF file, and they don't really think about the fact that the resulting PDF file may easily end up being over a gigabyte in size!)
You're better off having a folder that contains the audio clips, then loading them into an array of streams when the program starts up. That would be the simplest analogy to a TImageList but without the files being saved in the app itself.
An alternative might be to put the audio files into a zip file. Then you could attach the zip file as a resource to the app and extract the files from it. That would make it easier to build the app since you could change the contents of the zip file without having to change your build process at all.
Just be careful of referring to audios by name that might not be there. (This is a common problem that affects the use of fonts that may be attached to an app, and referring to one that's not there.)

Related

Ignore known header of video file

i have video uncompressed .avi video files. however they come with a known 2048kb header at the beginning of the file, such that no video program (Vlc player) recognises the file as video files. can i force VLC to ignore the first 2048kb? how?
what would be the easiest way to remove this header?
Unfortunately there is no known to me way of getting vlc to use a larger "probesize" or somehow just skip to byte X.
Also unfortunately there is no known to me way to add some "camouflage" or even add an empty chunk to the front of an avi container. Next approach could be to genereate a reference movie but also no automatic usage tools available at the best of my knowledge. And as there is also no way to just "set or change" the start offset of a file, we have to copy it.
My recommendation for copying parts of files is this sourceforge project: skf
https://sourceforge.net/projects/swissfileknife/?source=typ_redirect
some examples

Load many pictures in a form

I was asked to develop a game called "Flag Quiz" in which the player have to guess the correct name of the flag that appears in the middle of the screen.
Of course I have a lot of pictures (221 flags) and I have to put them inside the program because, when the button Play is pressed, the program has to pick randomly 10 of these flags.
Problem
I was thinking to use an ImageList but the flags are 480x311 and so Delphi asks me to separate the picutre in 30 different bitmaps. Can I do anything about this?
My idea, to avoid that problem, was the following (although I think that it's not very good): create 221 TPicture components (invisible to the user of course) and load in each of them a picture of a flag.
I'd prefer not using the last idea I had. Do you know any improvement?
This sort of problem is simply not suited to the form designer. You want to store 221 images, and managing that in the IDE will be horrible. Once you've got them all in you won't be able to see them readily because they will be base 16 encoded in a .dfm file. Under revision control it will be a mess because you won't be able to change individual images in a manageable and traceable manner.
The accepted way to do this is to use resources. If it were me, I'd arrange for my images to have predicatable names. For instance, flag1, flag2, etc. I'd generate a resource script (.rc) that listed all the flags. I'd compile that resource script to a compiled resource (.res) which is linked to the executable. I'd have the resource script and the image files committed to revision control.
Then at runtime you have a single TImage control to display the flag. Every time you need a new image you load it with TResourceStream, and push it into the TImage control.
Devexpress has a Componnect named cximagecolletion that you can put your images on it and save and load images from/to file
or you can save all flags in small access db and load it when you need using tadodataset
there is no doubt that if you put your images direct on your form your dfm grow very high and so you Get Into trouble
Personally I would store each file as an image in a dedicated subdirectory, using the country as a file name. Then I would read the subdirectory file names on entry to the program (so I have a list of countries that I can randomly choose from) and use TImage.LoadFromFile to display the flag. This is far easier to extend than using a resource file (IMHO).

How can I avoid having NSFileWrapper use lots memory when writing the file

I have an app that is using NSFileWrapper to create a backup of the user's data. This backup file contains text and media files (compression is not relevant here). Sometimes these backup files get quite large, over 200 MB in size. When I call NSFileWrapper -writeToURL... it appears to load the entire contents into memory as part of the writing process. On older devices, this causes my app to be terminated by the system due to memory constraints.
Is there a simple way to avoid having NSFileWrapper load everything into memory? I've read through every NSFileWrapper question on here that I could find. Any suggestions on how to tackle this?
Here is the current file structure of the backup file:
BackupContents.backupxyz
user.txt
- folder1
- audio files
asdf.caf
asdf2.caf
- folder2
- audio files
asdf3.caf
Again, please don't tell me to compress my audio files. That would only be a band-aid to a flawed design.
It seems like I could just move/copy all of the files into a directory using NSFileManager and then make that directory a package. Should I go down that path?
When an NSFileWrapper tree gets written out to disk, it will attempt to perform a hard-link of the original file to the the new location, but only if you supply a parameter for the originalContentsURL.
It sounds like you're constructing the file wrapper programmatically (for the backup scenario), so your files are probably scattered all over the filesystem. This would mean that when you writeToURL, you don't have an originalContentsURL. This means the hard-link logic is going to get skipped, and the file will get loaded so it can get rewritten.
So, if you want the hard-linking behavior, you need to find a way to provide an originalContentsURL. This is most easily done by supplying an appropriate URL to the initial writeToURL call.
Alternatively, you could try subclassing NSFileWrapper for regular files, and giving them an NSURL that they internally hang on to. You'd need to override writeToURL to pass this new URL up to super, but that URL should be enough to trigger the hard-link code. You'd want to then use this subclass of NSFileWrapper for the large files you want hard-linked in to place.

Opening a file in a memory stream with the correct program

My application saves files to a database field. It will take file types of .pdf, .doc, .xls, and .html (for example) save them to the table, so I can later extract the value and open it as a file.
Currently, I am saving a file (type pdf in this example) to a Varbinary field in a SQL table I created. I am then reading that file back into a memory stream using the following code:
TBlobField(FieldByName('FileData')).SaveToStream(FileData);
I can save this to desktop as a pdf just fine. However I would like to open it directly from the memory stream with the appropriate application (in this example adobe acrobat). I could write this to file first and then open it with shellexecute but i would rather open it directly. How would I go about accomplishing this? Any help would be greatly appreciated, I've looked all over and can only find examples using shellexecute to open Filepaths. ShellExecuteEx claims the lpFile can be set to an object but i haven't had any luck getting it to work.
You cannot do that. Memory is private to a process. When the Acrobat process executes, it cannot read your memory. You will have to save to a file and ask Acrobat to open that, or host a PDF viewer component in your process.

Download Directory and Contents

Is it possible to persuade the stream result to download an entire directory and it's contents? And if so, how? I've no problem getting it to download individual files, but I have a need to download a series of files that must be in a specific directory structure.
I don't think so.
Stream result allow you to download ONE content, with its MIME type, its name, etc.
This makes it impossible to work with a lot of files, with different names and content type.
What you can do is:
Render in a JSP the list of files (in anchor tags for example), everyone targeting the Action that will download that single file;
Call multiple Actions via scripting opening multiple pages (target="_blank") for every file you have (dangerous, annoying, almost useless...);
Create a zip with Java in server side, containing all your files and directories, then output the zip with Stream result.
I think you may consider the third option.

Resources