~ubuntu-branches/ubuntu/wily/kradio4/wily

« back to all changes in this revision

Viewing changes to plugins/v4lradio/v4lradio.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Pino Toscano, Pino Toscano
  • Date: 2011-01-16 10:37:20 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110116103720-hdne9plqu6uek40k
Tags: 4.0.2-1
[ Pino Toscano ]
* QA upload.
* New upstream release. (Closes: #609258)
* Bring back and update the kradio4-convert-presents.1 man page.
* Update copyright.
* debian/rules: pass first the sequence to `dh', then the arguments.

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
#include <QtCore/QFileInfo>
41
41
#include <QtCore/QList>
42
42
#include <QtCore/QSocketNotifier>
 
43
#include <QtCore/QDir>
43
44
 
44
45
#include <kconfiggroup.h>
45
46
#include <kiconloader.h>
106
107
    m_MuteOnPowerOff(false),
107
108
    m_VolumeZeroOnPowerOff(false),
108
109
    m_restorePowerOn(false),
 
110
    m_deviceProbeAtStartup(false),
109
111
    m_V4L_version_override(V4L_Version2),
110
112
    m_V4L_version_override_by_kernel_once(false),
111
113
    m_RDS_notify(NULL),
222
224
        s->register4_querySoundStreamRadioStation(this);
223
225
        s->register4_queryEnumerateSourceSoundStreams(this);
224
226
 
 
227
        s->register4_notifySoundStreamClosed(this);
225
228
        s->register4_notifySoundStreamSourceRedirected(this);
226
229
        s->register4_notifySoundStreamSinkRedirected(this);
227
230
        notifySoundStreamCreated(m_SoundStreamSinkID);
337
340
        sendMuteSink    (m_SoundStreamSinkID);
338
341
        sendUnmuteSink  (m_SoundStreamSinkID);
339
342
 
340
 
        notifyPowerChanged(true);
 
343
        notifyPowerChanged(isPowerOn());
341
344
        notifySoundStreamChanged(m_SoundStreamSourceID);
342
345
    }
343
346
 
364
367
    muteSource(m_SoundStreamSourceID, true);
365
368
    radio_done();
366
369
 
367
 
    sendStopPlayback(m_SoundStreamSinkID);
368
 
    sendStopCapture(m_SoundStreamSinkID);
369
 
    closeSoundStream(m_SoundStreamSourceID);
370
 
    closeSoundStream(m_SoundStreamSinkID);
371
 
    m_SoundStreamSourceID = createNewSoundStream(m_SoundStreamSourceID, false);
372
 
    m_SoundStreamSinkID   = m_SoundStreamSourceID;
 
370
    sendStopRecording(m_SoundStreamSinkID);
 
371
    sendStopPlayback (m_SoundStreamSinkID);
 
372
    sendStopCapture  (m_SoundStreamSinkID);
 
373
 
 
374
    SoundStreamID oldSourceID = m_SoundStreamSourceID;
 
375
    SoundStreamID oldSinkID   = m_SoundStreamSinkID;
 
376
    m_SoundStreamSourceID     = createNewSoundStream(m_SoundStreamSourceID, false);
 
377
    m_SoundStreamSinkID       = m_SoundStreamSourceID;
 
378
    closeSoundStream (oldSourceID);
 
379
    closeSoundStream (oldSinkID);
 
380
 
373
381
    notifySoundStreamCreated(m_SoundStreamSourceID);
374
382
    notifyCurrentSoundStreamSinkIDChanged  (m_SoundStreamSinkID);
375
383
    notifyCurrentSoundStreamSourceIDChanged(m_SoundStreamSourceID);
961
969
        powerOff();
962
970
        m_radioDev = s;
963
971
 
964
 
        m_caps = readV4LCaps(m_radioDev);
 
972
        m_caps = (p || m_deviceProbeAtStartup) ? readV4LCaps(m_radioDev) : V4LCaps();
965
973
        notifyRadioDeviceChanged(m_radioDev);
966
974
        notifyDescriptionChanged(m_caps.description);
967
975
        notifyCapabilitiesChanged(m_caps);
1036
1044
    QString old_channel          = m_CaptureMixerChannel;
1037
1045
    m_CaptureMixerID             = soundStreamClientID;
1038
1046
    ISoundStreamClient *mixer    = getSoundStreamClientWithID(m_CaptureMixerID);
1039
 
    QStringList         channels = mixer ? mixer->getPlaybackChannels() : QStringList();
 
1047
    QStringList         channels = mixer ? mixer->getCaptureChannels() : QStringList();
1040
1048
 
1041
1049
    if (channels.size()) {
1042
1050
        assignChannelIfValid(m_CaptureMixerChannel, channels[0], channels);  // lowest priority
1043
1051
    }
1044
1052
    assignChannelIfValid(m_CaptureMixerChannel, "PCM",       channels);
1045
1053
    assignChannelIfValid(m_CaptureMixerChannel, "Wave",      channels);
 
1054
    assignChannelIfValid(m_CaptureMixerChannel, "Master",    channels);
1046
1055
    assignChannelIfValid(m_CaptureMixerChannel, "Line",      channels);
1047
 
    assignChannelIfValid(m_CaptureMixerChannel, "Master",    channels);
1048
1056
    assignChannelIfValid(m_CaptureMixerChannel, "Capture",   channels);
1049
1057
    assignChannelIfValid(m_CaptureMixerChannel, ch,          channels);  // highest priority
1050
1058
 
1085
1093
 
1086
1094
V4LCaps V4LRadio::getCapabilities(const QString &dev) const
1087
1095
{
1088
 
    if (dev.isNull()) {
 
1096
    if (dev.isNull() || dev.isEmpty()) {
1089
1097
        return m_caps;
1090
1098
    } else {
1091
 
        return readV4LCaps(dev);
 
1099
        return (isPowerOn() || m_deviceProbeAtStartup) ? readV4LCaps(dev) : V4LCaps();
1092
1100
    }
1093
1101
}
1094
1102
 
1148
1156
    return true;
1149
1157
}
1150
1158
 
 
1159
bool V4LRadio::setDeviceProbeAtStartup(bool e)
 
1160
{
 
1161
    if (e != m_deviceProbeAtStartup) {
 
1162
        m_deviceProbeAtStartup = e;
 
1163
        notifyDeviceProbeAtStartupChanged(m_deviceProbeAtStartup);
 
1164
    }
 
1165
    return true;
 
1166
}
 
1167
 
1151
1168
bool V4LRadio::setMuteOnPowerOff(bool a)
1152
1169
{
1153
1170
    if (a != m_MuteOnPowerOff) {
1171
1188
    if (vo != m_V4L_version_override) {
1172
1189
        m_V4L_version_override = vo;
1173
1190
        notifyV4LVersionOverrideChanged(m_V4L_version_override);
1174
 
        m_caps = readV4LCaps(m_radioDev);
 
1191
        m_caps = (isPowerOn() || m_deviceProbeAtStartup) ? readV4LCaps(m_radioDev) : V4LCaps();
1175
1192
        notifyCapabilitiesChanged(m_caps);
1176
1193
        notifyDescriptionChanged(m_caps.description);
1177
1194
    }
1219
1236
 
1220
1237
    config.writeEntry("V4LVersionOverride",                       (int)m_V4L_version_override);
1221
1238
    config.writeEntry("V4LVersionOverrideByKernelOnce",           (int)m_V4L_version_override_by_kernel_once);
 
1239
    config.writeEntry("DeviceProbeAtStartup",                     m_deviceProbeAtStartup);
1222
1240
    saveRadioDeviceID(config);
1223
1241
 
1224
1242
}
1250
1268
        }
1251
1269
    }
1252
1270
 
1253
 
 
1254
 
    QString base_devname = "/dev/radio";
1255
 
 
1256
 
    QStringList testlist (base_devname );
1257
 
    for (int i = 0; i < 9; ++i)
1258
 
        testlist.append(base_devname + QString::number(i));
1259
 
 
1260
 
    QString found_devname;
1261
 
    for (QList<QString>::const_iterator it = testlist.begin(); it != testlist.end(); ++it) {
1262
 
        QFile f(*it);
1263
 
        if (f.exists()) {
1264
 
            QFileInfo info(f);
1265
 
            if (info.isReadable() && info.isWritable()) {
1266
 
                found_devname = *it;
 
1271
    QString found_devname = "";
 
1272
    foreach (DeviceInfo devItem, getDeviceProposals()) {
 
1273
        if (devItem.path.contains("radio") && devItem.info.exists()) {
 
1274
            found_devname = devItem.path;
 
1275
            if (devItem.info.isReadable() && devItem.info.isWritable()) {
1267
1276
                break;
1268
1277
            }
1269
1278
            else {
1270
 
                if (found_devname.isNull())
1271
 
                    found_devname = *it;
1272
 
                logWarning(i18n("Device %1 does exist but is not readable/writable. Please check device permissions.", *it));
 
1279
                logWarning(i18n("Device %1 does exist but is not readable/writable. Please check device permissions.", devItem.path));
1273
1280
            }
1274
1281
        }
1275
1282
    }
1276
1283
 
1277
 
    QString default_devname = found_devname.isNull() ? base_devname : found_devname;
 
1284
    QString default_devname = "/dev/radio0";
 
1285
    if (found_devname.isEmpty()) {
 
1286
        logWarning(i18n("Could not find any radio device. Using the default path for now: %1", default_devname));
 
1287
    } else {
 
1288
        default_devname = found_devname;
 
1289
    }
1278
1290
 
1279
 
    QString devname = config.readEntry ("RadioDev", default_devname);
 
1291
    QString devname        = config.readEntry("RadioDev",             default_devname);
 
1292
    m_deviceProbeAtStartup = config.readEntry("DeviceProbeAtStartup", true);
1280
1293
 
1281
1294
    if (found_devname.isNull() && devname == default_devname) {
1282
1295
        logError(i18n("Could not find an accessible v4l(2) radio device."));
1323
1336
    notifyActivePlaybackChanged(m_ActivePlayback, m_ActivePlaybackMuteCaptureChannelPlayback);
1324
1337
    notifyMuteOnPowerOffChanged(m_MuteOnPowerOff);
1325
1338
    notifyForceRDSEnabledChanged(m_RDSForceEnabled);
 
1339
    notifyDeviceProbeAtStartupChanged(m_deviceProbeAtStartup);
1326
1340
    notifyVolumeZeroOnPowerOffChanged(m_VolumeZeroOnPowerOff);
1327
1341
    notifyV4LVersionOverrideChanged(m_V4L_version_override);
1328
1342
 
1344
1358
        notifyPlaybackVolumeChanged(m_SoundStreamSinkID, m_defaultPlaybackVolume);
1345
1359
}
1346
1360
 
 
1361
 
 
1362
 
 
1363
QList<DeviceInfo> V4LRadio::getDeviceProposals(const QString &base) const
 
1364
{
 
1365
    QList<DeviceInfo>               retval;
 
1366
    QDir                            devdir(base);
 
1367
    QStringList                     filterList;   filterList << "*radio*" << "*video*";
 
1368
    QFileInfoList                   deviceInfos = devdir.entryInfoList(filterList, QDir::System, QDir::Name);
 
1369
    QFileInfoList                   subdirs     = devdir.entryInfoList(QStringList(), QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Executable | QDir::Readable, QDir::Name);
 
1370
 
 
1371
    foreach(const QFileInfo &deviceInfo, deviceInfos) {
 
1372
        if (deviceInfo.exists()) {
 
1373
            QString devName = deviceInfo.absoluteFilePath();
 
1374
            bool    permsOK = deviceInfo.isReadable() && deviceInfo.isWritable();
 
1375
            V4LCaps caps    = getCapabilities(devName);
 
1376
            QString descr   = caps.deviceDescription;
 
1377
            descr           = descr.isEmpty() ? devName : descr + "[" + devName + "]";
 
1378
            if (!permsOK) {
 
1379
                descr = i18n("%1 (insufficient permissions)").arg(descr);
 
1380
            }
 
1381
            retval.append(DeviceInfo(devName, deviceInfo, caps, descr));
 
1382
        }
 
1383
    }
 
1384
 
 
1385
    foreach(const QFileInfo &subdir, subdirs) {
 
1386
        retval.append(getDeviceProposals(subdir.absoluteFilePath()));
 
1387
    }
 
1388
 
 
1389
    return retval;
 
1390
}
 
1391
 
 
1392
 
 
1393
 
1347
1394
void V4LRadio::startPlugin()
1348
1395
{
1349
1396
    PluginBase::startPlugin();
1401
1448
    notifyCapabilitiesChanged(m_caps);
1402
1449
    notifyDescriptionChanged(m_caps.description);
1403
1450
 
1404
 
/*    m_mixer_fd = open(m_mixerDev, O_RDONLY);
1405
 
    if (m_mixer_fd < 0) {
1406
 
        radio_done();
1407
 
 
1408
 
        logError("V4LRadio::radio_init: " +
1409
 
                 i18n("Cannot open mixer device %1", m_mixerDev));
1410
 
        return;
1411
 
    }
1412
 
*/
1413
1451
    m_radio_fd = open(m_radioDev.toLocal8Bit(), O_RDONLY);
1414
1452
    if (m_radio_fd < 0) {
1415
1453
        radio_done();
1444
1482
        stopSeek();
1445
1483
 
1446
1484
    if (m_radio_fd >= 0) close (m_radio_fd);
1447
 
//     if (m_mixer_fd >= 0) close (m_mixer_fd);
1448
1485
 
1449
1486
    if (m_RDS_notify)
1450
1487
        delete m_RDS_notify;
1451
1488
    m_RDS_notify = NULL;
1452
1489
 
1453
1490
    m_radio_fd = -1;
1454
 
//  m_mixer_fd = -1;
1455
1491
}
1456
1492
 
1457
1493
 
1494
1530
        l = l < CAPS_NAME_LEN ? l : CAPS_NAME_LEN;
1495
1531
        memcpy(buffer, caps.name, l);
1496
1532
        buffer[l] = 0;
1497
 
        v4l_caps[V4L_Version1].description = i18n("V4L Plugin (V4L%1 mode): %2", V4L_Version1, buffer);
 
1533
        v4l_caps[V4L_Version1].description       = i18n("V4L Plugin (V4L%1 mode): %2", V4L_Version1, buffer);
 
1534
        v4l_caps[V4L_Version1].deviceDescription = QString("%1").arg(buffer);
1498
1535
 
1499
1536
        v4l_caps[V4L_Version1].hasMute = false;
1500
1537
        v4l_caps[V4L_Version1].unsetVolume();
1537
1574
        l = l < CAPS_NAME_LEN ? l : CAPS_NAME_LEN;
1538
1575
        memcpy(buffer, caps.name, l);
1539
1576
        buffer[l] = 0;
1540
 
        v4l_caps[V4L_Version2].description = i18n("V4L Plugin (V4L%1 mode): %2", V4L_Version2, buffer);
 
1577
        v4l_caps[V4L_Version2].description       = i18n("V4L Plugin (V4L%1 mode): %2", V4L_Version2, buffer);
 
1578
        v4l_caps[V4L_Version2].deviceDescription = QString("%1").arg(buffer);
1541
1579
 
1542
1580
        v4l2_queryctrl  ctrl;
1543
1581
 
1604
1642
        }
1605
1643
    }
1606
1644
    if (!any_found) {
1607
 
        logError(i18n("V4L not detected"));
 
1645
        logWarning(i18n("V4L not detected"));
1608
1646
    }
1609
1647
 
1610
1648
    close(fd);
1634
1672
 
1635
1673
    logDebug("V4L final caps: " + c.getDebugDescription());
1636
1674
 
1637
 
//     logDebug(c.hasMute   ? i18n("Radio is mutable")         : i18n("Radio is not mutable"));
1638
 
//     logDebug(c.hasVolume ? i18n("Radio has Volume Control") : i18n("Radio has no Volume Control"));
1639
 
//     logDebug(c.hasBass   ? i18n("Radio has Bass Control")   : i18n("Radio has no Bass Control"));
1640
 
//     logDebug(c.hasTreble ? i18n("Radio has Treble Control") : i18n("Radio has no Treble Control"));
1641
 
 
1642
1675
    return c;
1643
1676
}
1644
1677
 
1817
1850
                    break;
1818
1851
            }
1819
1852
 
1820
 
            r = ioctl(m_radio_fd, write ? VIDIOCSAUDIO : VIDIOCGAUDIO, m_audio);
 
1853
            r = ioctl(m_radio_fd, (write ? VIDIOCSAUDIO : VIDIOCGAUDIO), m_audio);
1821
1854
 
1822
1855
            m_stereo = (r == 0) && ((m_audio->mode  & VIDEO_SOUND_STEREO) != 0);
1823
1856
 
2008
2041
}
2009
2042
 
2010
2043
 
 
2044
bool V4LRadio::noticeSoundStreamClosed(SoundStreamID id)
 
2045
{
 
2046
    if (m_SoundStreamSinkID == id || m_SoundStreamSourceID == id) {
 
2047
        // FIXME: only power off if power off did not cause the sound stream close
 
2048
        powerOff();
 
2049
        return true;
 
2050
    } else {
 
2051
        return false;
 
2052
    }
 
2053
}
 
2054
 
2011
2055
 
2012
2056
bool V4LRadio::noticeSoundStreamSinkRedirected(SoundStreamID oldID, SoundStreamID newID)
2013
2057
{