Add receiver diagnostics and remote PicCap handover

This commit is contained in:
matze19999 committed 2026-10-06 18:35:56 +02:00
1 parent ae01879d45
commit 42aeaf56ea
19 files changed
+322 -50

No files matched your search

+20 -8
View File
@@ -17,6 +17,8 @@ static bool (*cancel_call)(void*,unsigned long,LSError*);
static unsigned long piccap_token,media_token;
static uint64_t piccap_deadline,media_deadline;
static unsigned clear_samples;
static TargetConfig piccap_target;
static char piccap_error[128];
static bool piccap_request(int command);
static inline bool piccap_installed(void){return access(PICCAP_BINARY,X_OK)==0;}
static bool handover_save(bool enabled){
@@ -39,7 +41,7 @@ static bool media_reply(void *h,void *m,void *ctx){
if(protection==PLAYBACK_CLEAR){if(clear_samples<2)clear_samples++;}else clear_samples=0;
return true;
}
/* Commands: 0 status, 1 start, 2 stop. Confirm stopped status before VT reuse. */
/* Commands: 0 status, 1 start, 2 stop, 3 getSettings, 4 setSettings. Confirm stopped status before VT reuse. */
static bool piccap_reply(void *h,void *m,void *ctx){
(void)h;int command=(int)(intptr_t)ctx;piccap_busy=false;piccap_token=0;
void *root=playback_json.parse(payload(m));bool ok=playback_true(&playback_json,root,"returnValue");
@@ -55,7 +57,16 @@ static bool piccap_reply(void *h,void *m,void *ctx){
if(!retries.paused)retries.due=milliseconds();
}
}else if(!piccap_installed()){piccap_owned=false;capture_source=SOURCE_HISTOGRAM;piccap_connected=false;}
}else if(command==3 && capture_source==SOURCE_PICCAP_STARTING){
void *port=playback_field(&playback_json,root,"port"),*socket=playback_field(&playback_json,root,"unix-socket");
bool same=ok && playback_is(&playback_json,root,"address",target_piccap_host(&piccap_target)) && port && playback_json.type(port)==3 && strtoul(playback_json.string(port),NULL,10)==piccap_target.piccap_port && socket && playback_json.type(socket)==1 && !playback_json.boolean(socket);
if(ok){if(!piccap_request(same?1:4)){capture_source=SOURCE_PICCAP_STOPPING;snprintf(piccap_error,sizeof(piccap_error),"PicCap endpoint request failed");}}
else {capture_source=SOURCE_PICCAP_STOPPING;snprintf(piccap_error,sizeof(piccap_error),"Cannot read PicCap settings");}
}else if(command==4){
if(!ok){capture_source=SOURCE_PICCAP_STOPPING;snprintf(piccap_error,sizeof(piccap_error),"PicCap rejected receiver settings");}
/* setSettings restarts PicCap itself; status confirms ownership. */
}else if(command==1 && !ok){capture_source=SOURCE_PICCAP_STOPPING;handover_cooldown=milliseconds()+10000;}
if(command>=3 && capture_source==SOURCE_PICCAP_STOPPING)handover_cooldown=milliseconds()+10000;
if(root)playback_json.put(root);
next_piccap_probe=milliseconds()+500;
if(command==2)piccap_request(0);
@@ -63,9 +74,10 @@ static bool piccap_reply(void *h,void *m,void *ctx){
}
static bool piccap_request(int command){
if(piccap_busy)return false;
const char *uri=command==1?"luna://org.webosbrew.piccap.service/start":command==2?"luna://org.webosbrew.piccap.service/stop":"luna://org.webosbrew.piccap.service/status";
const char *uri=command==3?"luna://org.webosbrew.piccap.service/getSettings":command==4?"luna://org.webosbrew.piccap.service/setSettings":command==1?"luna://org.webosbrew.piccap.service/start":command==2?"luna://org.webosbrew.piccap.service/stop":"luna://org.webosbrew.piccap.service/status";
LSError e;error_init(&e);
piccap_busy=call_once(service_handle,uri,"{}",piccap_reply,(void*)(intptr_t)command,&piccap_token,&e);
char data[160];snprintf(data,sizeof(data),"{\"address\":\"%s\",\"port\":%u,\"unix-socket\":false}",target_piccap_host(&piccap_target),piccap_target.piccap_port);
piccap_busy=call_once(service_handle,uri,command==4?data:"{}",piccap_reply,(void*)(intptr_t)command,&piccap_token,&e);
piccap_deadline=milliseconds()+3000;
error_free(&e);if(command)piccap_action_at=milliseconds();return piccap_busy;
}
@@ -73,20 +85,20 @@ static bool piccap_request(int command){
static bool handover_tick(void){
uint64_t now=milliseconds();
if(media_busy && now>=media_deadline){LSError e;error_init(&e);cancel_call(service_handle,media_token,&e);error_free(&e);media_busy=false;media_token=0;protection=PLAYBACK_UNKNOWN;clear_samples=0;}
if(piccap_busy && now>=piccap_deadline){LSError e;error_init(&e);cancel_call(service_handle,piccap_token,&e);error_free(&e);piccap_busy=false;piccap_token=0;capture_source=SOURCE_PICCAP_STOPPING;next_piccap_probe=0;}
if(piccap_busy && now>=piccap_deadline){snprintf(piccap_error,sizeof(piccap_error),"PicCap request timed out");LSError e;error_init(&e);cancel_call(service_handle,piccap_token,&e);error_free(&e);piccap_busy=false;piccap_token=0;capture_source=SOURCE_PICCAP_STOPPING;next_piccap_probe=0;}
if(handover_enabled && piccap_installed() && !retries.paused && playback_json.lib && !media_busy && now>=next_media_probe){
LSError e;error_init(&e);
media_busy=call_once(service_handle,"luna://com.webos.media/getActivePipelines","{}",media_reply,NULL,&media_token,&e);
media_deadline=now+3000;
error_free(&e);next_media_probe=now+1000;
}
bool clear=handover_enabled && target_piccap_local(&target) && piccap_installed() && !retries.paused && !retries.blocked &&
bool clear=handover_enabled && target_piccap_compatible(&target) && piccap_installed() && !retries.paused && !retries.blocked &&
protection==PLAYBACK_CLEAR && clear_samples>=2 && now-protection_at<3000 && now>=handover_cooldown;
if(capture_source==SOURCE_HISTOGRAM && clear){
stop_capture();retries.due=0;piccap_owned=true;capture_source=SOURCE_PICCAP_STARTING;
if(!piccap_request(1)){capture_source=SOURCE_PICCAP_STOPPING;handover_cooldown=now+10000;}
piccap_target=target;piccap_error[0]=0;stop_capture();retries.due=0;piccap_owned=true;capture_source=SOURCE_PICCAP_STARTING;
if(!piccap_request(3)){capture_source=SOURCE_PICCAP_STOPPING;handover_cooldown=now+10000;}
}
if(piccap_owned && !clear && capture_source!=SOURCE_PICCAP_STOPPING){capture_source=SOURCE_PICCAP_STOPPING;next_piccap_probe=0;}
if(piccap_owned && (!clear || strcmp(piccap_target.host,target.host) || piccap_target.piccap_port!=target.piccap_port) && capture_source!=SOURCE_PICCAP_STOPPING){capture_source=SOURCE_PICCAP_STOPPING;next_piccap_probe=0;}
if(piccap_owned && !piccap_busy && now>=next_piccap_probe){
if(capture_source==SOURCE_PICCAP_STOPPING)piccap_request(2);else piccap_request(0);
next_piccap_probe=now+1000;