Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QMediaDevices::audioInputsChanged() Signal Not Emitting on Device Change

QMediaDevices::audioInputsChanged() Signal Not Emitting on Device Change

Scheduled Pinned Locked Moved Solved General and Desktop
audio deviceinputdevicesingletonsignal & slotsignals
10 Posts 3 Posters 620 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    papisant
    wrote on 13 Nov 2024, 10:51 last edited by
    #1

    I am having an issue with the signal audioInputsChanged() from QMediaDevices not emitting as expected when the default audio input device changes at runtime. For example, when I have used the defaultAudioInput() and this gets unplugged, I'd like to update what I was doing with it.

    What I’ve Tried:
    I’m using QMediaDevices to listen for changes in the audio input devices. The code connects to the audioInputsChanged() signal of QMediaDevices to trigger the onTest() slot in my class.
    However, even when the default audio input changes (which I can verify by accessing defaultAudioInput() with a timer), the connected slot (onTest()) is not being called. This leads me to believe that the signal is not being emitted or connected correctly.

    The connection to audioInputsChanged is made using the following code inside the constructor:

    MyClass(QObject* parent)
            : QObject{parent},
    m_mediaDevices{std::make_shared<QMediaDevices>(this)}
        {
            qInfo() << "default " << m_mediaDevices->defaultAudioInput().description();
    
            connect(m_mediaDevices.get(), &QMediaDevices::audioInputsChanged, this, &MyClass::onTest);
        }
    
        void MyClass::onTest() {
            qInfo() << "on test";
        }
    

    Expected Behavior:
    The onTest() method should be called whenever the default audio input device changes, but it is not getting triggered.

    Things I Have Already Checked:
    I have created a QTimer to call a function periodically (onDeviceChanged()), which works as expected getting the QMediaDevices::defaultAudioInput().

    Has anyone encountered a similar issue, or can anyone point out what might be causing the signal not to trigger when the input device changes?

    1 Reply Last reply
    0
    • P papisant
      14 Nov 2024, 08:45

      @JonB I am using connect(m_mediaDevices.get(), &QMediaDevices::audioInputsChanged, ...) as per the original post with no luck.

      The last two posts include the QMediaDevices devices as I tried that after finding the mentioned video because I though the problem could be in the connection as QMediaDevices::instance() does not exist. So both approaches I tried and described here don't work.

      J Offline
      J Offline
      JonB
      wrote on 14 Nov 2024, 08:51 last edited by
      #7

      @papisant
      OK, well at least the m_mediaDevices.get() has a chance of working. If you want to test the later approach make devices either be a class member variable or new it.

      1 Reply Last reply
      0
      • P Offline
        P Offline
        papisant
        wrote on 13 Nov 2024, 13:07 last edited by papisant
        #2

        Also doing this is not working:
        (connection taken from https://youtu.be/a5_T1vuEa18?si=2NknlBbw6wh2nd5N&t=590)

          QMediaDevices devices;
           bool con = connect(&devices, &QMediaDevices::audioInputsChanged, [](){qInfo() << "devices changed";});
        

        By the way, when checking on "con" I can see that the connect statement is true.

        J 1 Reply Last reply 14 Nov 2024, 06:53
        0
        • P papisant
          13 Nov 2024, 13:07

          Also doing this is not working:
          (connection taken from https://youtu.be/a5_T1vuEa18?si=2NknlBbw6wh2nd5N&t=590)

            QMediaDevices devices;
             bool con = connect(&devices, &QMediaDevices::audioInputsChanged, [](){qInfo() << "devices changed";});
          

          By the way, when checking on "con" I can see that the connect statement is true.

          J Online
          J Online
          jsulm
          Lifetime Qt Champion
          wrote on 14 Nov 2024, 06:53 last edited by
          #3

          @papisant said in QMediaDevices::audioInputsChanged() Signal Not Emitting on Device Change:

          QMediaDevices devices;
          bool con = connect(&devices, &QMediaDevices::audioInputsChanged, {qInfo() << "devices changed";});

          Where is this code located?
          devices is a local variable here...

          https://forum.qt.io/topic/113070/qt-code-of-conduct

          P 1 Reply Last reply 14 Nov 2024, 08:19
          1
          • J jsulm
            14 Nov 2024, 06:53

            @papisant said in QMediaDevices::audioInputsChanged() Signal Not Emitting on Device Change:

            QMediaDevices devices;
            bool con = connect(&devices, &QMediaDevices::audioInputsChanged, {qInfo() << "devices changed";});

            Where is this code located?
            devices is a local variable here...

            P Offline
            P Offline
            papisant
            wrote on 14 Nov 2024, 08:19 last edited by papisant
            #4

            @jsulm I thought QMediaDevices was a singleton. Well, right now it is located in MyClass, which instantiates MyClass2.
            In MyClass2, I use:

            defaultDevice = QMediaDevices::defaultAudioInput()
            

            I thought I could listen for a change in the defaultAudioInput in MyClass, as I'd like to notify the change for other places too.
            Nonetheless, listening for the change in MyClass2 does not seem to work also.
            It is like the signal never gets emitted.

            In MyClass, if I do this, I can see the change when it happens using the Timer. But not by the firing of the audioInputsChanged() signal. This code is illustrative.

            MyClass2* m_myClass2Obj = new MyClass2();
            QTimer* timer = new QTimer();
            timer->start(1000);
            connect(timer, &QTimer::timeout, this, [this](){m_myClass2Obj->onDeviceChanged();});
            
            QMediaDevices devices;
            connect(&devices, &QMediaDevices::audioInputsChanged, {qInfo() << "devices changed";});
            

            In MyClass2 I'd have (with the m_currentDevice initialized to the default device in its constructor):

            void MyClass2::onDeviceChanged()
            {
                          qInfo() << "onDeviceChanged";
                     QAudioDevice currentDefaultDevice = QMediaDevices::defaultAudioInput();
             
                          qInfo() << "current default device: " << QMediaDevices::defaultAudioInput().description();
            
                     // Check if the device has changed
                     if (currentDefaultDevice != m_currentDevice) 
                     {
                         // I see the device changing by checking every second for the defaultAudioInput, but never from audioInputsChanged
                         qDebug() << "Audio input device has changed!";
                     }
            }
            
            J 1 Reply Last reply 14 Nov 2024, 08:43
            0
            • P papisant
              14 Nov 2024, 08:19

              @jsulm I thought QMediaDevices was a singleton. Well, right now it is located in MyClass, which instantiates MyClass2.
              In MyClass2, I use:

              defaultDevice = QMediaDevices::defaultAudioInput()
              

              I thought I could listen for a change in the defaultAudioInput in MyClass, as I'd like to notify the change for other places too.
              Nonetheless, listening for the change in MyClass2 does not seem to work also.
              It is like the signal never gets emitted.

              In MyClass, if I do this, I can see the change when it happens using the Timer. But not by the firing of the audioInputsChanged() signal. This code is illustrative.

              MyClass2* m_myClass2Obj = new MyClass2();
              QTimer* timer = new QTimer();
              timer->start(1000);
              connect(timer, &QTimer::timeout, this, [this](){m_myClass2Obj->onDeviceChanged();});
              
              QMediaDevices devices;
              connect(&devices, &QMediaDevices::audioInputsChanged, {qInfo() << "devices changed";});
              

              In MyClass2 I'd have (with the m_currentDevice initialized to the default device in its constructor):

              void MyClass2::onDeviceChanged()
              {
                            qInfo() << "onDeviceChanged";
                       QAudioDevice currentDefaultDevice = QMediaDevices::defaultAudioInput();
               
                            qInfo() << "current default device: " << QMediaDevices::defaultAudioInput().description();
              
                       // Check if the device has changed
                       if (currentDefaultDevice != m_currentDevice) 
                       {
                           // I see the device changing by checking every second for the defaultAudioInput, but never from audioInputsChanged
                           qDebug() << "Audio input device has changed!";
                       }
              }
              
              J Offline
              J Offline
              JonB
              wrote on 14 Nov 2024, 08:43 last edited by
              #5

              @papisant said in QMediaDevices::audioInputsChanged() Signal Not Emitting on Device Change:

              QMediaDevices devices;
              connect(&devices, &QMediaDevices::audioInputsChanged, {qInfo() << "devices changed";});
              

              In both your last two posts you show this. This won't work as shown because of the scope of QMediaDevices devices if that is a local variable. Admittedly that is not the case if you actually have connect(m_mediaDevices.get(), &QMediaDevices::audioInputsChanged, ...) per your original post, so you should verify what you are actually using.

              P 1 Reply Last reply 14 Nov 2024, 08:45
              1
              • J JonB
                14 Nov 2024, 08:43

                @papisant said in QMediaDevices::audioInputsChanged() Signal Not Emitting on Device Change:

                QMediaDevices devices;
                connect(&devices, &QMediaDevices::audioInputsChanged, {qInfo() << "devices changed";});
                

                In both your last two posts you show this. This won't work as shown because of the scope of QMediaDevices devices if that is a local variable. Admittedly that is not the case if you actually have connect(m_mediaDevices.get(), &QMediaDevices::audioInputsChanged, ...) per your original post, so you should verify what you are actually using.

                P Offline
                P Offline
                papisant
                wrote on 14 Nov 2024, 08:45 last edited by papisant
                #6

                @JonB I am using connect(m_mediaDevices.get(), &QMediaDevices::audioInputsChanged, ...) as per the original post with no luck.

                The last two posts include the QMediaDevices devices as I tried that after finding the mentioned video because I though the problem could be in the connection as QMediaDevices::instance() does not exist. So both approaches I tried and described here don't work.

                J 1 Reply Last reply 14 Nov 2024, 08:51
                0
                • P papisant
                  14 Nov 2024, 08:45

                  @JonB I am using connect(m_mediaDevices.get(), &QMediaDevices::audioInputsChanged, ...) as per the original post with no luck.

                  The last two posts include the QMediaDevices devices as I tried that after finding the mentioned video because I though the problem could be in the connection as QMediaDevices::instance() does not exist. So both approaches I tried and described here don't work.

                  J Offline
                  J Offline
                  JonB
                  wrote on 14 Nov 2024, 08:51 last edited by
                  #7

                  @papisant
                  OK, well at least the m_mediaDevices.get() has a chance of working. If you want to test the later approach make devices either be a class member variable or new it.

                  1 Reply Last reply
                  0
                  • P Offline
                    P Offline
                    papisant
                    wrote on 14 Nov 2024, 11:27 last edited by
                    #8

                    @JonB thank you for your recommendation. Using QMediaDevices m_devices; as a class member variable and connecting it did the trick. Now I see my slot getting called. Will check that the functional part of it works, but the issue with the signal is now solved. Thanks. Marking this as solved.

                    J 2 Replies Last reply 14 Nov 2024, 12:16
                    0
                    • P papisant
                      14 Nov 2024, 11:27

                      @JonB thank you for your recommendation. Using QMediaDevices m_devices; as a class member variable and connecting it did the trick. Now I see my slot getting called. Will check that the functional part of it works, but the issue with the signal is now solved. Thanks. Marking this as solved.

                      J Offline
                      J Offline
                      JonB
                      wrote on 14 Nov 2024, 12:16 last edited by JonB
                      #9

                      @papisant
                      Well, I'm not sure why it did not work with your original m_mediaDevices{std::make_shared<QMediaDevices>(this) which would surely be a class member too.

                      Anyway, the important take away from this is: when connecting a signal you must look at the scope/lifetime of the signalling object (same for the slot). If either of these is a "local variable" that means the object will go out of scope and be destroyed at the end of the function they are in. And when Qt sees either the signalling or slot object being destroyed it auto-disconnects any connected signals/slots for that object (for obvious reasons). A connection only persists as long as both signal & slot objects are in existence. That is why class members are often used, or the object must be newed and not deleted.

                      1 Reply Last reply
                      1
                      • P papisant
                        14 Nov 2024, 11:27

                        @JonB thank you for your recommendation. Using QMediaDevices m_devices; as a class member variable and connecting it did the trick. Now I see my slot getting called. Will check that the functional part of it works, but the issue with the signal is now solved. Thanks. Marking this as solved.

                        J Offline
                        J Offline
                        JonB
                        wrote on 14 Nov 2024, 12:24 last edited by
                        #10
                        This post is deleted!
                        1 Reply Last reply
                        0
                        • P papisant has marked this topic as solved on 14 Nov 2024, 15:26

                        1/10

                        13 Nov 2024, 10:51

                        • Login

                        • Login or register to search.
                        1 out of 10
                        • First post
                          1/10
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved