2 * wavelist.c - part of gwave
3 * routines to handle the scrolling list of potentialy-displayable waveforms,
4 * and other stuff related to loading of data files.
6 * Copyright (C) 1998, 1999 Stephen G. Tell
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public
19 * License along with this software; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36 #include <guile-gnome-gobject/gobject.h>
39 #include <scwm_guile.h>
42 #define WAVELIST_IMPLEMENTATION
45 #include <measurebtn.h>
48 GList
*wdata_list
= NULL
;
49 static char file_tag_chars
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
50 static const int n_file_tags
= sizeof(file_tag_chars
)/sizeof(char);
51 static int next_file_tagno
= 0;
53 static GtkWidget
*create_wavelist_menu(GWDataFile
*wdata
);
54 void gwfile_add_wv_to_list(gpointer d
/*WaveVar* */,
55 gpointer p
/*GWDataFile */);
57 void wavelist_button_click(GtkWidget
*widget
,
58 GdkEventButton
*event
, gpointer data
);
60 XSCM_HOOK(new_wavefile_hook
,"new-wavefile-hook", 1, (SCM DF
),
61 "This hook is invoked when a new waveform file is successfully loaded."
62 "It is called with the new GWDataFile, DF, as its only argument.");
64 XSCM_HOOK(new_wavelist_hook
,"new-wavelist-hook", 1, (SCM DF
),
65 "This hook is invoked when the variable list window for a"
66 "GWDataFile is created. The GWDataFile object, DF, is passed as an"
67 "argument. Note that variable-list windows can be created and"
68 "destroyed many times during the life of a GWDataFile. One of the principle"
69 "uses of this hook is creating the menus such for the variable-list window.");
72 * Load a waveform file, adding it to the list of files from which
73 * variables can be chosen to add to the display.
76 load_wave_file(char *fname
, char *ftype
)
82 wdata
= g_new0(GWDataFile
, 1);
83 wdata
->wf
= wf_read(fname
, ftype
);
85 if(wdata
->wf
== NULL
) {
89 wdata
->wf
->udata
= wdata
;
91 /* give the file a short (fow now, 1-character) "tag" to identify it
92 * in the menu and variable labels.
94 wdata
->ftag
= g_new(char, 2);
95 wdata
->ftag
[0] = file_tag_chars
[next_file_tagno
];
96 wdata
->ftag
[1] = '\0';
97 next_file_tagno
= (next_file_tagno
+ 1) % n_file_tags
;
98 wdata
->ndv
= wdata
->wf
->wf_ndv
;
99 wdata
->wvhl
= NULL
; /* empty GSList of WaveVarH* */
101 wdata_list
= g_list_append(wdata_list
, wdata
);
102 wdata
->outstanding_smob
= 1;
103 SGT_NEWCELL_SMOB(wdata
->smob
, GWDataFile
, wdata
);
104 call1_hooks(new_wavefile_hook
, wdata
->smob
);
107 cmd_show_wave_list(NULL
, wdata
);
112 SCM_DEFINE(load_wavefile_x
, "load-wavefile!", 1, 1, 0, (SCM file
, SCM filetype
),
113 "Load waveform data from FILE into memory, and make it available for"
114 "display. If FILETYPE is specified, it indicates the format of the file"
115 "and which wavefile reader to use, otherwise the format is inferred"
116 "from the filename and file contents. Returns a GWDataFile object"
117 "which can be used to refer to the loaded data.")
118 #define FUNC_NAME s_load_wavefile_x
123 VALIDATE_ARG_STR_NEWCOPY(1, file
, fname
);
124 VALIDATE_ARG_STR_NEWCOPY_USE_NULL(2, filetype
, ftype
);
125 df
= load_wave_file(fname
, ftype
);
137 * Delete a wave file.
138 * callback from menu: wavelist->file->delete
141 delete_wave_file(GtkWidget
*w
, GWDataFile
*wdata
)
145 /* remove references from displayed waves */
146 remove_wfile_waves(wdata
);
148 /* remove per-file GUI stuff */
149 if(wdata
->wlist_win
&& GTK_WIDGET_VISIBLE(wdata
->wlist_win
))
150 gtk_widget_destroy(wdata
->wlist_win
);
152 /* invalidate WaveVar pointers in handles.
153 * Can't free WaveVar because un-GCed smobs may point to them
155 for(list
= wdata
->wvhl
; list
; list
= list
->next
) {
156 WaveVarH
*wvh
= (WaveVarH
*)list
->data
;
160 /* now nuke the data */
163 wdata_list
= g_list_remove(wdata_list
, wdata
);
165 if(wdata
->outstanding_smob
) {
167 fprintf(stderr
, "defering free of GWDataFile\n");
170 fprintf(stderr
, "free GWDataFile 0x%x\n", wdata
);
175 SCM_DEFINE(datafile_delete_x
, "wavefile-delete!", 1, 0, 0,
177 "Delete from memory the waveform data from OBJ.")
178 #define FUNC_NAME s_datafile_delete_x
181 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
184 delete_wave_file(NULL
, wdata
);
185 return SCM_UNSPECIFIED
;
190 * command or callback from menu: wavelist->file->reload
193 reload_wave_file(GtkWidget
*w
, GWDataFile
*wdata
)
199 /* FIXME:sgt: get file type from old file, if it was specified
200 * when loading it originaly
202 new_wf
= wf_read(wdata
->wf
->wf_filename
, NULL
);
204 fprintf(stderr
, "reload_wave_file: failed to read %s\n", wdata
->wf
->wf_filename
);
205 /* FIXME:sgt put up error message in window */
210 wdata
->wf
->udata
= wdata
;
211 /* printf("reload_wave_file(%s) old=%lx new=%lx\n",
212 wdata->wf->wf_filename, old_wf, new_wf); */
214 update_wfile_waves(wdata
);
216 /* remove old buttons from list, and add new ones */
217 if(wdata
->wlist_win
&& GTK_WIDGET_VISIBLE(wdata
->wlist_win
)) {
218 gtk_container_foreach(GTK_CONTAINER(wdata
->wlist_box
),
219 (GtkCallback
) gtk_widget_destroy
, NULL
);
220 wf_foreach_wavevar(wdata
->wf
, gwfile_add_wv_to_list
, (gpointer
)wdata
);
228 reload_wave_file_w(gpointer p
, gpointer d
)
230 GWDataFile
*wdata
= (GWDataFile
*)p
;
231 reload_wave_file(NULL
, wdata
);
236 * plan: replace this with update_all_wave_files(), which checks
237 * file dates/sizes and only reloads those that need it.
240 reload_all_wave_files(GtkWidget
*w
)
243 g_list_foreach(wdata_list
, reload_wave_file_w
, NULL
);
246 SCM_DEFINE(reload_all_files_x
, "reload-all-files!", 0, 0, 0, (),
248 #define FUNC_NAME s_reload_all_files_x
251 g_list_foreach(wdata_list
, reload_wave_file_w
, NULL
);
252 return SCM_UNSPECIFIED
;
256 SCM_DEFINE(datafile_reload_x
, "wavefile-reload!", 1, 0, 0,
258 "Reread the data file for OBJ. Useful for updating the display"
259 " after simulation has been rerun.")
260 #define FUNC_NAME s_datafile_reload_x
263 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
266 reload_wave_file(NULL
, wdata
);
267 return SCM_UNSPECIFIED
;
272 * Callback for use with wv_foreach_wavevar:
274 * Add a button for each variable in the file to the win_wlist box for it.
275 * Arrange for the buttons to be drag-and-drop sources for placing the
276 * variables into wavepanels.
278 * formerly add_variables_to_list(GWDataFile *wdata)
281 gwfile_add_wv_to_list(gpointer d
, gpointer p
)
283 WaveVar
*wv
= (WaveVar
*)d
;
284 GWDataFile
*wdata
= (GWDataFile
*)p
;
288 if(wv_is_multisweep(wv
)) {
290 sprintf(lab
, "%s @ %s=%g", wv
->wv_name
,
291 wv
->wtable
->name
, wv
->wtable
->swval
);
292 button
= gtk_button_new_with_label(lab
);
294 button
= gtk_button_new_with_label(wv
->wv_name
);
297 gtk_box_pack_start (GTK_BOX (wdata
->wlist_box
), button
, FALSE
, FALSE
, 0);
298 gtk_widget_show (button
);
300 if(GTK_IS_TOOLTIPS(wtable
->ttips
))
301 gtk_tooltips_set_tip(GTK_TOOLTIPS(wtable
->ttips
), button
,
302 "Wavefile Variable.\nDrag-and-Drop to a WavePanel.", "");
304 dnd_setup_source(GTK_WINDOW(wdata
->wlist_win
), button
, wv
);
306 gtk_signal_connect (GTK_OBJECT(button
), "button-press-event",
307 GTK_SIGNAL_FUNC(wavelist_button_click
),
312 * Show the variable-list window for a waveform data file.
313 * If the window already exists, simply raise it to the top.
316 cmd_show_wave_list(GtkWidget
*w
, GWDataFile
*wdata
)
320 GtkWidget
*scrolled_window
;
326 fprintf(stderr
, "cmd_show_wave_list: wdata is NULL");
330 if(!wdata
->wlist_win
) {
333 wdata
->wlist_win
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
334 gtk_widget_set_name(wdata
->wlist_win
, "data list window");
335 sprintf(buf
, "gwave: %.64s", wdata
->wf
->wf_filename
);
336 gtk_window_set_title(GTK_WINDOW(wdata
->wlist_win
), buf
);
337 gtk_widget_set_usize(wdata
->wlist_win
, 150, 300);
338 { /* suggest that the window manager try to put the wavelist
339 * window somewhere to the left of the main window.
340 * This nonsense really belongs in a smarter window manager,
341 * but users are demanding somthing.
348 && wtable
->window
&& wtable
->window
->window
) {
349 gdk_window_get_position(wtable
->window
->window
,
353 diddle
= (diddle
+ 1) % 4;
355 gtk_widget_set_uposition(wdata
->wlist_win
, x
-175, y
);
357 gtk_signal_connect (GTK_OBJECT (wdata
->wlist_win
), "destroy",
358 GTK_SIGNAL_FUNC(gtk_widget_destroyed
),
359 &(wdata
->wlist_win
));
361 box1
= gtk_vbox_new(FALSE
, 0);
362 gtk_container_add(GTK_CONTAINER(wdata
->wlist_win
), box1
);
363 gtk_widget_show(box1
);
364 wdata
->wlist_menubar
= gtk_menu_bar_new();
365 gtk_widget_show(wdata
->wlist_menubar
);
366 gtk_box_pack_start (GTK_BOX (box1
), wdata
->wlist_menubar
, FALSE
, FALSE
, 0);
368 if(strlen(wdata
->wf
->wf_filename
) > 16) {
369 char *cp
= strrchr(wdata
->wf
->wf_filename
, '/');
371 sprintf(buf
, "%s: .../%.64s", wdata
->ftag
, cp
+1);
373 sprintf(buf
, "%s: .../%.64s", wdata
->ftag
, wdata
->wf
->wf_filename
);
375 sprintf(buf
, "%s: %.64s", wdata
->ftag
, wdata
->wf
->wf_filename
);
377 label
= gtk_label_new(buf
);
378 gtk_label_set_justify(GTK_LABEL(label
), GTK_JUSTIFY_LEFT
);
379 gtk_widget_show(label
);
380 gtk_box_pack_start (GTK_BOX (box1
), label
, FALSE
, FALSE
, 0);
384 scrolled_window
= gtk_scrolled_window_new (NULL
, NULL
);
385 gtk_container_border_width (GTK_CONTAINER (scrolled_window
), 10);
386 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window
),
387 GTK_POLICY_AUTOMATIC
,
389 GTK_WIDGET_UNSET_FLAGS (GTK_SCROLLED_WINDOW (scrolled_window
)->vscrollbar
, GTK_CAN_FOCUS
);
390 gtk_box_pack_start(GTK_BOX (box1
), scrolled_window
,
392 gtk_widget_show (scrolled_window
);
394 wdata
->wlist_box
= gtk_vbox_new (FALSE
, 0);
395 gtk_container_border_width (GTK_CONTAINER (wdata
->wlist_box
), 10);
396 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window
),
398 gtk_container_set_focus_vadjustment(
399 GTK_CONTAINER (wdata
->wlist_box
),
400 gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window
)));
401 gtk_widget_show (wdata
->wlist_box
);
403 dnd_init(wdata
->wlist_win
);
404 wf_foreach_wavevar(wdata
->wf
, gwfile_add_wv_to_list
, (gpointer
)wdata
);
406 call1_hooks(new_wavelist_hook
, wdata
->smob
);
408 gtk_widget_show(wdata
->wlist_win
);
410 gdk_window_raise(wdata
->wlist_win
->window
);
415 * Called for all button presses on wavelist button.
416 * If it is a doubleclick, add variable to the "current" wavepanel immediately.
419 wavelist_button_click(GtkWidget
*widget
,
420 GdkEventButton
*bevent
,
423 WaveVar
*dv
= (WaveVar
*)data
;
424 if(bevent
->type
== GDK_2BUTTON_PRESS
) {
425 /* printf("doubleclicked %s %s\n", dv->wfile->ss->filename,
427 add_var_to_panel(NULL
, dv
);
431 SCM_DEFINE(wavefile_show_listwin_x
, "wavefile-show-listwin!", 1, 0, 0,
433 "Displays the scrolling list of the variables in OBJ, from which they"
434 "can be dragged into a waveform display panel.")
435 #define FUNC_NAME s_wavefile_show_listwin_x
438 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
441 fprintf(stderr
, "%s wdata=0x%x\n", FUNC_NAME
, wdata
);
443 cmd_show_wave_list(NULL
, wdata
);
444 return SCM_UNSPECIFIED
;
449 /* maybe I should just expose the GTkWindow itself, and destroy from guile */
450 SCM_DEFINE(wavefile_remove_listwin_x
, "wavefile-remove-listwin!", 1, 0, 0,
452 "Removes the variable-list window for OBJ")
453 #define FUNC_NAME s_wavefile_remove_listwin_x
456 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
458 if(wdata
->wf
&& wdata
->wlist_win
)
459 gtk_widget_destroy(wdata
->wlist_win
);
460 return SCM_UNSPECIFIED
;
465 /* Primitives for accessing GWDataFile info from scheme */
467 SCM_DEFINE(wavefile_file_name
, "wavefile-file-name", 1, 0, 0,
469 "Returns the filename from which the GWDataFile OBJ was loaded."
470 "If OBJ is invalid because the datafile has been deleted,"
472 #define FUNC_NAME s_wavefile_file_name
475 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
478 return scm_makfrom0str(wdata
->wf
->wf_filename
);
485 SCM_DEFINE(wavefile_nsweeps
, "wavefile-nsweeps", 1, 0, 0,
487 "Returns the number of sweeps for which data is present in GWDataFile DF.")
488 #define FUNC_NAME s_wavefile_nsweeps
491 VALIDATE_ARG_GWDataFile_COPY(1, df
, wdata
);
493 return scm_long2num(wdata
->wf
->wf_ntables
);
497 SCM_DEFINE(wavefile_sweeps
, "wavefile-sweeps", 1, 0, 0,
499 "Returns a list of sweeps contained in GWDataFile DF. Each element of the list is a pair, of the form (sweepname . sweepvalue)")
500 #define FUNC_NAME s_wavefile_nsweeps
503 SCM result
= SCM_EOL
;
508 VALIDATE_ARG_GWDataFile_COPY(1, df
, wdata
);
514 for(i
= 0; i
< wf
->wf_ntables
; i
++) {
515 wt
= wf_wtable(wf
, i
);
516 p
= scm_cons(scm_makfrom0str(wt
->name
), scm_make_real(wt
->swval
));
517 result
= scm_cons(p
, result
);
519 return scm_reverse(result
);
523 SCM_DEFINE(wavefile_tag
, "wavefile-tag", 1, 0, 0,
525 "Returns the short identifying tag for the GWDataFile OBJ.")
526 #define FUNC_NAME s_wavefile_tag
529 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
531 return scm_makfrom0str(wdata
->ftag
);
535 SCM_DEFINE(wavefile_set_tag_x
, "wavefile-set-tag!", 2, 0, 0,
537 "Set the short identifying tag for the GWDataFile OBJ to STR.")
538 #define FUNC_NAME s_wavefile_set_tag_x
542 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
543 VALIDATE_ARG_STR_NEWCOPY(1, str
, s
);
546 return SCM_UNSPECIFIED
;
547 /* BUG: any visiblewave button labels and wavelist menu entries
548 * won't be affected by the change in ftag */
552 SCM_DEFINE(wavefile_listwin_menubar
, "wavefile-listwin-menubar", 1, 0, 0,
554 "Returns the GTK Menubar for the variable-list window of the"
555 " * GWDataFile OBJ, or #f if the window doesn't exist.")
556 #define FUNC_NAME s_wavefile_listwin_menubar
559 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
561 if(wdata
->wlist_win
&& wdata
->wlist_menubar
)
562 return scm_c_gtype_instance_to_scm(GTK_OBJECT(wdata
->wlist_menubar
));
569 wavefile_to_scm(void *vp
)
571 GWDataFile
*wdata
= (GWDataFile
*)vp
;
576 glist2scm(GList
*list
, SCM (*toscm
)(void*))
578 SCM result
= SCM_EOL
;
580 result
= scm_cons(toscm(list
->data
), result
);
586 SCM_DEFINE(wavefile_list
, "wavefile-list", 0, 0, 0, (),
587 "Returns a list containing all waveform data files")
588 #define FUNC_NAME s_wavefile_list
590 return glist2scm(wdata_list
, wavefile_to_scm
);
595 SCM_DEFINE(wavefile_all_variables
, "wavefile-all-variables", 1, 0, 0, (SCM df
),
596 "Returns a list of WaveVars, composed of all variables in the GWDataFile DF.")
597 #define FUNC_NAME s_wavefile_all_variables
600 SCM result
= SCM_EOL
;
606 VALIDATE_ARG_GWDataFile_COPY(1, df
, wdata
);
612 for(i
= 0; i
< wf
->wf_ntables
; i
++) {
613 wt
= wf_wtable(wf
, i
);
614 for(j
= 0; j
< wf
->wf_ndv
; j
++) {
619 wvh
= g_new0(WaveVarH
, 1);
623 wdata
->wvhl
= g_slist_prepend(wdata
->wvhl
, wvh
);
624 SGT_NEWCELL_SMOB(wvsmob
, WaveVar
, wvh
);
627 wvh
= (WaveVarH
*)wv
->udata
;
630 result
= scm_cons(wvsmob
, result
);
633 return scm_reverse(result
);
638 SCM_DEFINE(wavefile_variable
, "wavefile-variable", 3, 0, 0,
639 (SCM df
, SCM vname
, SCM swindex
),
640 "Returns a WaveVar representing the variable named VNAME in sweep/table/segment SWINDEX in the GWDataFile DF. Return #f if there is no variable named VNAME")
641 #define FUNC_NAME s_wavefile_variable
644 SCM result
= SCM_BOOL_F
;
648 VALIDATE_ARG_GWDataFile_COPY(1, df
, wdata
);
649 VALIDATE_ARG_STR_NEWCOPY(2, vname
, s
);
650 VALIDATE_ARG_INT_MIN_COPY(3, swindex
, 0, swp
);
652 if(wdata
->wf
&& swp
< wdata
->wf
->wf_ntables
) {
653 WaveVar
*wv
= wf_find_variable(wdata
->wf
, s
, swp
);
657 wvh
= g_new0(WaveVarH
, 1);
661 wdata
->wvhl
= g_slist_prepend(wdata
->wvhl
, wvh
);
662 SGT_NEWCELL_SMOB(result
, WaveVar
, wvh
);
665 wvh
= (WaveVarH
*)wv
->udata
;
675 SCM_DEFINE(variable_signame
, "variable-signame", 1, 0, 0,
677 "Return the signal name for the variable VAR.")
678 #define FUNC_NAME s_variable_signame
681 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var
,wv
);
684 return scm_makfrom0str(wv
->sv
->name
);
691 SCM_DEFINE(variable_sweepname
, "variable-sweepname", 1, 0, 0,
693 "Return the sweep name or table name for the variable VAR.")
694 #define FUNC_NAME s_variable_sweepname
697 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var
,wv
);
700 return scm_makfrom0str(wv
->wtable
->name
);
707 SCM_DEFINE(variable_sweepindex
, "variable-sweepindex", 1, 0, 0,
709 "Return the sweep table index for the variable VAR. Sweeps/tables are numbered starting with 0. ")
710 #define FUNC_NAME s_variable_sweepindex
713 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var
,wv
);
716 return scm_long2num(wv
->wtable
->swindex
);
723 SCM_DEFINE(variable_wavefile
, "variable-wavefile", 1, 0, 0,
725 "Return the WaveFile that the variable VAR is contained in.")
726 // Really, the GWDataFile smob.
727 #define FUNC_NAME s_variable_wavefile
730 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var
,wv
);
733 GWDataFile
*df
= wvar_gwdatafile(wv
);
734 df
->outstanding_smob
= 1;
741 SCM_DEFINE(export_variables
, "export-variables", 2, 2, 0,
742 (SCM varlist
, SCM port
, SCM from
, SCM to
),
743 "Write the data for all variables in VARLIST to PORT in tabular ascii form"
744 "If FROM and TO are specified, writes only data points for which the"
745 "independent variable is between FROM and TO includsive."
746 "All variables in VARLIST must share the same independent variable")
747 #define FUNC_NAME s_export_variables
752 double from_val
, to_val
;
758 /* validate varlist and count elements */
759 for (l
= varlist
; SCM_NNULLP(l
); l
= SCM_CDR (l
)) {
761 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,v
,wv
);
763 scm_misc_error(FUNC_NAME
, "invalid WaveVar ~s", SCM_LIST1(v
));
767 else if(iv
!= wv
->wv_iv
) {
768 scm_misc_error(FUNC_NAME
, "All WaveVars in VARLIST must relate to the same independent variable", SCM_UNDEFINED
);
771 VALIDATE_ARG_DBL_COPY_USE_DEF(3,from
,from_val
, iv
->wds
[0].min
);
772 VALIDATE_ARG_DBL_COPY_USE_DEF(4,to
,to_val
, iv
->wds
[0].max
);
774 if(from_val
> to_val
)
775 return SCM_UNSPECIFIED
;
776 starti
= wf_find_point(iv
, from_val
);
777 endi
= wf_find_point(iv
, to_val
);
779 for(i
= starti
; i
<= endi
; i
++) {
780 x
= wds_get_point(&iv
->wds
[0], i
);
781 sprintf(buf
, "%g", x
);
783 for (l
= varlist
; SCM_NNULLP(l
); l
= SCM_CDR (l
)) {
785 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,v
,wv
);
786 g_assert(wv
); /* should have been checked above */
787 y
= wds_get_point(&wv
->wds
[0], i
);
788 sprintf(buf
, " %g", y
);
791 scm_puts("\n", port
);
794 return SCM_UNSPECIFIED
;
799 * On the C side we never free WaveVars without freeing the whole
800 * WaveFile structure. When guile GC's one, we invalidate the pointer
801 * in the handle, and then check to see if we can dump the whole
803 * Methinks we need a more formal reference-counting scheme instead of
804 * all this ad-hockery.
806 int wavefile_try_free(GWDataFile
*wdata
)
809 if(wdata
->outstanding_smob
)
813 if(wdata
->wvhl
) /* nonempty list means outstanding handles remain */
817 printf("free GWDataFile 0x%x during gc\n", wdata
);
820 return sizeof(GWDataFile
);
823 /* standard SMOB functions for GWDataFile: free, mark, print, GWDataFile? */
825 free_GWDataFile(SCM obj
)
827 GWDataFile
*wdata
=GWDataFile(obj
);
828 wdata
->outstanding_smob
= 0;
829 return wavefile_try_free(wdata
);
832 static void mark_GWDataFile_wvh(void *p
, void *d
)
834 WaveVarH
*wvh
= (WaveVarH
*)p
;
836 scm_gc_mark(wvh
->smob
);
840 mark_GWDataFile(SCM obj
)
842 GWDataFile
*wdata
= GWDataFile(obj
);
843 g_slist_foreach(wdata
->wvhl
, mark_GWDataFile_wvh
, NULL
);
849 print_GWDataFile(SCM obj
, SCM port
, scm_print_state
*ARG_IGNORE(pstate
))
851 scm_puts("#<GWDataFile ", port
);
852 if(GWDataFile(obj
)->wf
)
853 scm_puts(GWDataFile(obj
)->wf
->wf_filename
, port
);
855 scm_puts("invalid", port
);
860 SCM_DEFINE(GWDataFile_p
, "GWDataFile?", 1, 0, 0,
862 "Returns #t if OBJ is a gwave data file object, otherwise #f.")
863 #define FUNC_NAME s_GWDataFile_p
865 return SCM_BOOL_FromBool(GWDataFile_P(obj
));
869 /* standard SMOB functions for WaveVar: free, mark, print, WaveVar? */
872 free_WaveVar(SCM obj
)
874 WaveVarH
*wvh
= WaveVarH(obj
);
880 printf("free_WaveVar(wvh=%lx wv=%lx)\n", wvh
, wvh
->wv
);
881 df
->wvhl
= g_slist_remove(df
->wvhl
, wvh
);
882 fsize
= wavefile_try_free(wvh
->df
);
887 return fsize
+ sizeof(WaveVarH
);
891 mark_WaveVar(SCM obj
)
897 print_WaveVar(SCM obj
, SCM port
, scm_print_state
*ARG_IGNORE(pstate
))
899 WaveVarH
*wvh
= WaveVarH(obj
);
902 scm_puts("#<WaveVar ", port
);
904 scm_puts(wvh
->df
->wf
->wf_filename
, port
);
906 sprintf(buf
, "%d", wvh
->wv
->wtable
->swindex
);
909 scm_puts(wvh
->wv
->sv
->name
, port
);
911 scm_intprint((long)wvh
->wv
, 16, port
);
913 scm_puts("invalid", port
);
919 SCM_DEFINE(WaveVar_p
, "WaveVar?", 1, 0, 0,
921 "Returns #t if OBJ is a wave-file variable object, otherwise #f.")
922 #define FUNC_NAME s_WaveVar_p
924 return SCM_BOOL_FromBool(WaveVarH_P(obj
));
928 /* guile initialization */
930 MAKE_SMOBFUNS(GWDataFile
);
931 MAKE_SMOBFUNS(WaveVar
);
935 REGISTER_SCWMSMOBFUNS(GWDataFile
);
936 REGISTER_SCWMSMOBFUNS(WaveVar
);
938 #ifndef SCM_MAGIC_SNARF_INITS
939 #include "wavelist.x"