Exemple #1
0
/**
 * Read a filename from the file descriptor and create a file_info struct.
 *
 * @return A file_info struct or NULL if there is nothing to read.
 */
static struct file_info *
file_info_get(const char *root, int fd)
{
  static struct varbuf fn = VARBUF_INIT;
  struct file_info *fi;
  size_t root_len;

  varbuf_reset(&fn);
  root_len = varbuf_printf(&fn, "%s/", root);

  while (1) {
    int res;

    varbuf_grow(&fn, 1);
    res = fd_read(fd, (fn.buf + fn.used), 1);
    if (res < 0)
      return NULL;
    if (res == 0) /* EOF -> parent died. */
      return NULL;
    if (fn.buf[fn.used] == '\0')
      break;

    varbuf_trunc(&fn, fn.used + 1);
    if (fn.used >= MAXFILENAME)
      ohshit(_("file name '%.50s...' is too long"), fn.buf + root_len);
  }

  fi = file_info_new(fn.buf + root_len);
  if (lstat(fn.buf, &(fi->st)) != 0)
    ohshite(_("unable to stat file name '%.250s'"), fn.buf);

  return fi;
}
static void
get_folder_content_for_each_child_cb (GFile     *file,
				      GFileInfo *info,
				      gpointer   user_data)
{
	LoadData *load_data = user_data;
	FileInfo *file_info;

	file_info = file_info_new (file, info);
	load_data->files = g_list_prepend (load_data->files, file_info);
}
/*
 * Read the next filename from a filedescriptor and create a file_info struct
 * for it. If there is nothing to read return NULL.
 */
