"Fossies" - the Fresh Open Source Software Archive

Member "snd-20.9/snd-find.c" (5 Feb 2020, 6737 Bytes) of package /linux/misc/snd-20.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "snd-find.c" see the Fossies "Dox" file reference documentation.

    1 #include "snd.h"
    2 
    3 static void clear_search_state(void)
    4 {
    5   if (Xen_is_procedure(ss->search_proc)) 
    6     {
    7       snd_unprotect_at(ss->search_proc_loc);
    8       ss->search_proc_loc = NOT_A_GC_LOC;
    9     }
   10   ss->search_proc = Xen_undefined;
   11 
   12   if (ss->search_expr) free(ss->search_expr);
   13   ss->search_expr = NULL;
   14 }
   15 
   16 
   17 #if (!USE_NO_GUI)
   18 
   19 static void find_report(chan_info *cp, const char *msg)
   20 {
   21   /* msg can be NULL */
   22   if (cp)
   23     status_report(cp->sound, "%s", msg);
   24   find_dialog_set_label(msg);
   25 }
   26 
   27 
   28 static bool search_in_progress = false;
   29 static chan_info *previous_channel = NULL;
   30 #define MANY_PASSES 100000
   31 
   32 static mus_long_t channel_find_forward(chan_info *cp)
   33 {
   34   mus_long_t i, end, start;
   35 
   36   end = current_samples(cp);
   37   start = cursor_sample(cp) + 1;
   38   if (start >= end)
   39     start = 0;
   40   i = scan_channel(cp, start, end, ss->search_proc);
   41   if (i < end)
   42     return(i);
   43   return(-1);
   44 }
   45 
   46 
   47 static mus_long_t channel_find_backward(chan_info *cp)
   48 {
   49   bool reported = false;
   50   mus_long_t i, start, passes;
   51   snd_fd *sf = NULL;
   52   Xen res;
   53 
   54   start = cursor_sample(cp) - 1;
   55   if (start < 0)
   56     start = current_samples(cp) - 1;
   57 
   58   sf = init_sample_read(start, cp, READ_BACKWARD);
   59   if (!sf)
   60     return(-1);
   61 
   62   ss->stopped_explicitly = false;
   63   for (i = start, passes = 0; i >= 0; i--, passes++)
   64     {
   65       res = Xen_call_with_1_arg(ss->search_proc, 
   66                 C_double_to_Xen_real((double)(read_sample(sf))), 
   67                 "search function");
   68       if (!Xen_is_false(res)) 
   69     break;
   70       if (passes >= MANY_PASSES)
   71     {
   72       passes = 0;
   73       check_for_event();
   74       if (!(ss->stopped_explicitly))
   75         {
   76           char *msg;
   77           msg = mus_format("search at minute %d", (int)floor(i / (snd_srate(cp->sound) * 60)));
   78           find_report(cp, msg);
   79           free(msg);
   80           reported = true;
   81         }
   82       /* if user types C-s during an active search, we risk stomping on our current pointers */
   83       if (!(cp->sound->active)) break;
   84     }
   85       if (ss->stopped_explicitly) break;
   86     }
   87 
   88   ss->stopped_explicitly = false;
   89   if (reported) find_report(cp, NULL);
   90   free_snd_fd(sf);
   91 
   92   if (i >= 0)
   93     return(i);
   94   return(-1);
   95 }
   96 
   97 
   98 static char *channel_search(chan_info *cp, read_direction_t direction)
   99 {
  100   mus_long_t samp;
  101   char *s1, *s2, *msg;
  102 
  103   if (direction == READ_FORWARD)
  104     samp = channel_find_forward(cp);
  105   else samp = channel_find_backward(cp);
  106   
  107   previous_channel = cp;
  108 
  109   if (samp == -1)
  110     return(NULL);
  111 
  112   s1 = prettyf(chn_sample(samp, cp, cp->edit_ctr), 2);
  113   s2 = x_axis_location_to_string(cp, (double)samp / (double)snd_srate(cp->sound));
  114   msg = mus_format("%s at %s (%" print_mus_long ")", s1, s2, samp);
  115   cursor_moveto_without_verbosity(cp, samp);
  116   free(s1);
  117   free(s2);
  118 
  119   return(msg);
  120 }
  121 
  122 
  123 static char *global_search(read_direction_t direction, bool repeating)
  124 {
  125   int i;
  126 
  127   if ((repeating) &&
  128       ((!previous_channel) ||
  129        (!(previous_channel->sound)) ||
  130        (!(previous_channel->sound->active))))
  131     repeating = false;
  132        
  133   for (i = 0; i < ss->max_sounds; i++)
  134     {
  135       snd_info *sp;
  136       uint32_t j;
  137       sp = ss->sounds[i];
  138       if ((sp) &&
  139       (sp->inuse == SOUND_NORMAL))
  140     for (j = 0; j < sp->nchans; j++)
  141       {
  142         chan_info *cp;
  143         cp = (chan_info *)(sp->chans[j]);
  144         if ((!repeating) ||
  145         (cp == previous_channel))
  146           {
  147         char *msg;
  148         repeating = false; /* after we find the channel, look at everything */
  149         msg = channel_search(cp, direction);
  150         if (msg)
  151           return(msg);
  152           }
  153       }
  154     }
  155   return(NULL);
  156 }
  157 
  158 
  159 #if HAVE_EXTENSION_LANGUAGE
  160 void find_dialog_find(char *str, read_direction_t direction, chan_info *cp)
  161 {
  162   Xen proc;
  163   bool repeating_search = false;
  164 
  165   if (search_in_progress) 
  166     {
  167       find_report(cp, "search already in progress");
  168       return;
  169     }
  170 
  171   proc = Xen_false;
  172 
  173   /* str can be null, or equal to the previous call's str -- in this case use
  174    *   the current search procedure if possible, else complain.
  175    * if str not null, make a new (local?) search-procedure
  176    */
  177 
  178   if ((!str) || 
  179       (!(*str)) ||
  180       (mus_strcmp(str, ss->search_expr)))
  181     {
  182       proc = ss->search_proc;
  183       if (!(Xen_is_procedure(proc)))
  184     return;
  185       repeating_search = true;
  186     }
  187   else
  188     {
  189       char *buf = NULL;
  190 
  191       redirect_errors_to(errors_to_find_text, NULL);
  192       proc = snd_catch_any(eval_str_wrapper, str, str);
  193       redirect_errors_to(NULL, NULL);
  194 
  195       if ((!(Xen_is_procedure(proc))) ||
  196       (!(procedure_arity_ok(proc, 1))))
  197     return;
  198 
  199       clear_search_state(); /* free previous, if any */
  200       repeating_search = false;
  201 
  202       ss->search_proc = proc;
  203       ss->search_expr = mus_strdup(str);
  204       ss->search_proc_loc = snd_protect(proc);
  205 
  206       buf = (char *)calloc(PRINT_BUFFER_SIZE, sizeof(char));
  207       snprintf(buf, PRINT_BUFFER_SIZE, "%s %s", I_find, str);
  208       find_dialog_set_label(buf);
  209       free(buf);
  210     }
  211 
  212   /* now we have a search procedure, possibly optimized */
  213 
  214   search_in_progress = true;
  215   find_dialog_stop_label(true);
  216   redirect_xen_error_to(stop_search_if_error, NULL);
  217   if (cp)
  218     str = channel_search(cp, direction);
  219   else str = global_search(direction, repeating_search);
  220   redirect_xen_error_to(NULL, NULL);
  221   find_dialog_stop_label(false);
  222   search_in_progress = false;
  223 
  224   if ((str) && (*str)) 
  225     {
  226       find_report(cp, str);
  227       free(str);
  228     }
  229   else find_report(cp, "not found");
  230 }
  231 #endif
  232 #endif
  233 /* end no gui */
  234 
  235 
  236 
  237 /* -------------------------------------------------------------------------------- */
  238 
  239 static Xen g_search_procedure(void)
  240 {
  241   #define H_search_procedure "(" S_search_procedure "): the function used by the find dialog or C-s if none is otherwise specified."
  242   return(ss->search_proc);
  243 }
  244 
  245 
  246 static Xen g_set_search_procedure(Xen proc)
  247 {
  248   char *error = NULL;
  249   /* (set! (search-procedure) (lambda (y) #t)) -> #<procedure #f ((n) #t)> */
  250   
  251   Xen_check_type(Xen_is_procedure(proc) || Xen_is_false(proc), proc, 1, S_set S_search_procedure, "a procedure or " PROC_FALSE);
  252 
  253   error = procedure_ok(proc, 1, S_search_procedure, "search", 1);
  254   if (!error)
  255     {
  256       clear_search_state();
  257       if (Xen_is_procedure(proc))
  258     {
  259       ss->search_proc = proc;
  260       ss->search_proc_loc = snd_protect(proc);
  261     }
  262     }
  263   else 
  264     {
  265       Xen errstr;
  266       errstr = C_string_to_Xen_string(error);
  267       free(error);
  268       return(snd_bad_arity_error(S_set S_search_procedure, errstr, proc));
  269     }
  270   return(proc);
  271 }
  272 
  273 
  274 Xen_wrap_no_args(g_search_procedure_w, g_search_procedure)
  275 Xen_wrap_1_arg(g_set_search_procedure_w, g_set_search_procedure)
  276 
  277 void g_init_find(void)
  278 {
  279   Xen_define_typed_dilambda(S_search_procedure, g_search_procedure_w, H_search_procedure,
  280                 S_set S_search_procedure, g_set_search_procedure_w,  0, 0, 1, 0,
  281                 s7_make_circular_signature(s7, 0, 1, s7_t(s7)), s7_make_circular_signature(s7, 0, 1, s7_t(s7)));
  282 }