void VinylControlControl::slotControlVinylSeek(double change) { if(isnan(change) || change > 1.14 || change < -1.14) { // This seek is ridiculous. return; } double total_samples = getTotalSamples(); double new_playpos = round(change*total_samples); // Do nothing if no track is loaded. if (!m_pCurrentTrack) { return; } if (m_pControlVinylEnabled->get() > 0.0 && m_pControlVinylMode->get() == MIXXX_VCMODE_RELATIVE) { int cuemode = (int)m_pControlVinylCueing->get(); //if in preroll, always seek if (new_playpos < 0) { seek(change); return; } else if (cuemode == MIXXX_RELATIVE_CUE_OFF) { return; //if off, do nothing } else if (cuemode == MIXXX_RELATIVE_CUE_ONECUE) { //if onecue, just seek to the regular cue seekAbs(m_pCurrentTrack->getCuePoint()); return; } double distance = 0; int nearest_playpos = -1; QList<Cue*> cuePoints = m_pCurrentTrack->getCuePoints(); QListIterator<Cue*> it(cuePoints); while (it.hasNext()) { Cue* pCue = it.next(); if (pCue->getType() != Cue::CUE || pCue->getHotCue() == -1) { continue; } int cue_position = pCue->getPosition(); //pick cues closest to new_playpos if ((nearest_playpos == -1) || (fabs(new_playpos - cue_position) < distance)) { nearest_playpos = cue_position; distance = fabs(new_playpos - cue_position); } } if (nearest_playpos == -1) { if (new_playpos >= 0) { //never found an appropriate cue, so don't seek? return; } //if negative, allow a seek by falling down to the bottom } else { seekAbs(nearest_playpos); return; } } // just seek where it wanted to originally seek(change); }
void BaseTrackPlayer::slotLoadTrack(TrackPointer track, bool bPlay) { // Before loading the track, ensure we have access. This uses lazy // evaluation to make sure track isn't NULL before we dereference it. if (!track.isNull() && !Sandbox::askForAccess(track->getCanonicalLocation())) { // We don't have access. return; } //Disconnect the old track's signals. if (m_pLoadedTrack) { // Save the loops that are currently set in a loop cue. If no loop cue is // currently on the track, then create a new one. int loopStart = m_pLoopInPoint->get(); int loopEnd = m_pLoopOutPoint->get(); if (loopStart != -1 && loopEnd != -1 && even(loopStart) && even(loopEnd) && loopStart <= loopEnd) { Cue* pLoopCue = NULL; QList<Cue*> cuePoints = m_pLoadedTrack->getCuePoints(); QListIterator<Cue*> it(cuePoints); while (it.hasNext()) { Cue* pCue = it.next(); if (pCue->getType() == Cue::LOOP) { pLoopCue = pCue; } } if (!pLoopCue) { pLoopCue = m_pLoadedTrack->addCue(); pLoopCue->setType(Cue::LOOP); } pLoopCue->setPosition(loopStart); pLoopCue->setLength(loopEnd - loopStart); } // WARNING: Never. Ever. call bare disconnect() on an object. Mixxx // relies on signals and slots to get tons of things done. Don't // randomly disconnect things. // m_pLoadedTrack->disconnect(); disconnect(m_pLoadedTrack.data(), 0, m_pBPM, 0); disconnect(m_pLoadedTrack.data(), 0, this, 0); disconnect(m_pLoadedTrack.data(), 0, m_pKey, 0); m_pReplayGain->slotSet(0); // Causes the track's data to be saved back to the library database. emit(unloadingTrack(m_pLoadedTrack)); } m_pLoadedTrack = track; // Listen for updates to the file's BPM connect(m_pLoadedTrack.data(), SIGNAL(bpmUpdated(double)), m_pBPM, SLOT(slotSet(double))); connect(m_pLoadedTrack.data(), SIGNAL(keyUpdated(double)), m_pKey, SLOT(slotSet(double))); // Listen for updates to the file's Replay Gain connect(m_pLoadedTrack.data(), SIGNAL(ReplayGainUpdated(double)), this, SLOT(slotSetReplayGain(double))); //Request a new track from the reader emit(loadTrack(track, bPlay)); }
/** Upgrade from <= 1.7 library to 1.8 DB format */ void LegacyLibraryImporter::import() { // TODO(XXX) SETTINGS_PATH may change in new Mixxx Versions. Here we need // the SETTINGS_PATH from Mixxx V <= 1.7 QString settingPath17 = QDir::homePath().append("/").append(SETTINGS_PATH); QString trackXML = settingPath17.append("mixxxtrack.xml"); QFile file(trackXML); QDomDocument doc("TrackList"); if(!file.open(QIODevice::ReadOnly)) { //qDebug() << "Could not import legacy 1.7 XML library: " << trackXML; return; } QString* errorMsg = NULL; int* errorLine = NULL; int* errorColumn = NULL; qDebug() << "Starting upgrade from 1.7 library..."; QHash<int, QString> playlistHashTable; //Maps track indices onto track locations QList<LegacyPlaylist> legacyPlaylists; // <= 1.7 playlists if (doc.setContent(&file, false, errorMsg, errorLine, errorColumn)) { QDomNodeList playlistList = doc.elementsByTagName("Playlist"); QDomNode playlist; for (int i = 0; i < playlistList.size(); i++) { LegacyPlaylist legPlaylist; playlist = playlistList.at(i); QString name = playlist.firstChildElement("Name").text(); legPlaylist.name = name; //Store the IDs in the hash table so we can map them to track locations later, //and also store them in-order in a temporary playlist struct. QDomElement listNode = playlist.firstChildElement("List").toElement(); QDomNodeList trackIDs = listNode.elementsByTagName("Id"); for (int j = 0; j < trackIDs.size(); j++) { int id = trackIDs.at(j).toElement().text().toInt(); if (!playlistHashTable.contains(id)) playlistHashTable.insert(id, ""); legPlaylist.indexes.push_back(id); //Save this track id. } //Save this playlist in our list. legacyPlaylists.push_back(legPlaylist); } QDomNodeList trackList = doc.elementsByTagName("Track"); QDomNode track; for (int i = 0; i < trackList.size(); i++) { //blah, can't figure out how to use an iterator with QDomNodeList track = trackList.at(i); TrackInfoObject trackInfo17(track); //Only add the track to the DB if the file exists on disk, //because Mixxx <= 1.7 had no logic to deal with detecting deleted //files. if (trackInfo17.exists()) { //Create a TrackInfoObject by directly parsing //the actual MP3/OGG/whatever because 1.7 didn't parse //genre and album tags (so the imported TIO doesn't have //those fields). emit(progress("Upgrading Mixxx 1.7 Library: " + trackInfo17.getTitle())); // Read the metadata we couldn't support in <1.8 from file. QFileInfo fileInfo(trackInfo17.getLocation()); //Ensure we have the absolute file path stored trackInfo17.setLocation(fileInfo.absoluteFilePath()); TrackInfoObject trackInfoNew(trackInfo17.getLocation()); trackInfo17.setGenre(trackInfoNew.getGenre()); trackInfo17.setAlbum(trackInfoNew.getAlbum()); trackInfo17.setYear(trackInfoNew.getYear()); trackInfo17.setType(trackInfoNew.getType()); trackInfo17.setTrackNumber(trackInfoNew.getTrackNumber()); trackInfo17.setKeys(trackInfoNew.getKeys()); trackInfo17.setHeaderParsed(true); // Import the track's saved cue point if it is non-zero. float fCuePoint = trackInfo17.getCuePoint(); if (fCuePoint != 0.0f) { Cue* pCue = trackInfo17.addCue(); pCue->setType(Cue::CUE); pCue->setPosition(fCuePoint); } // Provide a no-op deleter b/c this Track is on the stack. TrackPointer pTrack(&trackInfo17, &doNothing); m_trackDao.saveTrack(pTrack); //Check if this track is used in a playlist anywhere. If it is, save the //track location. (The "id" of a track in 1.8 is a database index, so it's totally //different. Using the track location is the best way for us to identify the song.) int id = trackInfo17.getId(); if (playlistHashTable.contains(id)) playlistHashTable[id] = trackInfo17.getLocation(); } } //Create the imported playlists QListIterator<LegacyPlaylist> it(legacyPlaylists); LegacyPlaylist current; while (it.hasNext()) { current = it.next(); emit(progress("Upgrading Mixxx 1.7 Playlists: " + current.name)); //Create the playlist with the imported name. //qDebug() << "Importing playlist:" << current.name; int playlistId = m_playlistDao.createPlaylist(current.name); //For each track ID in the XML... QList<int> trackIDs = current.indexes; for (int i = 0; i < trackIDs.size(); i++) { QString trackLocation; int id = trackIDs[i]; //qDebug() << "track ID:" << id; //Try to resolve the (XML's) track ID to a track location. if (playlistHashTable.contains(id)) { trackLocation = playlistHashTable[id]; //qDebug() << "Resolved to:" << trackLocation; } //Get the database's track ID (NOT the XML's track ID!) int dbTrackId = m_trackDao.getTrackId(trackLocation); if (dbTrackId >= 0) { // Add it to the database's playlist. // TODO(XXX): Care if the append succeeded. m_playlistDao.appendTrackToPlaylist(dbTrackId, playlistId); } } } QString upgrade_filename = settingPath17.append("DBUPGRADED"); //now create stub so that the library is not readded next time program loads QFile upgradefile(upgrade_filename); if (!upgradefile.open(QIODevice::WriteOnly | QIODevice::Text)) qDebug() << "Couldn't open" << upgrade_filename << "for writing"; else { file.write("",0); file.close(); } } else { qDebug() << errorMsg << " line: " << errorLine << " column: " << errorColumn; } file.close(); }
void BaseTrackPlayerImpl::slotFinishLoading(TrackPointer pTrackInfoObject) { m_replaygainPending = false; // Read the tags if required if (!m_pLoadedTrack->getHeaderParsed()) { m_pLoadedTrack->parse(false); } // m_pLoadedTrack->setPlayedAndUpdatePlaycount(true); // Actually the song is loaded but not played // Update the BPM and duration values that are stored in ControlObjects m_pDuration->set(m_pLoadedTrack->getDuration()); m_pBPM->slotSet(m_pLoadedTrack->getBpm()); m_pKey->slotSet(m_pLoadedTrack->getKey()); m_pReplayGain->slotSet(m_pLoadedTrack->getReplayGain()); // Update the PlayerInfo class that is used in EngineShoutcast to replace // the metadata of a stream PlayerInfo::instance().setTrackInfo(getGroup(), m_pLoadedTrack); // Reset the loop points. m_pLoopInPoint->slotSet(-1); m_pLoopOutPoint->slotSet(-1); const QList<Cue*> trackCues = pTrackInfoObject->getCuePoints(); QListIterator<Cue*> it(trackCues); while (it.hasNext()) { Cue* pCue = it.next(); if (pCue->getType() == Cue::LOOP) { int loopStart = pCue->getPosition(); int loopEnd = loopStart + pCue->getLength(); if (loopStart != -1 && loopEnd != -1 && even(loopStart) && even(loopEnd)) { m_pLoopInPoint->slotSet(loopStart); m_pLoopOutPoint->slotSet(loopEnd); break; } } } if(m_pConfig->getValueString(ConfigKey("[Mixer Profile]", "EqAutoReset"), 0).toInt()) { if (m_pLowFilter != NULL) { m_pLowFilter->set(1.0); } if (m_pMidFilter != NULL) { m_pMidFilter->set(1.0); } if (m_pHighFilter != NULL) { m_pHighFilter->set(1.0); } if (m_pLowFilterKill != NULL) { m_pLowFilterKill->set(0.0); } if (m_pMidFilterKill != NULL) { m_pMidFilterKill->set(0.0); } if (m_pHighFilterKill != NULL) { m_pHighFilterKill->set(0.0); } m_pPreGain->set(1.0); } int reset = m_pConfig->getValueString(ConfigKey( "[Controls]", "SpeedAutoReset"), QString("%1").arg(RESET_PITCH)).toInt(); switch (reset) { case RESET_PITCH_AND_SPEED: // Note: speed may affect pitch if (m_pSpeed != NULL) { m_pSpeed->set(0.0); } // Fallthrough intended case RESET_PITCH: if (m_pPitchAdjust != NULL) { m_pPitchAdjust->set(0.0); } } emit(newTrackLoaded(m_pLoadedTrack)); }
void CueStack_Test::postRun() { QLCFixtureDef* def = m_doc->fixtureDefCache()->fixtureDef("Futurelight", "DJScan250"); QVERIFY(def != NULL); QLCFixtureMode* mode = def->modes().first(); QVERIFY(mode != NULL); Fixture* fxi = new Fixture(m_doc); fxi->setFixtureDefinition(def, mode); fxi->setName("Test Scanner"); fxi->setAddress(10); fxi->setUniverse(0); m_doc->addFixture(fxi); MasterTimer mt(m_doc); QList<Universe*> ua; ua.append(new Universe(0, new GrandMaster())); CueStack cs(m_doc); cs.setFadeInSpeed(100); cs.setFadeOutSpeed(200); cs.setDuration(300); Cue cue; cue.setName("One"); cue.setValue(0, 255); cue.setValue(1, 255); cue.setValue(500, 255); cue.setValue(10, 255); // LTP cue.setValue(11, 255); // LTP cs.appendCue(cue); cue = Cue(); cue.setName("Two"); cue.setValue(500, 255); cue.setValue(3, 255); cue.setValue(4, 255); cue.setValue(11, 255); // LTP cs.appendCue(cue); cs.preRun(); // Switch to cue one cs.switchCue(-1, 0, ua); QCOMPARE(cs.m_fader->channels().size(), 5); QSignalSpy cueSpy(&cs, SIGNAL(currentCueChanged(int))); QSignalSpy stopSpy(&cs, SIGNAL(stopped())); cs.postRun(&mt); QCOMPARE(cs.m_fader, (GenericFader*) NULL); QCOMPARE(cs.m_currentIndex, -1); QCOMPARE(cueSpy.size(), 1); QCOMPARE(cueSpy.at(0).size(), 1); QCOMPARE(cueSpy.at(0).at(0).toInt(), -1); QCOMPARE(stopSpy.size(), 1); // Only HTP channels go to MasterTimer's GenericFader QCOMPARE(mt.m_fader->channels().size(), 3); FadeChannel fc; fc.setChannel(0); QCOMPARE(mt.m_fader->channels().contains(fc), true); fc.setChannel(1); QCOMPARE(mt.m_fader->channels().contains(fc), true); fc.setChannel(500); QCOMPARE(mt.m_fader->channels().contains(fc), true); }
void CueStack_Test::switchCue() { QLCFixtureDef* def = m_doc->fixtureDefCache()->fixtureDef("Futurelight", "DJScan250"); QVERIFY(def != NULL); QLCFixtureMode* mode = def->modes().first(); QVERIFY(mode != NULL); Fixture* fxi = new Fixture(m_doc); fxi->setFixtureDefinition(def, mode); fxi->setName("Test Scanner"); fxi->setAddress(10); fxi->setUniverse(0); m_doc->addFixture(fxi); QList<Universe*> ua; ua.append(new Universe(0, new GrandMaster())); CueStack cs(m_doc); cs.setFadeInSpeed(100); cs.setFadeOutSpeed(200); cs.setDuration(300); Cue cue; cue.setName("One"); cue.setValue(0, 255); cue.setValue(1, 255); cue.setValue(500, 255); cue.setValue(10, 255); // LTP cue.setValue(11, 255); // LTP cue.setFadeInSpeed(20); cue.setFadeOutSpeed(40); cs.appendCue(cue); cue = Cue(); cue.setName("Two"); cue.setValue(500, 255); cue.setValue(3, 255); cue.setValue(4, 255); cue.setValue(11, 255); // LTP cue.setFadeInSpeed(60); cue.setFadeOutSpeed(80); cs.appendCue(cue); cs.preRun(); // Do nothing with invalid cue indices cs.switchCue(-1, -1, ua); QCOMPARE(cs.m_fader->channels().size(), 0); cs.switchCue(-1, 3, ua); QCOMPARE(cs.m_fader->channels().size(), 0); // Switch to cue one cs.switchCue(3, 0, ua); QCOMPARE(cs.m_fader->channels().size(), 5); FadeChannel fc; fc.setChannel(0); QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(255)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(0)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(20)); fc.setChannel(1); QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(255)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(1)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(20)); fc.setChannel(10); QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(255)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(10)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(20)); fc.setChannel(11); QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(255)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(11)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(20)); fc.setChannel(500); QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(255)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(500)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(20)); fc.setChannel(3); QCOMPARE(cs.m_fader->channels()[fc].channel(), QLCChannel::invalid()); fc.setChannel(4); QCOMPARE(cs.m_fader->channels()[fc].channel(), QLCChannel::invalid()); fc.setChannel(0); cs.m_fader->m_channels[fc].setCurrent(127); fc.setChannel(1); cs.m_fader->m_channels[fc].setCurrent(127); fc.setChannel(10); cs.m_fader->m_channels[fc].setCurrent(127); fc.setChannel(11); cs.m_fader->m_channels[fc].setCurrent(127); fc.setChannel(500); cs.m_fader->m_channels[fc].setCurrent(127); // Switch to cue two cs.switchCue(0, 1, ua); QCOMPARE(cs.m_fader->channels().size(), 7); fc.setChannel(0); QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(127)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(127)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(0)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(40)); fc.setChannel(1); QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(127)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(127)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(1)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(40)); fc.setChannel(11); // LTP channel also in the next cue QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(127)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(127)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(255)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(11)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(60)); fc.setChannel(500); QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(127)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(127)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(255)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(500)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(60)); fc.setChannel(3); QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(255)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(3)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(60)); fc.setChannel(4); QCOMPARE(cs.m_fader->channels()[fc].start(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].current(), uchar(0)); QCOMPARE(cs.m_fader->channels()[fc].target(), uchar(255)); QCOMPARE(cs.m_fader->channels()[fc].channel(), uint(4)); QCOMPARE(cs.m_fader->channels()[fc].fadeTime(), uint(60)); // Stop cs.switchCue(1, -1, ua); QCOMPARE(cs.m_fader->channels().size(), 7); MasterTimer mt(m_doc); cs.postRun(&mt); }
TEST(CueSettings,EmptyCue) { // Avoid using references to const values in EXPECT_EQ statements const Cue::Align defaultAlign = Cue::defaultAlign; const int defaultLine = Cue::defaultLine; const int defaultPosition = Cue::defaultPosition; const int defaultSize = Cue::defaultSize; const bool defaultSnapToLines = Cue::defaultSnapToLines; const Cue::Vertical defaultVertical = Cue::defaultVertical; // Trying to set empty cue settings should always fail Cue cue; // Id cue.setId("Phnglui mglw nafh Cthulhu R'lyeh wgah nagl fhtagn"); EXPECT_STREQ("", cue.id()); // Text cue.setText("Phnglui mglw nafh Cthulhu R'lyeh wgah nagl fhtagn"); EXPECT_STREQ("", cue.text()); // StartTime cue.setStartTime(68.067); EXPECT_EQ(MalformedTimestamp, cue.startTime()); // EndTime cue.setEndTime(98.678); EXPECT_EQ(MalformedTimestamp, cue.endTime()); // Align EXPECT_FALSE(cue.setAlign(Cue::Start)); EXPECT_FALSE(cue.setAlign(Cue::Middle)); EXPECT_FALSE(cue.setAlign(Cue::End)); EXPECT_FALSE(cue.setAlign(Cue::Left)); EXPECT_FALSE(cue.setAlign(Cue::Right)); EXPECT_FALSE(cue.setAlign("start")); EXPECT_FALSE(cue.setAlign("middle")); EXPECT_FALSE(cue.setAlign("end")); EXPECT_FALSE(cue.setAlign("left")); EXPECT_FALSE(cue.setAlign("right")); EXPECT_EQ(defaultAlign,cue.align()); // Line EXPECT_FALSE(cue.setLine(0, false)); EXPECT_FALSE(cue.setLine(0, false)); EXPECT_FALSE(cue.setLine(-101, true)); EXPECT_FALSE(cue.setLine(101, true)); EXPECT_FALSE(cue.setLine("0%")); EXPECT_FALSE(cue.setLine("100%")); EXPECT_FALSE(cue.setLine("-101")); EXPECT_FALSE(cue.setLine("1001")); EXPECT_EQ(defaultLine, cue.line()); EXPECT_EQ(defaultSnapToLines, cue.snapToLines()); // Position EXPECT_FALSE(cue.setPosition(0)); EXPECT_FALSE(cue.setPosition(100)); EXPECT_FALSE(cue.setPosition("0%")); EXPECT_FALSE(cue.setPosition("100%")); EXPECT_EQ(defaultPosition, cue.position()); // Size EXPECT_FALSE(cue.setSize(0)); EXPECT_FALSE(cue.setSize(100)); EXPECT_FALSE(cue.setSize("0%")); EXPECT_FALSE(cue.setSize("100%")); EXPECT_EQ(defaultSize, cue.size()); // Vertical EXPECT_FALSE(cue.setVertical(Cue::Horizontal)); EXPECT_FALSE(cue.setVertical(Cue::VerticalLeftToRight)); EXPECT_FALSE(cue.setVertical(Cue::VerticalRightToLeft)); EXPECT_FALSE(cue.setVertical("")); EXPECT_FALSE(cue.setVertical("lr")); EXPECT_FALSE(cue.setVertical("rl")); EXPECT_EQ(defaultVertical, cue.vertical()); }