static struct file_info *
getfi(const char *root, int fd)
{
  static char* fn = NULL;
  static size_t fnlen = 0;
  size_t i= 0;
  struct file_info *fi;
  size_t rl = strlen(root);

  if (fn == NULL) {
    fnlen = rl + MAXFILENAME;
    fn = m_malloc(fnlen);
  } else if (fnlen < (rl + MAXFILENAME)) {
    fnlen = rl + MAXFILENAME;
    fn = m_realloc(fn, fnlen);
  }
  i=sprintf(fn,"%s/",root);
  
  while (1) {
    int	res;
    if (i>=fnlen) {
      fnlen += MAXFILENAME;
      fn = m_realloc(fn, fnlen);
    }
    if ((res=read(fd, (fn+i), sizeof(*fn)))<0) {
      if ((errno==EINTR) || (errno==EAGAIN))
	continue;
      else
	return NULL;
    }
    if (res==0)	// EOF -> parent died
      return NULL;
    if (fn[i] == '\0')
      break;

    i++;

    if (i >= MAXFILENAME)
      ohshit(_("file name '%.50s...' is too long"), fn + rl + 1);
  }

  fi = file_info_new(fn + rl + 1);
  lstat(fn, &(fi->st));

  return fi;
}
Exemple #4
0
static void
file_treewalk_feed(const char *dir, int fd_out)
{
  struct treeroot *tree;
  struct treenode *node;
  struct file_info *fi;
  struct file_info *symlist = NULL;
  struct file_info *symlist_end = NULL;

  tree = treewalk_open(dir, TREEWALK_NONE, NULL);
  for (node = treewalk_node(tree); node ; node = treewalk_next(tree)) {
    const char *virtname = treenode_get_virtname(node);
    char *nodename;

    if (strncmp(virtname, BUILDCONTROLDIR, strlen(BUILDCONTROLDIR)) == 0)
      continue;

    nodename = str_fmt("./%s", virtname);

    if (strchr(nodename, '\n'))
      ohshit(_("newline not allowed in pathname '%s'"), nodename);

    /* We need to reorder the files so we can make sure that symlinks
     * will not appear before their target. */
    if (S_ISLNK(treenode_get_mode(node))) {
      fi = file_info_new(nodename);
      file_info_list_append(&symlist, &symlist_end, fi);
    } else {
      if (fd_write(fd_out, nodename, strlen(nodename) + 1) < 0)
        ohshite(_("failed to write filename to tar pipe (%s)"),
                _("data member"));
    }

    free(nodename);
  }
  treewalk_close(tree);

  for (fi = symlist; fi; fi = fi->next)
    if (fd_write(fd_out, fi->fn, strlen(fi->fn) + 1) < 0)
      ohshite(_("failed to write filename to tar pipe (%s)"), _("data member"));

  file_info_list_free(symlist);
}
Exemple #5
0
int ms_audio_diff(const char *file1, const char *file2, double *ret, int max_shift_percent, MSAudioDiffProgressNotify func, void *user_data){
	FileInfo *fi1,*fi2;
	int64_t *xcorr;
	int xcorr_size;
	int max_shift_samples;
	int max_index_r;
	int max_index_l;
	double max_r, max_l;

	*ret=0;

	fi1=file_info_new(file1);
	if (fi1==NULL) return 0;
	fi2=file_info_new(file2);
	if (fi2==NULL){
		file_info_destroy(fi1);
		return -1;
	}

	if (fi1->rate!=fi2->rate){
		ms_error("Comparing files of different sampling rates is not supported (%d vs %d)", fi1->rate, fi2->rate);
		return -1;
	}

	if (fi1->nchannels!=fi2->nchannels){
		ms_error("Comparing files with different number of channels is not supported (%d vs %d)", fi1->nchannels, fi2->nchannels);
		return -1;
	}

	file_info_compute_energy(fi1);
	file_info_compute_energy(fi2);

	if (fi1->energy_r==0 || fi2->energy_r==0){
		/*avoid division by zero*/
		ms_error("One of the two files is pure silence.");
		return -1;
	}

	max_shift_samples = MIN(fi1->nsamples, fi2->nsamples) * MIN(MAX(1, max_shift_percent), 100) / 100;
	xcorr_size=max_shift_samples*2;
	xcorr=ms_new0(int64_t,xcorr_size);
	if (fi1->nchannels == 2){
		max_index_r=compute_cross_correlation_interleaved(fi1->buffer,fi1->nsamples,fi2->buffer,fi2->nsamples,xcorr,xcorr_size, func, user_data, 0, max_shift_samples);
		max_r=xcorr[max_index_r];
		ms_message("max_r=%g", (double)max_r);
		max_r/=sqrt((double)fi1->energy_r*(double)fi2->energy_r);

		max_index_l=compute_cross_correlation_interleaved(fi1->buffer,fi1->nsamples,fi2->buffer,fi2->nsamples,xcorr,xcorr_size, func, user_data, 1, max_shift_samples);
		max_l=xcorr[max_index_l];
		ms_message("max_l=%g", (double)max_l);
		max_l/=sqrt((double)fi1->energy_l*(double)fi2->energy_l);
		ms_message("Max stereo cross-correlation obtained at position [%i,%i], similarity factor=%g,%g",
			   max_index_r-max_shift_samples,max_index_l-max_shift_samples,max_r, max_l);
		*ret = 0.5 * (fabs(max_r) + fabs(max_l)) * (1 - (double)abs(max_index_r-max_index_l)/(double)xcorr_size);
	}else{
		max_index_r=compute_cross_correlation(fi1->buffer,fi1->nsamples,fi2->buffer,fi2->nsamples,xcorr,xcorr_size, func, user_data, max_shift_samples);
		max_r=xcorr[max_index_r];
		max_r/=(sqrt(fi1->energy_r)*sqrt(fi2->energy_r));
		*ret=max_r;
		ms_message("Max cross-correlation obtained at position [%i], similarity factor=%g",max_index_r-max_shift_samples,*ret);
	}
	ms_free(xcorr);
	file_info_destroy(fi1);
	file_info_destroy(fi2);
	return 0;
}
Exemple #6
0
static gboolean library_view_update_info(library_view_t* view)
{
  if (view->run_timeout) {
    
    // update play buttons
    playlist_player_t* player = backtobasics_player(view->btb);
    if (view->btn_play == NULL) {
      view->btn_play = GTK_WIDGET(gtk_builder_get_object(view->builder, "tbtn_library_play"));
    }
    if (view->btn_pause == NULL) {
      view->btn_pause = GTK_WIDGET(gtk_builder_get_object(view->builder, "tbtn_library_pause"));
    }
    GtkWidget* btn_play = view->btn_play;
    GtkWidget* btn_pause = view->btn_pause;
    if (!playlist_player_is_playing(player)) {
      if (!gtk_widget_get_visible(btn_play)) gtk_widget_show_all(btn_play);
      if (gtk_widget_get_visible(btn_pause)) gtk_widget_hide(btn_pause);
    } else if (playlist_player_is_playing(player)) {
      if (gtk_widget_get_visible(btn_play)) gtk_widget_hide(btn_play);
      if (!gtk_widget_get_visible(btn_pause)) gtk_widget_show_all(btn_pause);
    }
    
    // update slider and time
    long tr_tm = playlist_player_get_track_position_in_ms(player);
    track_t* track = playlist_player_get_track(player);
    int index = playlist_player_get_track_index(player);
    
    int a = tr_tm / 1000;
    int b = view->time_in_ms / 1000;
    
    if (a != b) {
      view->time_in_ms = tr_tm;
      int min = tr_tm / 1000 / 60;
      int sec = (tr_tm / 1000) % 60;
      { 
        char s[200]; 
        sprintf(s,"<span size=\"x-small\"><b><i>%02d:%02d</i></b></span>", min, sec);
        GtkLabel* lbl = GTK_LABEL(gtk_builder_get_object(view->builder, "lbl_time"));
        gtk_label_set_markup(lbl, s);
        
        // update presets
        reflect_presets(view->btb);
      }
      
      GtkScale* sc_playback = GTK_SCALE(gtk_builder_get_object(view->builder, "sc_library_playback"));
      double perc = 0.0;
      if (track != NULL) {
        int len_in_ms = track_get_length_in_ms(track);
        
        if (len_in_ms != view->len_in_ms) {
          view->len_in_ms = len_in_ms;
          int min = len_in_ms / 1000 / 60;
          int sec = (len_in_ms / 1000) % 60;
          {
            char s[200];
            sprintf(s,"<span size=\"x-small\"><b><i>%02d:%02d</i></b></span>", min, sec);
            GtkLabel* lbl = GTK_LABEL(gtk_builder_get_object(view->builder, "lbl_total"));
            gtk_label_set_markup(lbl, s);
          }
        }
        
        perc = (((double) tr_tm) / ((double) len_in_ms)) * 100.0;
        if (!view->sliding) {
          gtk_range_set_value(GTK_RANGE(sc_playback), perc);
        }
      }

      // update track info
      if (index != view->track_index || 
            (track != NULL && track_get_id(track) != view->track_id)) {
        log_debug3("updating track info, index = %d, %p", index, track);
        view->track_index = index;
        if (track != NULL) {
          
          // fetch lyric if possible
          if (strcmp(track_get_lyric(track),"") == 0) {
            struct lyric_cb* cb = (struct lyric_cb*) mc_malloc(sizeof(struct lyric_cb));
            cb->track_id = mc_strdup(track_get_id(track));
            cb->view = view;
            fetch_lyric(track, library_view_process_lyric, cb);
          } else {
            struct lyric_cb* cb = (struct lyric_cb*) mc_malloc(sizeof(struct lyric_cb));
            cb->track_id = mc_strdup(track_get_id(track));
            cb->view = view;
            library_view_process_lyric(mc_strdup(track_get_lyric(track)), cb);
          }
            
          // Print artist info
          view->track_id = track_get_id(track);
          log_debug2("artid = %s", track_get_artid(track));
          char s[200];
          char c = ',';
          char c1 = ',';
          char *artist = text_to_html(track_get_artist(track));
          char *title = text_to_html(track_get_title(track));
          char *piece = text_to_html(track_get_piece(track));
          
          if (strcmp(track_get_artist(track), "") == 0) { c = ' '; }
          if (strcmp(track_get_piece(track), "") == 0) { c1 = ' '; }
          snprintf(s, 125,
                   "%s%c %s%c %s", 
                   artist,
                   c,
                   piece,
                   c1,
                   title
                   );
          mc_free(artist);
          mc_free(title);
          mc_free(piece);
          char ss[400];
          log_debug2("s = %s", s);
          sprintf(ss,"<span size=\"x-small\"><i><b>%s</b></i></span>",s);
          GtkLabel* lbl = GTK_LABEL(gtk_builder_get_object(view->builder, "lbl_song_info"));
          gtk_label_set_markup(lbl, ss);
          
          log_debug2("artid = %s", track_get_artid(track));
          file_info_t* info = file_info_new(track_get_artid(track));
          if (!file_info_is_file(info)) {
            file_info_destroy(info);
            char *path = backtobasics_logo(view->btb); 
            info = file_info_new(path);
            mc_free(path);
            //info = file_info_new(backtobasics_logo(view->btb));
          }
          
          if (file_info_is_file(info)) {
            GError *err = NULL;
            GdkPixbuf* pb = gdk_pixbuf_new_from_file_at_scale(file_info_path(info),
                                                              view->img_w, view->img_h,
                                                              TRUE,
                                                              &err
                                                              );
            if (pb != NULL) {
              GtkImage* img = GTK_IMAGE(gtk_builder_get_object(view->builder, "img_art"));
              gtk_image_set_from_pixbuf(img, pb);
              g_object_unref(pb);
            } else {
              log_error3("error loading image art: %d, %s", err->code, err->message);
              //g_free(err);
            }
          }
          file_info_destroy(info);
        }

        log_debug("track hash");

        
        // Select the track in the librarylist if the librarylist is still
        // the same
        if (playlist_model_tracks_hash(view->playlist_model) == playlist_player_get_hash(player)) {
          GtkTreeView* tview = view->tview;
          GtkTreePath* path = gtk_tree_path_new();
          gtk_tree_path_append_index(path, index);
          gtk_tree_view_set_cursor(tview, path, NULL, FALSE);
          gtk_tree_path_free(path);
        } 
        log_debug("track hash 2");
        
      }

      //log_debug3("lib hash = %lld, pl hash = %lld", view->library_list_hash, playlist_player_get_hash(player));
      
      // TODO
      if (playlist_model_tracks_hash(view->playlist_model) ==  playlist_player_get_hash(player)) {
        //view->track_index = -1;
      } else {
        
        GtkTreeView* tview = view->tview;
        GtkTreeSelection* sel = gtk_tree_view_get_selection(tview);
        gtk_tree_selection_unselect_all(sel);
      }
      
    }
    
    // update repeat info
    playlist_player_repeat_t repeat = playlist_player_get_repeat(player);
    if (view->repeat != repeat) {
      log_debug3("repeat = %d, view repeat = %d", repeat, view->repeat);
      view->repeat = repeat;
      GtkWidget* r_btn = GTK_WIDGET(gtk_builder_get_object(view->builder, "tbtn_repeat"));
      GtkWidget* r1_btn = GTK_WIDGET(gtk_builder_get_object(view->builder, "tbtn_repeat_one"));
      GtkWidget* rlist_btn = GTK_WIDGET(gtk_builder_get_object(view->builder, "tbtn_repeat_all"));
      log_debug4("r = %p, r1 = %p, rall = %p", r_btn, r1_btn, rlist_btn);
      switch (repeat) {
        case PLP_NO_REPEAT: {
          gtk_widget_show_all(r_btn);
          gtk_widget_hide(rlist_btn);
          gtk_widget_hide(r1_btn);
        }
        break;
        case PLP_TRACK_REPEAT: {
          gtk_widget_hide(r_btn);
          gtk_widget_show_all(r1_btn);
          gtk_widget_hide(rlist_btn);
        }
        break;
        case PLP_LIST_REPEAT: {
          gtk_widget_hide(r1_btn);
          gtk_widget_show_all(rlist_btn);
          gtk_widget_hide(r_btn);
        }
        break;
      }
    }

    
    return TRUE;
  } else {
    return FALSE;
  }
}
Exemple #7
0
void library_view_init(library_view_t* view)
{
  // library view.
  GObject* object = gtk_builder_get_object(view->builder,"view_library");
  g_object_set_data(object, "library_view_t", (gpointer) view);
  
  // playlists (initially not viewed)
  //GtkWidget* scw_playlists = GTK_WIDGET(gtk_builder_get_object(view->builder,"scw_playlists"));
  //gtk_widget_hide(scw_playlists);

  // library list
  GtkTreeView* tview = GTK_TREE_VIEW(gtk_builder_get_object(view->builder, "tv_library"));
  view->tview = tview;
  GtkTreeViewColumn *col;
  GtkCellRenderer* renderer;
  
  renderer = gtk_cell_renderer_text_new();
  
  view->cols = (GtkTreeViewColumn**) mc_malloc(sizeof(GtkTreeViewColumn*) * PLAYLIST_MODEL_N_COLUMNS);
  playlist_column_enum e;
  for(e = PLAYLIST_MODEL_COL_NR; e < PLAYLIST_MODEL_N_COLUMNS; ++e) {
    col = gtk_tree_view_column_new_with_attributes(i18n_column_name(e), renderer, "text", e, NULL);
    gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
    char path [500];
    sprintf(path, "library.column.%s.width", column_id(e));
    int width = el_config_get_int(btb_config(view->btb), path, 100);
    if (width < 10) { width = 100; }
    g_object_set_data(G_OBJECT(col), "column_id", (gpointer) column_id(e));
    gtk_tree_view_column_set_fixed_width(col, width);
    gtk_tree_view_column_set_reorderable(col, TRUE);
    gtk_tree_view_column_set_resizable(col, TRUE);
    gtk_tree_view_column_set_clickable(col, TRUE);
    g_signal_connect(col, "clicked", (GCallback) library_view_library_col_sort, view);
    g_signal_connect (col, "notify::width", G_CALLBACK (library_view_col_width_set), view);
    view->cols[e] = col;
    g_object_ref(view->cols[e]);
    gtk_tree_view_append_column(tview, col);
  }
  
  gtk_tree_view_set_model(tview, GTK_TREE_MODEL(playlist_model_gtk_model(view->playlist_model)));
  
  // Aspect lists
  int width;
  
  // Genres
  tview = GTK_TREE_VIEW(gtk_builder_get_object(view->builder, "tv_genre_aspect"));
  col = gtk_tree_view_column_new_with_attributes(_("Genre"), renderer, "text", 0, NULL);
  gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
  //width = el_config_get_int(btb_config(view->btb), "library.aspects.column_width", 200);
  //gtk_tree_view_column_set_fixed_width(col, width);
  gtk_tree_view_append_column(tview, col);
  gtk_tree_view_set_model(tview, string_model_gtk_model(view->genre_model));
  
  // Artists
  tview = GTK_TREE_VIEW(gtk_builder_get_object(view->builder, "tv_artist_aspect"));
  col = gtk_tree_view_column_new_with_attributes(_("Artists"), renderer, "text", 0, NULL);
  gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
  //width = el_config_get_int(btb_config(view->btb), "library.aspects.column_width", 200);
  //gtk_tree_view_column_set_fixed_width(col, width);
  gtk_tree_view_append_column(tview, col);
  gtk_tree_view_set_model(tview, string_model_gtk_model(view->artist_model));
  
  // Albums
  tview = GTK_TREE_VIEW(gtk_builder_get_object(view->builder, "tv_album_aspect"));
  col = gtk_tree_view_column_new_with_attributes(_("Artists"), renderer, "text", 0, NULL);
  gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
  //width = el_config_get_int(btb_config(view->btb), "library.aspects.column_width", 200);
  //gtk_tree_view_column_set_fixed_width(col, width);
  gtk_tree_view_append_column(tview, col);
  gtk_tree_view_set_model(tview, string_model_gtk_model(view->album_model));
  
  // Activate genres
  library_view_aspect_page(view, GENRE_ASPECT);
  GtkToggleToolButton* g_btn = GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(view->builder, "tbtn_genres"));
  gtk_toggle_tool_button_set_active(g_btn, TRUE);
  
  // playback scale, song info
  GtkScale* sc_playback = GTK_SCALE(gtk_builder_get_object(view->builder, "sc_library_playback"));
  gtk_range_set_range(GTK_RANGE(sc_playback), 0.0, 100.0);
  { 
    char ss[300];
    sprintf(ss,"<span size=\"x-small\"><i><b> </b></i></span>");
    GtkLabel* lbl = GTK_LABEL(gtk_builder_get_object(view->builder, "lbl_song_info"));
    gtk_label_set_markup(lbl, ss);
  }
  
  // Set logo
  {
    char *path = backtobasics_logo(view->btb); 
    file_info_t* info = file_info_new(path);
    mc_free(path);
    if (file_info_is_file(info)) {
      GError *err = NULL;
      GdkPixbuf* pb = gdk_pixbuf_new_from_file_at_scale(file_info_path(info),
                                                        view->img_w, view->img_h,
                                                        TRUE,
                                                        &err
                                                        );
      GtkImage* img = GTK_IMAGE(gtk_builder_get_object(view->builder, "img_art"));
      gtk_widget_set_size_request(GTK_WIDGET(img), view->img_w, view->img_h);
      if (pb != NULL) {
        gtk_image_set_from_pixbuf(img, pb);
        g_object_unref(pb);
      } else {
        log_error3("error loading image art: %d, %s", err->code, err->message);
        //g_free(err);
      }
    }
    file_info_destroy(info);
  }
  
  // Playlists
  tview = GTK_TREE_VIEW(gtk_builder_get_object(view->builder, "tv_playlists"));
  col = gtk_tree_view_column_new_with_attributes(_("Playlist"), renderer, "text", 0, NULL);
  gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED);
  width = el_config_get_int(btb_config(view->btb), "library.playlists.column_width", 200);
  gtk_tree_view_column_set_fixed_width(col, width);
  gtk_tree_view_append_column(tview, col);
  
  gtk_tree_view_set_model(tview, playlists_model_gtk_model(view->playlists_model));
  
  // Lyric view
  view->lyric_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
  view->lbl_lyric_track = GTK_LABEL(gtk_builder_get_object(view->builder, "lbl_lyric_track"));
  GtkScrolledWindow* scw_lyric = GTK_SCROLLED_WINDOW(gtk_builder_get_object(view->builder, "scw_lyric"));
  gtk_container_add(GTK_CONTAINER(scw_lyric), GTK_WIDGET(view->lyric_view));
  
  // visibility of columns
  {
    const char* names[] = {
      "chk_col_nr", "chk_col_title", "chk_col_artist", "chk_col_composer",
      "chk_col_piece", "chk_col_album", "chk_col_albumartist", "chk_col_genre",
      "chk_col_year", "chk_col_length", NULL
    };
    
    const playlist_column_enum es[] = {
      PLAYLIST_MODEL_COL_NR, PLAYLIST_MODEL_COL_TITLE, PLAYLIST_MODEL_COL_ARTIST,
      PLAYLIST_MODEL_COL_COMPOSER, PLAYLIST_MODEL_COL_PIECE, 
      PLAYLIST_MODEL_COL_ALBUM_TITLE, PLAYLIST_MODEL_COL_ALBUM_ARTIST,
      PLAYLIST_MODEL_COL_GENRE, PLAYLIST_MODEL_COL_YEAR, PLAYLIST_MODEL_COL_LENGTH,
      PLAYLIST_MODEL_N_COLUMNS
    };
    
    int i;
    for(i = 0;names[i] != NULL; ++i) {
      GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(gtk_builder_get_object(view->builder, names[i]));
      gtk_widget_set_name(GTK_WIDGET(item), names[i]);
      char cfgitem[100];
      sprintf(cfgitem, "library.cols.%s", names[i]);
      int yes = el_config_get_int(btb_config(view->btb), cfgitem, 1);
      gtk_check_menu_item_set_active(item, yes);
      gtk_tree_view_column_set_visible(view->cols[es[i]], yes);
    }
  }
  
  // Start timeout every 250 ms
  g_timeout_add(250, (GSourceFunc) library_view_update_info, view); 
}
Exemple #8
0
/**
 * Check if conffiles contains sane information.
 */
