53
53
import org .freedesktop .dbus .types .Variant ;
54
54
55
55
import java .awt .*;
56
- import java .util . Collections ;
56
+ import java .io . IOException ;
57
57
import java .util .List ;
58
- import java .util .Map ;
59
- import java .util .UUID ;
58
+ import java .util .*;
60
59
import java .util .concurrent .CompletableFuture ;
61
60
import java .util .concurrent .Executors ;
62
61
import java .util .concurrent .ScheduledExecutorService ;
@@ -73,13 +72,15 @@ public class PipelineManager {
73
72
private ScheduledExecutorService scheduledExecutorService ;
74
73
75
74
76
- record XdgStreamDetails (Integer streamId , FileDescriptor fileDescriptor ) {}
75
+ record XdgStreamDetails (Integer streamId , FileDescriptor fileDescriptor ) {
76
+ }
77
+
77
78
/**
78
79
* Uses D-BUS to get the XDG ScreenCast stream ID & pipewire filedescriptor
79
80
*
80
- * @throws RuntimeException on any concurrency or D-BUS issues
81
81
* @return XDG ScreenCast stream details containing the ID from org.freedesktop.portal.ScreenCast:Start and
82
82
* FileDescriptor from org.freedesktop.portal.ScreenCast:OpenPipeWireRemote
83
+ * @throws RuntimeException on any concurrency or D-BUS issues
83
84
*/
84
85
@ SneakyThrows
85
86
@ SuppressWarnings ("all" )
@@ -96,38 +97,51 @@ public static XdgStreamDetails getXdgStreamDetails() {
96
97
dBusConnection .addGenericSigHandler (matchRule , signal -> {
97
98
try {
98
99
if (signal .getParameters ().length == 2 // verify amount of arguments
99
- && signal .getParameters ()[0 ] instanceof UInt32 // verify argument types
100
- && signal .getParameters ()[1 ] instanceof DBusMap
101
- && ((UInt32 )signal .getParameters ()[0 ]).intValue () == 0 // verify success-code
100
+ && signal .getParameters ()[0 ] instanceof UInt32 // verify argument types
101
+ && signal .getParameters ()[1 ] instanceof DBusMap
102
+ && ((UInt32 ) signal .getParameters ()[0 ]).intValue () == 0 // verify success-code
102
103
) {
103
104
// parse signal & set appropriate Future as the result
104
105
if (((DBusMap <?, ?>) signal .getParameters ()[1 ]).containsKey ("session_handle" )) {
105
- sessionHandleMaybe .complete ((String )(((Variant <?>)((DBusMap <?, ?>) signal .getParameters ()[1 ]).get ("session_handle" )).getValue ()));
106
+ sessionHandleMaybe .complete ((String ) (((Variant <?>) ((DBusMap <?, ?>) signal .getParameters ()[1 ]).get ("session_handle" )).getValue ()));
106
107
} else if (((DBusMap <?, ?>) signal .getParameters ()[1 ]).containsKey ("streams" )) {
107
- streamIdMaybe .complete (((UInt32 )((Object []) ((List <?>) (((Variant <?>) ((DBusMap <?, ?>) signal .getParameters ()[1 ]).get ("streams" )).getValue ())).get (0 ))[0 ]).intValue ());
108
+ if (((DBusMap <?, ?>) signal .getParameters ()[1 ]).get ("restore_token" ) != null ) {
109
+ String restoreToken = (String ) ((Variant <?>) ((DBusMap <?, ?>) signal .getParameters ()[1 ]).get ("restore_token" )).getValue ();
110
+ try {
111
+ if (!restoreToken .equals (MainSingleton .getInstance ().config .getScreenCastRestoreToken ())) {
112
+ MainSingleton .getInstance ().config .setScreenCastRestoreToken ((String ) ((Variant <?>) ((DBusMap <?, ?>) signal .getParameters ()[1 ]).get ("restore_token" )).getValue ());
113
+ StorageManager storageManager = new StorageManager ();
114
+ storageManager .writeConfig (MainSingleton .getInstance ().config , null );
115
+ }
116
+ } catch (IOException e ) {
117
+ log .error ("Can't write config file." );
118
+ }
119
+ }
120
+ streamIdMaybe .complete (((UInt32 ) ((Object []) ((List <?>) (((Variant <?>) ((DBusMap <?, ?>) signal .getParameters ()[1 ]).get ("streams" )).getValue ())).get (0 ))[0 ]).intValue ());
108
121
}
109
122
}
110
123
} catch (DBusException e ) {
111
124
throw new RuntimeException (e ); // couldn't parse, fail early
112
125
}
113
126
});
114
-
115
127
screenCastIface .CreateSession (Map .of ("session_handle_token" , new Variant <>(handleToken )));
116
128
DBusPath receivedSessionHandle = new DBusPath (sessionHandleMaybe .get ());
117
-
118
- screenCastIface .SelectSources (receivedSessionHandle ,
119
- Map .of (
120
- "multiple" , new Variant <>(false ),
121
- "types" , new Variant <>(new UInt32 (1 |2 )) // bitmask, 1 - screens, 2 - windows
122
- )
123
- );
129
+ String restoreToken = MainSingleton .getInstance ().config .getScreenCastRestoreToken ();
130
+ Map <String , Variant <?>> selectSourcesMap = new HashMap <>() {{
131
+ put ("multiple" , new Variant <>(false ));
132
+ put ("types" , new Variant <>(new UInt32 (1 | 2 ))); // bitmask, 1 - screens, 2 - windows
133
+ put ("persist_mode" , new Variant <>(new UInt32 (2 )));
134
+ }};
135
+ if (restoreToken != null ) {
136
+ selectSourcesMap .put ("restore_token" , new Variant <>(restoreToken ));
137
+ }
138
+ screenCastIface .SelectSources (receivedSessionHandle , selectSourcesMap );
124
139
screenCastIface .Start (receivedSessionHandle , "" , Collections .emptyMap ());
125
-
126
- return streamIdMaybe .thenApply (streamId -> {
140
+ var c = streamIdMaybe .thenApply (streamId -> {
127
141
FileDescriptor fileDescriptor = screenCastIface .OpenPipeWireRemote (receivedSessionHandle , Collections .emptyMap ()); // block until stream started before calling OpenPipeWireRemote
128
-
129
142
return new XdgStreamDetails (streamId , fileDescriptor );
130
143
}).get ();
144
+ return c ;
131
145
}
132
146
133
147
/**
@@ -139,7 +153,7 @@ public static String getLinuxPipelineParams() {
139
153
String gstreamerPipeline ;
140
154
String pipeline ;
141
155
if (MainSingleton .getInstance ().config .getCaptureMethod ().equals (Configuration .CaptureMethod .PIPEWIREXDG .name ())
142
- || MainSingleton .getInstance ().config .getCaptureMethod ().equals (Configuration .CaptureMethod .PIPEWIREXDG_NVIDIA .name ())) {
156
+ || MainSingleton .getInstance ().config .getCaptureMethod ().equals (Configuration .CaptureMethod .PIPEWIREXDG_NVIDIA .name ())) {
143
157
if (MainSingleton .getInstance ().config .getCaptureMethod ().equals (Configuration .CaptureMethod .PIPEWIREXDG .name ())) {
144
158
pipeline = Constants .GSTREAMER_PIPELINE_PIPEWIREXDG ;
145
159
} else {
0 commit comments