// Manual simulator integration fixture. Generates pixels/PCM only; never captures a device. // Run in a disposable directory: [av1]. Login is saved in fixture-login. #include #include #include #include #include #include #include #include #include #include #include using namespace crossdesk; struct Fixture { PeerPtr* peer=nullptr; std::atomic connected{false}; std::atomic selected{0}; std::mutex mutex; std::vector> messages; std::string remote; std::atomic signal{-1}; int keys=0,mouse=0,settings=0,clipboard=0; void Send(RemoteAction& a) {const auto s=a.to_json();SendReliableDataFrame(peer,s.data(),s.size(),kControlStream);} }; int main(int argc,char**argv) { if(argc<3)return 2;umask(0077); #if defined(__OHOS__) setenv("SSL_CERT_DIR","/etc/security/certificates",1); #endif std::string login;{std::ifstream input("fixture-login");input>>login;} Fixture f;Params p{};snprintf(p.signal_server_ip,sizeof(p.signal_server_ip),"%s",argv[1]);p.signal_server_port=atoi(argv[2]);p.user_id=login.c_str();p.user_data=&f; p.turn_mode=TurnAutoUdpTcp;p.enable_srtp=true;p.av1_encoding=argc>3;p.video_frame_rate=30;p.video_quality=QualityMedium; p.video_content_type=VideoContentType::ScreenContent;p.video_degradation_preference=VideoDegradationPreference::MaintainResolution; p.on_signal_status=[](SignalStatus s,const char*,size_t,void*u){static_cast(u)->signal=s;}; p.on_net_status_report=[](const char*id,size_t n,TraversalMode mode,const MiniRtcNetTrafficStats*,const char*,size_t,void*){ if(mode==UnknownMode&&id&&n&&std::string(id,n).find('@')!=std::string::npos){std::ofstream out("fixture-login");out.write(id,n);} }; p.on_connection_status=[](ConnectionStatus s,const char*id,size_t n,void*u){auto*f=static_cast(u);std::lock_guard lock(f->mutex);f->remote.assign(id,n);f->connected=s==Connected;if(s==Connected)f->selected=0;}; p.on_receive_data_buffer=[](const char*d,size_t n,const char*,size_t,const char*s,size_t l,void*u){auto*f=static_cast(u);std::lock_guard lock(f->mutex);f->messages.emplace_back(std::string(s,l),std::string(d,n));}; f.peer=CreatePeer(&p);AddVideoStream(f.peer,"Display1");AddVideoStream(f.peer,"Display2");AddAudioStream(f.peer,kAudioStream);AddDataStream(f.peer,kDataStream,false); for(auto s:{kKeyboardStream,kMouseStream,kControlStream,kClipboardStream,kFileStream,kFileFeedbackStream})AddDataStream(f.peer,s,true); if(Init(f.peer))return 3; mobile_controller::FileTransferSession files([&](const char*s,const char*b,size_t n){return SendReliableDataFrame(f.peer,b,n,s);}, [](const std::string&,double p,bool,const std::string&path){if(p==1&&!path.empty())std::ofstream("received-result")< pixels(640*360*3/2,128);int16_t pcm[480]{}; const auto end=std::chrono::steady_clock::now()+std::chrono::minutes(15); while(std::chrono::steady_clock::now()> messages;{std::lock_guard lock(f.mutex);messages.swap(f.messages);} if(f.connected&&!info){auto a=MakeHostInformation("Synthetic mobile fixture",{{"Test pattern",0,0,640,360},{"Second display",0,0,640,360}},true,"1.6.1",HostPlatform::Windows);a.i.supports_video_settings=true;f.Send(a);FreeRemoteAction(a);info=true; const std::string clip="CrossDesk synthetic clipboard";SendReliableDataFrame(f.peer,clip.data(),clip.size(),kClipboardStream); {std::ofstream out("sample.txt");out<<"Synthetic mobile file transfer\n";}files.Start("sample.txt","fixture.txt");} if(!f.connected)info=false; for(auto&[stream,bytes]:messages){ if(stream==kFileStream)files.Receive(bytes.data(),bytes.size());else if(stream==kFileFeedbackStream)files.Ack(bytes.data(),bytes.size()); else if(stream==kClipboardStream){f.clipboard++;SendReliableDataFrame(f.peer,bytes.data(),bytes.size(),kClipboardStream);} else {RemoteAction a{};if(!a.from_json(bytes))continue; if(a.type==host_infomation)info=false; if(a.type==keyboard)f.keys++;if(a.type==mouse)f.mouse++;if(a.type==display_id)f.selected=a.d; if(a.type==video_settings){f.settings++;a.type=video_settings_status;a.vs.accepted=true;f.Send(a);}FreeRemoteAction(a);} } if(f.connected){ files.Pump();MiniRtcAudioFrame audio{};audio.data=reinterpret_cast(pcm);audio.size=sizeof(pcm);SendAudioFrame(f.peer,&audio,kAudioStream); if(iteration%3==0){for(int y=0;y<360;y++)for(int x=0;x<640;x++)pixels[y*640+x]=uint8_t(35+(x/80)*24+((y+iteration)%180<12?30:0)); std::fill(pixels.begin()+640*360,pixels.end(),128);for(size_t i=640*360;i(pixels.data()); frame.captured_timestamp=std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); SendVideoFrame(f.peer,&frame,f.selected?"Display2":"Display1");} } if(iteration++%100==0)std::ofstream("fixture-status")<<"signal="<