Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support macOS promise file handling #6458

Merged
merged 1 commit into from
May 28, 2024

Conversation

grliszas14
Copy link
Contributor

Resolves: #6376

Getting file handle of file that hasn't been downloaded yet (in the middle of download) is a blocking call. If file is big or internet connection is slow this call freezes whole app.
Moved blocking call to a separate thread and allowed user to cancel import (if so, user goes back to usual flow, thread is going to finish it's job but the result is ignored, thread cleans up after itself)

  • I signed CLA
  • The title of the pull request describes an issue it addresses
  • If changes are extensive, then there is a sequence of easily reviewable commits
  • Each commit's message describes its purpose and effects
  • There are no behavior changes unnecessary for the stated purpose of the PR

Recommended:

  • Each commit compiles and runs on my machine without known undesirable changes of behavior

@@ -26,6 +28,12 @@ class IMPORT_EXPORT_API ImportProgressListener
};

virtual ~ImportProgressListener();

/// Set of functions called by importer before getting file handle as it may take a while to process
/// when dealing with file promise on macOS
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think doxygen-style comment will be recognized as comment to the first function only, not a whole group. Should be single-line C-style comment //

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

private:
void OnCancel(wxCommandEvent& event);

wxStaticText* m_statusText;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't mix code-style in a single header, we use camel-case prefixed with m for member variable names (except for POD structures)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -0,0 +1,25 @@
#pragma once
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File header comment is missing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

#include <wx/wx.h>
#include "wxPanelWrapper.h"

class ImportInfoDialog : public wxDialogWrapper
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -1306,6 +1308,26 @@ class ImportProgress final

}

void OnImportStarted(const wxString &filename) override
{
mImportInfoDialog = new ImportInfoDialog(filename, NULL, -1, XO("Importing files"));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dialog will appear on every import, even for tiny files that are readable, won't it be too intrusive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there is a way to determine if file is already readable or in the middle of download so I guess it needs to stay that way.
There's other option though: there is a progress dialog displayed right after obtaining file handle - instead of showing ImportInfo dialog and then ProgressDialog, we could display only ProgressDialog but sooner - but this needs some refactoring because ProgressDialog expects file handle in its constructor.
Right now it looks like ImportInfo dialog "evolves" into ProgressDialog

std::future<std::unique_ptr<ImportFileHandle>> future = promise->get_future();
std::thread([promise, plugin, fName, pProj]() mutable {
try {
auto result = plugin->Open(fName, pProj);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you make sure that all calls are thread-safe? Isn't it enough to try simply fopen file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried it, unfortunately fopen returns false-positive true and after that when you call plugin->Open UI freezes anyway.
I think this is the only option we have. The most vulnerable scenario is when user cancels importing because thread is working until it finishes it's job and by that time we're out of scope so I've used shared_ptr to take care of promise object to be still available (avoiding potential segfault that way)

{
wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

m_statusText = new wxStaticText(this, wxID_ANY, wxString::Format(wxT("Importing %s..."), filename.AfterLast(wxFileName::GetPathSeparator())));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use either XO or _ macro for translatable strings, otherwise gettext will not see your string definition

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

else
CenterOnScreen();

Bind(wxEVT_BUTTON, &ImportInfoDialog::OnCancel, this, wxID_CANCEL);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handler is already bound to the event via event table you've defined above, one of them should be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

wxYield();
}

bool OnCheckImportCancelled() override
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is...?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't be called after OnImportStartCleanup

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

return mImportInfoDialog->IsCancelled();
}

void OnImportStartCleanup() override
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't need to be a part of interface. Please consider using ProjectWindows or assigning this dialog directly to a project frame via GetProjectFrame

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assigned dialog to project frame but left function and renamed it (still need to call EndModal)

@grliszas14 grliszas14 force-pushed the copy_paste_improvements branch 3 times, most recently from 0bf2c03 to 0e54b3c Compare May 24, 2024 08:16
@@ -311,10 +312,10 @@ inline std::unique_ptr<ProgressDialog> MakeProgress(
*/
inline std::unique_ptr<GenericProgressDialog> MakeGenericProgress(
const WindowPlacement &placement,
const TranslatableString &title, const TranslatableString &message)
const TranslatableString &title, const TranslatableString &message, int style = 0x0002 | 0x0008 | 0x0020)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last thing: lib-basic-ui is a toolkit-neutral library, better define enum and map it to a framework-specific value in the library that implements BasicUI interface, which is lib-wx-init

if(err != 0 || (S_ISREG(s.st_mode) && s.st_blocks == 0))
{
int dialogStyle = BasicUI::ProgressCanAbort | BasicUI::ProgressAppModal | BasicUI::ProgressShowElapsedTime | BasicUI::ProgressSmooth;
auto dialog = BasicUI::MakeGenericProgress({}, XO("Audacity"), XO("This may take several seconds"), dialogStyle);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be XO("Importing files"), XO("Importing %s...") where %s is the file that currently is being imported

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed 👍

@grliszas14 grliszas14 merged commit 17a0b53 into audacity:master May 28, 2024
10 checks passed
@grliszas14 grliszas14 deleted the copy_paste_improvements branch May 28, 2024 16:51
@vsverchinsky
Copy link
Collaborator

@grliszas14 for a single-commit PR's please use "rebase and merge", that makes history look much clearer. Ideally before merging a branch with multiple commits rebase your branch on top of recent master first, wait checks are complete and then do "merge commit"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support clipboard promise when importing through copy/paste
3 participants