bool TagReader::IsMediaFile(const QString& filename) const {
  qLog(Debug) << "Checking for valid file" << filename;

  std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
  return !fileref->isNull() && fileref->tag();
}
Exemple #2
0
void RingControl::startRinging(RingType t)
{
    stopRing();

    if(t == Call && !d->callEnabled)
        return;
    else if(t == Msg && !d->msgEnabled)
        return;

    if(qLogEnabled(QtopiaServer)) {
        QString type;
        switch(t) {
            case NotRinging:
                type = "NotRinging";
                break;
            case Call:
                type = "Call";
                break;
            case Msg:
                type = "Message";
                break;
        }
        qLog(QtopiaServer) << "RingControl: Ringing" << type;
    }

    if(t == NotRinging)
        return;

    d->ringtime.start();

    QPhoneProfile profile = d->profileManager->activeProfile();
    QString ringToneDoc;

    // try contact ringtone

    if (t == Call) {

        // try personalized ring tone
        ringToneDoc = findRingTone();
        // try profile ring tone
        // try video ring tone first.
        if (ringToneDoc.isEmpty()) {
            ringToneDoc = profile.videoTone().fileName();

            if (!ringToneDoc.isEmpty()) {
                d->videoTone = true;
            }
        }

        // try profile ring tone
        if (ringToneDoc.isEmpty() || d->videoToneFailed) {
            ringToneDoc = profile.callTone().fileName();
            d->videoTone = false;
            d->videoToneFailed = false;
        }

        // last resort, fall back to system ring tone
        if (ringToneDoc.isEmpty())
            ringToneDoc = profile.systemCallTone().fileName();

        d->curRingTone = ringToneDoc;

        d->curAlertType = profile.callAlert();
    }
    else if (t == Msg)
    {
        d->curAlertType = profile.msgAlert();

        if (d->curAlertType == QPhoneProfile::Continuous ||
            d->curAlertType == QPhoneProfile::Ascending)
        {
            d->msgTid = startTimer(msgRingTime());
        }

        ringToneDoc = profile.messageTone().fileName();

        // fall back if above settings lead to non-existent ringtone.
        if (ringToneDoc.isEmpty())
            ringToneDoc = profile.systemMessageTone().fileName();

        d->curRingTone = ringToneDoc;
    }

    if (profile.vibrate())
    {
        QVibrateAccessory vib;
        vib.setVibrateNow( true );
        d->vibrateActive = true;
        d->vrbTid = startTimer(vibrateDuration());
    }

    if(d->curAlertType == QPhoneProfile::Ascending)
        d->lastRingVolume = 1;
    else
        d->lastRingVolume = d->ringVolume;

    d->currentRingSource = t;

    if(d->lastRingVolume && d->curAlertType != QPhoneProfile::Off) {
        initSound();
#ifdef MEDIA_SERVER
        if ( !d->videoTone ) {
            if(d->soundcontrol && d->soundcontrol->sound()->fileName() != ringToneDoc) {
                delete d->soundcontrol->sound();
                delete d->soundcontrol;
                d->soundcontrol = 0;
            }
            if (!d->soundcontrol) {
                d->soundcontrol = new QSoundControl(new QSound(d->curRingTone));
                connect(d->soundcontrol, SIGNAL(done()), this, SLOT(nextRing()) );
          }
            d->soundcontrol->setPriority(QSoundControl::RingTone);
            d->soundcontrol->setVolume(volmap[d->lastRingVolume]);

            d->soundcontrol->sound()->play();
        } else {
            qLog(Media) << "Video ringtone selected" << d->curRingTone;
            QtopiaIpcSendEnvelope env = d->videoAdaptor->send( MESSAGE(playVideo(QString)) );
            env << d->curRingTone;
        }
#elif defined(Q_WS_QWS)
        if(d->soundclient)
            d->soundclient->play(0, d->curRingTone,
                                 volmap[d->lastRingVolume],
                                 QWSSoundClient::Priority);
#endif
    }

    emit ringTypeChanged(d->currentRingSource);
}
Exemple #3
0
void NeoModemService::reset()
{
    qLog(Modem) << "Gta04ModemService::reset()";
}
void SpotifyClient::Init(quint16 port) {
  qLog(Debug) << "Connecting to port" << port;

  protocol_socket_->connectToHost(QHostAddress::LocalHost, port);
}
void SubsonicService::OnPingFinished(QNetworkReply* reply) {
  reply->deleteLater();

  if (reply->error() != QNetworkReply::NoError) {
    switch (reply->error()) {
      case QNetworkReply::ConnectionRefusedError:
        login_state_ = LoginState_ConnectionRefused;
        break;
      case QNetworkReply::HostNotFoundError:
        login_state_ = LoginState_HostNotFound;
        break;
      case QNetworkReply::TimeoutError:
        login_state_ = LoginState_Timeout;
        break;
      case QNetworkReply::SslHandshakeFailedError:
        login_state_ = LoginState_SslError;
        break;
      default:  // Treat uncaught error types here as generic
        login_state_ = LoginState_BadServer;
        break;
    }
    qLog(Error) << "Failed to connect ("
                << Utilities::EnumToString(QNetworkReply::staticMetaObject,
                                           "NetworkError", reply->error())
                << "):" << reply->errorString();
  } else {
    QXmlStreamReader reader(reply);
    reader.readNextStartElement();
    QStringRef status = reader.attributes().value("status");
    int http_status_code =
        reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    if (status == "ok") {
      login_state_ = LoginState_Loggedin;
    } else if (http_status_code >= 300 && http_status_code <= 399) {
      // Received a redirect status code, follow up on it.
      QUrl redirect_url =
          reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
      if (redirect_url.isEmpty()) {
        qLog(Debug) << "Received HTTP code " << http_status_code
                    << ", but no URL";
        login_state_ = LoginState_RedirectNoUrl;
      } else {
        redirect_count_++;
        qLog(Debug) << "Redirect receieved to "
                    << redirect_url.toString(QUrl::RemoveQuery)
                    << ", current redirect count is " << redirect_count_;
        if (redirect_count_ <= kMaxRedirects) {
          working_server_ = ScrubUrl(redirect_url).toString(QUrl::RemoveQuery);
          Ping();
          // To avoid the LoginStateChanged, as it will come from the recursive
          // request.
          return;
        } else {
          // Redirect limit exceeded
          login_state_ = LoginState_RedirectLimitExceeded;
        }
      }
    } else {
      reader.readNextStartElement();
      int error = reader.attributes().value("code").toString().toInt();
      qLog(Error) << "Subsonic error ("
                  << Utilities::EnumToString(SubsonicService::staticMetaObject,
                                             "ApiError", error)
                  << "):" << reader.attributes().value("message").toString();
      switch (error) {
        // "Parameter missing" for "ping" is always blank username or password
        case ApiError_ParameterMissing:
        case ApiError_BadCredentials:
          login_state_ = LoginState_BadCredentials;
          break;
        case ApiError_OutdatedClient:
          login_state_ = LoginState_OutdatedClient;
          break;
        case ApiError_OutdatedServer:
          login_state_ = LoginState_OutdatedServer;
          break;
        case ApiError_Unlicensed:
          login_state_ = LoginState_Unlicensed;
          break;
        default:
          login_state_ = LoginState_OtherError;
          break;
      }
    }
  }
  qLog(Debug) << "Login state changed:"
              << Utilities::EnumToString(SubsonicService::staticMetaObject,
                                         "LoginState", login_state_);
  emit LoginStateChanged(login_state_);
}
bool GstEnginePipeline::Init() {
  // Here we create all the parts of the gstreamer pipeline - from the source
  // to the sink.  The parts of the pipeline are split up into bins:
  //   uri decode bin -> audio bin
  // The uri decode bin is a gstreamer builtin that automatically picks the
  // right type of source and decoder for the URI.

  // The audio bin gets created here and contains:
  //   queue ! audioconvert ! <caps32>
  //         ! ( rgvolume ! rglimiter ! audioconvert2 ) ! tee
  // rgvolume and rglimiter are only created when replaygain is enabled.

  // After the tee the pipeline splits.  One split is converted to 16-bit int
  // samples for the scope, the other is kept as float32 and sent to the
  // speaker.
  //   tee1 ! probe_queue ! probe_converter ! <caps16> ! probe_sink
  //   tee2 ! audio_queue ! equalizer_preamp ! equalizer ! volume ! audioscale
  //        ! convert ! audiosink

  // Audio bin
  audiobin_ = gst_bin_new("audiobin");
  gst_bin_add(GST_BIN(pipeline_), audiobin_);

  // Create the sink
  if (!(audiosink_ = engine_->CreateElement(sink_, audiobin_))) return false;

  if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "device") &&
      !device_.toString().isEmpty()) {
    switch (device_.type()) {
      case QVariant::Int:
        g_object_set(G_OBJECT(audiosink_),
                     "device", device_.toInt(),
                     nullptr);
        break;
      case QVariant::String:
        g_object_set(G_OBJECT(audiosink_),
                     "device", device_.toString().toUtf8().constData(),
                     nullptr);
        break;

      #ifdef Q_OS_WIN32
      case QVariant::ByteArray: {
        GUID guid = QUuid(device_.toByteArray());
        g_object_set(G_OBJECT(audiosink_),
                     "device", &guid,
                     nullptr);
        break;
      }
      #endif  // Q_OS_WIN32

      default:
        qLog(Warning) << "Unknown device type" << device_;
        break;
    }
  }

  // Create all the other elements
  GstElement* tee, *probe_queue, *probe_converter, *probe_sink, *audio_queue,
      *convert;

  queue_ = engine_->CreateElement("queue2", audiobin_);
  audioconvert_ = engine_->CreateElement("audioconvert", audiobin_);
  tee = engine_->CreateElement("tee", audiobin_);

  probe_queue = engine_->CreateElement("queue", audiobin_);
  probe_converter = engine_->CreateElement("audioconvert", audiobin_);
  probe_sink = engine_->CreateElement("fakesink", audiobin_);

  audio_queue = engine_->CreateElement("queue", audiobin_);
  equalizer_preamp_ = engine_->CreateElement("volume", audiobin_);
  equalizer_ = engine_->CreateElement("equalizer-nbands", audiobin_);
  stereo_panorama_ = engine_->CreateElement("audiopanorama", audiobin_);
  volume_ = engine_->CreateElement("volume", audiobin_);
  audioscale_ = engine_->CreateElement("audioresample", audiobin_);
  convert = engine_->CreateElement("audioconvert", audiobin_);

  if (!queue_ || !audioconvert_ || !tee || !probe_queue || !probe_converter ||
      !probe_sink || !audio_queue || !equalizer_preamp_ || !equalizer_ ||
      !stereo_panorama_ || !volume_ || !audioscale_ || !convert) {
    return false;
  }

  // Create the replaygain elements if it's enabled.  event_probe is the
  // audioconvert element we attach the probe to, which will change depending
  // on whether replaygain is enabled.  convert_sink is the element after the
  // first audioconvert, which again will change.
  GstElement* event_probe = audioconvert_;
  GstElement* convert_sink = tee;

  if (rg_enabled_) {
    rgvolume_ = engine_->CreateElement("rgvolume", audiobin_);
    rglimiter_ = engine_->CreateElement("rglimiter", audiobin_);
    audioconvert2_ = engine_->CreateElement("audioconvert", audiobin_);
    event_probe = audioconvert2_;
    convert_sink = rgvolume_;

    if (!rgvolume_ || !rglimiter_ || !audioconvert2_) {
      return false;
    }

    // Set replaygain settings
    g_object_set(G_OBJECT(rgvolume_), "album-mode", rg_mode_, nullptr);
    g_object_set(G_OBJECT(rgvolume_), "pre-amp", double(rg_preamp_), nullptr);
    g_object_set(G_OBJECT(rglimiter_), "enabled", int(rg_compression_),
                 nullptr);
  }

  // Create a pad on the outside of the audiobin and connect it to the pad of
  // the first element.
  GstPad* pad = gst_element_get_static_pad(queue_, "sink");
  gst_element_add_pad(audiobin_, gst_ghost_pad_new("sink", pad));
  gst_object_unref(pad);

  // Add a data probe on the src pad of the audioconvert element for our scope.
  // We do it here because we want pre-equalized and pre-volume samples
  // so that our visualization are not be affected by them.
  pad = gst_element_get_static_pad(event_probe, "src");
  gst_pad_add_probe(
      pad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, &EventHandoffCallback, this, NULL);
  gst_object_unref(pad);

  // Configure the fakesink properly
  g_object_set(G_OBJECT(probe_sink), "sync", TRUE, nullptr);

  // Set the equalizer bands
  g_object_set(G_OBJECT(equalizer_), "num-bands", 10, nullptr);

  int last_band_frequency = 0;
  for (int i = 0; i < kEqBandCount; ++i) {
    GstObject* band = GST_OBJECT(gst_child_proxy_get_child_by_index(
        GST_CHILD_PROXY(equalizer_), i));

    const float frequency = kEqBandFrequencies[i];
    const float bandwidth = frequency - last_band_frequency;
    last_band_frequency = frequency;

    g_object_set(G_OBJECT(band), "freq", frequency, "bandwidth", bandwidth,
                 "gain", 0.0f, nullptr);
    g_object_unref(G_OBJECT(band));
  }

  // Set the stereo balance.
  g_object_set(G_OBJECT(stereo_panorama_), "panorama", stereo_balance_,
               nullptr);

  // Set the buffer duration.  We set this on this queue instead of the
  // decode bin (in ReplaceDecodeBin()) because setting it on the decode bin
  // only affects network sources.
  // Disable the default buffer and byte limits, so we only buffer based on
  // time.
  g_object_set(G_OBJECT(queue_), "max-size-buffers", 0, nullptr);
  g_object_set(G_OBJECT(queue_), "max-size-bytes", 0, nullptr);
  g_object_set(G_OBJECT(queue_), "max-size-time", buffer_duration_nanosec_,
               nullptr);
  g_object_set(G_OBJECT(queue_), "low-percent", buffer_min_fill_, nullptr);

  if (buffer_duration_nanosec_ > 0) {
    g_object_set(G_OBJECT(queue_), "use-buffering", true, nullptr);
  }

  gst_element_link_many(queue_, audioconvert_, convert_sink, nullptr);

  // Link the elements with special caps
  // The scope path through the tee gets 16-bit ints.
  GstCaps* caps16 = gst_caps_new_simple ("audio/x-raw",
                                         "format", G_TYPE_STRING, "S16LE",
                                         NULL);
  gst_element_link_filtered(probe_converter, probe_sink, caps16);
  gst_caps_unref(caps16);

  // Link the outputs of tee to the queues on each path.
  gst_pad_link(gst_element_get_request_pad(tee, "src_%u"),
               gst_element_get_static_pad(probe_queue, "sink"));
  gst_pad_link(gst_element_get_request_pad(tee, "src_%u"),
               gst_element_get_static_pad(audio_queue, "sink"));

  // Link replaygain elements if enabled.
  if (rg_enabled_) {
    gst_element_link_many(rgvolume_, rglimiter_, audioconvert2_, tee, nullptr);
  }

  // Link everything else.
  gst_element_link(probe_queue, probe_converter);
  gst_element_link_many(audio_queue, equalizer_preamp_, equalizer_,
                        stereo_panorama_, volume_, audioscale_, convert,
                        audiosink_, nullptr);

  // Add probes and handlers.
  gst_pad_add_probe(gst_element_get_static_pad(probe_converter, "src"),
                    GST_PAD_PROBE_TYPE_BUFFER,
                    HandoffCallback, this, nullptr);
  gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
                           BusCallbackSync, this, nullptr);
  bus_cb_id_ = gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)),
                                 BusCallback, this);

  MaybeLinkDecodeToAudio();

  return true;
}
Exemple #7
0
void CddaDevice::Init() {
  QMutexLocker locker(&mutex_init_);
  song_count_ = 0; // Reset song count, in case it was already set
  cdio_ = cdio_open (url_.path().toLocal8Bit().constData(), DRIVER_DEVICE);
  if (cdio_ == NULL) {
    return;
  }
  // Create gstreamer cdda element
  cdda_ = gst_element_make_from_uri (GST_URI_SRC, "cdda://", NULL);
  if (cdda_ == NULL) {
    model_->Reset();
    return;
  }

  GST_CDDA_BASE_SRC(cdda_)->device = g_strdup (url_.path().toLocal8Bit().constData());

  // Change the element's state to ready and paused, to be able to query it
  if (gst_element_set_state(cdda_, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE ||
      gst_element_set_state(cdda_, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
    model_->Reset();
    gst_element_set_state(cdda_, GST_STATE_NULL);
    gst_object_unref(GST_OBJECT(cdda_));
    return;
  }

  // Get number of tracks
  GstFormat fmt = gst_format_get_by_nick ("track");
  GstFormat out_fmt = fmt;
  gint64 num_tracks = 0;
  if (!gst_element_query_duration (cdda_, &out_fmt, &num_tracks) || out_fmt != fmt) {
    qLog(Error) << "Error while querying cdda GstElement";
    model_->Reset();
    gst_object_unref(GST_OBJECT(cdda_));
    return;
  }

  SongList songs;
  for (int track_number = 1; track_number <= num_tracks; track_number++) {
    // Init song
    Song song;
    guint64 duration = 0;
    // quint64 == ulonglong and guint64 == ulong, therefore we must cast
    if (gst_tag_list_get_uint64 (GST_CDDA_BASE_SRC(cdda_)->tracks[track_number-1].tags,
                                 GST_TAG_DURATION, &duration)) {
      song.set_length_nanosec((quint64)duration);
    }
    song.set_id(track_number);
    song.set_valid(true);
    song.set_filetype(Song::Type_Cdda);
    song.set_url(QUrl(QString("cdda://%1/%2").arg(url_.path()).arg(track_number)));
    song.set_title(QString("Track %1").arg(track_number));
    song.set_track(track_number);
    songs << song;
  }
  song_count_ = num_tracks;
  connect(this, SIGNAL(SongsDiscovered(const SongList&)), model_, SLOT(SongsDiscovered(const SongList&)));
  emit SongsDiscovered(songs);

  // Generate MusicBrainz DiscId
  gst_tag_register_musicbrainz_tags();
  GstElement *pipe = gst_pipeline_new ("pipeline");
  gst_bin_add (GST_BIN (pipe), cdda_);
  gst_element_set_state (pipe, GST_STATE_READY);
  gst_element_set_state (pipe, GST_STATE_PAUSED);
  GstMessage *msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe),
                    GST_CLOCK_TIME_NONE,
                    GST_MESSAGE_TAG);
  GstTagList *tags = NULL;
  gst_message_parse_tag (msg, &tags);
  char *string_mb = NULL;
  if (gst_tag_list_get_string (tags, GST_TAG_CDDA_MUSICBRAINZ_DISCID, &string_mb)) {
    QString musicbrainz_discid(string_mb);
    qLog(Info) << "MusicBrainz discid: " << musicbrainz_discid;

    MusicBrainzClient *musicbrainz_client = new MusicBrainzClient(this);
    connect(musicbrainz_client,
            SIGNAL(Finished(const QString&, const QString&, MusicBrainzClient::ResultList)),
            SLOT(AudioCDTagsLoaded(const QString&, const QString&, MusicBrainzClient::ResultList)));
    musicbrainz_client->StartDiscIdRequest(musicbrainz_discid);
    g_free(string_mb);
  }

  // Clean all the Gstreamer objects we have used: we don't need them anymore
  gst_element_set_state (pipe, GST_STATE_NULL);
  // This will also cause cdda_ to be unref'd.
  gst_object_unref(GST_OBJECT(pipe));
  gst_object_unref(GST_OBJECT(msg));
  gst_tag_list_free(tags);
}
void Windows7ThumbBar::HandleWinEvent(MSG* msg) {
#ifdef Q_OS_WIN32
  if (button_created_message_id_ == 0) {
    // Compute the value for the TaskbarButtonCreated message
    button_created_message_id_ = RegisterWindowMessage("TaskbarButtonCreated");
    qLog(Debug) << "TaskbarButtonCreated message ID registered" << button_created_message_id_;
  }

  if (msg->message == button_created_message_id_) {
    HRESULT hr;
    qLog(Debug) << "Button created";
    // Unref the old taskbar list if we had one
    if (taskbar_list_) {
      qLog(Debug) << "Releasing old taskbar list";
      reinterpret_cast<ITaskbarList3*>(taskbar_list_)->Release();
      taskbar_list_ = NULL;
    }

    // Copied from win7 SDK shobjidl.h
    static const GUID CLSID_ITaskbarList ={ 0x56FDF344,0xFD6D,0x11d0,{0x95,0x8A,0x00,0x60,0x97,0xC9,0xA0,0x90}};
    // Create the taskbar list
    hr = CoCreateInstance(CLSID_ITaskbarList, NULL, CLSCTX_ALL,
                         IID_ITaskbarList3, (void**) &taskbar_list_);
    if (hr != S_OK) {
      qLog(Warning) << "Error creating the ITaskbarList3 interface" << hex << DWORD (hr);
      return;
    }

    ITaskbarList3* taskbar_list = reinterpret_cast<ITaskbarList3*>(taskbar_list_);
    hr = taskbar_list->HrInit();
    if (hr != S_OK) {
      qLog(Warning) << "Error initialising taskbar list" << hex << DWORD (hr);
      taskbar_list->Release();
      taskbar_list_ = NULL;
      return;
    }

    // Add the buttons
    qLog(Debug) << "Initialising" << actions_.count() << "buttons";
    THUMBBUTTON buttons[kMaxButtonCount];
    for (int i=0 ; i<actions_.count() ; ++i) {
      const QAction* action = actions_[i];
      THUMBBUTTON* button = &buttons[i];
      button->iId = i;
      SetupButton(action, button);
    }

    qLog(Debug) << "Adding buttons";
    hr = taskbar_list->ThumbBarAddButtons(widget_->winId(), actions_.count(), buttons);
    if (hr != S_OK)
      qLog(Debug) << "Failed to add buttons" << hex << DWORD (hr);
    for (int i = 0; i < actions_.count(); i++) {
      if (buttons[i].hIcon > 0)
        DestroyIcon (buttons[i].hIcon);
    }
  } else if (msg->message == WM_COMMAND) {
    const int button_id = LOWORD(msg->wParam);

    if (button_id >= 0 && button_id < actions_.count()) {
      if (actions_[button_id]) {
        qLog(Debug) << "Button activated";
        actions_[button_id]->activate(QAction::Trigger);
      }
    }
  }
#endif // Q_OS_WIN32
}
Exemple #9
0
void SpotifyService::PlaylistsUpdated(const pb::spotify::Playlists& response) {
  if (login_task_id_) {
    app_->task_manager()->SetTaskFinished(login_task_id_);
    login_task_id_ = 0;
  }

  // Create starred and inbox playlists if they're not here already
  if (!search_) {
    search_ =
        new QStandardItem(IconLoader::Load("edit-find", IconLoader::Base), 
                          tr("Search results"));
    search_->setToolTip(
        tr("Start typing something on the search box above to "
           "fill this search results list"));
    search_->setData(Type_SearchResults, InternetModel::Role_Type);
    search_->setData(InternetModel::PlayBehaviour_MultipleItems,
                     InternetModel::Role_PlayBehaviour);

    starred_ = new QStandardItem(QIcon(":/star-on.png"), tr("Starred"));
    starred_->setData(Type_StarredPlaylist, InternetModel::Role_Type);
    starred_->setData(true, InternetModel::Role_CanLazyLoad);
    starred_->setData(InternetModel::PlayBehaviour_MultipleItems,
                      InternetModel::Role_PlayBehaviour);
    starred_->setData(true, InternetModel::Role_CanBeModified);

    inbox_ = new QStandardItem(IconLoader::Load("mail-message", 
                               IconLoader::Base), tr("Inbox"));
    inbox_->setData(Type_InboxPlaylist, InternetModel::Role_Type);
    inbox_->setData(true, InternetModel::Role_CanLazyLoad);
    inbox_->setData(InternetModel::PlayBehaviour_MultipleItems,
                    InternetModel::Role_PlayBehaviour);

    toplist_ = new QStandardItem(QIcon(), tr("Top tracks"));
    toplist_->setData(Type_Toplist, InternetModel::Role_Type);
    toplist_->setData(true, InternetModel::Role_CanLazyLoad);
    toplist_->setData(InternetModel::PlayBehaviour_MultipleItems,
                      InternetModel::Role_PlayBehaviour);

    root_->appendRow(search_);
    root_->appendRow(toplist_);
    root_->appendRow(starred_);
    root_->appendRow(inbox_);
  } else {
    // Always reset starred playlist
    // TODO: might be improved by including starred playlist in the response,
    // and reloading it only when needed, like other playlists.
    starred_->removeRows(0, starred_->rowCount());
    LazyPopulate(starred_);
  }

  // Don't do anything if the playlists haven't changed since last time.
  if (!DoPlaylistsDiffer(response)) {
    qLog(Debug) << "Playlists haven't changed - not updating";
    return;
  }
  qLog(Debug) << "Playlist have changed: updating";

  // Remove and recreate the other playlists
  for (QStandardItem* item : playlists_) {
    item->parent()->removeRow(item->row());
  }
  playlists_.clear();

  for (int i = 0; i < response.playlist_size(); ++i) {
    const pb::spotify::Playlists::Playlist& msg = response.playlist(i);

    QString playlist_title = QStringFromStdString(msg.name());
    if (!msg.is_mine()) {
      const std::string& owner = msg.owner();
      playlist_title +=
          tr(", by ") + QString::fromUtf8(owner.c_str(), owner.size());
    }
    QStandardItem* item = new QStandardItem(playlist_title);
    item->setData(InternetModel::Type_UserPlaylist, InternetModel::Role_Type);
    item->setData(true, InternetModel::Role_CanLazyLoad);
    item->setData(msg.index(), Role_UserPlaylistIndex);
    item->setData(msg.is_mine(), InternetModel::Role_CanBeModified);
    item->setData(InternetModel::PlayBehaviour_MultipleItems,
                  InternetModel::Role_PlayBehaviour);
    item->setData(QUrl(QStringFromStdString(msg.uri())),
                  InternetModel::Role_Url);

    root_->appendRow(item);
    playlists_ << item;

    // Preload the playlist items so that drag & drop works immediately.
    LazyPopulate(item);
  }
}
void Database::StaticInit() {
  if (sStaticInitDone) {
    return;
  }
  sStaticInitDone = true;

  sFTSTokenizer = new sqlite3_tokenizer_module;
  sFTSTokenizer->iVersion = 0;
  sFTSTokenizer->xCreate = &Database::FTSCreate;
  sFTSTokenizer->xDestroy = &Database::FTSDestroy;
  sFTSTokenizer->xOpen = &Database::FTSOpen;
  sFTSTokenizer->xNext = &Database::FTSNext;
  sFTSTokenizer->xClose = &Database::FTSClose;

#ifdef HAVE_STATIC_SQLITE
  // We statically link libqsqlite.dll on windows and mac so these symbols are already
  // available
  _sqlite3_value_type = sqlite3_value_type;
  _sqlite3_value_int64 = sqlite3_value_int64;
  _sqlite3_value_text = sqlite3_value_text;
  _sqlite3_result_int64 = sqlite3_result_int64;
  _sqlite3_user_data = sqlite3_user_data;

  _sqlite3_open = sqlite3_open;
  _sqlite3_errmsg = sqlite3_errmsg;
  _sqlite3_close = sqlite3_close;
  _sqlite3_backup_init = sqlite3_backup_init;
  _sqlite3_backup_step = sqlite3_backup_step;
  _sqlite3_backup_finish = sqlite3_backup_finish;
  _sqlite3_backup_pagecount = sqlite3_backup_pagecount;
  _sqlite3_backup_remaining = sqlite3_backup_remaining;

  sLoadedSqliteSymbols = true;
  return;
#else // HAVE_STATIC_SQLITE
  QString plugin_path = QLibraryInfo::location(QLibraryInfo::PluginsPath) +
                        "/sqldrivers/libqsqlite";

  QLibrary library(plugin_path);
  if (!library.load()) {
    qLog(Error) << "QLibrary::load() failed for " << plugin_path;
    return;
  }

  _sqlite3_value_type = reinterpret_cast<int (*) (sqlite3_value*)>(
      library.resolve("sqlite3_value_type"));
  _sqlite3_value_int64 = reinterpret_cast<sqlite_int64 (*) (sqlite3_value*)>(
      library.resolve("sqlite3_value_int64"));
  _sqlite3_value_text = reinterpret_cast<const uchar* (*) (sqlite3_value*)>(
      library.resolve("sqlite3_value_text"));
  _sqlite3_result_int64 = reinterpret_cast<void (*) (sqlite3_context*, sqlite_int64)>(
      library.resolve("sqlite3_result_int64"));
  _sqlite3_user_data = reinterpret_cast<void* (*) (sqlite3_context*)>(
      library.resolve("sqlite3_user_data"));

  _sqlite3_open = reinterpret_cast<int (*) (const char*, sqlite3**)>(
      library.resolve("sqlite3_open"));
  _sqlite3_errmsg = reinterpret_cast<const char* (*) (sqlite3*)>(
      library.resolve("sqlite3_errmsg"));
  _sqlite3_close = reinterpret_cast<int (*) (sqlite3*)>(
      library.resolve("sqlite3_close"));
  _sqlite3_backup_init = reinterpret_cast<
      sqlite3_backup* (*) (sqlite3*, const char*, sqlite3*, const char*)>(
          library.resolve("sqlite3_backup_init"));
  _sqlite3_backup_step = reinterpret_cast<int (*) (sqlite3_backup*, int)>(
      library.resolve("sqlite3_backup_step"));
  _sqlite3_backup_finish = reinterpret_cast<int (*) (sqlite3_backup*)>(
      library.resolve("sqlite3_backup_finish"));
  _sqlite3_backup_pagecount = reinterpret_cast<int (*) (sqlite3_backup*)>(
      library.resolve("sqlite3_backup_pagecount"));
  _sqlite3_backup_remaining = reinterpret_cast<int (*) (sqlite3_backup*)>(
      library.resolve("sqlite3_backup_remaining"));

  if (!_sqlite3_value_type ||
      !_sqlite3_value_int64 ||
      !_sqlite3_value_text ||
      !_sqlite3_result_int64 ||
      !_sqlite3_user_data ||
      !_sqlite3_open ||
      !_sqlite3_errmsg ||
      !_sqlite3_close ||
      !_sqlite3_backup_init ||
      !_sqlite3_backup_step ||
      !_sqlite3_backup_finish ||
      !_sqlite3_backup_pagecount ||
      !_sqlite3_backup_remaining) {
    qLog(Error) << "Couldn't resolve sqlite symbols";
    sLoadedSqliteSymbols = false;
  } else {
    sLoadedSqliteSymbols = true;
  }
#endif
}
QSqlDatabase Database::Connect() {
  QMutexLocker l(&connect_mutex_);

  // Create the directory if it doesn't exist
  if (!QFile::exists(directory_)) {
    QDir dir;
    if (!dir.mkpath(directory_)) {
    }
  }

  const QString connection_id =
      QString("%1_thread_%2").arg(connection_id_).arg(
        reinterpret_cast<quint64>(QThread::currentThread()));

  // Try to find an existing connection for this thread
  QSqlDatabase db = QSqlDatabase::database(connection_id);
  if (db.isOpen()) {
    return db;
  }

  db = QSqlDatabase::addDatabase("QSQLITE", connection_id);

  if (!injected_database_name_.isNull())
    db.setDatabaseName(injected_database_name_);
  else
    db.setDatabaseName(directory_ + "/" + kDatabaseFilename);

  if (!db.open()) {
    app_->AddError("Database: " + db.lastError().text());
    return db;
  }

  // Find Sqlite3 functions in the Qt plugin.
  StaticInit();

  {
    QSqlQuery set_fts_tokenizer("SELECT fts3_tokenizer(:name, :pointer)", db);
    set_fts_tokenizer.bindValue(":name", "unicode");
    set_fts_tokenizer.bindValue(":pointer", QByteArray(
        reinterpret_cast<const char*>(&sFTSTokenizer), sizeof(&sFTSTokenizer)));
    if (!set_fts_tokenizer.exec()) {
      qLog(Warning) << "Couldn't register FTS3 tokenizer";
    }
    // Implicit invocation of ~QSqlQuery() when leaving the scope
    // to release any remaining database locks!
  }

  if (db.tables().count() == 0) {
    // Set up initial schema
    qLog(Info) << "Creating initial database schema";
    UpdateDatabaseSchema(0, db);
  }

  // Attach external databases
  foreach (const QString& key, attached_databases_.keys()) {
    QString filename = attached_databases_[key].filename_;

    if (!injected_database_name_.isNull())
      filename = injected_database_name_;

    // Attach the db
    QSqlQuery q("ATTACH DATABASE :filename AS :alias", db);
    q.bindValue(":filename", filename);
    q.bindValue(":alias", key);
    if (!q.exec()) {
      qFatal("Couldn't attach external database '%s'", key.toAscii().constData());
    }
  }

  if(startup_schema_version_ == -1) {
    UpdateMainSchema(&db);
  }

  // We might have to initialise the schema in some attached databases now, if
  // they were deleted and don't match up with the main schema version.
  foreach (const QString& key, attached_databases_.keys()) {
    // Find out if there are any tables in this database
    QSqlQuery q(QString("SELECT ROWID FROM %1.sqlite_master"
                        " WHERE type='table'").arg(key), db);
    if (!q.exec() || !q.next()) {
      q.finish();
      ExecSchemaCommandsFromFile(db, attached_databases_[key].schema_, 0);
    }
  }

  return db;
}
Exemple #12
0
void PBObserver::onGameInfo(RMessage *msg)
{
	PBLobbyDriver *drv = PBLobbyDriver::fromMessage(msg);

	Q_ASSERT(drv);

	PBSiteGameInfo *gi= _games->gameInfo(msg->getString("gameId"));
	
	PBGameInfo temp;
	msg->get(&temp);

	if(!gi->owner())	// if not observed by anyone
	{
		if(gi->canOpen())
		{	if(drv->canHandleMoreTables())
			{
				gi->setOwner(drv);	// locks the game
				gi->setLastUpdateTime(QTime::currentTime());
				gi->updateState(&temp);
				qLog(Debug)<<"LOCKED "<<gi->gameId()<<" by "<<gi->ownerId();
				openTable(msg, gi);
			}
		}else
		{
			qLog(Debug)<<"CLOSETOURNEY_NOT_OWNER_CANT_OPEN "<<gi->gameId();
			closeTourney(msg, gi);
		}
		
	}else
	{
		PBLobbyDriver *obsDrv = gi->owner();

		if(drv==obsDrv)
		{
			gi->updateState(&temp);
			if(gi->tableOpened())
			{
				gi->setNeedTableOpened(-1); // opened ok
				if(gi->tourneyOpened())
				{
					qLog(Debug)<<"CLOSETOURNEY_TOPEN "<<gi->gameId()<<" OWN="<<gi->ownerId();
					closeTourney(msg,gi);
				}
			}
			else if(gi->canOpen())
			{
				qLog(Debug)<<"REOBSERVE "<<gi->gameId()<<" by "<<gi->ownerId();
				// was closde by someone manualy
				openTable(msg, gi);
			}else{
				// not opend, cannot open - unlock
				qLog(Debug)<<"CLOSETOURNEY_CANTOPEN, UNLOCK "<<gi->gameId()<<" "<<gi->ownerId();
				gi->setOwner(0); // unlock
				gi->setTableOpened(0);
				gi->setTourneyOpened(0);
			}
			gi->setLastUpdateTime(QTime::currentTime());
		}else   // locked by	 other driver
		{
			qLog(Debug)<<"CLOSE "<<gi->gameId()<<" locked by "<<gi->ownerId()<<" upd from "<<gi->driver();
			closeTourney(msg, gi);
		}
	}
	
	_games->dump();
}
Exemple #13
0
void NeoHardware::cableConnected(bool b)
{
    qLog(Hardware)<< __PRETTY_FUNCTION__ << b;
    vsoUsbCable.setAttribute("cableConnected", b);
    vsoUsbCable.sync();
}
Exemple #14
0
QByteArray TagReader::LoadEmbeddedArt(const QString& filename) const {
  if (filename.isEmpty()) return QByteArray();

  qLog(Debug) << "Loading art from" << filename;

#ifdef Q_OS_WIN32
  TagLib::FileRef ref(filename.toStdWString().c_str());
#else
  TagLib::FileRef ref(QFile::encodeName(filename).constData());
#endif

  if (ref.isNull() || !ref.file()) return QByteArray();

  // MP3
  TagLib::MPEG::File* file = dynamic_cast<TagLib::MPEG::File*>(ref.file());
  if (file && file->ID3v2Tag()) {
    TagLib::ID3v2::FrameList apic_frames =
        file->ID3v2Tag()->frameListMap()["APIC"];
    if (apic_frames.isEmpty()) return QByteArray();

    TagLib::ID3v2::AttachedPictureFrame* pic =
        static_cast<TagLib::ID3v2::AttachedPictureFrame*>(apic_frames.front());

    return QByteArray((const char*)pic->picture().data(),
                      pic->picture().size());
  }

  // Ogg vorbis/speex
  TagLib::Ogg::XiphComment* xiph_comment =
      dynamic_cast<TagLib::Ogg::XiphComment*>(ref.file()->tag());

  if (xiph_comment) {
    TagLib::Ogg::FieldListMap map = xiph_comment->fieldListMap();

#if TAGLIB_MAJOR_VERSION <= 1 && TAGLIB_MINOR_VERSION < 11
    // Other than the below mentioned non-standard COVERART,
    // METADATA_BLOCK_PICTURE
    // is the proposed tag for cover pictures.
    // (see http://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE)
    if (map.contains("METADATA_BLOCK_PICTURE")) {
      TagLib::StringList pict_list = map["METADATA_BLOCK_PICTURE"];
      for (std::list<TagLib::String>::iterator it = pict_list.begin();
           it != pict_list.end(); ++it) {
        QByteArray data(QByteArray::fromBase64(it->toCString()));
        TagLib::ByteVector tdata(data.data(), data.size());
        TagLib::FLAC::Picture p(tdata);
        if (p.type() == TagLib::FLAC::Picture::FrontCover)
          return QByteArray(p.data().data(), p.data().size());
      }
      // If there was no specific front cover, just take the first picture
      QByteArray data(QByteArray::fromBase64(
          map["METADATA_BLOCK_PICTURE"].front().toCString()));
      TagLib::ByteVector tdata(data.data(), data.size());
      TagLib::FLAC::Picture p(tdata);
      return QByteArray(p.data().data(), p.data().size());
    }
#else
    TagLib::List<TagLib::FLAC::Picture*> pics = xiph_comment->pictureList();
    if (!pics.isEmpty()) {
      for (auto p : pics) {
        if (p->type() == TagLib::FLAC::Picture::FrontCover)
          return QByteArray(p->data().data(), p->data().size());
      }
      // If there was no specific front cover, just take the first picture
      std::list<TagLib::FLAC::Picture*>::iterator it = pics.begin();
      TagLib::FLAC::Picture* picture = *it;

      return QByteArray(picture->data().data(), picture->data().size());
    }
#endif

    // Ogg lacks a definitive standard for embedding cover art, but it seems
    // b64 encoding a field called COVERART is the general convention
    if (!map.contains("COVERART")) return QByteArray();

    return QByteArray::fromBase64(map["COVERART"].toString().toCString());
  }

#ifdef TAGLIB_HAS_FLAC_PICTURELIST
  // Flac
  TagLib::FLAC::File* flac_file = dynamic_cast<TagLib::FLAC::File*>(ref.file());
  if (flac_file && flac_file->xiphComment()) {
    TagLib::List<TagLib::FLAC::Picture*> pics = flac_file->pictureList();
    if (!pics.isEmpty()) {
      // Use the first picture in the file - this could be made cleverer and
      // pick the front cover if it's present.

      std::list<TagLib::FLAC::Picture*>::iterator it = pics.begin();
      TagLib::FLAC::Picture* picture = *it;

      return QByteArray(picture->data().data(), picture->data().size());
    }
  }
#endif

  // MP4/AAC
  TagLib::MP4::File* aac_file = dynamic_cast<TagLib::MP4::File*>(ref.file());
  if (aac_file) {
    TagLib::MP4::Tag* tag = aac_file->tag();
    const TagLib::MP4::ItemListMap& items = tag->itemListMap();
    TagLib::MP4::ItemListMap::ConstIterator it = items.find("covr");
    if (it != items.end()) {
      const TagLib::MP4::CoverArtList& art_list = it->second.toCoverArtList();

      if (!art_list.isEmpty()) {
        // Just take the first one for now
        const TagLib::MP4::CoverArt& art = art_list.front();
        return QByteArray(art.data().data(), art.data().size());
      }
    }
  }

  return QByteArray();
}
void SpotifyBlobDownloader::ReplyFinished() {
  QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
  if (reply->error() != QNetworkReply::NoError) {
    // Handle network errors
    ShowError(reply->errorString());
    return;
  }

  // Is everything finished?
  for (QNetworkReply* reply : replies_) {
    if (!reply->isFinished()) {
      return;
    }
  }

  // Read files into memory first.
  QMap<QString, QByteArray> file_data;
  QStringList signature_filenames;

  for (QNetworkReply* reply : replies_) {
    const QString filename = reply->url().path().section('/', -1, -1);

    if (filename.endsWith(kSignatureSuffix)) {
      signature_filenames << filename;
    }

    file_data[filename] = reply->readAll();
  }

#ifdef HAVE_QCA
  // Load the public key
  QCA::ConvertResult conversion_result;
  QCA::PublicKey key = QCA::PublicKey::fromPEMFile(
      ":/clementine-spotify-public.pem", &conversion_result);
  if (QCA::ConvertGood != conversion_result) {
    ShowError("Failed to load Spotify public key");
    return;
  }

  // Verify signatures
  for (const QString& signature_filename : signature_filenames) {
    QString actual_filename = signature_filename;
    actual_filename.remove(kSignatureSuffix);

    qLog(Debug) << "Verifying" << actual_filename << "against"
                << signature_filename;

    if (!key.verifyMessage(file_data[actual_filename],
                           file_data[signature_filename], QCA::EMSA3_SHA1)) {
      ShowError("Invalid signature: " + actual_filename);
      return;
    }
  }
#endif  // HAVE_QCA

  // Make the destination directory and write the files into it
  QDir().mkpath(path_);

  for (const QString& filename : file_data.keys()) {
    const QString dest_path = path_ + "/" + filename;

    if (filename.endsWith(kSignatureSuffix)) continue;

    qLog(Info) << "Writing" << dest_path;

    QFile file(dest_path);
    if (!file.open(QIODevice::WriteOnly)) {
      ShowError("Failed to open " + dest_path + " for writing");
      return;
    }

    file.write(file_data[filename]);
    file.close();
    file.setPermissions(QFile::Permissions(0x7755));

#ifdef Q_OS_UNIX
    const int so_pos = filename.lastIndexOf(".so.");
    if (so_pos != -1) {
      QString link_path = path_ + "/" + filename.left(so_pos + 3);
      QStringList version_parts = filename.mid(so_pos + 4).split('.');

      while (!version_parts.isEmpty()) {
        qLog(Debug) << "Linking" << dest_path << "to" << link_path;
        int ret = symlink(dest_path.toLocal8Bit().constData(),
                          link_path.toLocal8Bit().constData());

        if (ret != 0) {
          qLog(Warning) << "Creating symlink failed with return code" << ret;
        }

        link_path += "." + version_parts.takeFirst();
      }
    }
#endif  // Q_OS_UNIX
  }

  EmitFinished();
}
Exemple #16
0
void SpotifyService::FillPlaylist(
    QStandardItem* item, const pb::spotify::LoadPlaylistResponse& response) {
  qLog(Debug) << "Filling playlist:" << item->text();
  FillPlaylist(item, response.track());
}
Exemple #17
0
QString Chromaprinter::CreateFingerprint() {
  Q_ASSERT(QThread::currentThread() != qApp->thread());

  buffer_.open(QIODevice::WriteOnly);

  GMainContext* context = g_main_context_new();
  g_main_context_push_thread_default(context);
  event_loop_ = g_main_loop_new(context, FALSE);

  pipeline_ = gst_pipeline_new("pipeline");
  GstElement* src      = CreateElement("filesrc", pipeline_);
  GstElement* decode   = CreateElement("decodebin2", pipeline_);
  GstElement* convert  = CreateElement("audioconvert", pipeline_);
  GstElement* resample = CreateElement("audioresample", pipeline_);
  GstElement* sink     = CreateElement("appsink", pipeline_);

  if (!src || !decode || !convert || !resample || !sink) {
    return QString();
  }

  convert_element_ = convert;

  // Connect the elements
  gst_element_link_many(src, decode, NULL);
  gst_element_link_many(convert, resample, NULL);

  // Chromaprint expects mono floats at a sample rate of 11025Hz.
  GstCaps* caps = gst_caps_new_simple(
      "audio/x-raw-int",
      "width", G_TYPE_INT, 16,
      "channels", G_TYPE_INT, kDecodeChannels,
      "rate", G_TYPE_INT, kDecodeRate,
      NULL);
  gst_element_link_filtered(resample, sink, caps);
  gst_caps_unref(caps);

  GstAppSinkCallbacks callbacks;
  memset(&callbacks, 0, sizeof(callbacks));
  callbacks.new_buffer = NewBufferCallback;
  gst_app_sink_set_callbacks(reinterpret_cast<GstAppSink*>(sink), &callbacks, this, NULL);
  g_object_set(G_OBJECT(sink), "sync", FALSE, NULL);
  g_object_set(G_OBJECT(sink), "emit-signals", TRUE, NULL);

  // Set the filename
  g_object_set(src, "location", filename_.toUtf8().constData(), NULL);

  // Connect signals
  CHECKED_GCONNECT(decode, "new-decoded-pad", &NewPadCallback, this);
  gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), BusCallbackSync, this);
  guint bus_callback_id = gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), BusCallback, this);

  QTime time;
  time.start();

  // Start playing
  gst_element_set_state(pipeline_, GST_STATE_PLAYING);

  g_main_loop_run(event_loop_);
  g_main_loop_unref(event_loop_);
  g_main_context_unref(context);

  int decode_time = time.restart();

  buffer_.close();
  QByteArray data = buffer_.data();

  ChromaprintContext* chromaprint = chromaprint_new(CHROMAPRINT_ALGORITHM_DEFAULT);
  chromaprint_start(chromaprint, kDecodeRate, kDecodeChannels);
  chromaprint_feed(chromaprint, reinterpret_cast<void*>(data.data()), data.size() / 2);
  chromaprint_finish(chromaprint);

  void* fprint = NULL;
  int size = 0;
  int ret = chromaprint_get_raw_fingerprint(chromaprint, &fprint, &size);
  QByteArray fingerprint;
  if (ret == 1) {
    void* encoded = NULL;
    int encoded_size = 0;
    chromaprint_encode_fingerprint(
        fprint, size, CHROMAPRINT_ALGORITHM_DEFAULT, &encoded, &encoded_size, 1);

    fingerprint.append(reinterpret_cast<char*>(encoded), encoded_size);

    chromaprint_dealloc(fprint);
    chromaprint_dealloc(encoded);
  }
  chromaprint_free(chromaprint);
  int codegen_time = time.elapsed();

  qLog(Debug) << "Decode time:" << decode_time << "Codegen time:" << codegen_time;

  // Cleanup
  callbacks.new_buffer = NULL;
  gst_app_sink_set_callbacks(reinterpret_cast<GstAppSink*>(sink), &callbacks, this, NULL);
  gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), NULL, NULL);
  g_source_remove(bus_callback_id);
  gst_element_set_state(pipeline_, GST_STATE_NULL);
  gst_object_unref(pipeline_);

  return fingerprint;
}
Exemple #18
0
bool QAudioInputPrivate::open( QObject *input )
{
    // Open the Alsa capture device.
    bool    rc = true;
    int     err;

    unsigned int        freakuency = frequency;

    if ((err = snd_pcm_open(&handle,
                             m_device.constData(), //"plughw:0,0"
                             SND_PCM_STREAM_CAPTURE,
                                 0/*SND_PCM_ASYNC*/)) < 0) {

        qWarning( "QAudioInput: snd_pcm_open: error %d", err);

        rc = false;
    }
    else {
        snd_pcm_hw_params_t *hwparams;

        // We want non-blocking mode.
        snd_pcm_nonblock(handle, 1);

        // Set the desired parameters.
        snd_pcm_hw_params_alloca(&hwparams);

        err = snd_pcm_hw_params_any(handle, hwparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_any: err %d", err);
        }

        err = snd_pcm_hw_params_set_access(handle, hwparams,
                                           access);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_access: err %d",err);
        }

        err = snd_pcm_hw_params_set_format(handle, hwparams,format);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_format: err %d",err);
        }

        err = snd_pcm_hw_params_set_channels(handle,hwparams,(unsigned int)channels);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_channels: err %d",err);
        }

        err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &freakuency, 0);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_rate_near: err %d",err);
        }
        if(freakuency > 1.05 * frequency || freakuency < 0.95 * frequency) {
            qWarning("QAudioInput: warning, sample rate %i not supported by the hardware, using %u", frequency, freakuency);
        }

        if ( samplesPerBlock != -1 ) {
            // Set buffer and period sizes based on the supplied block size.
            sample_size = (snd_pcm_uframes_t)( samplesPerBlock * channels / 8 );
            err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &freakuency, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_rate_near: err %d",err);
            }
            if(freakuency > 1.05 * frequency || freakuency < 0.95 * frequency) {
                qWarning( "QAudioInput: warning, sample rate %i not supported by the hardware, using %u", frequency, freakuency);
            }

            err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err %d",err);
            }
            period_time = 1000000 * 256 / frequency;
            err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_period_time_near: err %d",err);
            }
        } else {
            // Use the largest buffer and period sizes we can.
            err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err %d",err);
            }
            period_time = 1000000 * 256 / frequency;
            err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_period_time_near: err %d",err);
            }
       }

        err = snd_pcm_hw_params(handle, hwparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params: err %d",err);
        }

        int                  dir;
        unsigned int         vval, vval2;
        snd_pcm_access_t     aval;
        snd_pcm_format_t     fval;
        snd_pcm_subformat_t  sval;

        qLog(QAudioInput) << "PCM handle name = " << snd_pcm_name(handle);
        qLog(QAudioInput) << "PCM state = " << snd_pcm_state_name(snd_pcm_state(handle));

        snd_pcm_hw_params_get_access(hwparams,&aval);
        vval = (unsigned int)aval;
        if ( (int)vval != (int)access ) {
            qLog(QAudioInput) << QString("access type not set, want %1 got %2")
                       .arg(snd_pcm_access_name((snd_pcm_access_t)access))
                       .arg(snd_pcm_access_name((snd_pcm_access_t)vval));
            access = (snd_pcm_access_t)vval;
        }
        qLog(QAudioInput) << "access type = " << snd_pcm_access_name((snd_pcm_access_t)vval);

        snd_pcm_hw_params_get_format(hwparams, &fval);
        vval = (unsigned int)fval;
        if ( (int)vval != (int)format ) {
            qLog(QAudioInput) << QString("format type not set, want %1 got %2")
                       .arg(snd_pcm_format_name((snd_pcm_format_t)format))
                       .arg(snd_pcm_format_name((snd_pcm_format_t)vval));
            format = (snd_pcm_format_t)vval;
        }
        qLog(QAudioInput) << QString("format = '%1' (%2)")
            .arg(snd_pcm_format_name((snd_pcm_format_t)vval))
            .arg(snd_pcm_format_description((snd_pcm_format_t)vval))
            .toLatin1().constData();

        snd_pcm_hw_params_get_subformat(hwparams,&sval);
        vval = (unsigned int)sval;
        qLog(QAudioInput) << QString("subformat = '%1' (%2)")
            .arg(snd_pcm_subformat_name((snd_pcm_subformat_t)vval))
            .arg(snd_pcm_subformat_description((snd_pcm_subformat_t)vval))
            .toLatin1().constData();

        snd_pcm_hw_params_get_channels(hwparams, &vval);
        if ( (int)vval != (int)channels ) {
            qLog(QAudioInput) << QString("channels type not set, want %1 got %2").arg(channels).arg(vval);
            channels = vval;
        }
        qLog(QAudioInput) << "channels = " << vval;

        snd_pcm_hw_params_get_rate(hwparams, &vval, &dir);
        if ( (int)vval != (int)frequency ) {
            qLog(QAudioInput) << QString("frequency type not set, want %1 got %2").arg(frequency).arg(vval);
            frequency = vval;
        }
        qLog(QAudioInput) << "rate =" <<  vval << " bps";

        snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir);
        qLog(QAudioInput) << "period time =" << period_time << " us";
        snd_pcm_hw_params_get_period_size(hwparams,&period_size, &dir);
        qLog(QAudioInput) << "period size =" << (int)period_size;
        snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir);
        qLog(QAudioInput) << "buffer time =" << buffer_time;
        snd_pcm_hw_params_get_buffer_size(hwparams,(snd_pcm_uframes_t *) &buffer_size);
        qLog(QAudioInput) << "buffer size =" << (int)buffer_size;
        snd_pcm_hw_params_get_periods(hwparams, &vval, &dir);
        qLog(QAudioInput) << "periods per buffer =" << vval;
        snd_pcm_hw_params_get_rate_numden(hwparams, &vval, &vval2);
        qLog(QAudioInput) << QString("exact rate = %1/%2 bps").arg(vval).arg(vval2).toLatin1().constData();
        vval = snd_pcm_hw_params_get_sbits(hwparams);
        qLog(QAudioInput) << "significant bits =" << vval;
        snd_pcm_hw_params_get_tick_time(hwparams,&vval, &dir);
        qLog(QAudioInput) << "tick time =" << vval;
        vval = snd_pcm_hw_params_is_batch(hwparams);
        qLog(QAudioInput) << "is batch =" << vval;
        vval = snd_pcm_hw_params_is_block_transfer(hwparams);
        qLog(QAudioInput) << "is block transfer =" << vval;
        vval = snd_pcm_hw_params_is_double(hwparams);
        qLog(QAudioInput) << "is double =" << vval;
        vval = snd_pcm_hw_params_is_half_duplex(hwparams);
        qLog(QAudioInput) << "is half duplex =" << vval;
        vval = snd_pcm_hw_params_is_joint_duplex(hwparams);
        qLog(QAudioInput) << "is joint duplex =" << vval;
        vval = snd_pcm_hw_params_can_overrange(hwparams);
        qLog(QAudioInput) << "can overrange =" << vval;
        vval = snd_pcm_hw_params_can_mmap_sample_resolution(hwparams);
        qLog(QAudioInput) << "can mmap =" << vval;
        vval = snd_pcm_hw_params_can_pause(hwparams);
        qLog(QAudioInput) << "can pause =" << vval;
        vval = snd_pcm_hw_params_can_resume(hwparams);
        qLog(QAudioInput) << "can resume =" << vval;
        vval = snd_pcm_hw_params_can_sync_start(hwparams);
        qLog(QAudioInput) << "can sync start =" << vval;

        snd_pcm_sw_params_t *swparams;
        snd_pcm_sw_params_alloca(&swparams);
        err = snd_pcm_sw_params_current(handle, swparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_current: err %d",err);
        }
        err = snd_pcm_sw_params_set_start_threshold(handle,swparams,period_size);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_set_start_threshold: err %d",err);
        }
        err = snd_pcm_sw_params_set_avail_min(handle, swparams,period_size);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_set_avail_min: err %d",err);
        }
        err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_set_xfer_align: err %d",err);
        }
        err = snd_pcm_sw_params(handle, swparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params: err %d",err);
        }

        snd_pcm_prepare(handle);
        snd_pcm_start(handle);

        int     count = snd_pcm_poll_descriptors_count(handle);
        pollfd  *pfds = new pollfd[count];

        snd_pcm_poll_descriptors(handle, pfds, count);

        for (int i = 0; i < count; ++i)
        {
            if ((pfds[i].events & POLLIN) != 0) {
                notifier = new QSocketNotifier(pfds[i].fd, QSocketNotifier::Read);
                QObject::connect(notifier,
                                 SIGNAL(activated(int)),
                                 input,
                                 SIGNAL(readyRead()));

                break;
            }
        }

        if (notifier == NULL) {
            rc = false;
        }

        delete pfds;
    }

    return rc;
}
GstPadProbeReturn GstEnginePipeline::HandoffCallback(GstPad*,
                                                     GstPadProbeInfo* info,
                                                     gpointer self) {
  GstEnginePipeline* instance = reinterpret_cast<GstEnginePipeline*>(self);
  GstBuffer* buf = gst_pad_probe_info_get_buffer(info);

  QList<BufferConsumer*> consumers;
  {
    QMutexLocker l(&instance->buffer_consumers_mutex_);
    consumers = instance->buffer_consumers_;
  }

  for (BufferConsumer* consumer : consumers) {
    gst_buffer_ref(buf);
    consumer->ConsumeBuffer(buf, instance->id());
  }

  // Calculate the end time of this buffer so we can stop playback if it's
  // after the end time of this song.
  if (instance->end_offset_nanosec_ > 0) {
    quint64 start_time = GST_BUFFER_TIMESTAMP(buf) - instance->segment_start_;
    quint64 duration = GST_BUFFER_DURATION(buf);
    quint64 end_time = start_time + duration;

    if (end_time > instance->end_offset_nanosec_) {
      if (instance->has_next_valid_url()) {
        if (instance->next_url_ == instance->url_ &&
            instance->next_beginning_offset_nanosec_ ==
                instance->end_offset_nanosec_) {
          // The "next" song is actually the next segment of this file - so
          // cheat and keep on playing, but just tell the Engine we've moved on.
          instance->end_offset_nanosec_ = instance->next_end_offset_nanosec_;
          instance->next_url_ = QUrl();
          instance->next_beginning_offset_nanosec_ = 0;
          instance->next_end_offset_nanosec_ = 0;

          // GstEngine will try to seek to the start of the new section, but
          // we're already there so ignore it.
          instance->ignore_next_seek_ = true;
          emit instance->EndOfStreamReached(instance->id(), true);
        } else {
          // We have a next song but we can't cheat, so move to it normally.
          instance->TransitionToNext();
        }
      } else {
        // There's no next song
        emit instance->EndOfStreamReached(instance->id(), false);
      }
    }
  }

  if (instance->emit_track_ended_on_time_discontinuity_) {
    if (GST_BUFFER_FLAG_IS_SET(buf, GST_BUFFER_FLAG_DISCONT) ||
        GST_BUFFER_OFFSET(buf) < instance->last_buffer_offset_) {
      qLog(Debug) << "Buffer discontinuity - emitting EOS";
      instance->emit_track_ended_on_time_discontinuity_ = false;
      emit instance->EndOfStreamReached(instance->id(), true);
    }
  }

  instance->last_buffer_offset_ = GST_BUFFER_OFFSET(buf);

  return GST_PAD_PROBE_OK;
}
Exemple #20
0
int main(int argc, char* argv[]) {
  if (CrashReporting::SendCrashReport(argc, argv)) {
    return 0;
  }

  CrashReporting crash_reporting;

#ifdef Q_OS_DARWIN
  // Do Mac specific startup to get media keys working.
  // This must go before QApplication initialisation.
  mac::MacMain();

  if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_8) {
    // Work around 10.9 issue.
    // https://bugreports.qt.io/browse/QTBUG-32789
    QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
  }
