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 void gwfile_add_wv_to_list(gpointer d
/*WaveVar* */,
54 gpointer p
/*GWDataFile */);
56 void wavelist_button_click(GtkWidget
*widget
,
57 GdkEventButton
*event
, gpointer data
);
59 XSCM_HOOK(new_wavefile_hook
,"new-wavefile-hook", 1, (SCM DF
),
60 "This hook is invoked when a new waveform file is successfully loaded."
61 "It is called with the new GWDataFile, DF, as its only argument.");
63 XSCM_HOOK(new_wavelist_hook
,"new-wavelist-hook", 1, (SCM DF
),
64 "This hook is invoked when the variable list window for a"
65 "GWDataFile is created. The GWDataFile object, DF, is passed as an"
66 "argument. Note that variable-list windows can be created and"
67 "destroyed many times during the life of a GWDataFile. One of the principle"
68 "uses of this hook is creating the menus such for the variable-list window.");
71 * Load a waveform file, adding it to the list of files from which
72 * variables can be chosen to add to the display.
75 load_wave_file(char *fname
, char *ftype
)
79 wdata
= g_new0(GWDataFile
, 1);
80 wdata
->wf
= wf_read(fname
, ftype
);
82 if(wdata
->wf
== NULL
) {
86 wdata
->wf
->udata
= wdata
;
88 /* give the file a short (fow now, 1-character) "tag" to identify it
89 * in the menu and variable labels.
91 wdata
->ftag
= g_new(char, 2);
92 wdata
->ftag
[0] = file_tag_chars
[next_file_tagno
];
93 wdata
->ftag
[1] = '\0';
94 next_file_tagno
= (next_file_tagno
+ 1) % n_file_tags
;
95 wdata
->ndv
= wdata
->wf
->wf_ndv
;
96 wdata
->wvhl
= NULL
; /* empty GSList of WaveVarH* */
98 wdata_list
= g_list_append(wdata_list
, wdata
);
99 wdata
->outstanding_smob
= 1;
100 SGT_NEWCELL_SMOB(wdata
->smob
, GWDataFile
, wdata
);
101 call1_hooks(new_wavefile_hook
, wdata
->smob
);
104 cmd_show_wave_list(NULL
, wdata
);
109 SCM_DEFINE(load_wavefile_x
, "load-wavefile!", 1, 1, 0, (SCM file
, SCM filetype
),
110 "Load waveform data from FILE into memory, and make it available for"
111 "display. If FILETYPE is specified, it indicates the format of the file"
112 "and which wavefile reader to use, otherwise the format is inferred"
113 "from the filename and file contents. Returns a GWDataFile object"
114 "which can be used to refer to the loaded data.")
115 #define FUNC_NAME s_load_wavefile_x
120 VALIDATE_ARG_STR_NEWCOPY(1, file
, fname
);
121 VALIDATE_ARG_STR_NEWCOPY_USE_NULL(2, filetype
, ftype
);
122 df
= load_wave_file(fname
, ftype
);
134 * Delete a wave file.
135 * callback from menu: wavelist->file->delete
138 delete_wave_file(GtkWidget
*w
, GWDataFile
*wdata
)
141 /* remove references from displayed waves */
142 remove_wfile_waves(wdata
);
144 /* remove per-file GUI stuff */
145 if(wdata
->wlist_win
&& GTK_WIDGET_VISIBLE(wdata
->wlist_win
))
146 gtk_widget_destroy(wdata
->wlist_win
);
148 /* invalidate WaveVar pointers in handles.
149 * Can't free WaveVar because un-GCed smobs may point to them
151 for(list
= wdata
->wvhl
; list
; list
= list
->next
) {
152 WaveVarH
*wvh
= (WaveVarH
*)list
->data
;
156 /* now nuke the data */
159 wdata_list
= g_list_remove(wdata_list
, wdata
);
161 if(wdata
->outstanding_smob
) {
163 fprintf(stderr
, "defering free of GWDataFile\n");
166 fprintf(stderr
, "free GWDataFile 0x%x\n", wdata
);
171 SCM_DEFINE(datafile_delete_x
, "wavefile-delete!", 1, 0, 0,
173 "Delete from memory the waveform data from OBJ.")
174 #define FUNC_NAME s_datafile_delete_x
177 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
180 delete_wave_file(NULL
, wdata
);
181 return SCM_UNSPECIFIED
;
186 * command or callback from menu: wavelist->file->reload
189 reload_wave_file(GtkWidget
*w
, GWDataFile
*wdata
)
194 /* FIXME:sgt: get file type from old file, if it was specified
195 * when loading it originaly
197 new_wf
= wf_read(wdata
->wf
->wf_filename
, NULL
);
199 fprintf(stderr
, "reload_wave_file: failed to read %s\n", wdata
->wf
->wf_filename
);
200 /* FIXME:sgt put up error message in window */
205 wdata
->wf
->udata
= wdata
;
206 /* printf("reload_wave_file(%s) old=%lx new=%lx\n",
207 wdata->wf->wf_filename, old_wf, new_wf); */
209 update_wfile_waves(wdata
);
211 /* remove old buttons from list, and add new ones */
212 if(wdata
->wlist_win
&& GTK_WIDGET_VISIBLE(wdata
->wlist_win
)) {
213 gtk_container_foreach(GTK_CONTAINER(wdata
->wlist_box
),
214 (GtkCallback
) gtk_widget_destroy
, NULL
);
215 wf_foreach_wavevar(wdata
->wf
, gwfile_add_wv_to_list
, (gpointer
)wdata
);
223 reload_wave_file_w(gpointer p
, gpointer d
)
225 GWDataFile
*wdata
= (GWDataFile
*)p
;
226 reload_wave_file(NULL
, wdata
);
231 * plan: replace this with update_all_wave_files(), which checks
232 * file dates/sizes and only reloads those that need it.
235 reload_all_wave_files(GtkWidget
*w
)
237 g_list_foreach(wdata_list
, reload_wave_file_w
, NULL
);
240 SCM_DEFINE(reload_all_files_x
, "reload-all-files!", 0, 0, 0, (),
242 #define FUNC_NAME s_reload_all_files_x
244 g_list_foreach(wdata_list
, reload_wave_file_w
, NULL
);
245 return SCM_UNSPECIFIED
;
249 SCM_DEFINE(datafile_reload_x
, "wavefile-reload!", 1, 0, 0,
251 "Reread the data file for OBJ. Useful for updating the display"
252 " after simulation has been rerun.")
253 #define FUNC_NAME s_datafile_reload_x
256 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
259 reload_wave_file(NULL
, wdata
);
260 return SCM_UNSPECIFIED
;
265 * Callback for use with wv_foreach_wavevar:
267 * Add a button for each variable in the file to the win_wlist box for it.
268 * Arrange for the buttons to be drag-and-drop sources for placing the
269 * variables into wavepanels.
271 * formerly add_variables_to_list(GWDataFile *wdata)
274 gwfile_add_wv_to_list(gpointer d
, gpointer p
)
276 WaveVar
*wv
= (WaveVar
*)d
;
277 GWDataFile
*wdata
= (GWDataFile
*)p
;
280 if(wv_is_multisweep(wv
)) {
282 sprintf(lab
, "%s @ %s=%g", wv
->wv_name
,
283 wv
->wtable
->name
, wv
->wtable
->swval
);
284 button
= gtk_button_new_with_label(lab
);
286 button
= gtk_button_new_with_label(wv
->wv_name
);
289 gtk_box_pack_start (GTK_BOX (wdata
->wlist_box
), button
, FALSE
, FALSE
, 0);
290 gtk_widget_show (button
);
292 if(GTK_IS_TOOLTIPS(wtable
->ttips
))
293 gtk_tooltips_set_tip(GTK_TOOLTIPS(wtable
->ttips
), button
,
294 "Wavefile Variable.\nDrag-and-Drop to a WavePanel.", "");
296 dnd_setup_source(GTK_WINDOW(wdata
->wlist_win
), button
, wv
);
298 gtk_signal_connect (GTK_OBJECT(button
), "button-press-event",
299 GTK_SIGNAL_FUNC(wavelist_button_click
),
304 * Show the variable-list window for a waveform data file.
305 * If the window already exists, simply raise it to the top.
308 cmd_show_wave_list(GtkWidget
*w
, GWDataFile
*wdata
)
311 GtkWidget
*scrolled_window
;
315 fprintf(stderr
, "cmd_show_wave_list: wdata is NULL");
319 if(!wdata
->wlist_win
) {
322 wdata
->wlist_win
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
323 gtk_widget_set_name(wdata
->wlist_win
, "data list window");
324 sprintf(buf
, "gwave: %.64s", wdata
->wf
->wf_filename
);
325 gtk_window_set_title(GTK_WINDOW(wdata
->wlist_win
), buf
);
326 gtk_widget_set_usize(wdata
->wlist_win
, 150, 300);
327 { /* suggest that the window manager try to put the wavelist
328 * window somewhere to the left of the main window.
329 * This nonsense really belongs in a smarter window manager,
330 * but users are demanding somthing.
337 && wtable
->window
&& wtable
->window
->window
) {
338 gdk_window_get_position(wtable
->window
->window
,
342 diddle
= (diddle
+ 1) % 4;
344 gtk_widget_set_uposition(wdata
->wlist_win
, x
-175, y
);
346 gtk_signal_connect (GTK_OBJECT (wdata
->wlist_win
), "destroy",
347 GTK_SIGNAL_FUNC(gtk_widget_destroyed
),
348 &(wdata
->wlist_win
));
350 box1
= gtk_vbox_new(FALSE
, 0);
351 gtk_container_add(GTK_CONTAINER(wdata
->wlist_win
), box1
);
352 gtk_widget_show(box1
);
353 wdata
->wlist_menubar
= gtk_menu_bar_new();
354 gtk_widget_show(wdata
->wlist_menubar
);
355 gtk_box_pack_start (GTK_BOX (box1
), wdata
->wlist_menubar
, FALSE
, FALSE
, 0);
357 if(strlen(wdata
->wf
->wf_filename
) > 16) {
358 char *cp
= strrchr(wdata
->wf
->wf_filename
, '/');
360 sprintf(buf
, "%s: .../%.64s", wdata
->ftag
, cp
+1);
362 sprintf(buf
, "%s: .../%.64s", wdata
->ftag
, wdata
->wf
->wf_filename
);
364 sprintf(buf
, "%s: %.64s", wdata
->ftag
, wdata
->wf
->wf_filename
);
366 label
= gtk_label_new(buf
);
367 gtk_label_set_justify(GTK_LABEL(label
), GTK_JUSTIFY_LEFT
);
368 gtk_widget_show(label
);
369 gtk_box_pack_start (GTK_BOX (box1
), label
, FALSE
, FALSE
, 0);
373 scrolled_window
= gtk_scrolled_window_new (NULL
, NULL
);
374 gtk_container_border_width (GTK_CONTAINER (scrolled_window
), 10);
375 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window
),
376 GTK_POLICY_AUTOMATIC
,
378 GTK_WIDGET_UNSET_FLAGS (GTK_SCROLLED_WINDOW (scrolled_window
)->vscrollbar
, GTK_CAN_FOCUS
);
379 gtk_box_pack_start(GTK_BOX (box1
), scrolled_window
,
381 gtk_widget_show (scrolled_window
);
383 wdata
->wlist_box
= gtk_vbox_new (FALSE
, 0);
384 gtk_container_border_width (GTK_CONTAINER (wdata
->wlist_box
), 10);
385 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window
),
387 gtk_container_set_focus_vadjustment(
388 GTK_CONTAINER (wdata
->wlist_box
),
389 gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window
)));
390 gtk_widget_show (wdata
->wlist_box
);
392 dnd_init(wdata
->wlist_win
);
393 wf_foreach_wavevar(wdata
->wf
, gwfile_add_wv_to_list
, (gpointer
)wdata
);
395 call1_hooks(new_wavelist_hook
, wdata
->smob
);
397 gtk_widget_show(wdata
->wlist_win
);
399 gdk_window_raise(wdata
->wlist_win
->window
);
404 * Called for all button presses on wavelist button.
405 * If it is a doubleclick, add variable to the "current" wavepanel immediately.
408 wavelist_button_click(GtkWidget
*widget
,
409 GdkEventButton
*bevent
,
412 WaveVar
*dv
= (WaveVar
*)data
;
413 if(bevent
->type
== GDK_2BUTTON_PRESS
) {
414 /* printf("doubleclicked %s %s\n", dv->wfile->ss->filename,
416 add_var_to_panel(NULL
, dv
);
420 SCM_DEFINE(wavefile_show_listwin_x
, "wavefile-show-listwin!", 1, 0, 0,
422 "Displays the scrolling list of the variables in OBJ, from which they"
423 "can be dragged into a waveform display panel.")
424 #define FUNC_NAME s_wavefile_show_listwin_x
427 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
430 fprintf(stderr
, "%s wdata=0x%x\n", FUNC_NAME
, wdata
);
432 cmd_show_wave_list(NULL
, wdata
);
433 return SCM_UNSPECIFIED
;
438 /* maybe I should just expose the GTkWindow itself, and destroy from guile */
439 SCM_DEFINE(wavefile_remove_listwin_x
, "wavefile-remove-listwin!", 1, 0, 0,
441 "Removes the variable-list window for OBJ")
442 #define FUNC_NAME s_wavefile_remove_listwin_x
445 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
447 if(wdata
->wf
&& wdata
->wlist_win
)
448 gtk_widget_destroy(wdata
->wlist_win
);
449 return SCM_UNSPECIFIED
;
454 /* Primitives for accessing GWDataFile info from scheme */
456 SCM_DEFINE(wavefile_file_name
, "wavefile-file-name", 1, 0, 0,
458 "Returns the filename from which the GWDataFile OBJ was loaded."
459 "If OBJ is invalid because the datafile has been deleted,"
461 #define FUNC_NAME s_wavefile_file_name
464 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
467 return scm_makfrom0str(wdata
->wf
->wf_filename
);
474 SCM_DEFINE(wavefile_nsweeps
, "wavefile-nsweeps", 1, 0, 0,
476 "Returns the number of sweeps for which data is present in GWDataFile DF.")
477 #define FUNC_NAME s_wavefile_nsweeps
480 VALIDATE_ARG_GWDataFile_COPY(1, df
, wdata
);
482 return scm_long2num(wdata
->wf
->wf_ntables
);
486 SCM_DEFINE(wavefile_sweeps
, "wavefile-sweeps", 1, 0, 0,
488 "Returns a list of sweeps contained in GWDataFile DF. Each element of the list is a pair, of the form (sweepname . sweepvalue)")
489 #define FUNC_NAME s_wavefile_nsweeps
492 SCM result
= SCM_EOL
;
497 VALIDATE_ARG_GWDataFile_COPY(1, df
, wdata
);
503 for(i
= 0; i
< wf
->wf_ntables
; i
++) {
504 wt
= wf_wtable(wf
, i
);
505 p
= scm_cons(scm_makfrom0str(wt
->name
), scm_make_real(wt
->swval
));
506 result
= scm_cons(p
, result
);
508 return scm_reverse(result
);
512 SCM_DEFINE(wavefile_tag
, "wavefile-tag", 1, 0, 0,
514 "Returns the short identifying tag for the GWDataFile OBJ.")
515 #define FUNC_NAME s_wavefile_tag
518 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
520 return scm_makfrom0str(wdata
->ftag
);
524 SCM_DEFINE(wavefile_set_tag_x
, "wavefile-set-tag!", 2, 0, 0,
526 "Set the short identifying tag for the GWDataFile OBJ to STR.")
527 #define FUNC_NAME s_wavefile_set_tag_x
531 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
532 VALIDATE_ARG_STR_NEWCOPY(1, str
, s
);
535 return SCM_UNSPECIFIED
;
536 /* BUG: any visiblewave button labels and wavelist menu entries
537 * won't be affected by the change in ftag */
541 SCM_DEFINE(wavefile_listwin_menubar
, "wavefile-listwin-menubar", 1, 0, 0,
543 "Returns the GTK Menubar for the variable-list window of the"
544 " * GWDataFile OBJ, or #f if the window doesn't exist.")
545 #define FUNC_NAME s_wavefile_listwin_menubar
548 VALIDATE_ARG_GWDataFile_COPY(1, obj
, wdata
);
550 if(wdata
->wlist_win
&& wdata
->wlist_menubar
)
551 return scm_c_gtype_instance_to_scm(GTK_OBJECT(wdata
->wlist_menubar
));
558 wavefile_to_scm(void *vp
)
560 GWDataFile
*wdata
= (GWDataFile
*)vp
;
565 glist2scm(GList
*list
, SCM (*toscm
)(void*))
567 SCM result
= SCM_EOL
;
569 result
= scm_cons(toscm(list
->data
), result
);
575 SCM_DEFINE(wavefile_list
, "wavefile-list", 0, 0, 0, (),
576 "Returns a list containing all waveform data files")
577 #define FUNC_NAME s_wavefile_list
579 return glist2scm(wdata_list
, wavefile_to_scm
);
584 SCM_DEFINE(wavefile_all_variables
, "wavefile-all-variables", 1, 0, 0, (SCM df
),
585 "Returns a list of WaveVars, composed of all variables in the GWDataFile DF.")
586 #define FUNC_NAME s_wavefile_all_variables
589 SCM result
= SCM_EOL
;
595 VALIDATE_ARG_GWDataFile_COPY(1, df
, wdata
);
601 for(i
= 0; i
< wf
->wf_ntables
; i
++) {
602 wt
= wf_wtable(wf
, i
);
603 for(j
= 0; j
< wf
->wf_ndv
; j
++) {
608 wvh
= g_new0(WaveVarH
, 1);
612 wdata
->wvhl
= g_slist_prepend(wdata
->wvhl
, wvh
);
613 SGT_NEWCELL_SMOB(wvsmob
, WaveVar
, wvh
);
616 wvh
= (WaveVarH
*)wv
->udata
;
619 result
= scm_cons(wvsmob
, result
);
622 return scm_reverse(result
);
627 SCM_DEFINE(wavefile_variable
, "wavefile-variable", 3, 0, 0,
628 (SCM df
, SCM vname
, SCM swindex
),
629 "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")
630 #define FUNC_NAME s_wavefile_variable
633 SCM result
= SCM_BOOL_F
;
636 VALIDATE_ARG_GWDataFile_COPY(1, df
, wdata
);
637 VALIDATE_ARG_STR_NEWCOPY(2, vname
, s
);
638 VALIDATE_ARG_INT_MIN_COPY(3, swindex
, 0, swp
);
640 if(wdata
->wf
&& swp
< wdata
->wf
->wf_ntables
) {
641 WaveVar
*wv
= wf_find_variable(wdata
->wf
, s
, swp
);
645 wvh
= g_new0(WaveVarH
, 1);
649 wdata
->wvhl
= g_slist_prepend(wdata
->wvhl
, wvh
);
650 SGT_NEWCELL_SMOB(result
, WaveVar
, wvh
);
653 wvh
= (WaveVarH
*)wv
->udata
;
663 SCM_DEFINE(variable_signame
, "variable-signame", 1, 0, 0,
665 "Return the signal name for the variable VAR.")
666 #define FUNC_NAME s_variable_signame
669 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var
,wv
);
672 return scm_makfrom0str(wv
->sv
->name
);
679 SCM_DEFINE(variable_sweepname
, "variable-sweepname", 1, 0, 0,
681 "Return the sweep name or table name for the variable VAR.")
682 #define FUNC_NAME s_variable_sweepname
685 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var
,wv
);
688 return scm_makfrom0str(wv
->wtable
->name
);
695 SCM_DEFINE(variable_sweepindex
, "variable-sweepindex", 1, 0, 0,
697 "Return the sweep table index for the variable VAR. Sweeps/tables are numbered starting with 0. ")
698 #define FUNC_NAME s_variable_sweepindex
701 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var
,wv
);
704 return scm_long2num(wv
->wtable
->swindex
);
711 SCM_DEFINE(variable_wavefile
, "variable-wavefile", 1, 0, 0,
713 "Return the WaveFile that the variable VAR is contained in.")
714 // Really, the GWDataFile smob.
715 #define FUNC_NAME s_variable_wavefile
718 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,var
,wv
);
721 GWDataFile
*df
= wvar_gwdatafile(wv
);
722 df
->outstanding_smob
= 1;
729 SCM_DEFINE(export_variables
, "export-variables", 2, 2, 0,
730 (SCM varlist
, SCM port
, SCM from
, SCM to
),
731 "Write the data for all variables in VARLIST to PORT in tabular ascii form"
732 "If FROM and TO are specified, writes only data points for which the"
733 "independent variable is between FROM and TO includsive."
734 "All variables in VARLIST must share the same independent variable")
735 #define FUNC_NAME s_export_variables
740 double from_val
, to_val
;
745 /* validate varlist and count elements */
746 for (l
= varlist
; SCM_NNULLP(l
); l
= SCM_CDR (l
)) {
748 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,v
,wv
);
750 scm_misc_error(FUNC_NAME
, "invalid WaveVar ~s", SCM_LIST1(v
));
754 else if(iv
!= wv
->wv_iv
) {
755 scm_misc_error(FUNC_NAME
, "All WaveVars in VARLIST must relate to the same independent variable", SCM_UNDEFINED
);
758 VALIDATE_ARG_DBL_COPY_USE_DEF(3,from
,from_val
, iv
->wds
[0].min
);
759 VALIDATE_ARG_DBL_COPY_USE_DEF(4,to
,to_val
, iv
->wds
[0].max
);
761 if(from_val
> to_val
)
762 return SCM_UNSPECIFIED
;
763 starti
= wf_find_point(iv
, from_val
);
764 endi
= wf_find_point(iv
, to_val
);
766 for(i
= starti
; i
<= endi
; i
++) {
767 x
= wds_get_point(&iv
->wds
[0], i
);
768 sprintf(buf
, "%g", x
);
770 for (l
= varlist
; SCM_NNULLP(l
); l
= SCM_CDR (l
)) {
772 VALIDATE_ARG_VisibleWaveOrWaveVar_COPY(1,v
,wv
);
773 g_assert(wv
); /* should have been checked above */
774 y
= wds_get_point(&wv
->wds
[0], i
);
775 sprintf(buf
, " %g", y
);
778 scm_puts("\n", port
);
781 return SCM_UNSPECIFIED
;
786 * On the C side we never free WaveVars without freeing the whole
787 * WaveFile structure. When guile GC's one, we invalidate the pointer
788 * in the handle, and then check to see if we can dump the whole
790 * Methinks we need a more formal reference-counting scheme instead of
791 * all this ad-hockery.
793 int wavefile_try_free(GWDataFile
*wdata
)
796 if(wdata
->outstanding_smob
)
800 if(wdata
->wvhl
) /* nonempty list means outstanding handles remain */
804 printf("free GWDataFile 0x%x during gc\n", wdata
);
807 return sizeof(GWDataFile
);
810 /* standard SMOB functions for GWDataFile: free, mark, print, GWDataFile? */
812 free_GWDataFile(SCM obj
)
814 GWDataFile
*wdata
=GWDataFile(obj
);
815 wdata
->outstanding_smob
= 0;
816 return wavefile_try_free(wdata
);
819 static void mark_GWDataFile_wvh(void *p
, void *d
)
821 WaveVarH
*wvh
= (WaveVarH
*)p
;
823 scm_gc_mark(wvh
->smob
);
827 mark_GWDataFile(SCM obj
)
829 GWDataFile
*wdata
= GWDataFile(obj
);
830 g_slist_foreach(wdata
->wvhl
, mark_GWDataFile_wvh
, NULL
);
836 print_GWDataFile(SCM obj
, SCM port
, scm_print_state
*ARG_IGNORE(pstate
))
838 scm_puts("#<GWDataFile ", port
);
839 if(GWDataFile(obj
)->wf
)
840 scm_puts(GWDataFile(obj
)->wf
->wf_filename
, port
);
842 scm_puts("invalid", port
);
847 SCM_DEFINE(GWDataFile_p
, "GWDataFile?", 1, 0, 0,
849 "Returns #t if OBJ is a gwave data file object, otherwise #f.")
850 #define FUNC_NAME s_GWDataFile_p
852 return SCM_BOOL_FromBool(GWDataFile_P(obj
));
856 /* standard SMOB functions for WaveVar: free, mark, print, WaveVar? */
859 free_WaveVar(SCM obj
)
861 WaveVarH
*wvh
= WaveVarH(obj
);
867 printf("free_WaveVar(wvh=%lx wv=%lx)\n", wvh
, wvh
->wv
);
868 df
->wvhl
= g_slist_remove(df
->wvhl
, wvh
);
869 fsize
= wavefile_try_free(wvh
->df
);
874 return fsize
+ sizeof(WaveVarH
);
878 mark_WaveVar(SCM obj
)
884 print_WaveVar(SCM obj
, SCM port
, scm_print_state
*ARG_IGNORE(pstate
))
886 WaveVarH
*wvh
= WaveVarH(obj
);
889 scm_puts("#<WaveVar ", port
);
891 scm_puts(wvh
->df
->wf
->wf_filename
, port
);
893 sprintf(buf
, "%d", wvh
->wv
->wtable
->swindex
);
896 scm_puts(wvh
->wv
->sv
->name
, port
);
898 scm_intprint((long)wvh
->wv
, 16, port
);
900 scm_puts("invalid", port
);
906 SCM_DEFINE(WaveVar_p
, "WaveVar?", 1, 0, 0,
908 "Returns #t if OBJ is a wave-file variable object, otherwise #f.")
909 #define FUNC_NAME s_WaveVar_p
911 return SCM_BOOL_FromBool(WaveVarH_P(obj
));
915 /* guile initialization */
917 MAKE_SMOBFUNS(GWDataFile
);
918 MAKE_SMOBFUNS(WaveVar
);
922 REGISTER_SCWMSMOBFUNS(GWDataFile
);
923 REGISTER_SCWMSMOBFUNS(WaveVar
);
925 #ifndef SCM_MAGIC_SNARF_INITS
926 #include "wavelist.x"