1 /* Copyright 2017, Ableton AG, Berlin. All rights reserved. 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * 16 * If you would like to incorporate Link into a proprietary software application, 17 * please contact <link-devs@ableton.com>. 18 */ 19 20 #pragma once 21 22 #include <ableton/discovery/NetworkByteStreamSerializable.hpp> 23 #include <ableton/link/Beats.hpp> 24 #include <chrono> 25 #include <tuple> 26 27 namespace ableton 28 { 29 namespace link 30 { 31 32 // A tuple of (isPlaying, time) that represents the playing state 33 // with an according timestamp in microseconds. It also serves as a 34 // payload entry. 35 36 struct StartStopState 37 { 38 static const std::int32_t key = 'stst'; 39 static_assert(key == 0x73747374, "Unexpected byte order"); 40 41 using StartStopStateTuple = std::tuple<bool, Beats, std::chrono::microseconds>; 42 43 StartStopState() = default; 44 StartStopStateableton::link::StartStopState45 StartStopState( 46 const bool aIsPlaying, const Beats aBeats, const std::chrono::microseconds aTimestamp) 47 : isPlaying(aIsPlaying) 48 , beats(aBeats) 49 , timestamp(aTimestamp) 50 { 51 } 52 operator ==(const StartStopState & lhs,const StartStopState & rhs)53 friend bool operator==(const StartStopState& lhs, const StartStopState& rhs) 54 { 55 return std::tie(lhs.isPlaying, lhs.beats, lhs.timestamp) 56 == std::tie(rhs.isPlaying, rhs.beats, rhs.timestamp); 57 } 58 operator !=(const StartStopState & lhs,const StartStopState & rhs)59 friend bool operator!=(const StartStopState& lhs, const StartStopState& rhs) 60 { 61 return !(lhs == rhs); 62 } 63 64 // Model the NetworkByteStreamSerializable concept sizeInByteStream(const StartStopState & state)65 friend std::uint32_t sizeInByteStream(const StartStopState& state) 66 { 67 return discovery::sizeInByteStream(state.asTuple()); 68 } 69 70 template <typename It> toNetworkByteStream(const StartStopState & state,It out)71 friend It toNetworkByteStream(const StartStopState& state, It out) 72 { 73 return discovery::toNetworkByteStream(state.asTuple(), std::move(out)); 74 } 75 76 template <typename It> fromNetworkByteStreamableton::link::StartStopState77 static std::pair<StartStopState, It> fromNetworkByteStream(It begin, It end) 78 { 79 using namespace std; 80 using namespace discovery; 81 auto result = 82 Deserialize<StartStopStateTuple>::fromNetworkByteStream(move(begin), move(end)); 83 auto state = 84 StartStopState{get<0>(result.first), get<1>(result.first), get<2>(result.first)}; 85 return make_pair(move(state), move(result.second)); 86 } 87 88 bool isPlaying{false}; 89 Beats beats{0.}; 90 std::chrono::microseconds timestamp{0}; 91 92 private: asTupleableton::link::StartStopState93 StartStopStateTuple asTuple() const 94 { 95 return std::make_tuple(isPlaying, beats, timestamp); 96 } 97 }; 98 99 struct ApiStartStopState 100 { 101 ApiStartStopState() = default; 102 ApiStartStopStateableton::link::ApiStartStopState103 ApiStartStopState(const bool aIsPlaying, const std::chrono::microseconds aTime) 104 : isPlaying(aIsPlaying) 105 , time(aTime) 106 { 107 } 108 operator ==(const ApiStartStopState & lhs,const ApiStartStopState & rhs)109 friend bool operator==(const ApiStartStopState& lhs, const ApiStartStopState& rhs) 110 { 111 return std::tie(lhs.isPlaying, lhs.time) == std::tie(rhs.isPlaying, rhs.time); 112 } 113 operator !=(const ApiStartStopState & lhs,const ApiStartStopState & rhs)114 friend bool operator!=(const ApiStartStopState& lhs, const ApiStartStopState& rhs) 115 { 116 return !(lhs == rhs); 117 } 118 119 bool isPlaying{false}; 120 std::chrono::microseconds time{0}; 121 }; 122 } // namespace link 123 } // namespace ableton 124