#endif

  QCoreApplication::setApplicationName("Clementine");
  QCoreApplication::setApplicationVersion(CLEMENTINE_VERSION_DISPLAY);
  QCoreApplication::setOrganizationName("Clementine");
  QCoreApplication::setOrganizationDomain("clementine-player.org");

// This makes us show up nicely in gnome-volume-control
#if !GLIB_CHECK_VERSION(2, 36, 0)
  g_type_init();  // Deprecated in glib 2.36.0
#endif
  g_set_application_name(QCoreApplication::applicationName().toLocal8Bit());

  RegisterMetaTypes();

  // Initialise logging.  Log levels are set after the commandline options are
  // parsed below.
  logging::Init();
  g_log_set_default_handler(reinterpret_cast<GLogFunc>(&logging::GLog),
                            nullptr);

  CommandlineOptions options(argc, argv);

  {
    // Only start a core application now so we can check if there's another
    // Clementine running without needing an X server.
    // This MUST be done before parsing the commandline options so QTextCodec
    // gets the right system locale for filenames.
    QtSingleCoreApplication a(argc, argv);
    CheckPortable();
    crash_reporting.SetApplicationPath(a.applicationFilePath());

    // Parse commandline options - need to do this before starting the
    // full QApplication so it works without an X server
    if (!options.Parse()) return 1;
    logging::SetLevels(options.log_levels());

    if (a.isRunning()) {
      if (options.is_empty()) {
        qLog(Info)
            << "Clementine is already running - activating existing window";
      }

      QByteArray serializedOptions = options.Serialize();
      if (a.sendMessage(serializedOptions, 5000)) {
        qLog(Info) << "Options found, sent message to running instance";
        return 0;
      }
      // Couldn't send the message so start anyway
    }
  }

