qtmobility/plugins/multimedia/v4l/radio/v4lradiocontrol_maemo5.cpp
changeset 14 6fbed849b4f4
parent 11 06b8e2af4411
child 15 1f895d8a5b2b
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
    48 #include <stdio.h>
    48 #include <stdio.h>
    49 #include <sys/types.h>
    49 #include <sys/types.h>
    50 #include <sys/ioctl.h>
    50 #include <sys/ioctl.h>
    51 #include <fcntl.h>
    51 #include <fcntl.h>
    52 #include <unistd.h>
    52 #include <unistd.h>
       
    53 
       
    54 #define HEADPHONE_STATE_FILE "/sys/devices/platform/gpio-switch/headphone/state"
       
    55 #define HEADPHONE_CONNECTED_STATE "connected"
       
    56 #define HEADPHONE_DISCONNECTED_STATE "disconnected"
       
    57 
       
    58 #define FMRXENABLER_DBUS_SERVICE "de.pycage.FMRXEnabler"
       
    59 #define FMRXENABLER_DBUS_OBJ_PATH "/de/pycage/FMRXEnabler"
       
    60 #define FMRXENABLER_DBUS_IFACE_NAME "de.pycage.FMRXEnabler"
       
    61 
       
    62 gboolean
       
    63 state_file_changed(GIOChannel* source, GIOCondition /*condition*/, gpointer data)
       
    64 {
       
    65     V4LRadioControl* radioControl = (V4LRadioControl*)data;
       
    66     gchar* result;
       
    67 
       
    68     g_io_channel_seek_position(source, 0, G_SEEK_SET, NULL);
       
    69     g_io_channel_read_line(source, &result, NULL, NULL, NULL);
       
    70     g_strstrip(result);
       
    71 
       
    72     if (g_ascii_strcasecmp(result, HEADPHONE_DISCONNECTED_STATE) == 0) {
       
    73         radioControl->enablePipeline(false);
       
    74     } else if (g_ascii_strcasecmp(result, HEADPHONE_CONNECTED_STATE) == 0) {
       
    75         // Wait 400ms until audio is routed again to headphone to prevent sound coming from speakers
       
    76         QTimer::singleShot(400,radioControl,SLOT(enablePipeline()));
       
    77     }
       
    78 
       
    79 #ifdef MULTIMEDIA_MAEMO_DEBUG
       
    80     qDebug() << "Headphone is now" << result;
       
    81 #endif
       
    82 
       
    83     g_free(result);
       
    84     return true;
       
    85 }
    53 
    86 
    54 V4LRadioControl::V4LRadioControl(QObject *parent)
    87 V4LRadioControl::V4LRadioControl(QObject *parent)
    55     : QRadioTunerControl(parent)
    88     : QRadioTunerControl(parent)
    56     , fd(1)
    89     , fd(1)
    57     , m_error(false)
    90     , m_error(false)
    62     , scanning(false)
    95     , scanning(false)
    63     , currentBand(QRadioTuner::FM)
    96     , currentBand(QRadioTuner::FM)
    64     , pipeline(0)
    97     , pipeline(0)
    65 {
    98 {
    66     if (QDBusConnection::systemBus().isConnected()) {
    99     if (QDBusConnection::systemBus().isConnected()) {
    67         FMRXEnablerIFace = new QDBusInterface("de.pycage.FMRXEnabler",
   100         FMRXEnablerIFace = new QDBusInterface(FMRXENABLER_DBUS_SERVICE,
    68                                              "/de/pycage/FMRXEnabler",
   101                                               FMRXENABLER_DBUS_OBJ_PATH,
    69                                              "de.pycage.FMRXEnabler",
   102                                               FMRXENABLER_DBUS_IFACE_NAME,
    70                                              QDBusConnection::systemBus());
   103                                               QDBusConnection::systemBus());
       
   104     }
       
   105 
       
   106     createGstPipeline();
       
   107 
       
   108     GIOChannel* headphoneStateFile = NULL;
       
   109     headphoneStateFile = g_io_channel_new_file(HEADPHONE_STATE_FILE, "r", NULL);
       
   110     if (headphoneStateFile != NULL) {
       
   111         g_io_add_watch(headphoneStateFile, G_IO_PRI, state_file_changed, this);
       
   112     } else {
       
   113 #ifdef MULTIMEDIA_MAEMO_DEBUG
       
   114         qWarning() << QString("File %1 can't be read!").arg(HEADPHONE_STATE_FILE) ;
       
   115         qWarning() << "Monitoring headphone state isn't possible!";
       
   116 #endif
    71     }
   117     }
    72 
   118 
    73     enableFMRX();
   119     enableFMRX();
    74     createGstPipeline();
       
    75     initRadio();
   120     initRadio();
    76     setupHeadPhone();
   121     setupHeadPhone();
    77 
   122 
    78     setMuted(false);
   123     setMuted(false);
    79 
   124 
    80     timer = new QTimer(this);
   125     timer = new QTimer(this);
    81     timer->setInterval(200);
   126     timer->setInterval(200);
    82     connect(timer,SIGNAL(timeout()),this,SLOT(search()));
   127     connect(timer,SIGNAL(timeout()),this,SLOT(search()));
    83     timer->start();
       
    84 
   128 
    85     tickTimer = new QTimer(this);
   129     tickTimer = new QTimer(this);
    86     tickTimer->setInterval(10000);
   130     tickTimer->setInterval(10000);
    87     connect(tickTimer,SIGNAL(timeout()),this,SLOT(enableFMRX()));
   131     connect(tickTimer,SIGNAL(timeout()),this,SLOT(enableFMRX()));
    88     tickTimer->start();
   132     tickTimer->start();
    98 
   142 
    99     if(fd > 0)
   143     if(fd > 0)
   100         ::close(fd);
   144         ::close(fd);
   101 }
   145 }
   102 
   146 
       
   147 void V4LRadioControl::enablePipeline(bool enable)
       
   148 {
       
   149     if (enable == true)
       
   150         gst_element_set_state (pipeline, GST_STATE_PLAYING);
       
   151     else
       
   152         gst_element_set_state (pipeline, GST_STATE_NULL);
       
   153 }
       
   154 
   103 void V4LRadioControl::enableFMRX()
   155 void V4LRadioControl::enableFMRX()
   104 {
   156 {
   105     if (FMRXEnablerIFace && FMRXEnablerIFace->isValid()) {
   157     if (FMRXEnablerIFace && FMRXEnablerIFace->isValid()) {
   106         FMRXEnablerIFace->call("request"); // Return value ignored
   158         FMRXEnablerIFace->call("request"); // Return value ignored
   107     }
   159     }
   133 bool V4LRadioControl::isAvailable() const
   185 bool V4LRadioControl::isAvailable() const
   134 {
   186 {
   135     return available;
   187     return available;
   136 }
   188 }
   137 
   189 
   138 QtMediaServices::AvailabilityError V4LRadioControl::availabilityError() const
   190 QtMultimedia::AvailabilityError V4LRadioControl::availabilityError() const
   139 {
   191 {
   140     if (fd > 0)
   192     if (fd > 0)
   141         return QtMediaServices::NoError;
   193         return QtMultimedia::NoError;
   142     else
   194     else
   143         return QtMediaServices::ResourceError;
   195         return QtMultimedia::ResourceError;
   144 }
   196 }
   145 
   197 
   146 QRadioTuner::State V4LRadioControl::state() const
   198 QRadioTuner::State V4LRadioControl::state() const
   147 {
   199 {
   148     return fd > 0 ? QRadioTuner::ActiveState : QRadioTuner::StoppedState;
   200     return fd > 0 ? QRadioTuner::ActiveState : QRadioTuner::StoppedState;
   262                 freq.frequency = (int)(f/62500);
   314                 freq.frequency = (int)(f/62500);
   263             }
   315             }
   264             ::ioctl(fd, VIDIOC_S_FREQUENCY, &freq);
   316             ::ioctl(fd, VIDIOC_S_FREQUENCY, &freq);
   265             currentFreq = f;
   317             currentFreq = f;
   266             emit frequencyChanged(currentFreq);
   318             emit frequencyChanged(currentFreq);
       
   319 	    
       
   320             int signal = signalStrength();
       
   321             if(sig != signal) {
       
   322                 sig = signal;
       
   323                 emit signalStrengthChanged(sig);
       
   324             }
   267         }
   325         }
   268     }
   326     }
   269 }
   327 }
   270 
   328 
   271 bool V4LRadioControl::isStereo() const
   329 bool V4LRadioControl::isStereo() const
   379     if (elem)
   437     if (elem)
   380         volume = vol(elem);
   438         volume = vol(elem);
   381 
   439 
   382     snd_hctl_close(hctl);
   440     snd_hctl_close(hctl);
   383 
   441 
   384     return (volume/63.0) * 100;
   442     return (volume/118.0) * 100;
   385 }
   443 }
   386 
   444 
   387 void V4LRadioControl::setVolume(int volume)
   445 void V4LRadioControl::setVolume(int volume)
   388 {
   446 {
   389 
   447     int vol = (volume / 100.0) * 118; // 118 is a headphone max setting
   390     int vol = (volume / 100.0) * 63; // 63 is a headphone max setting
       
   391     callAmixer("Line DAC Playback Volume", QString().setNum(vol)+QString(",")+QString().setNum(vol));
   448     callAmixer("Line DAC Playback Volume", QString().setNum(vol)+QString(",")+QString().setNum(vol));
   392 }
   449 }
   393 
   450 
   394 bool V4LRadioControl::isMuted() const
   451 bool V4LRadioControl::isMuted() const
   395 {
   452 {
   410 
   467 
   411     settings["Jack Function"] = "Headset";
   468     settings["Jack Function"] = "Headset";
   412     settings["Left DAC_L1 Mixer HP Switch"] = "off";
   469     settings["Left DAC_L1 Mixer HP Switch"] = "off";
   413     settings["Right DAC_R1 Mixer HP Switch"] = "off";
   470     settings["Right DAC_R1 Mixer HP Switch"] = "off";
   414     settings["Line DAC Playback Switch"] = "on";
   471     settings["Line DAC Playback Switch"] = "on";
   415     settings["Line DAC Playback Volume"] = "63,63"; // Volume is set to 100%
   472     settings["Line DAC Playback Volume"] = "118,118"; // Volume is set to 100%
   416     settings["HPCOM DAC Playback Switch"] = "off";
   473     settings["HPCOM DAC Playback Switch"] = "off";
   417     settings["Left DAC_L1 Mixer HP Switch"] = "off";
   474     settings["Left DAC_L1 Mixer HP Switch"] = "off";
   418     settings["Left DAC_L1 Mixer Line Switch"] = "on";
   475     settings["Left DAC_L1 Mixer Line Switch"] = "on";
   419     settings["Right DAC_R1 Mixer HP Switch"] = "off";
   476     settings["Right DAC_R1 Mixer HP Switch"] = "off";
   420     settings["Right DAC_R1 Mixer Line Switch"] = "on";
   477     settings["Right DAC_R1 Mixer Line Switch"] = "on";
   478     count = snd_ctl_elem_info_get_count(info);
   535     count = snd_ctl_elem_info_get_count(info);
   479 
   536 
   480     snd_ctl_elem_value_set_id(control, id);
   537     snd_ctl_elem_value_set_id(control, id);
   481 
   538 
   482     tmp = 0;
   539     tmp = 0;
   483     for (int idx = 0; idx < count && idx < 128; idx++)
   540     for (uint idx = 0; idx < count && idx < 128; idx++)
   484     {
   541     {
   485         switch (type)
   542         switch (type)
   486         {
   543         {
   487             case SND_CTL_ELEM_TYPE_BOOLEAN:
   544             case SND_CTL_ELEM_TYPE_BOOLEAN:
       
   545 #ifdef MULTIMEDIA_MAEMO_DEBUG
   488                 qDebug() << "SND_CTL_ELEM_TYPE_BOOLEAN" << SND_CTL_ELEM_TYPE_BOOLEAN;
   546                 qDebug() << "SND_CTL_ELEM_TYPE_BOOLEAN" << SND_CTL_ELEM_TYPE_BOOLEAN;
       
   547 #endif
   489                 if ((value == "on") ||(value == "1"))
   548                 if ((value == "on") ||(value == "1"))
   490                 {
   549                 {
   491                     tmp = 1;
   550                     tmp = 1;
   492                 }
   551                 }
   493                 snd_ctl_elem_value_set_boolean(control, idx, tmp);
   552                 snd_ctl_elem_value_set_boolean(control, idx, tmp);
   495             case SND_CTL_ELEM_TYPE_ENUMERATED:
   554             case SND_CTL_ELEM_TYPE_ENUMERATED:
   496                 tmp = getEnumItemIndex(handle, info, value);
   555                 tmp = getEnumItemIndex(handle, info, value);
   497                 snd_ctl_elem_value_set_enumerated(control, idx, tmp);
   556                 snd_ctl_elem_value_set_enumerated(control, idx, tmp);
   498                 break;
   557                 break;
   499             case SND_CTL_ELEM_TYPE_INTEGER:
   558             case SND_CTL_ELEM_TYPE_INTEGER:
       
   559 #ifdef MULTIMEDIA_MAEMO_DEBUG
   500                 qDebug() << "SND_CTL_ELEM_TYPE_INTEGER" << SND_CTL_ELEM_TYPE_INTEGER;
   560                 qDebug() << "SND_CTL_ELEM_TYPE_INTEGER" << SND_CTL_ELEM_TYPE_INTEGER;
       
   561 #endif
   501                 tmp = atoi(value.toAscii());
   562                 tmp = atoi(value.toAscii());
   502                 if (tmp <  snd_ctl_elem_info_get_min(info))
   563                 if (tmp <  snd_ctl_elem_info_get_min(info))
   503                     tmp = snd_ctl_elem_info_get_min(info);
   564                     tmp = snd_ctl_elem_info_get_min(info);
   504                 else if (tmp > snd_ctl_elem_info_get_max(info))
   565                 else if (tmp > snd_ctl_elem_info_get_max(info))
   505                     tmp = snd_ctl_elem_info_get_max(info);
   566                     tmp = snd_ctl_elem_info_get_max(info);
   551 }
   612 }
   552 
   613 
   553 void V4LRadioControl::cancelSearch()
   614 void V4LRadioControl::cancelSearch()
   554 {
   615 {
   555     scanning = false;
   616     scanning = false;
       
   617     timer->stop();
   556 }
   618 }
   557 
   619 
   558 void V4LRadioControl::searchForward()
   620 void V4LRadioControl::searchForward()
   559 {
   621 {
   560     // Scan up
   622     // Scan up
   561     if(scanning) {
   623     if(scanning) {
   562         scanning = false;
   624         cancelSearch();
   563         return;
   625         return;
   564     }
   626     }
   565     scanning = true;
   627     scanning = true;
   566     forward  = true;
   628     forward  = true;
       
   629     timer->start();
   567 }
   630 }
   568 
   631 
   569 void V4LRadioControl::searchBackward()
   632 void V4LRadioControl::searchBackward()
   570 {
   633 {
   571     // Scan down
   634     // Scan down
   572     if(scanning) {
   635     if(scanning) {
   573         scanning = false;
   636         cancelSearch();
   574         return;
   637         return;
   575     }
   638     }
   576     scanning = true;
   639     scanning = true;
   577     forward  = false;
   640     forward  = false;
       
   641     timer->start();
   578 }
   642 }
   579 
   643 
   580 void V4LRadioControl::start()
   644 void V4LRadioControl::start()
   581 {
   645 {
   582 }
   646 }
   598     return QString();
   662     return QString();
   599 }
   663 }
   600 
   664 
   601 void V4LRadioControl::search()
   665 void V4LRadioControl::search()
   602 {
   666 {
       
   667     if(!scanning) return;
       
   668 
       
   669     if(forward) {
       
   670         setFrequency(currentFreq+step);
       
   671     } else {
       
   672         setFrequency(currentFreq-step);
       
   673     }
       
   674     
   603     int signal = signalStrength();
   675     int signal = signalStrength();
   604     if(sig != signal) {
   676     if(sig != signal) {
   605         sig = signal;
   677         sig = signal;
   606         emit signalStrengthChanged(sig);
   678         emit signalStrengthChanged(sig);
   607     }
   679     }
   608 
   680     
   609     if(!scanning) return;
       
   610 
       
   611     if (signal > 25) {
   681     if (signal > 25) {
   612         cancelSearch();
   682         cancelSearch();
   613         return;
   683         return;
   614     }
   684     }
   615 
       
   616     if(forward) {
       
   617         setFrequency(currentFreq+step);
       
   618     } else {
       
   619         setFrequency(currentFreq-step);
       
   620     }
       
   621     emit signalStrengthChanged(signalStrength());
       
   622 }
   685 }
   623 
   686 
   624 bool V4LRadioControl::initRadio()
   687 bool V4LRadioControl::initRadio()
   625 {
   688 {
   626     v4l2_tuner tuner;
   689     v4l2_tuner tuner;
   635 
   698 
   636     if(fd != -1) {
   699     if(fd != -1) {
   637         // Capabilites
   700         // Capabilites
   638         memset(&cap, 0, sizeof(cap));
   701         memset(&cap, 0, sizeof(cap));
   639         if(::ioctl(fd, VIDIOC_QUERYCAP, &cap ) >= 0) {
   702         if(::ioctl(fd, VIDIOC_QUERYCAP, &cap ) >= 0) {
   640             if(((cap.capabilities & V4L2_CAP_RADIO) == 0) && ((cap.capabilities & V4L2_CAP_AUDIO) == 0))
   703             available = true;
   641                 available = true;
       
   642         }
   704         }
   643 
   705 
   644         tuner.index = 0;
   706         tuner.index = 0;
   645 
   707 
   646         if (ioctl(fd, VIDIOC_G_TUNER, &tuner) < 0) {
   708         if (ioctl(fd, VIDIOC_G_TUNER, &tuner) < 0) {