@@ -99,6 +99,33 @@ static void exit_on_signal(int signum) {
9999 exit_from_hal ();
100100 exit (1 );
101101}
102+
103+ /* Read just the SAMPLES value from config file before loading scope_rt */
104+ static int read_samples_from_config (const char * filename )
105+ {
106+ FILE * fp ;
107+ char buf [100 ];
108+ int samples = 0 ;
109+
110+ fp = fopen (filename , "r" );
111+ if (fp == NULL ) {
112+ return 0 ; /* file doesn't exist, use default */
113+ }
114+ while (fgets (buf , sizeof (buf ), fp ) != NULL ) {
115+ /* Support both "SAMPLES nnn" and "# SAMPLES nnn" for backward compatibility */
116+ /* Older halscope versions will ignore "# SAMPLES" as a comment */
117+ if (strncasecmp (buf , "SAMPLES " , 8 ) == 0 ) {
118+ samples = atoi (buf + 8 );
119+ break ;
120+ } else if (strncasecmp (buf , "# SAMPLES " , 10 ) == 0 ) {
121+ samples = atoi (buf + 10 );
122+ break ;
123+ }
124+ }
125+ fclose (fp );
126+ return samples ;
127+ }
128+
102129/***********************************************************************
103130* MAIN() FUNCTION *
104131************************************************************************/
@@ -141,9 +168,30 @@ int main(int argc, gchar * argv[])
141168 break ;
142169 }
143170 }
144- if (argc > optind ) num_samples = atoi (argv [argc - 1 ]);
171+ /* first try to read samples from config file */
172+ num_samples = read_samples_from_config (ifilename );
173+ /* command line num_samples overrides config file, but only if it's a valid number */
174+ if (argc > optind ) {
175+ int cmdline_samples = atoi (argv [optind ]);
176+ if (cmdline_samples > 0 ) {
177+ num_samples = cmdline_samples ;
178+ }
179+ }
180+ /* apply defaults and bounds */
145181 if (num_samples <= 0 )
146182 num_samples = SCOPE_NUM_SAMPLES_DEFAULT ;
183+ if (num_samples < SCOPE_NUM_SAMPLES_MIN ) {
184+ rtapi_print_msg (RTAPI_MSG_WARN ,
185+ "SCOPE: num_samples %d too small, using %d\n" ,
186+ num_samples , SCOPE_NUM_SAMPLES_MIN );
187+ num_samples = SCOPE_NUM_SAMPLES_MIN ;
188+ }
189+ if (num_samples > SCOPE_NUM_SAMPLES_MAX ) {
190+ rtapi_print_msg (RTAPI_MSG_WARN ,
191+ "SCOPE: num_samples %d too large, using %d\n" ,
192+ num_samples , SCOPE_NUM_SAMPLES_MAX );
193+ num_samples = SCOPE_NUM_SAMPLES_MAX ;
194+ }
147195
148196 /* connect to the HAL */
149197 comp_id = hal_init ("halscope" );
@@ -161,6 +209,10 @@ int main(int argc, gchar * argv[])
161209 hal_exit (comp_id );
162210 exit (1 );
163211 }
212+ } else {
213+ /* scope_rt already loaded - we'll check if sample count matches later */
214+ rtapi_print_msg (RTAPI_MSG_DBG ,
215+ "SCOPE: scope_rt already loaded, requested %d samples\n" , num_samples );
164216 }
165217 /* set up a shared memory region for the scope data */
166218 shm_id = rtapi_shmem_new (SCOPE_SHM_KEY , comp_id , sizeof (scope_shm_control_t ));
@@ -191,6 +243,16 @@ int main(int argc, gchar * argv[])
191243 ctrl_usr = & ctrl_struct ;
192244 init_usr_control_struct (shm_base );
193245
246+ /* check if loaded scope_rt has different sample count than requested */
247+ if (ctrl_shm -> buf_len != num_samples ) {
248+ rtapi_print_msg (RTAPI_MSG_WARN ,
249+ "SCOPE: scope_rt was loaded with %d samples, but config requested %d.\n"
250+ "To change sample count, unload scope_rt first or restart LinuxCNC.\n" ,
251+ ctrl_shm -> buf_len , num_samples );
252+ }
253+ /* store requested samples for saving to config */
254+ ctrl_usr -> horiz .requested_samples = num_samples ;
255+
194256 /* init watchdog */
195257 ctrl_shm -> watchdog = 10 ;
196258 /* set main window */
@@ -278,6 +340,33 @@ void start_capture(void)
278340 /* already running! */
279341 return ;
280342 }
343+
344+ /* Check if data is from log file */
345+ if (ctrl_usr -> data_from_log_file ) {
346+ GtkWidget * dialog = gtk_message_dialog_new (
347+ GTK_WINDOW (ctrl_usr -> main_win ),
348+ GTK_DIALOG_MODAL ,
349+ GTK_MESSAGE_WARNING ,
350+ GTK_BUTTONS_OK_CANCEL ,
351+ _ ("Overwrite loaded log file data?" ));
352+
353+ gtk_message_dialog_format_secondary_text (
354+ GTK_MESSAGE_DIALOG (dialog ),
355+ _ ("Starting acquisition will clear the data loaded from the CSV file. Continue?" ));
356+
357+ int response = gtk_dialog_run (GTK_DIALOG (dialog ));
358+ gtk_widget_destroy (dialog );
359+
360+ if (response != GTK_RESPONSE_OK ) {
361+ /* User cancelled, switch back to STOP mode */
362+ set_run_mode (STOP );
363+ return ;
364+ }
365+
366+ /* Clear the flag */
367+ ctrl_usr -> data_from_log_file = 0 ;
368+ }
369+
281370 for (n = 0 ; n < 16 ; n ++ ) {
282371 /* point to user space channel data */
283372 chan = & (ctrl_usr -> chan [n ]);
@@ -436,12 +525,41 @@ static void init_usr_control_struct(void *shmem)
436525 /* set all 16 channels to "no source assigned" */
437526 for (n = 0 ; n < 16 ; n ++ ) {
438527 ctrl_usr -> chan [n ].data_source_type = -1 ;
528+ ctrl_usr -> chan [n ].is_phantom = 0 ;
439529 }
530+ ctrl_usr -> data_from_log_file = 0 ;
440531 /* done */
441532}
442533
443534static void menuitem_response (gchar * string ) {
444- printf ("%s\n" , string );
535+ if (strcmp (string , "file/open datafile" ) == 0 ) {
536+ open_log_cb (GTK_WINDOW (ctrl_usr -> main_win ));
537+ } else {
538+ printf ("%s\n" , string );
539+ }
540+ }
541+
542+ void open_log_cb (GtkWindow * parent )
543+ {
544+ GtkWidget * filew ;
545+ GtkFileChooser * chooser ;
546+
547+ filew = gtk_file_chooser_dialog_new (_ ("Open Log File:" ),
548+ parent ,
549+ GTK_FILE_CHOOSER_ACTION_OPEN ,
550+ _ ("_Cancel" ), GTK_RESPONSE_CANCEL ,
551+ _ ("_Open" ), GTK_RESPONSE_ACCEPT ,
552+ NULL );
553+
554+ chooser = GTK_FILE_CHOOSER (filew );
555+ set_file_filter (chooser , "Text CSV (.csv)" , "*.csv" );
556+
557+ if (gtk_dialog_run (GTK_DIALOG (filew )) == GTK_RESPONSE_ACCEPT ) {
558+ char * filename = gtk_file_chooser_get_filename (chooser );
559+ read_log_file (filename );
560+ g_free (filename );
561+ }
562+ gtk_widget_destroy (filew );
445563}
446564
447565static void about (void ) {
@@ -546,7 +664,7 @@ static void define_menubar(GtkWidget *vboxtop) {
546664 gtk_menu_shell_append (GTK_MENU_SHELL (filemenu ), fileopendatafile );
547665 g_signal_connect_swapped (fileopendatafile , "activate" ,
548666 G_CALLBACK (menuitem_response ), "file/open datafile" );
549- gtk_widget_set_sensitive (GTK_WIDGET (fileopendatafile ), FALSE); // XXX
667+ gtk_widget_set_sensitive (GTK_WIDGET (fileopendatafile ), TRUE);
550668 gtk_widget_show (fileopendatafile );
551669
552670 filesavedatafile = gtk_menu_item_new_with_mnemonic (_ ("S_ave Log File" ));
@@ -626,9 +744,9 @@ static void define_scope_windows(void)
626744{
627745 GtkWidget * vbox , * hbox , * vboxtop , * vboxbottom , * vboxleft , * vboxright , * hboxright ;
628746
629- /* create main window, set its minimum size and title */
747+ /* create main window, set its default size and title */
630748 ctrl_usr -> main_win = gtk_window_new (GTK_WINDOW_TOPLEVEL );
631- gtk_widget_set_size_request ( GTK_WIDGET (ctrl_usr -> main_win ), 650 , 400 );
749+ gtk_window_set_default_size ( GTK_WINDOW (ctrl_usr -> main_win ), 1050 , 550 );
632750 gtk_window_set_title (GTK_WINDOW (ctrl_usr -> main_win ), _ ("HAL Oscilloscope" ));
633751
634752 /* top level - big vbox, menu above, everything else below */
0 commit comments