#ifdef Q_OS_DARWIN
  // Must happen after QCoreApplication::setOrganizationName().
  setenv(
      "XDG_CONFIG_HOME",
      Utilities::GetConfigPath(Utilities::Path_Root).toLocal8Bit().constData(),
      1);
#endif

  // Output the version, so when people attach log output to bug reports they
  // don't have to tell us which version they're using.
  qLog(Info) << "Clementine" << CLEMENTINE_VERSION_DISPLAY;

  // Seed the random number generators.
  time_t t = time(nullptr);
  srand(t);
  qsrand(t);

  IncreaseFDLimit();

  QtSingleApplication a(argc, argv);

#ifdef HAVE_LIBLASTFM
  lastfm::ws::ApiKey = LastFMService::kApiKey;
  lastfm::ws::SharedSecret = LastFMService::kSecret;
  lastfm::setNetworkAccessManager(new NetworkAccessManager);
#endif

  // A bug in Qt means the wheel_scroll_lines setting gets ignored and replaced
  // with the default value of 3 in QApplicationPrivate::initialize.
  {
    QSettings qt_settings(QSettings::UserScope, "Trolltech");
    qt_settings.beginGroup("Qt");
    QApplication::setWheelScrollLines(
        qt_settings.value("wheelScrollLines", QApplication::wheelScrollLines())
            .toInt());
  }