static void
check_conffiles(const char *ctrldir, const char *rootdir)
{
  FILE *cf;
  struct varbuf controlfile = VARBUF_INIT;
  char conffilename[MAXCONFFILENAME + 1];
  struct file_info *conffiles_head = NULL;
  struct file_info *conffiles_tail = NULL;

  varbuf_printf(&controlfile, "%s/%s", ctrldir, CONFFILESFILE);

  cf = fopen(controlfile.buf, "r");
  if (cf == NULL) {
    if (errno == ENOENT)
      return;

    ohshite(_("error opening conffiles file"));
  }

  while (fgets(conffilename, MAXCONFFILENAME + 1, cf)) {
    struct stat controlstab;
    int n;

    n = strlen(conffilename);
    if (!n)
      ohshite(_("empty string from fgets reading conffiles"));

    if (conffilename[n - 1] != '\n')
      ohshit(_("conffile name '%s' is too long, or missing final newline"),
             conffilename);

    conffilename[n - 1] = '\0';
    varbuf_reset(&controlfile);
    varbuf_printf(&controlfile, "%s/%s", rootdir, conffilename);
    if (lstat(controlfile.buf, &controlstab)) {
      if (errno == ENOENT) {
        if ((n > 1) && c_isspace(conffilename[n - 2]))
          warning(_("conffile filename '%s' contains trailing white spaces"),
                  conffilename);
        ohshit(_("conffile '%.250s' does not appear in package"), conffilename);
      } else
        ohshite(_("conffile '%.250s' is not stattable"), conffilename);
    } else if (!S_ISREG(controlstab.st_mode)) {
      warning(_("conffile '%s' is not a plain file"), conffilename);
    }

    if (file_info_find_name(conffiles_head, conffilename)) {
      warning(_("conffile name '%s' is duplicated"), conffilename);
    } else {
      struct file_info *conffile;

      conffile = file_info_new(conffilename);
      file_info_list_append(&conffiles_head, &conffiles_tail, conffile);
    }
  }

  file_info_list_free(conffiles_head);
  varbuf_destroy(&controlfile);

  if (ferror(cf))
    ohshite(_("error reading conffiles file"));
  fclose(cf);
}
/* Overly complex function that builds a .deb file
 */
