CommandLine autoplay

Hello dear programmers.
I am using a global variable to run a file from the command line. This is probably not correct, but it works on both Mac and Windows. The only thing I can’t figure out is how to enable autoplay when clicking on a file. If I use the function in the main, then the player stops working correctly.
The code:
Main.cpp

#include <JuceHeader.h>
#include "PlayingSoundFilesTutorial_01.h"
//==============================================================================
String pathWay; //global variable
//==============================================================================
class Application    : public JUCEApplication
{
public:
................................
    void initialise (const String& commandLine) override
    {
        mainWindow.reset (new MainWindow (getApplicationName()));
        
        String potentialPath = commandLine.unquoted();
        File file;
        if (File::isAbsolutePath (potentialPath))
        {
            file = File (potentialPath);
            pathWay = file.getFullPathName();
        }
    }
    
    void shutdown() override {...}
===============================================================
    void systemRequestedQuit() override {...}
   
    void anotherInstanceStarted (const String& commandLine) override
    {       
        String potentialPath = commandLine.unquoted();
        File file;
        if (File::isAbsolutePath (potentialPath))
        {
            file = File (potentialPath);
            pathWay = file.getFullPathName();
        }
    }   //==========================================================================
    class MainWindow    : public DocumentWindow
    {
    ................................
    };

private:
    std::unique_ptr<MainWindow> mainWindow;
};

//==============================================================================
START_JUCE_APPLICATION (Application)

MainContentComponent.h

#pragma once
extern String pathWay;
//==============================================================================
class MainContentComponent:     public AudioAppComponent,
                                                       public ChangeListener
{...}
public: {...}

~MainContentComponent() override {...}
    void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override {...}
    void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override {...}
    void releaseResources() override {...}
  ................................
private:

    void openButtonClicked()
    {
        chooser = std::make_unique<FileChooser> ("Select a Wave file to play...",
                                                       File{},
                                                       "*.wav, *.aiff, *.mp3, *.mp4");
        auto chooserFlags = FileBrowserComponent::openMode
                          | FileBrowserComponent::canSelectFiles;

        chooser->launchAsync (chooserFlags, [this] (const FileChooser& fc)
        {
            auto file = fc.getResult();

            if (file != File{})
            {
                auto* reader = formatManager.createReaderFor (file);

                if (reader != nullptr)
                {
                    auto newSource = std::make_unique<AudioFormatReaderSource> (reader, true);
                    transportSource.setSource (newSource.get(), 0, nullptr, reader->sampleRate);
                    playButton.setEnabled (true);
                    readerSource.reset (newSource.release());
                    DBG(reader->getFormatName());
                    DBG(file.getFullPathName());
                    pathWay = file.getFullPathName(); //global variable
                    grabKeyboardFocus();
                    if (autoPlay == 1)
                        changeState (Starting);
                    else
                        changeState (Stopped);
                }
            }
        });
    }

    void playButtonClicked()
    {       
        File file {pathWay}; //global variable
        
        if (file.exists())
        {        
            auto* reader = formatManager.createReaderFor (file);

            if (reader != nullptr)
            {
                auto newSource = std::make_unique<AudioFormatReaderSource> (reader, true);
                transportSource.setSource (newSource.get(), 0, nullptr, reader->sampleRate);
                playButton.setEnabled (true);
                readerSource.reset (newSource.release());
                DBG(reader->getFormatName());
                DBG(file.getFullPathName());
                changeState (Starting);            
            }            
        }
        else
            changeState (Starting); 
    }


    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
};

Thank you all in advance for your response.

Do you mean “auto play” when double clicking a file from the OS? this is configured in the OS, not your application. Essentially you need to configure the OS that your program should be launched for a given file type.

The OS is set up that way. Double-clicking the program loads and opens the file, but i have to press the play button to play it. By autoplay, I meant automatic playback of the downloaded file. An attempt to move the playButtonClicked function to Main.cpp destroys the player itself and playback does not work correctly.

AH! my bad! You should just be able to call the playButtonClicked() function. This should be an elementary C++ task. I’m not in a c++ tutoring mood at the moment, so I will leave that for someone else to help with. :nerd_face:

