How to delete files created with ExtAudioFileCreateWithURL in c++? - c++

I am doing low level audio processing on iOS. As a result parts of my application are written in c++.
There I create and write to audio files. Files are created using ExtAudioFileCreateWithURL and written to using ExtAudioFileWriteAsync. Files are closed using ExtAudioFileDispose.
Sometimes files need to be deleted.
How do I delete files created with ExtAudioFileCreateWithURL in c++?
Since the files are opened with a CFURLRef the function CFURLDestroyResource seems to be the way to do this, but this function is deprecated and it is unclear to me what would replace this function.

I eventually managed to tackle this problem by writing a helper function in a Objective-C file and calling that function from the C++ code.
bool removeItemAtURL(CFURLRef url) {
NSFileManager *fileManager = [NSFileManager defaultManager];
return [fileManager removeItemAtURL: (__bridge NSURL *)url error: NULL];
}
Although this works I am unsure if it is save to use the NSFilemanger object in a time critical audio rendering thread. If so then it would be best to let deletion of files be handled in a different thread.

Related

uwp: How download files when app is in suspended mode

There is queue with links of files to download. I'm trying find the way to continue downloading when application goes to suspend mode.
According to official microsoft documentation suitable class for this is BackgroundDownloader, but it's handles only one current downloading process. It looks wrong to call in loop CreateDownload() method for every link without waiting for the completion of previous links, isn't right?
More logical in my opinion is using in-process background task. I see it this way:
Implement Run(IBackgroundTaskInstance) method of interface IBackgroundTask (it should stay alive even when app is suspended, right?)
Using custom event transmit the queue to the implemented method
Inside Run(IBackgroundTaskInstance) method use BackgroundDownloader (by implementing the execution of one instance at a time)
But I'm stuck even with simple implementation for one file downloading. Bellow my Run(IBackgroundTaskInstance) method implementation:
void Task::DownloaderTask::Run(IBackgroundTaskInstance ^ taskInstance)
{
TaskDeferral = taskInstance->GetDeferral();
std::wstring filename = L"Pleiades_large.jpg";
Uri^ uri = ref new Uri(ref new Platform::String(L"https://upload.wikimedia.org/wikipedia/commons/4/4e/Pleiades_large.jpg"));
Concurrency::create_task(KnownFolders::GetFolderForUserAsync(nullptr, KnownFolderId::PicturesLibrary))
.then([this, filename, uri](StorageFolder^ picturesLibrary)
{
return picturesLibrary->CreateFileAsync(ref new Platform::String(filename.c_str()), CreationCollisionOption::GenerateUniqueName);
}).then([this, filename, uri](StorageFile^ destinationFile) {
BackgroundDownloader^ downloader = ref new BackgroundDownloader();
DownloadOperation^ download = downloader->CreateDownload(uri, destinationFile);
download->StartAsync();
}).then([this](Concurrency::task<void> previousTask)
{
try
{
previousTask.get();
TaskDeferral->Complete();
}
catch (Platform::Exception^ ex)
{
wchar_t buffer[1024];
swprintf_s(buffer, L"Exception: %s", ex->Message);
OutputDebugString(buffer);
}
});
}
The code above only creates empty file, but using the same code without BackgroundTask it works correctly. I didn't find any restrictions for BackgroundDownloader inside BackgroundTask.
So, my questions are:
Is it right way of usage BackgroundTask?
Is there another approach to solving the problem?
Is this problem solvable at all?
I've found the cause of the unexpected behavior:
The line of code TaskDeferral->Complete(); was at the end of the method at first while it should be at the end of async call.
Therefore, initial implementation (published in question) is correct.
All that had to be done was to Rebuild project.

How to access the meta data of QMediaPlayer?

