Skip to main content

query_vdj_state/
query_vdj_state.rs

1//! VirtualDJ State Query Example
2//! 
3//! This example demonstrates how to use the PluginContext to safely query
4//! VirtualDJ state information like track titles, positions, and BPM values,
5//! similar to the UdpSender.cpp example.
6
7use virtualdj_plugin_sdk::{PluginBase, PluginContext, PluginInfo, Result};
8
9/// A plugin that demonstrates querying VirtualDJ state
10pub struct StateQueryPlugin {
11    // In a real plugin, you would store the PluginContext here
12    // for use in your plugin callbacks
13}
14
15impl StateQueryPlugin {
16    pub fn new() -> Self {
17        StateQueryPlugin {}
18    }
19
20    /// Example method showing how to query various VirtualDJ state values
21    /// This mirrors the pattern used in UdpSender.cpp
22    pub fn query_deck_info(&self, context: &PluginContext, deck: i32) -> Result<()> {
23        // Get track title (like GetInfoText("deck 1 get_title") in C++)
24        let title = context.get_info_string(&format!("deck {} get_title", deck))?;
25        println!("Deck {} title: {}", deck, title);
26
27        // Get position as a double (like GetInfoDouble("deck 1 get_position") in C++)
28        let position = context.get_info_double(&format!("deck {} get_position", deck))?;
29        println!("Deck {} position: {}", deck, position);
30
31        // Check if deck is audible
32        let audible = context.get_info_string(&format!("deck {} is_audible", deck))?;
33        println!("Deck {} is audible: {}", deck, audible);
34
35        Ok(())
36    }
37
38    /// Example showing how to iterate through cues and query their properties
39    pub fn query_deck_cues(&self, context: &PluginContext, deck: i32) -> Result<()> {
40        // Get track title
41        let title = context.get_info_string(&format!("deck {} get_title", deck))?;
42        
43        // Get current position
44        let cursor_percent = context.get_info_double(&format!("deck {} get_position", deck))?;
45        
46        println!("\nQuerying cues for deck {} ({})", deck, title);
47        println!("Current position: {:.2}%", cursor_percent * 100.0);
48
49        // Check cues 1-8 (you can extend to 128 like in the C++ version)
50        for cue in 1..=8 {
51            // Check if cue exists
52            let has_cue = context.get_info_string(&format!("deck {} has_cue {}", deck, cue))?;
53            
54            if has_cue.to_lowercase() != "on" {
55                continue;
56            }
57
58            // Get cue name
59            let cue_name = context.get_info_string(&format!("deck {} cue_name {}", deck, cue))?;
60            
61            // Get cue position
62            let cue_pos = context.get_info_double(&format!("deck {} cue_pos {}", deck, cue))?;
63            
64            if cue_pos >= 0.0 {
65                println!("  Cue {}: {} (position: {:.2}%)", cue, cue_name, cue_pos * 100.0);
66            }
67        }
68
69        Ok(())
70    }
71
72    /// Example showing how to send commands (like SendCommand in C++)
73    pub fn send_example_command(&self, context: &PluginContext) -> Result<()> {
74        // Play deck 1
75        context.send_command("deck 1 play")?;
76        println!("Sent: deck 1 play");
77
78        // You can also use the parsed information to make decisions
79        let active_deck_str = context.get_info_string("get_activedeck")?;
80        let active_deck: i32 = active_deck_str.parse().unwrap_or(1);
81        println!("Active deck: {}", active_deck);
82
83        Ok(())
84    }
85}
86
87fn main() {
88    println!("VirtualDJ State Query Example");
89    println!("=============================\n");
90    println!("This example demonstrates how to use PluginContext to query VirtualDJ state.");
91    println!("In a real plugin, you would use this pattern in your plugin callbacks.\n");
92    
93    println!("Example usage patterns:\n");
94    
95    println!("1. Query track information:");
96    println!("   let title = context.get_info_string(\"deck 1 get_title\")?;");
97    println!("   let position = context.get_info_double(\"deck 1 get_position\")?;\n");
98    
99    println!("2. Query cue information:");
100    println!("   let has_cue = context.get_info_string(\"deck 1 has_cue 1\")?;");
101    println!("   let cue_pos = context.get_info_double(\"deck 1 cue_pos 1\")?;\n");
102    
103    println!("3. Send commands:");
104    println!("   context.send_command(\"deck 1 play\")?;");
105    println!("   context.send_command(\"mixer master volume 50\")?;\n");
106    
107    println!("Note: This example is a reference. To use PluginContext:");
108    println!("- You need a valid VirtualDJ plugin pointer");
109    println!("- You need access to the VdjCallbacks struct");
110    println!("- Typically this is done within your plugin's on_load() or other callbacks\n");
111    
112    let plugin = StateQueryPlugin::new();
113    let info = plugin.get_info();
114    println!("Plugin: {} v{}", info.name, info.version);
115}
116
117impl PluginBase for StateQueryPlugin {
118    fn on_load(&mut self) -> Result<()> {
119        println!("State Query Plugin loaded!");
120        Ok(())
121    }
122
123    fn get_info(&self) -> PluginInfo {
124        PluginInfo {
125            name: "VDJ State Query Example".to_string(),
126            author: "VirtualDJ SDK".to_string(),
127            description: "Demonstrates querying VirtualDJ state safely".to_string(),
128            version: "1.0.0".to_string(),
129            flags: 0,
130        }
131    }
132
133    fn on_parameter(&mut self, _id: i32) -> Result<()> {
134        Ok(())
135    }
136}
137
138#[cfg(test)]
139mod tests {
140    use super::*;
141
142    #[test]
143    fn test_state_query_plugin_creation() {
144        let plugin = StateQueryPlugin::new();
145        let info = plugin.get_info();
146        assert_eq!(info.name, "VDJ State Query Example");
147    }
148}