Could you maybe share your entire code? This kind of behaviour indicates, that you make a mistake using C++. As @cpr2323 already wrote, the semantics of your code is very simple:
If your receive the file, just call the clickButton method.

Just a side note: You might want to add JUCE_ASSERT_MESSAGE_THREAD on the top of anotherInstanceStarted. My feeling says, that JUCE handles it this way, but you can never be too safe. It’s also a good indication for the reading of the code, what you are implying.

On Windows it works:

player.reset (new MainContentComponent());
player->playButtonClicked();

but can’t stop playback. I also don’t understand why it doesn’t work thrumbnail.
on Mac it doesn’t works.
This is my first experience. I’ve been learning C++ for only three months.

Sorry, I can’t just unpack an archive. Could you upload you source to git? If it’s only two or three classes, you can also upload them at hastebin or pastebin.

Just from looking into the main class: you are creating the AudioPlayer in line 99. If you want to access that instance (what seems to be the plan when looking at the unique_ptr just sitting around) you have to load the file into that instance. So maybe just pass the reference to your object managed by the unique ptr and try it from there. Make sure to set the boolean in l99 to false, as the main window isn’t the one owning the instance anymore. Thats what the unique_ptr would be for.

Hi Rincewind.
Thanks a lot for your answer. I did as you suggested, but autoplay is still in the background. Maybe I misunderstood you? It is still difficult for me, because I have no experience at all. I don’t even know if global variables can be used in commandLine. By the way, I had the same situation in the demo PlayingSoundFilesTutorial.

 class MainWindow    : public DocumentWindow
    {
    public:
        MainWindow (String name)
            : DocumentWindow (name,
                              Desktop::getInstance().getDefaultLookAndFeel()
                                                          .findColour (ResizableWindow::backgroundColourId),
                              DocumentWindow::allButtons)
        {
            setUsingNativeTitleBar (true);
            setContentOwned (new AudioPlayer(), false); // Line 99!

           #if JUCE_IOS || JUCE_ANDROID
            setFullScreen (true);
           #else
            setResizable (true, false);
            setResizeLimits (800, 280, 10000, 280);
            centreWithSize (getWidth(), getHeight());
           #endif

            setVisible (true);
            
            audioPlayer.reset (new AudioPlayer());
            audioPlayer->playButtonClicked();
        }

        void closeButtonPressed() override
        {
            JUCEApplication::getInstance()->systemRequestedQuit();
        }

    private:
        std::unique_ptr<AudioPlayer> audioPlayer;
        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
    };

It would be perfect from commandLine to give a command to the AudioPlayer class to press playButton. Only physical pressing on the playButton loads the file in the audio stream. But unfortunately I do not know how to do it. Any options for commands from initialise launch a player in the background stream.
Unfortunately, I did not find any example of a player with a commandLine implementation.

The hole commandLine stuff is not your problem. This will work by itself as soon as you get your software design right. The problem still remains. Currently you are creating two audio players. One in line 99 and one a few lines later (again with the new statement). Try removing line 99 and add setContentOwned(audioPlayer.get(), false); between the second creation and the button press.

And remember what the expected behaviour from your current code is. At the moment, when the main window is created, you are creating a new audio player and are pressing the button. (I remember the button click opening a dialog for file selection first). The next thing you want to do is to skip the dialog opening and use the already selected file passed to initialise and anotherInstanceStarted.

Hi Rincewind .
Thanks for the answer. Unfortunately, it doesn’t work yet. I noticed that if I paste the command audioPlayer.reset (new AudioPlayer()); into a initialise function
or to a class mainWindow, then background playback is turned on. Don’t even need a command audioPlayer->playButtonClicked();. How else can I initialize AudioPlayer class?
AudioPlayer audioPlayer; does not work.

I’m sorry, but the problem is your questions just don’t make any sense. To really solve your problem you need to learn about programming with C++ (or programming in general) and maybe start out with an easier task.
E.g. if you want to know why the AudioPlayer starts playing by itself after creation, take a look into the constructor of AudioPlayer. And then if thats not the correct behaviour, remove the corresponding code. The problem is not the way you initialise AudioPlayer. The problem is what happens WHEN you initialise AudioPlayer

1 Like

Thank you Rincewind!
Sometimes qualified advice gives more than a whole course of study.