#ifdef Q_OS_DARWIN
  QCoreApplication::setLibraryPaths(
      QStringList() << QCoreApplication::applicationDirPath() + "/../PlugIns");
#endif

  a.setQuitOnLastWindowClosed(false);

  // Do this check again because another instance might have started by now
  if (a.isRunning() && a.sendMessage(options.Serialize(), 5000)) {
    return 0;
  }

#ifndef Q_OS_DARWIN
  // Gnome on Ubuntu has menu icons disabled by default.  I think that's a bad
  // idea, and makes some menus in Clementine look confusing.
  QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus, false);
#else
  QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus, true);
  // Fixes focus issue with NSSearchField, see QTBUG-11401
  QCoreApplication::setAttribute(Qt::AA_NativeWindows, true);
#endif

  SetGstreamerEnvironment();

// Set the permissions on the config file on Unix - it can contain passwords
// for internet services so it's important that other users can't read it.
// On Windows these are stored in the registry instead.
#ifdef Q_OS_UNIX
  {
    QSettings s;

    // Create the file if it doesn't exist already
    if (!QFile::exists(s.fileName())) {
      QFile file(s.fileName());
      file.open(QIODevice::WriteOnly);
    }

    // Set -rw-------
    QFile::setPermissions(s.fileName(), QFile::ReadOwner | QFile::WriteOwner);
  }