I want to access the metadata of the mp3 file and put it in the labels but the program doesn't read it.
I read http://doc.qt.io/qt-5/qmediametadata.html.
I wrote this code but it doesn't work properly (besides QFileInfo).
path = item->text(); //text is a path from QFileDialog::getOpenFileName
/*QMediaPlayer*/ sound.setMedia(QUrl::fromLocalFile(path));
QFileInfo info(path);
ui->label_3->setText(sound.metaData("Title").toString());
if (ui->label_3->text()=="")
ui->label_3->setText(sound.metaData("AlbumTitle").toString());
if (ui->label_3->text()=="")
ui->label_3->setText(info.baseName());
ui->label_5->setText(sound.metaData("Author").toString());
if (ui->label_5->text()=="")
ui->label_5->setText(sound.metaData("AlbumArtist").toString());
if (ui->label_5->text()=="")
ui->label_5->setText(sound.metaData("Composer").toString());
Library and multimedia are added.
Cause
It takes time for the media to be loaded after calling QMediaPlayer::setMedia, hence requesting the meta data right after the media has been set results in:
QVariant(Invalid)
Solution
I would suggest you to wait for the media to be loaded by connecting to the QMediaPlayer::mediaStatusChanged and reading the meta data once the status becomes QMediaPlayer::LoadedMedia.
Note: If you make sound a local variable, it would be destroyed when it goes out of scope. Better use auto *sound = new QMediaPlayer(this);.
Example
Here is an example I have prepared for you of how you could change your code in order to implement to proposed solution:
connect(sound, &QMediaPlayer::mediaStatusChanged, [this, sound, info](QMediaPlayer::MediaStatus status){
if (status == QMediaPlayer::LoadedMedia) {
ui->label_3->setText(sound->metaData("Title").toString());
if (ui->label_3->text()=="")
ui->label_3->setText(sound->metaData("AlbumTitle").toString());
if (ui->label_3->text()=="")
ui->label_3->setText(info.baseName());
ui->label_5->setText(sound->metaData("Author").toString());
if (ui->label_5->text()=="")
ui->label_5->setText(sound->metaData("AlbumArtist").toString());
if (ui->label_5->text()=="")
ui->label_5->setText(sound->metaData("Composer").toString());
}
});

WinRT API WIndows::System::Launcher::LaunchFileAsync() usage from C++

I'm trying to launch an image using WinRT API WIndows::System::Launcher::LaunchFileAsync().
Code snippet is as follows:
RoInitialize(RO_INIT_MULTITHREADED);
String^ imagePath = ref new String(L"C:\\Users\\GoodMan\\Pictures\\wood.png");
auto file = Storage::StorageFile::GetFileFromPathAsync(imagePath);
Windows::System::Launcher::LaunchFileAsync(file);
I'm getting this error from the LaunchFileAsync() API:
error C2665: 'Windows::System::Launcher::LaunchFileAsync' : none of
the 2 overloads could convert all the argument types
Can I please get help how to solve this. I'm very new to WinRT C++ coding .
The method GetFileFromPathAsync does not return a StorageFile, but it returns IAsyncOperation<StorageFile>^. What you have to do is convert the latter to the former, as follows:
using namespace concurrency;
String^ imagePath = ref new String(L"C:\\Users\\GoodMan\\Pictures\\wood.png");
auto task = create_task(Windows::Storage::StorageFile::GetFileFromPathAsync(imagePath));
task.then([this](Windows::Storage::StorageFile^ file)
{
Windows::System::Launcher::LaunchFileAsync(file);
});
Generally all Windows Store app framework methods that end in Async will return either an IAsyncOperation, or a task. These methods are what are known as asynchronous methods, and require some special handling. See this article for more info: Asynchronous programming in C++ .
So now everything is great, correct? Well, not quite. There is another issue with your code. It is that when you run the code above, you will get an access-denied error. The reason is that Windows Store Apps are sandboxed, and you cannot generally access just any file on the filesystem.
You are in luck, though, because you are trying to access a file in your Pictures folder. The Pictures folder is a special folder that Windows Store apps have access to. You can get at it using the KnownFolders class:
using namespace concurrency;
Windows::Storage::StorageFolder^ pictures =
Windows::Storage::KnownFolders::PicturesLibrary;
auto task = create_task(pictures->GetFileAsync("wood.png"));
task.then([this](Windows::Storage::StorageFile^ file)
{
Windows::System::Launcher::LaunchFileAsync(file);
});
Note that in order to access the Pictures folder your application has to declare it in the project manifest. To do so, double click on the Package.appmanifest file in the project "tree" in Visual Studio, and select the Capabilities tab. Then under Capabilities, check Pictures Library.

