diff --git a/src/lib/handler/funscripthandler.cpp b/src/lib/handler/funscripthandler.cpp index 9e81128..57c310d 100644 --- a/src/lib/handler/funscripthandler.cpp +++ b/src/lib/handler/funscripthandler.cpp @@ -169,6 +169,33 @@ void FunscriptHandler::jsonToFunscript(QJsonObject json) } } } + + // Parse "axes" format (array of {id, actions} objects) + if(json.contains(m_axesJSONObjectName) && json[m_axesJSONObjectName].isArray()) + { + auto jsonAxes = json[m_axesJSONObjectName].toArray(); + for(auto val : jsonAxes) + { + QJsonObject axisObj = val.toObject(); + if(axisObj.contains("id") && axisObj.contains("actions")) + { + Track track = trackFromTCodeChannel(axisObj["id"].toString()); + if(track != Track::None && track != Track::Stroke) + { + ChannelModel33* channel = TCodeChannelLookup::getChannel(TCodeChannelLookup::ToString(track)); + if(channel && channel->Type != ChannelType::HalfOscillate) + { + Funscript funscript; + jsonToFunscript(axisObj, funscript); + setFunscriptSettings(track, funscript); + m_funscripts.insert(track, funscript); + SettingsHandler::setFunscriptLoaded(TCodeChannelLookup::ToString(track), true); + } + } + } + } + } + if(!m_funscripts.contains(Track::Stroke)) { Funscript funscript; @@ -630,9 +657,11 @@ QList FunscriptHandler::getSFMATracks(QString libraryItemMediaPath) return scriptInfos; // scriptInfos.append({"Default", libraryItemMediaPathNoExt, scriptPath, TCodeChannelLookup::ToString(Track::Stroke), ScriptType::MAIN, ScriptContainerType::BASE, "" }); - if(!json[m_sfmaJSONObjectName].isNull()) + QString libraryItemMediaNameNoExt = XFileUtil::getNameNoExtension(libraryItemMediaPath); + + // Check "channels" format (object with track name keys) + if(!json[m_sfmaJSONObjectName].isNull() && json[m_sfmaJSONObjectName].isObject()) { - QString libraryItemMediaNameNoExt = XFileUtil::getNameNoExtension(libraryItemMediaPath); auto jsonTracks = json[m_sfmaJSONObjectName].toObject(); auto channels = TCodeChannelLookup::getChannels(); foreach(QString channelName, channels) @@ -645,9 +674,52 @@ QList FunscriptHandler::getSFMATracks(QString libraryItemMediaPath) } } } + + // Check "axes" format (array of {id, actions} objects) + if(json.contains(m_axesJSONObjectName) && json[m_axesJSONObjectName].isArray()) + { + auto jsonAxes = json[m_axesJSONObjectName].toArray(); + for(auto val : jsonAxes) + { + QJsonObject axisObj = val.toObject(); + if(axisObj.contains("id") && axisObj.contains("actions")) + { + Track track = trackFromTCodeChannel(axisObj["id"].toString()); + if(track != Track::None && track != Track::Stroke) + { + ChannelModel33* channel = TCodeChannelLookup::getChannel(TCodeChannelLookup::ToString(track)); + if(channel && channel->Type != ChannelType::HalfOscillate) + scriptInfos.append({libraryItemMediaNameNoExt, libraryItemMediaNameNoExt, scriptPath, channel->trackName.isEmpty() ? axisObj["id"].toString() : channel->trackName, ScriptType::MAIN, ScriptContainerType::SFMA, "" }); + } + } + } + } + return scriptInfos; } +Track FunscriptHandler::trackFromTCodeChannel(const QString& tcodeChannel) +{ + // Strip modifier suffix (+/-) to get base channel name + QString base = tcodeChannel; + if(base.endsWith('+') || base.endsWith('-')) + base.chop(1); + + // Search the TCode version map for the matching Track + auto values = TCodeChannelLookup::GetSelectedVersionMap().values(); + auto keys = TCodeChannelLookup::GetSelectedVersionMap().keys(); + for(int i = 0; i < keys.length(); i++) + { + QString val = values[i]; + // Strip modifiers from map value too for comparison + if(val.endsWith('+') || val.endsWith('-')) + val.chop(1); + if(val == base) + return keys[i]; + } + return Track::None; +} + bool FunscriptHandler::isSFMA(QString libraryItemMediaPath) { QString scriptPath = XFileUtil::getPathNoExtension(libraryItemMediaPath) + ".funscript"; @@ -655,19 +727,40 @@ bool FunscriptHandler::isSFMA(QString libraryItemMediaPath) if(bytes.isEmpty()) return false; QJsonObject json = readJson(bytes); - if(json.isEmpty() || json[m_sfmaJSONObjectName].isNull()) + if(json.isEmpty()) return false; - auto jsonTracks = json[m_sfmaJSONObjectName].toObject(); - auto channels = TCodeChannelLookup::getChannels(); - foreach(QString channelName, channels) + // Check "channels" format + if(!json[m_sfmaJSONObjectName].isNull() && json[m_sfmaJSONObjectName].isObject()) { - ChannelModel33* channel = TCodeChannelLookup::getChannel(channelName); - if(channel->Type == ChannelType::HalfOscillate || channel->track == Track::Stroke) - continue; - if(jsonTracks.contains(channel->trackName)) - return true; + auto jsonTracks = json[m_sfmaJSONObjectName].toObject(); + auto channels = TCodeChannelLookup::getChannels(); + foreach(QString channelName, channels) + { + ChannelModel33* channel = TCodeChannelLookup::getChannel(channelName); + if(channel->Type == ChannelType::HalfOscillate || channel->track == Track::Stroke) + continue; + if(jsonTracks.contains(channel->trackName)) + return true; + } + } + + // Check "axes" format + if(json.contains(m_axesJSONObjectName) && json[m_axesJSONObjectName].isArray()) + { + auto jsonAxes = json[m_axesJSONObjectName].toArray(); + for(auto val : jsonAxes) + { + QJsonObject axisObj = val.toObject(); + if(axisObj.contains("id") && axisObj.contains("actions")) + { + Track track = trackFromTCodeChannel(axisObj["id"].toString()); + if(track != Track::None && track != Track::Stroke) + return true; + } + } } + return false; } diff --git a/src/lib/handler/funscripthandler.h b/src/lib/handler/funscripthandler.h index 3a1b49f..1fea1d7 100644 --- a/src/lib/handler/funscripthandler.h +++ b/src/lib/handler/funscripthandler.h @@ -64,12 +64,14 @@ public slots: static QList getSFMATracks(QString libraryItemMediaPath); static bool isMFS(QString libraryItemMediaPath); static QList getMFSTracks(QString libraryItemMediaPath); + static Track trackFromTCodeChannel(const QString& tcodeChannel); private: static inline QMutex mutex; static inline QHash m_funscripts; static inline const QString m_sfmaJSONObjectName = "channels"; + static inline const QString m_axesJSONObjectName = "axes"; bool m_loaded = false; bool _firstActionExecuted; static inline int m_offset; diff --git a/src/lib/handler/medialibraryhandler.cpp b/src/lib/handler/medialibraryhandler.cpp index 31dc57d..cd0eff5 100644 --- a/src/lib/handler/medialibraryhandler.cpp +++ b/src/lib/handler/medialibraryhandler.cpp @@ -677,7 +677,7 @@ void MediaLibraryHandler::processMetadata(LibraryListItem27 &item, bool &metadat if(item.type != LibraryListItemType::PlaylistInternal) { auto isMFS = item.metadata.isMFS; - auto isSFMA = item.metadata.isMFS; + auto isSFMA = item.metadata.isSFMA; if(discoverMultiAxis(item)) { if((isMFS != item.metadata.isMFS) || (isSFMA != item.metadata.isSFMA)) @@ -1690,6 +1690,7 @@ bool MediaLibraryHandler::discoverMultiAxis(LibraryListItem27 &item) { LogHandler::Debug("Discover MFS: "+item.ID); QStringList funscripts = TCodeChannelLookup::getValidMFSExtensions(); item.metadata.isMFS = false; + item.metadata.isSFMA = false; item.metadata.toolTip.clear(); item.metadata.MFSScripts.clear(); item.metadata.MFSTracks.clear(); diff --git a/src/lib/handler/settingshandler.cpp b/src/lib/handler/settingshandler.cpp index ad70916..3a3fc35 100644 --- a/src/lib/handler/settingshandler.cpp +++ b/src/lib/handler/settingshandler.cpp @@ -4,6 +4,8 @@ #include "../tool/migration.h" +MediaLibrarySettings* SettingsHandler::mediaLibrarySettings = nullptr; + const QString SettingsHandler::XTEVersion = "0.6b"; const float SettingsHandler::XTEVersionNum = 0.6f; const QString SettingsHandler::XTEVersionTimeStamp = QString(XTEVersion +" %1T%2").arg(__DATE__).arg(__TIME__); diff --git a/src/lib/handler/settingshandler.h b/src/lib/handler/settingshandler.h index e3bb9c8..2ad3b59 100644 --- a/src/lib/handler/settingshandler.h +++ b/src/lib/handler/settingshandler.h @@ -97,7 +97,7 @@ public slots: static const float XTEVersionNum; static bool getSettingsChanged(); - static inline MediaLibrarySettings* mediaLibrarySettings = 0; + static MediaLibrarySettings* mediaLibrarySettings; static bool getHideWelcomeScreen(); static void setHideWelcomeScreen(bool value);