#endif

  // Resources
  Q_INIT_RESOURCE(data);
  Q_INIT_RESOURCE(translations);

  // Add root CA cert for SoundCloud, whose certificate is missing on OS X.
  QSslSocket::addDefaultCaCertificates(
      QSslCertificate::fromPath(":/soundcloud-ca.pem", QSsl::Pem));
  QSslSocket::addDefaultCaCertificates(QSslCertificate::fromPath(
      ":/Equifax_Secure_Certificate_Authority.pem", QSsl::Pem));

  // Has the user forced a different language?
  QString override_language = options.language();
  if (override_language.isEmpty()) {
    QSettings s;
    s.beginGroup("General");
    override_language = s.value("language").toString();
  }

  const QString language = override_language.isEmpty()
                               ? Utilities::SystemLanguageName()
                               : override_language;

  // Translations
  LoadTranslation("qt", QLibraryInfo::location(QLibraryInfo::TranslationsPath),
                  language);
  LoadTranslation("clementine", ":/translations", language);
  LoadTranslation("clementine", a.applicationDirPath(), language);
  LoadTranslation("clementine", QDir::currentPath(), language);

#ifdef Q_OS_WIN32
  // Set the language for qtsparkle
  qtsparkle::LoadTranslations(language);
#endif

  // Icons
  IconLoader::Init();

  // This is a nasty hack to ensure that everything in libprotobuf is
  // initialised in the main thread.  It fixes issue 3265 but nobody knows why.
  // Don't remove this unless you can reproduce the error that it fixes.
  ParseAProto();
  QtConcurrent::run(&ParseAProto);

  Application app;
  app.set_language_name(language);

  // Network proxy
  QNetworkProxyFactory::setApplicationProxyFactory(
      NetworkProxyFactory::Instance());