void do_build(const char *const *argv) {
  static const char *const maintainerscripts[]= {
    PREINSTFILE, POSTINSTFILE, PRERMFILE, POSTRMFILE, NULL
  };
  
  char *m;
  const char *debar, *directory, *const *mscriptp, *versionstring, *arch;
  char *controlfile, *tfbuf;
  const char *envbuf;
  struct pkginfo *checkedinfo;
  struct arbitraryfield *field;
  FILE *ar, *cf;
  int p1[2],p2[2],p3[2], warns, errs, n, c, subdir, gzfd;
  pid_t c1,c2,c3;
  struct stat controlstab, datastab, mscriptstab, debarstab;
  char conffilename[MAXCONFFILENAME+1];
  time_t thetime= 0;
  struct file_info *fi;
  struct file_info *symlist = NULL;
  struct file_info *symlist_end = NULL;
  
/* Decode our arguments */
  directory = *argv++;
  if (!directory)
    badusage(_("--%s needs a <directory> argument"), cipaction->olong);
  /* template for our tempfiles */
  if ((envbuf= getenv("TMPDIR")) == NULL)
    envbuf= P_tmpdir;
  tfbuf = m_malloc(strlen(envbuf) + 13);
  strcpy(tfbuf,envbuf);
  strcat(tfbuf,"/dpkg.XXXXXX");
  subdir= 0;
  debar = *argv++;
  if (debar != NULL) {
    if (*argv) badusage(_("--build takes at most two arguments"));
    if (debar) {
      if (stat(debar,&debarstab)) {
        if (errno != ENOENT)
          ohshite(_("unable to check for existence of archive `%.250s'"),debar);
      } else if (S_ISDIR(debarstab.st_mode)) {
        subdir= 1;
      }
    }
  } else {
    m= m_malloc(strlen(directory) + sizeof(DEBEXT));
    strcpy(m, directory);
    path_rtrim_slash_slashdot(m);
    strcat(m, DEBEXT);
    debar= m;
  }
    
  /* Perform some sanity checks on the to-be-build package.
   */
  if (nocheckflag) {
    if (subdir)
      ohshit(_("target is directory - cannot skip control file check"));
    warning(_("not checking contents of control area."));
    printf(_("dpkg-deb: building an unknown package in '%s'.\n"), debar);
  } else {
    controlfile= m_malloc(strlen(directory) + sizeof(BUILDCONTROLDIR) +
                          sizeof(CONTROLFILE) + sizeof(CONFFILESFILE) +
                          sizeof(POSTINSTFILE) + sizeof(PREINSTFILE) +
                          sizeof(POSTRMFILE) + sizeof(PRERMFILE) +
                          MAXCONFFILENAME + 5);
    /* Lets start by reading in the control-file so we can check its contents */
    strcpy(controlfile, directory);
    strcat(controlfile, "/" BUILDCONTROLDIR "/" CONTROLFILE);
    warns= 0; errs= 0;
    parsedb(controlfile, pdb_recordavailable|pdb_rejectstatus,
            &checkedinfo, stderr, &warns);
    assert(checkedinfo->available.valid);
    if (strspn(checkedinfo->name,
               "abcdefghijklmnopqrstuvwxyz0123456789+-.")
        != strlen(checkedinfo->name))
      ohshit(_("package name has characters that aren't lowercase alphanums or `-+.'"));
    if (checkedinfo->priority == pri_other) {
      warning(_("'%s' contains user-defined Priority value '%s'"),
              controlfile, checkedinfo->otherpriority);
      warns++;
    }
    for (field= checkedinfo->available.arbs; field; field= field->next) {
      if (known_arbitrary_field(field))
        continue;

      warning(_("'%s' contains user-defined field '%s'"),
              controlfile, field->name);
      warns++;
    }
    checkversion(checkedinfo->available.version.version,
                 _("(upstream) version"), &errs);
    checkversion(checkedinfo->available.version.revision,
                 _("Debian revision"), &errs);
    if (errs) ohshit(_("%d errors in control file"),errs);

    if (subdir) {
      versionstring= versiondescribe(&checkedinfo->available.version,vdew_never);
      arch= checkedinfo->available.architecture; if (!arch) arch= "";
      m= m_malloc(sizeof(DEBEXT)+1+strlen(debar)+1+strlen(checkedinfo->name)+
                  strlen(versionstring)+1+strlen(arch));
      sprintf(m,"%s/%s_%s%s%s" DEBEXT,debar,checkedinfo->name,versionstring,
              arch[0] ? "_" : "", arch);
      debar= m;
    }
    printf(_("dpkg-deb: building package `%s' in `%s'.\n"), checkedinfo->name, debar);

    /* Check file permissions */
    strcpy(controlfile, directory);
    strcat(controlfile, "/" BUILDCONTROLDIR "/");
    if (lstat(controlfile, &mscriptstab))
      ohshite(_("unable to stat control directory"));
    if (!S_ISDIR(mscriptstab.st_mode))
      ohshit(_("control directory is not a directory"));
    if ((mscriptstab.st_mode & 07757) != 0755)
      ohshit(_("control directory has bad permissions %03lo (must be >=0755 "
             "and <=0775)"), (unsigned long)(mscriptstab.st_mode & 07777));

    for (mscriptp= maintainerscripts; *mscriptp; mscriptp++) {
      strcpy(controlfile, directory);
      strcat(controlfile, "/" BUILDCONTROLDIR "/");
      strcat(controlfile, *mscriptp);

      if (!lstat(controlfile,&mscriptstab)) {
        if (S_ISLNK(mscriptstab.st_mode)) continue;
        if (!S_ISREG(mscriptstab.st_mode))
          ohshit(_("maintainer script `%.50s' is not a plain file or symlink"),*mscriptp);
        if ((mscriptstab.st_mode & 07557) != 0555)
          ohshit(_("maintainer script `%.50s' has bad permissions %03lo "
                 "(must be >=0555 and <=0775)"),
                 *mscriptp, (unsigned long)(mscriptstab.st_mode & 07777));
      } else if (errno != ENOENT) {
        ohshite(_("maintainer script `%.50s' is not stattable"),*mscriptp);
      }
    }

    /* Check if conffiles contains sane information */
    strcpy(controlfile, directory);
    strcat(controlfile, "/" BUILDCONTROLDIR "/" CONFFILESFILE);
    if ((cf= fopen(controlfile,"r"))) {
      struct file_info *conffiles_head = NULL;
      struct file_info *conffiles_tail = NULL;

      while (fgets(conffilename,MAXCONFFILENAME+1,cf)) {
        n= strlen(conffilename);
        if (!n) ohshite(_("empty string from fgets reading conffiles"));
        if (conffilename[n-1] != '\n') {
          warning(_("conffile name '%.50s...' is too long, or missing final newline"),
		  conffilename);
          warns++;
          while ((c= getc(cf)) != EOF && c != '\n');
          continue;
        }
        conffilename[n - 1] = '\0';
        strcpy(controlfile, directory);
        strcat(controlfile, "/");
        strcat(controlfile, conffilename);
        if (lstat(controlfile,&controlstab)) {
	  if (errno == ENOENT) {
	    if((n > 1) && isspace(conffilename[n-2]))
	      warning(_("conffile filename '%s' contains trailing white spaces"),
	              conffilename);
	    ohshit(_("conffile `%.250s' does not appear in package"), conffilename);
	  } else
	    ohshite(_("conffile `%.250s' is not stattable"), conffilename);
        } else if (!S_ISREG(controlstab.st_mode)) {
          warning(_("conffile '%s' is not a plain file"), conffilename);
          warns++;
        }

        if (file_info_find_name(conffiles_head, conffilename))
          warning(_("conffile name '%s' is duplicated"), conffilename);
        else {
          struct file_info *conffile;

          conffile = file_info_new(conffilename);
          add_to_filist(&conffiles_head, &conffiles_tail, conffile);
        }
      }

      free_filist(conffiles_head);

      if (ferror(cf)) ohshite(_("error reading conffiles file"));
      fclose(cf);
    } else if (errno != ENOENT) {
      ohshite(_("error opening conffiles file"));
    }
    if (warns)
      warning(_("ignoring %d warnings about the control file(s)\n"), warns);
  }
  m_output(stdout, _("<standard output>"));
  
  /* Now that we have verified everything its time to actually
   * build something. Lets start by making the ar-wrapper.
   */
  if (!(ar=fopen(debar,"wb"))) ohshite(_("unable to create `%.255s'"),debar);
  if (setvbuf(ar, NULL, _IONBF, 0))
    ohshite(_("unable to unbuffer `%.255s'"), debar);
  /* Fork a tar to package the control-section of the package */
  unsetenv("TAR_OPTIONS");
  m_pipe(p1);
  if (!(c1= m_fork())) {
    m_dup2(p1[1],1); close(p1[0]); close(p1[1]);
    if (chdir(directory)) ohshite(_("failed to chdir to `%.255s'"),directory);
    if (chdir(BUILDCONTROLDIR)) ohshite(_("failed to chdir to .../DEBIAN"));
    execlp(TAR, "tar", "-cf", "-", "--format=gnu", ".", NULL);
    ohshite(_("failed to exec tar -cf"));
  }
  close(p1[1]);
  /* Create a temporary file to store the control data in. Immediately unlink
   * our temporary file so others can't mess with it.
   */
  if ((gzfd= mkstemp(tfbuf)) == -1) ohshite(_("failed to make tmpfile (control)"));
  /* make sure it's gone, the fd will remain until we close it */
  if (unlink(tfbuf)) ohshit(_("failed to unlink tmpfile (control), %s"),
      tfbuf);
  /* reset this, so we can use it elsewhere */
  strcpy(tfbuf,envbuf);
  strcat(tfbuf,"/dpkg.XXXXXX");
  /* And run gzip to compress our control archive */
  if (!(c2= m_fork())) {
    m_dup2(p1[0],0); m_dup2(gzfd,1); close(p1[0]); close(gzfd);
    compress_cat(compress_type_gzip, 0, 1, "9", _("control"));
  }
  close(p1[0]);
  waitsubproc(c2,"gzip -9c",0);
  waitsubproc(c1,"tar -cf",0);
  if (fstat(gzfd,&controlstab)) ohshite(_("failed to fstat tmpfile (control)"));
  /* We have our first file for the ar-archive. Write a header for it to the
   * package and insert it.
   */
  if (oldformatflag) {
    if (fprintf(ar, "%-8s\n%ld\n", OLDARCHIVEVERSION, (long)controlstab.st_size) == EOF)
      werr(debar);
  } else {
    thetime = time(NULL);
    if (fprintf(ar,
                "!<arch>\n"
                "debian-binary   %-12lu0     0     100644  %-10ld`\n"
                ARCHIVEVERSION "\n"
                "%s"
                ADMINMEMBER "%-12lu0     0     100644  %-10ld`\n",
                thetime,
                (long)sizeof(ARCHIVEVERSION),
                (sizeof(ARCHIVEVERSION)&1) ? "\n" : "",
                (unsigned long)thetime,
                (long)controlstab.st_size) == EOF)
      werr(debar);
  }                
                
  if (lseek(gzfd,0,SEEK_SET)) ohshite(_("failed to rewind tmpfile (control)"));
  fd_fd_copy(gzfd, fileno(ar), -1, _("control"));

  /* Control is done, now we need to archive the data. Start by creating
   * a new temporary file. Immediately unlink the temporary file so others
   * can't mess with it. */
  if (!oldformatflag) {
    close(gzfd);
    if ((gzfd= mkstemp(tfbuf)) == -1) ohshite(_("failed to make tmpfile (data)"));
    /* make sure it's gone, the fd will remain until we close it */
    if (unlink(tfbuf)) ohshit(_("failed to unlink tmpfile (data), %s"),
        tfbuf);
    /* reset these, in case we want to use the later */
    strcpy(tfbuf,envbuf);
    strcat(tfbuf,"/dpkg.XXXXXX");
  }
  /* Fork off a tar. We will feed it a list of filenames on stdin later.
   */
  m_pipe(p1);
  m_pipe(p2);
  if (!(c1= m_fork())) {
    m_dup2(p1[0],0); close(p1[0]); close(p1[1]);
    m_dup2(p2[1],1); close(p2[0]); close(p2[1]);
    if (chdir(directory)) ohshite(_("failed to chdir to `%.255s'"),directory);
    execlp(TAR, "tar", "-cf", "-", "--format=gnu", "--null", "-T", "-", "--no-recursion", NULL);
    ohshite(_("failed to exec tar -cf"));
  }
  close(p1[0]);
  close(p2[1]);
  /* Of course we should not forget to compress the archive as well.. */
  if (!(c2= m_fork())) {
    close(p1[1]);
    m_dup2(p2[0],0); close(p2[0]);
    m_dup2(oldformatflag ? fileno(ar) : gzfd,1);
    compress_cat(compress_type, 0, 1, compression, _("data"));
  }
  close(p2[0]);
  /* All the pipes are set, now lets run find, and start feeding
   * filenames to tar.
   */

  m_pipe(p3);
  if (!(c3= m_fork())) {
    m_dup2(p3[1],1); close(p3[0]); close(p3[1]);
    if (chdir(directory)) ohshite(_("failed to chdir to `%.255s'"),directory);
    execlp(FIND, "find", ".", "-path", "./" BUILDCONTROLDIR, "-prune", "-o",
           "-print0", NULL);
    ohshite(_("failed to exec find"));
  }
  close(p3[1]);
  /* We need to reorder the files so we can make sure that symlinks
   * will not appear before their target.
   */
  while ((fi=getfi(directory, p3[0]))!=NULL)
    if (S_ISLNK(fi->st.st_mode))
      add_to_filist(&symlist, &symlist_end, fi);
    else {
      if (write(p1[1], fi->fn, strlen(fi->fn)+1) ==- 1)
	ohshite(_("failed to write filename to tar pipe (data)"));
    }
  close(p3[0]);
  waitsubproc(c3,"find",0);

  for (fi= symlist;fi;fi= fi->next)
    if (write(p1[1], fi->fn, strlen(fi->fn)+1) == -1)
      ohshite(_("failed to write filename to tar pipe (data)"));
  /* All done, clean up wait for tar and gzip to finish their job */
  close(p1[1]);
  free_filist(symlist);
  waitsubproc(c2, _("<compress> from tar -cf"), 0);
  waitsubproc(c1,"tar -cf",0);
  /* Okay, we have data.tar.gz as well now, add it to the ar wrapper */
  if (!oldformatflag) {
    const char *datamember;
    switch (compress_type) {
    case compress_type_gzip:
      datamember = DATAMEMBER_GZ;
      break;
    case compress_type_bzip2:
      datamember = DATAMEMBER_BZ2;
      break;
    case compress_type_lzma:
      datamember = DATAMEMBER_LZMA;
      break;
    case compress_type_cat:
      datamember = DATAMEMBER_CAT;
      break;
    default:
      internerr("unkown compress_type '%i'", compress_type);
    }
    if (fstat(gzfd, &datastab))
      ohshite(_("failed to fstat tmpfile (data)"));
    if (fprintf(ar,
                "%s"
                "%s" "%-12lu0     0     100644  %-10ld`\n",
                (controlstab.st_size & 1) ? "\n" : "",
                datamember,
                (unsigned long)thetime,
                (long)datastab.st_size) == EOF)
      werr(debar);

    if (lseek(gzfd,0,SEEK_SET)) ohshite(_("failed to rewind tmpfile (data)"));
    fd_fd_copy(gzfd, fileno(ar), -1, _("cat (data)"));

    if (datastab.st_size & 1)
      if (putc('\n',ar) == EOF)
        werr(debar);
  }
  if (fclose(ar)) werr(debar);
                             
  exit(0);
}
Exemple #10
0
int main(char *argv[],int argc) {
  mc_init();
  el_bool stop = el_false;
  
  hre_t re_load = hre_compile("^load(&play)?\\s+(.*)$","i");
  hre_t re_play = hre_compile("^play$","i");
  hre_t re_pause = hre_compile("^pause$","i");
  hre_t re_next = hre_compile("^next$","i");
  hre_t re_previous = hre_compile("^prev(ious)?$","i");
  hre_t re_track = hre_compile("^track\\s+([0-9]+)$","i");
  hre_t re_quhit = hre_compile("^quit$","i");
  hre_t re_seek = hre_compile("^seek\\s([0-9]+([.][0-9]+)?)$","i");
  hre_t re_quit = hre_compile("^quit$","i");
  hre_t re_repeat = hre_compile("^repeat\\s+(off|list|track)$","i");
  hre_t re_again = hre_compile("^again$","i");
  hre_t re_scan = hre_compile("^scan\\s+(.*)$","i");
  
  file_info_t *history_file = mc_take_over(file_info_new_home(".btb_playlist"));
  printf("history file: %s\n", file_info_absolute_path(history_file));
  printf("history file: %s\n", file_info_path(history_file));
  if (file_info_exists(history_file)) {
    read_history(file_info_absolute_path(history_file));
  }
  
  i18n_set_language("nl");
  printf(_("Starting btb_playlist\n"));

  playlist_player_t *player = playlist_player_new();

  while (!stop) {
    char* line = readln(">", player);
    hre_trim(line);
    if (hre_has_match(re_quit, line)) {
      stop = el_true;
    } else if (hre_has_match(re_load, line)) {
      hre_matches m = hre_match(re_load, line);
      hre_match_t *mplay = hre_matches_get(m, 1);
      hre_match_t *match = hre_matches_get(m, 2);
      char* file = mc_strdup(hre_match_str(match));
      char* play = mc_strdup(hre_match_str(mplay));
      hre_matches_destroy(m);
      printf("loading '%s', '%s'\n", file, play);
      file_info_t *info = file_info_new(file);
      if (file_info_exists(info)) {
        if (file_info_is_file(info)) {
          if (file_info_can_read(info)) {
            const char *mediafile = NULL;
            track_array array;
            if (strcasecmp(file_info_ext(info),"cue") == 0) {
              array = tracks_from_cue(file_info_absolute_path(info));
              track_t* t = track_array_get(array, 0);
            } else {
              array = tracks_from_media(file_info_absolute_path(info));
            }
            playlist_t* pl = playlist_new("playlist");
            int i;
            for(i=0; i < track_array_count(array); ++i) {
              playlist_append(pl, track_array_get(array, i));
            }
            playlist_player_set_playlist(player, pl);
            track_array_destroy(array);
          }
        }
      }
      file_info_destroy(info);      
      if (strcasecmp(play,"&play")==0) { playlist_player_play(player); }
      mc_free(file);
      mc_free(play);
    } else if (hre_has_match(re_play, line)) {
      playlist_player_play(player);
    } else if (hre_has_match(re_pause, line)) {
      playlist_player_pause(player);
    } else if (hre_has_match(re_seek, line)) {
      hre_matches m = hre_match(re_seek, line);
      hre_match_t* match = hre_matches_get(m, 1);
      char* position = mc_strdup(hre_match_str(match));
      hre_matches_destroy(m);
      double s = atof(position);
      int ms = s * 1000;
      mc_free(position);
      playlist_player_seek(player, ms); 
    } else if (hre_has_match(re_next, line)) {
      playlist_player_next(player);
    } else if (hre_has_match(re_previous, line)) {
      playlist_player_previous(player);
    } else if (hre_has_match(re_track, line)) {
      hre_matches m = hre_match(re_track, line);
      hre_match_t* match = hre_matches_get(m, 1);
      char* nr = mc_strdup(hre_match_str(match));
      hre_matches_destroy(m);
      int index = atoi(nr);
      mc_free(nr);
      printf("setting track %d\n",index);
      playlist_player_set_track(player, index);
    } else if (hre_has_match(re_repeat, line)) {
      hre_matches m = hre_match(re_repeat, line);
      hre_match_t* match = hre_matches_get(m, 1);
      if (strcasecmp(hre_match_str(match),"track") == 0) {
        playlist_player_set_repeat(player, PLP_TRACK_REPEAT);
      } else if (strcasecmp(hre_match_str(match),"list") == 0) {
        playlist_player_set_repeat(player, PLP_LIST_REPEAT);
      } else {
        playlist_player_set_repeat(player, PLP_NO_REPEAT);
      }
      hre_matches_destroy(m);
    } else if (hre_has_match(re_again, line)) {
      playlist_player_again(player);
    } else if (hre_has_match(re_scan, line)) {
      hre_matches m = hre_match(re_scan, line);
      hre_match_t* match = hre_matches_get(m, 1);
      printf("scanning %s\n", hre_match_str(match));
      library_t* library = library_new();
      printf("calling scan_library\n");
      //scan_library(library, hre_match_str(match), library_cb);
      printf("\n");
      printf("library: %d tracks\n", library_count(library));
      printf("done scanning, destroying library\n");
      library_destroy(library);
      printf("library destroyed\n");
      hre_matches_destroy(m);
      printf("matches destroyed\n");
    }
    
    mc_free(line);
  }

  playlist_player_destroy(player);
  
  printf("%d\n",write_history(file_info_absolute_path(history_file)));
  
  file_info_destroy(history_file);
  hre_destroy(re_load);
  hre_destroy(re_play);
  hre_destroy(re_pause);
  hre_destroy(re_quit);
  hre_destroy(re_seek);
  hre_destroy(re_track);
  hre_destroy(re_next);
  hre_destroy(re_previous);
  hre_destroy(re_again);
  hre_destroy(re_repeat);
  hre_destroy(re_scan);
  
  return 0;
}