Get fd or handle from socket object

I want to create a native (c++) module for node.js which is able to send sockets to another node process, which is completely unrelated to the current process. To do so, I tought of using the ancillary library, which has a really, really easy API for this. The problem I have to solve now is how I can get the fd or the handle of a socket object of node.js.
There's a TCPWrap class in tcp_wrap.cc & tcp_wrap.h, which has a property called handle_, which holds a uv_tcp_t object from libuv, but that property is private. Also I can't #include because it's just a module of node.js an not directly in node.js itself. I don't know if it's a good idea to copy the source files to my module just to get the that class...
Have you any ides how I could do it?
I doesn't have to run on winows, tough.
Thanks!
I finally found a way to do it. You can find the node module here:
https://github.com/VanCoding/node-ancillary
I've just taken the headers "tcp_wrap.h","stream_wrap.h" and "handle_wrap.h" and then included "tcp_wrap.h".
I could then get the object the following way:
TCPWrap* wrap = static_cast<TCPWrap*>(args[0]->ToObject()->GetPointerFromInternalField(0));
StreamWrap* s = (StreamWrap*)wrap;
The following code then gives access to the file descriptor
s->GetStream()->fd

Monitoring a folder for new files in Windows

What is the best way to go about monitoring a folder to see when an image file has been added to it? Files are added approximately once a minute and the naming goes like this... image0001.jpg, image0002.jpg, image0003.jpg etc. I need to know when a file has been written to the folder so that my app can access and use it.
Look into directory change notifications.
As per previously mentioned, the directory change notifications is what you want.
I have looked into them as well, and the caveat I have seen is that windows will fire off the notification when the file starts to be written to the folder. If the file is large enough then you will receive the notification before the file has finished being written.
Check out this google search for various solutions for waiting until the file is completely written
Edit: I just saw that the question was tagged with c++, and I linked to a .Net search. Although what I provided may not be the correct language, I would think that you will still have the same issues on Windows no matter what system you are coding with.
FileSystemWatcher should be able to do that for you.
Change notifactions may cause some overhead, if you've NTFS, consider NTFS change journals.
You can use a polling method to monitor the folder. The loop will execute every 5 seconds, for example.
This method returns a list of new files:
List<string> files = new List<string>();
string path = #"C:\test\"; // whatever the path is
public List<string> GetNewFiles(string path)
{
// store all the filenames (only .jpg files) in a list
List<string> currentFiles = System.IO.Directory.GetFiles(path, "*.jpg");
if ( currentFiles.Count() > files.Count() )
{
count = newFiles.Length - files.Length;
List<string> newFiles = new List<string>();
foreach ( string file in currentFiles )
{
if ( !files.Contains(file) )
{
newFiles.Add(file);
}
}
}
files = currentFiles;
return newFiles;
}
This is the method that will poll every 5 seconds and call the previous method.
public void MonitorFolder()
{
while (true)
{
List<string> newFiles = GetNewFiles(path);
System.Threading.Thread.Sleep(5000); // 5000 milliseconds
}
}
Synch.variant FindFirstChangeNotification
Asynch.variant ReadDirectoryChangesW
This was the top google result for my search so I'll add this as an answer.
If you're using Qt, there's QFileSystemWatcher. I didn't know this existed and we happened to be using Qt, so I wasted more than a few hours using FindFirstChangeNotification to rewrite what was readily available to me until a colleague showed me the light.
Good learning experience though.
inotify might be your thing