#ifdef Q_OS_LINUX
  // In 11.04 Ubuntu decided that the system tray should be reserved for certain
  // whitelisted applications.  Clementine will override this setting and insert
  // itself into the list of whitelisted apps.
  UbuntuUnityHack hack;
#endif  // Q_OS_LINUX

  // Create the tray icon and OSD
  std::unique_ptr<SystemTrayIcon> tray_icon(
      SystemTrayIcon::CreateSystemTrayIcon());
  OSD osd(tray_icon.get(), &app);

#ifdef HAVE_DBUS
  mpris::Mpris mpris(&app);
#endif

  // Window
  MainWindow w(&app, tray_icon.get(), &osd, options);
#ifdef Q_OS_DARWIN
  mac::EnableFullScreen(w);
#endif  // Q_OS_DARWIN
#ifdef HAVE_GIO
  ScanGIOModulePath();
#endif
#ifdef HAVE_DBUS
  QObject::connect(&mpris, SIGNAL(RaiseMainWindow()), &w, SLOT(Raise()));
#endif
  QObject::connect(&a, SIGNAL(messageReceived(QByteArray)), &w,
                   SLOT(CommandlineOptionsReceived(QByteArray)));

  int ret = a.exec();

#ifdef Q_OS_LINUX
  // The nvidia driver would cause Clementine (or any application that used
  // opengl) to use 100% cpu on shutdown.  See:
  //   http://code.google.com/p/clementine-player/issues/detail?id=2088
  //   https://bugs.gentoo.org/show_bug.cgi?id=375615
  // Work around this problem by exiting immediately (and not running the buggy
  // nvidia atexit shutdown handler) if we're using one of the affected versions
  // of the nvidia driver.

  QFile self_maps("/proc/self/maps");
  if (self_maps.open(QIODevice::ReadOnly)) {
    QByteArray data = self_maps.readAll();
    if (data.contains("libnvidia-tls.so.")) {
      qLog(Warning) << "Exiting immediately to work around NVIDIA driver bug";
      _exit(ret);
    }
    self_maps.close();
  }
#endif

  return ret;
}
Exemple #21
0
void Organise::ProcessSomeFiles() {
  if (!started_) {
    transcode_temp_name_.open();

    if (!destination_->StartCopy(&supported_filetypes_)) {
      // Failed to start - mark everything as failed :(
      for (const Task& task : tasks_pending_)
        files_with_errors_ << task.song_.url().toLocalFile();
      tasks_pending_.clear();
    }
    started_ = true;
  }

  // None left?
  if (tasks_pending_.isEmpty()) {
    if (!tasks_transcoding_.isEmpty()) {
      // Just wait - FileTranscoded will start us off again in a little while
      qLog(Debug) << "Waiting for transcoding jobs";
      transcode_progress_timer_.start(kTranscodeProgressInterval, this);
      return;
    }

    UpdateProgress();

    destination_->FinishCopy(files_with_errors_.isEmpty());
    if (eject_after_)
      destination_->Eject();

    task_manager_->SetTaskFinished(task_id_);

    emit Finished(files_with_errors_);

    // Move back to the original thread so deleteLater() can get called in
    // the main thread's event loop
    moveToThread(original_thread_);
    deleteLater();

    // Stop this thread
    thread_->quit();
    return;
  }

  // We process files in batches so we can be cancelled part-way through.
  for (int i = 0; i < kBatchSize; ++i) {
    SetSongProgress(0);

    if (tasks_pending_.isEmpty())
      break;

    Task task = tasks_pending_.takeFirst();
    qLog(Info) << "Processing" << task.song_.url().toLocalFile();

    // Use a Song instead of a tag reader
    Song song = task.song_;
    if (!song.is_valid())
      continue;

    // Maybe this file is one that's been transcoded already?
    if (!task.transcoded_filename_.isEmpty()) {
      qLog(Debug) << "This file has already been transcoded";

      // Set the new filetype on the song so the formatter gets it right
      song.set_filetype(task.new_filetype_);

      // Fiddle the filename extension as well to match the new type
      song.set_url(QUrl::fromLocalFile(Utilities::FiddleFileExtension(song.basefilename(), task.new_extension_)));
      song.set_basefilename(Utilities::FiddleFileExtension(song.basefilename(), task.new_extension_));

      // Have to set this to the size of the new file or else funny stuff happens
      song.set_filesize(QFileInfo(task.transcoded_filename_).size());
    } else {
      // Figure out if we need to transcode it
      Song::FileType dest_type = CheckTranscode(song.filetype());
      if (dest_type != Song::Type_Unknown) {
        // Get the preset
        TranscoderPreset preset = Transcoder::PresetForFileType(dest_type);
        qLog(Debug) << "Transcoding with" << preset.name_;

        // Get a temporary name for the transcoded file
        task.transcoded_filename_ = transcode_temp_name_.fileName() + "-" +
                                    QString::number(transcode_suffix_++);
        task.new_extension_ = preset.extension_;
        task.new_filetype_ = dest_type;
        tasks_transcoding_[task.song_.url().toLocalFile()] = task;

        qLog(Debug) << "Transcoding to" << task.transcoded_filename_;

        // Start the transcoding - this will happen in the background and
        // FileTranscoded() will get called when it's done.  At that point the
        // task will get re-added to the pending queue with the new filename.
        transcoder_->AddJob(task.song_.url().toLocalFile(), preset, task.transcoded_filename_);
        transcoder_->Start();
        continue;
      }
    }

    MusicStorage::CopyJob job;
    job.source_ = task.transcoded_filename_.isEmpty() ?
      task.song_.url().toLocalFile() : task.transcoded_filename_;
    job.destination_ = format_.GetFilenameForSong(song);
    job.metadata_ = song;
    job.overwrite_ = overwrite_;
    job.remove_original_ = !copy_;
    job.progress_ = boost::bind(&Organise::SetSongProgress,
                                this, _1, !task.transcoded_filename_.isEmpty());

    if (!destination_->CopyToStorage(job)) {
      files_with_errors_ << task.song_.basefilename();
    }

    // Clean up the temporary transcoded file
    if (!task.transcoded_filename_.isEmpty())
      QFile::remove(task.transcoded_filename_);

    tasks_complete_++;
  }
  SetSongProgress(0);

  QTimer::singleShot(0, this, SLOT(ProcessSomeFiles()));
}
Exemple #22
0
bool NeoMultiplexerPlugin::detect( QSerialIODevice *device )
{
    qLog(Hardware) << __PRETTY_FUNCTION__;

    // Power on modem via sysfs
    QFile f("/sys/bus/platform/devices/neo1973-pm-gsm.0/power_on");
    if(f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
        f.write("0");
        f.close();
    }
    if(f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
        f.write("1");
        f.close();
    } else {
        qWarning() << "Modem power on failed "<< f.errorString();
    }
    
    // The FIC needs a special line discipline set on the device.
    QSerialPort *port = qobject_cast<QSerialPort *>( device );
    if (port) {
        int discipline = N_TIHTC;
        ::ioctl(port->fd(), TIOCSETD, &discipline);
    }
    device->discard();
    int rc;

    struct termios t;
    rc = tcgetattr(port->fd(), &t);
    t.c_cflag |= CRTSCTS;
    rc = tcsetattr(port->fd(), TCSANOW, &t);

    QValueSpaceItem deviceString("/Hardware/Neo/Device");
    if ( deviceString.value().toString() == "GTA02") {
        qLog(Hardware) << __PRETTY_FUNCTION__ << "is gta02";
        muxEnabled = true;
    } else {
        qLog(Hardware) << __PRETTY_FUNCTION__ << "is gta01";
        muxEnabled = false;
    }

    QSettings cfg("Trolltech", "Modem");
    QString multiplexing = cfg.value("Multiplexing/Active", "yes").toString();
    muxEnabled &= (multiplexing != "no");
    qLog(Mux) << "Neo multiplexing " << (muxEnabled ? "enabled" : "disabled")
              << multiplexing;

    // Make the modem talk to us. It can be a bit rough to get
    // it initialized... So we will empty the current buffer
    // and then send ^Z\r\n and wait for an OK or AT from the modem. This is
    // mostly based on ideas from ogsmd

    device->readAll();
    int attempts = 0;
    for (; attempts < 2; ++attempts) {
        if (QSerialIODeviceMultiplexer::chat(device, QChar(0x1a))) {
            qLog(Modem) << "Attempts needed to initialize the modem" << attempts;
            break;
        }
    }

    if (attempts == 2) {
        qWarning() << "Initializing the modem failed.";
        abort();
    }

    // disable echoing of commands
    QSerialIODeviceMultiplexer::chat(device, "ATE0");
    device->readAll();

    if (muxEnabled) {
        // Issue the AT+CMUX command to determine if this device
        // uses GSM 07.10-style multiplexing.
        return QGsm0710Multiplexer::cmuxChat( device, NEO_FRAME_SIZE, true );
    }
    return true;
}
void SpotifyClient::LogMessageCallback(sp_session* session, const char* data) {
  qLog(Debug) << "libspotify:" << QString::fromUtf8(data).trimmed();
}
bool EmailServiceProvider::connect()
{
    Q_D(EmailServiceProvider);

    Q_ASSERT(d->providerInfo);
    if (!d->providerInfo)
        return false;

    Q_ASSERT(!d->session && !d->service);
    if (d->session || d->service)
        return false;

    QScopedPointer<QList<vmime::ref<vmime::net::session> > > sessions(
        createSessionList(*d->providerInfo));
    Q_ASSERT(sessions);
    if (!sessions)
        return false;

    vmime::ref<vmime::net::session> session;
    vmime::ref<vmime::net::service> service;
    EmailServiceProviderInfo::ServiceTypes serviceType =
        d->providerInfo->serviceType();
    for(int i = 0; i < sessions->size(); ++i) {
        vmime::ref<vmime::net::session> currentSession = sessions->at(i);

        dumpToLog(currentSession);

        if (serviceType & EmailServiceProviderInfo::SMTP
            || serviceType & EmailServiceProviderInfo::SMTPS
            || serviceType & EmailServiceProviderInfo::SENDMAIL)
        {
            // transports
            try {
                vmime::ref<vmime::net::transport> transport =
                    currentSession->getTransport();
                transport->setTimeoutHandlerFactory(
                    vmime::create<EmailServiceTimeoutHandlerFactory>());

                if (d->dummyCert)
                    transport->setCertificateVerifier(
                        vmime::create<Security::DummyCertVerifier>());

                transport->connect();
                session = currentSession;
                service = transport;

                // break the for loop
                break;

            } catch (vmime::exception& e) {
                qLog() << e.what();
            }
        } else {
            // stores
            try {
                vmime::ref<vmime::net::store> store =
                    currentSession->getStore();
                store->setTimeoutHandlerFactory(
                    vmime::create<EmailServiceTimeoutHandlerFactory>());

                if (d->dummyCert)
                    store->setCertificateVerifier(
                        vmime::create<Security::DummyCertVerifier>());

                store->connect();
                session = currentSession;
                service = store;

                // break the for loop
                break;

            } catch (vmime::exception& e) {
                qLog() << e.what();
            }
        }
    }

    if (!session || !service)
        return false;

    d->session = session;
    d->service = service;
    return true;
}
Exemple #25
0
void SpotifyServer::Init() {
  if (!server_->listen(QHostAddress::LocalHost)) {
    qLog(Error) << "Couldn't open server socket" << server_->errorString();
  }
}
Exemple #26
0
void FixBdaddr::accept()
{
    if (m_data->m_imei.isEmpty()) {
        m_data->m_waitWidget = new QWaitWidget(this);
        m_data->m_waitWidget->setExpiryTime( 5000 );
        m_data->m_waitWidget->setCancelEnabled(true);
        m_data->m_waitWidget->setText( tr("Obtaining IMEI") );
        m_data->m_waitWidget->show();

        if (m_data->m_imei.isEmpty()) {
            QMessageBox::critical(this, tr("Change Bluetooth Address"),
                                  tr("Could not obtain IMEI, Bluetooth Address was NOT changed."));
            return;
        }
    }

    qLog(Bluetooth) << "Changing Bluetooth Address - IMEI: " << m_data->m_imei;

    if (m_data->m_list->currentItem()->text() == option2) {
        char buf[] = "AC:DE:48:00:00:00";
        int serial = m_data->m_imei.mid(8, 6).toInt();
        char subserial[6];
        snprintf(subserial, 6, "%5X", serial);
        subserial[5] = '\0';

        buf[10] = subserial[0];
        buf[12] = subserial[1];
        buf[13] = subserial[2];
        buf[15] = subserial[3];
        buf[16] = subserial[4];

        qLog(Bluetooth) << "Changing address to: " << buf;

        if (set_bdaddr(buf) != 0) {
            QMessageBox::critical(this, tr("Change Bluetooth Address"),
                                  tr("Could not write new device address."));
            return;
        }

        QMessageBox::information(this, tr("Change Bluetooth Address"),
                                 tr("Bluetooth Address changed to: ") + QString(buf) + ".  " +
                                         tr("Please reboot the device for changes to take effect"));
    }
    else if (m_data->m_list->currentItem()->text() == option1) {
        // Yuhuatel gave us an address block for DVT3 devices of
        // 00:19:65:00:08:01-00:19:65:00:08:64
        // Which is exactly 100 numbers
        // Only the last byte is changing
        char buf[] = "00:19:65:00:08:00";

        // For DVT4 devices, the block of addresses is:
        // 001965040000-0019650404B0
        int offset = 1;

        int position = find_imei(imeis, m_data->m_imei.toLatin1().constData());

        if (position != -1) {
            char tmp[3];
            snprintf(tmp, 3, "%02X", offset+position);
            buf[15] = tmp[0];
            buf[16] = tmp[1];
        }
        else {
            position = find_imei(imeisdvt4, m_data->m_imei.toLatin1().constData());

            if (position == -1) {
                QMessageBox::critical(this, tr("Change Bluetooth Address"),
                                    tr("Could not find your IMEI in the database.  Please contact [email protected]"));
                return;
            }

            char tmp[5];
            snprintf(tmp, 5, "%04X", offset+position);
            buf[9] = '0';
            buf[10] = '4';
            buf[12] = tmp[0];
            buf[13] = tmp[1];
            buf[15] = tmp[2];
            buf[16] = tmp[3];
        }

        qLog(Bluetooth) << "Changing address to: " << buf;

        if (set_bdaddr(buf) != 0) {
            QMessageBox::critical(this, tr("Change Bluetooth Address"),
                                  tr("Could not write new device address."));
            return;
        }

        QMessageBox::information(this, tr("Change Bluetooth Address"),
                                 tr("Bluetooth Address changed to: ") + QString(buf) + ".  " +
                                         tr("Please reboot the device for changes to take effect"));
    }

    QDialog::accept();
}
Exemple #27
0
void WavDecoder::start()
{
    if (!d->initialized)
    {
        if (QIODevice::open(QIODevice::ReadWrite | QIODevice::Unbuffered))
        {
            if (d->inputDevice->read((char*)&d->header, sizeof(CombinedHeader)) == sizeof(CombinedHeader))
            {
                if (memcmp(&d->header.riff.descriptor.id, riffId, 4) == 0 &&
                    memcmp(&d->header.riff.type, waveId, 4) == 0 &&
                    memcmp(&d->header.wave.descriptor.id, fmtId, 4) == 0)
                {
                    if (d->header.wave.audioFormat == 1)
                    {
                        d->outputInfo.type = QMediaDevice::Info::PCM;
                        d->outputInfo.frequency = qFromLittleEndian<quint32>(d->header.wave.sampleRate);
                        d->outputInfo.bitsPerSample = qFromLittleEndian<quint16>(d->header.wave.bitsPerSample);
                        d->outputInfo.channels = qFromLittleEndian<quint16>(d->header.wave.numChannels);
                        d->outputInfo.volume = d->muted ? 0 : d->volume;

                        d->length = quint32((double(d->header.riff.descriptor.size) /
                                        d->outputInfo.frequency /
                                        d->outputInfo.channels /
                                        (d->outputInfo.bitsPerSample / 8)) * 1000);

                        qLog(Media) << "WavDecoder::start(); Info" <<
                                    d->outputInfo.frequency <<
                                    d->outputInfo.bitsPerSample <<
                                    d->outputInfo.channels <<
                                    "length:" << d->length;

                        emit lengthChanged(d->length);

                        d->initialized = true;
#ifdef WAVGSM_SUPPORTED
                    } else if(d->header.wave.audioFormat == 49) {
                        d->inputDevice->seek(60);
                        d->input_data = (char *)malloc(WAV_DECODER_BUFFER);
                        d->input_pos = d->input_data;
                        d->input_length = 0;
                        d->output_data = (char *)malloc(WAV_DECODER_BUFFER*6);
                        d->output_pos = d->output_data;
                        d->output_length = 0;
                        d->gsmhandle = gsm_create();
                        int value = 1;
                        gsm_option( d->gsmhandle, GSM_OPT_WAV49, &value );

                        d->outputInfo.type = QMediaDevice::Info::PCM;
                        d->outputInfo.frequency = qFromLittleEndian<quint32>(d->header.wave.sampleRate);
                        d->outputInfo.bitsPerSample = 16;
                        d->outputInfo.channels = qFromLittleEndian<quint16>(d->header.wave.numChannels);
                        d->outputInfo.volume = d->volume;
                        d->length = d->inputDevice->dataType().dataSize*1000/d->header.wave.sampleRate*64/13;
                        qLog(Media) << "WavDecoder::start(); Info" <<
                                    d->outputInfo.frequency <<
                                    d->outputInfo.bitsPerSample <<
                                    d->outputInfo.channels <<
                                    "length:" << d->length;

                        emit lengthChanged(d->length);
                        d->initialized = true;
#endif
                    } else {
                        qWarning("WAV file is in %d audio format, not supported!",d->header.wave.audioFormat);
                    }
                }
            }
        }
    }

    if (d->initialized)
    {
        if (d->state == QtopiaMedia::Stopped)
            seek(0);

        d->state = QtopiaMedia::Playing;

        emit readyRead();
        emit playerStateChanged(d->state);
    }
}
Exemple #28
0
/*!
    This function sets the power management internal timeouts
    to the values passed in \a ivals. \a size determines the number of entries in
    \a ivals.


    The phone power manager maps the timeouts to the following actions:
        \list
        \o 0 -> dim light
        \o 1 -> turn off light
        \o 2 -> suspend device
        \endlist
*/
void PhonePowerManager::setIntervals(int* ivals, int size )
{
    //update value space
    QtopiaPowerManager::setIntervals( ivals, size );

    QSettings config("Trolltech","qpe");

    QString powerGroup = (powerstatus.wallStatus() == QPowerStatus::Available) ? "ExternalPower" : "BatteryPower";
    config.beginGroup( powerGroup );

    int *v = new int[size+1];
    for(int j=size; j>=0; j--)
        v[j]=0;

    m_levelToAction.clear();
    QMap<int,int> timeToAction;

    switch (size) {
    default:
    case 3:
        ivals[2] = interval(ivals[2], config, "Suspend","Interval", 60); // No tr
        v[2] = qMax( 1000*ivals[2] + 100, 100);
        m_suspendEnabled = ( (ivals[2] != 0) ? config.value("Suspend", true).toBool() : false );
        if (m_suspendEnabled)
            timeToAction.insert(v[2], PhonePowerManager::Suspend);
    case 2:
        ivals[1] = interval(ivals[1], config, "LightOff","Interval_LightOff", 30);
        if (ivals[1] == 0 && m_suspendEnabled)
            ivals[1] = ivals[2];
        v[1] = qMax( 1000*ivals[1], 100);
        if (timeToAction.contains(v[1]))
            v[1] = v[1]+100; //add few ms for next timeout
        m_lightOffEnabled = ( (ivals[1] != 0 ) ? config.value("LightOff", true).toBool() : false );
        m_lightOffEnabled |= m_suspendEnabled;
        if (m_lightOffEnabled)
            timeToAction.insert(v[1], PhonePowerManager::LightOff);
    case 1:
        ivals[0] = interval(ivals[0], config, "Dim","Interval_Dim", 20); // No tr
        v[0] = qMax( 1000*ivals[0], 100);
        while ( timeToAction.contains( v[0] ) )
            v[0] = v[0]+100; //add few ms for next timeout
        m_dimLightEnabled = ( (ivals[0] != 0) ? config.value("Dim", true).toBool() : false );
        if (m_dimLightEnabled)
            timeToAction.insert(v[0], PhonePowerManager::DimLight);
    case 0:
        break;
    }

    qLog(PowerManagement) << "PhonePowerManager::setIntervals:"
                          << ivals[0] << ivals[1] << ivals[2] <<" size: " << size;

    if ( !ivals[0] && !ivals[1] && !ivals[2] ) {
#ifdef Q_WS_QWS
        QWSServer::setScreenSaverInterval(0);
#endif
        delete [] v;
        return;
    }

    QList<int> keys = timeToAction.keys();
    qStableSort(keys.begin(), keys.end());

    //first element
    v[0] = keys.at(0);
    m_levelToAction.insert(0, timeToAction.value(v[0]));
    int sum = v[0];

    for (int j=1; j<keys.count(); j++)
    {
        v[j]=keys.at(j)-sum;
        sum+= v[j];
        m_levelToAction.insert(j, timeToAction.value(sum));
    }
    v[keys.count()] = 0;

    qLog(PowerManagement) << "PhonePowerManager::setIntervals:"
                          << v[0] << v[1] << v[2];
#ifdef Q_WS_QWS
    QWSServer::setScreenSaverIntervals(v);
#endif
    delete [] v;

    // when the backlight goes off, ignore the key that wakes it up
    int blocklevel = PhonePowerManager::LightOff;
    if ( !m_lightOffEnabled ) {
        // we're not turning the backlight off, ignore the key that wakes us up from suspend
        blocklevel = PhonePowerManager::Suspend;
        if ( !m_suspendEnabled ) {
            // we're not suspending, never ignore keys
            blocklevel = -1;
        }
    }
    // Now we need to map blocklevel from "action" to "level"
    if ( blocklevel != -1 ) {
        for ( QMap<int,int>::const_iterator it = m_levelToAction.begin(); it != m_levelToAction.end(); ++it ) {
            if ( blocklevel == it.value() ) {
                blocklevel = it.key();
                break;
            }
        }
    }
#ifdef Q_WS_QWS
    qLog(PowerManagement) << "Using Block level " << blocklevel;
    QWSServer::setScreenSaverBlockLevel(blocklevel);
#endif
}
Exemple #29
0
void NeoVibrateAccessory::setVibrateOnRing(const bool value)
{
    qLog(Modem) << "setVibrateOnRing " << value;
    setVibrateNow(value);
}
Exemple #30
0
bool TagReader::SaveSongRatingToFile(
    const QString& filename, const pb::tagreader::SongMetadata& song) const {
  if (filename.isNull()) return false;

  qLog(Debug) << "Saving song rating tags to" << filename;
  if (song.rating() < 0) {
    // The FMPS spec says unrated == "tag not present". For us, no rating
    // results in rating being -1, so don't write anything in that case.
    // Actually, we should also remove tag set in this case, but in
    // Clementine it is not possible to unset rating i.e. make a song "unrated".
    qLog(Debug) << "Unrated: do nothing";
    return true;
  }

  std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));

  if (!fileref || fileref->isNull())  // The file probably doesn't exist
    return false;

  if (TagLib::MPEG::File* file =
          dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
    TagLib::ID3v2::Tag* tag = file->ID3v2Tag(true);

    // Save as FMPS
    SetUserTextFrame("FMPS_Rating", QString::number(song.rating()), tag);

    // Also save as POPM
    TagLib::ID3v2::PopularimeterFrame* frame = GetPOPMFrameFromTag(tag);
    frame->setRating(ConvertToPOPMRating(song.rating()));

  } else if (TagLib::FLAC::File* file =
                 dynamic_cast<TagLib::FLAC::File*>(fileref->file())) {
    TagLib::Ogg::XiphComment* vorbis_comments = file->xiphComment(true);
    SetFMPSRatingVorbisComments(vorbis_comments, song);
  } else if (TagLib::Ogg::XiphComment* tag =
                 dynamic_cast<TagLib::Ogg::XiphComment*>(
                     fileref->file()->tag())) {
    SetFMPSRatingVorbisComments(tag, song);
  }
#ifdef TAGLIB_WITH_ASF
  else if (TagLib::ASF::File* file =
               dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
    TagLib::ASF::Tag* tag = file->tag();
    tag->addAttribute("FMPS/Rating", NumberToASFAttribute(song.rating()));
  }
#endif
  else if (TagLib::MP4::File* file =
               dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
    TagLib::MP4::Tag* tag = file->tag();
    tag->itemListMap()[kMP4_FMPS_Rating_ID] = TagLib::StringList(
        QStringToTaglibString(QString::number(song.rating())));
  } else {
    // Nothing to save: stop now
    return true;
  }

  bool ret = fileref->save();
#ifdef Q_OS_LINUX
  if (ret) {
    // Linux: inotify doesn't seem to notice the change to the file unless we
    // change the timestamps as well. (this is what touch does)
    utimensat(0, QFile::encodeName(filename).constData(), nullptr, 0);
  }
#endif  // Q_OS_LINUX
  return ret;
}