示例#1
0
文件: files.c 项目: Someone101/aleph
// search for named .dsc file and load into network param desc memory
extern u8 files_load_desc(const char* name) {
  char path[64] = DSP_PATH;
  void * fp;
  int nparams = -1;
  // word buffer for 4-byte unpickling
  u8 nbuf[4];
  // buffer for binary blob of single descriptor
  u8 dbuf[PARAM_DESC_PICKLE_BYTES];
  // unpacked descriptor
  ParamDesc desc;
  int i;
  u8 ret = 0;

  app_pause();

  strcat(path, name);
  strip_ext(path);
  strcat(path, ".dsc");

  print_dbg("\r\n  opening .dsc file at path: ");
  print_dbg(path);

  fp = fl_fopen(path, "r");
  if(fp == NULL) {
    print_dbg("... error opening .dsc file.");
    print_dbg(path);
    ret = 1;
  } else {

    // get number of parameters
    fake_fread(nbuf, 4, fp);
    unpickle_32(nbuf, (u32*)&nparams); 

    /// loop over params
    if(nparams > 0) {
      net_clear_params();
      //    net->numParams = nparams;

      for(i=0; i<nparams; i++) {
	//  FIXME: a little gross,
	// to be interleaving network and file manipulation like this...
	///....
	// read into desc buffer
	fake_fread(dbuf, PARAM_DESC_PICKLE_BYTES, fp);
	// unpickle directly into network descriptor memory
	pdesc_unpickle( &desc, dbuf );
	// copy descriptor to network and increment count
	net_add_param(i, (const ParamDesc*)(&desc));     
 
      }
    } else {
      print_dbg("\r\n error: crazy parameter count from descriptor file.");
      ret = 1;
    }
  }
  fl_fclose(fp);
  app_resume();
  return ret;
}
示例#2
0
int
insert_playlist(const char * path, char * name)
{
	struct song_metadata plist;
	struct stat file;
	int items = 0, matches, ret;
	char type[4];

	strncpy(type, strrchr(name, '.')+1, 4);

	if( start_plist(path, NULL, &file, NULL, type) != 0 )
	{
		DPRINTF(E_WARN, L_SCANNER, "Bad playlist [%s]\n", path);
		return -1;
	}
	while( (ret = next_plist_track(&plist, &file, NULL, type)) == 0 )
	{
		items++;
		freetags(&plist);
	}
	if( ret == 2 ) // Bad playlist -- contains binary characters
	{
		DPRINTF(E_WARN, L_SCANNER, "Bad playlist [%s]\n", path);
		return -1;
	}
	strip_ext(name);

	DPRINTF(E_DEBUG, L_SCANNER, "Playlist %s contains %d items\n", name, items);
	
	matches = sql_get_int_field(db, "SELECT count(*) from PLAYLISTS where NAME = '%q'", name);
	if( matches > 0 )
	{
		sql_exec(db, "INSERT into PLAYLISTS"
		             " (NAME, PATH, ITEMS) "
	        	     "VALUES"
		             " ('%q(%d)', '%q', %d)",
		             name, matches, path, items);
	}
	else
	{
		sql_exec(db, "INSERT into PLAYLISTS"
		             " (NAME, PATH, ITEMS) "
	        	     "VALUES"
		             " ('%q', '%q', %d)",
		             name, path, items);
	}

	sql_exec(db, "INSERT into DETAILS"
	             " (PATH, TIMESTAMP, MIME) "
	             "VALUES"
	             " ('%q', %ld, 'audio/x-mpegurl')",
	             path, 0);

	return 0;
}
示例#3
0
static void load_menu(void) {
  Tuple *t = dict_read_first(&items_iter);
  while(t != NULL) {
    char* id = (char*) t->value->cstring;
    char* name = split_id_name_pair(id);
    strip_ext(name);
    basic_menu_model_add_item(s_model, name, NULL, id);
    t = dict_read_next(&items_iter);
  }
  menu_layer_reload_data(s_menu);
  layer_set_hidden(s_lyr_loading, true);
}
示例#4
0
文件: files.c 项目: bbnickell/aleph
// search for specified dsp file and load it
u8 files_load_dsp_name(const char* name) {
  // don't need .ldr, but we do need .dsc...
  char descname[128];
  u8 nbuf[4];
  // buffer for binary blob of single descriptor
  u8 dbuf[PARAM_DESC_PICKLE_BYTES];
  // unpacked descriptor
  ParamDesc desc;
  u32 nparams;
  u8 ret = 0;
  FILE* fp;
  int i;
  strcpy(descname, workingDir);
  strcat(descname, name);
  strip_ext(descname);
  strcat(descname, ".dsc");

  fp = fopen(descname, "r");
  
  if(fp == NULL) {
    printf("\r\n module descriptor not found; path: %s", descname);
    ret = 1;
    return ret;
  }
  
  // get count of params
  fread(nbuf, 1, 4, fp);
  unpickle_32(nbuf, (u32*)&nparams); 

  /// loop over params
  if(nparams > 0) {
    printf("\r\n loading param descriptor; count: %d", nparams);
    net_clear_params();
    for(i=0; i<nparams; i++) {
      // read into desc buffer
      fread(dbuf, 1, PARAM_DESC_PICKLE_BYTES, fp);
      // unpickle directly into network descriptor memory
      pdesc_unpickle( &desc, dbuf );
      // copy descriptor to network and increment count
      net_add_param(i, (const ParamDesc*)(&desc));     
    }
  } else {
    ret = 1;
  }

  fclose(fp);

  scene_set_module_name(name);
  return ret;
}
void
check_for_captions(const char *path, int64_t detailID)
{
	char *file = malloc(MAXPATHLEN);
	char *id = NULL;

	sprintf(file, "%s", path);
	strip_ext(file);

	/* If we weren't given a detail ID, look for one. */
	if( !detailID )
	{
		id = sql_get_text_field(db, "SELECT ID from DETAILS where (PATH > '%q.' and PATH <= '%q.z')"
		                            " and MIME glob 'video/*' limit 1", file, file);
		if( id )
		{
			DPRINTF(E_DEBUG, L_METADATA, "New file %s looks like a caption file.\n", path);
			detailID = strtoll(id, NULL, 10);
		}
		else
		{
			DPRINTF(E_DEBUG, L_METADATA, "No file found for caption %s.\n", path);
			goto no_source_video;
		}
	}

	strcat(file, ".srt");
        DPRINTF(E_DEBUG, L_METADATA, "search %s.\n", file);
	if( access(file, R_OK) == 0 )
	{
		sql_exec(db, "INSERT into CAPTIONS"
		             " (ID, PATH) "
		             "VALUES"
		             " (%lld, %Q)", detailID, file);
                DPRINTF(E_DEBUG, L_INOTIFY, "INSERT into CAPTIONS (%lld, %s).\n", detailID, file);
	}
no_source_video:
	if( id )
		sqlite3_free(id);
	free(file);
}
示例#6
0
文件: metadata.c 项目: PterX/rt-n56u
void
check_for_captions(const char *path, int64_t detailID)
{
	char file[MAXPATHLEN];
	char *p;
	int ret;

	strncpyt(file, path, sizeof(file));
	p = strip_ext(file);
	if (!p)
		p = strrchr(file, '\0');

	/* If we weren't given a detail ID, look for one. */
	if (!detailID)
	{
		detailID = sql_get_int64_field(db, "SELECT ID from DETAILS where (PATH > '%q.' and PATH <= '%q.z')"
		                            " and MIME glob 'video/*' limit 1", file, file);
		if (detailID <= 0)
		{
			//DPRINTF(E_MAXDEBUG, L_METADATA, "No file found for caption %s.\n", path);
			return;
		}
	}

	strcpy(p, ".srt");
	ret = access(file, R_OK);
	if (ret != 0)
	{
		strcpy(p, ".smi");
		ret = access(file, R_OK);
	}

	if (ret == 0)
	{
		sql_exec(db, "INSERT into CAPTIONS"
		             " (ID, PATH) "
		             "VALUES"
		             " (%lld, %Q)", detailID, file);
	}
}
示例#7
0
bool gen_xsds(string &excel, string &xsd_dir)
{
	if(false == fileuitl::exist(excel))
	{
		ECHO_ERR("´íÎó: %s ·¾¶²»´æÔÚ", excel.c_str());
		return false;
	}

	if(false == fileuitl::exist(xsd_dir))
	{
		ECHO_ERR("´íÎó: %s ·¾¶²»´æÔÚ", xsd_dir.c_str());
		return false;
	}

	propunit_t unit;
	errvec_t errvec;

    bool ok = parseutil::parse_excel(excel, unit, errvec);
    if (!ok){
        ECHO_ERR("´íÎó: %s ½âÎöÎļþʧ°Ü", xsd_dir.c_str());
        proputil::echo_errvec(errvec);
        return false;
    }
	
	// proputil::parse(excel, unit, errvec);

	for(propdeclvec_t::iterator itr = unit.propdecls.begin(); itr != unit.propdecls.end(); ++itr)
	{
		propdecl_t &decl = *itr;
		string xsd = xsd_dir + "\\" + strip_ext(strip_dir(decl.filename)) + ".xsd";

		gen_xsd(decl, xsd);
	}

	return true;
}
示例#8
0
int64_t
GetImageMetadata(const char *path, char *name)
{
	ExifData *ed;
	ExifEntry *e = NULL;
	ExifLoader *l;
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	FILE *infile;
	int width=0, height=0, thumb=0;
	char make[32], model[64] = {'\0'};
	char b[1024];
	struct stat file;
	int64_t ret;
	image_s *imsrc;
	metadata_t m;
	uint32_t free_flags = 0xFFFFFFFF;
	memset(&m, '\0', sizeof(metadata_t));

	//DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing %s...\n", path);
	if ( stat(path, &file) != 0 )
		return 0;
	strip_ext(name);
	//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size);

	/* MIME hard-coded to JPEG for now, until we add PNG support */
	m.mime = strdup("image/jpeg");

	l = exif_loader_new();
	exif_loader_write_file(l, path);
	ed = exif_loader_get_data(l);
	exif_loader_unref(l);
	if( !ed )
		goto no_exifdata;

	e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL);
	if( e || (e = exif_content_get_entry(ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_DIGITIZED)) )
	{
		m.date = strdup(exif_entry_get_value(e, b, sizeof(b)));
		if( strlen(m.date) > 10 )
		{
			m.date[4] = '-';
			m.date[7] = '-';
			m.date[10] = 'T';
		}
		else {
			free(m.date);
			m.date = NULL;
		}
	}
	else {
		/* One last effort to get the date from XMP */
		image_get_jpeg_date_xmp(path, &m.date);
	}
	//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", m.date);

	e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
	if( e )
	{
		strncpyt(make, exif_entry_get_value(e, b, sizeof(b)), sizeof(make));
		e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MODEL);
		if( e )
		{
			strncpyt(model, exif_entry_get_value(e, b, sizeof(b)), sizeof(model));
			if( !strcasestr(model, make) )
				snprintf(model, sizeof(model), "%s %s", make, exif_entry_get_value(e, b, sizeof(b)));
			m.creator = escape_tag(trim(model), 1);
		}
	}
	//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * model: %s\n", model);

	e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_ORIENTATION);
	if( e )
	{
		int rotate;
		switch( exif_get_short(e->data, exif_data_get_byte_order(ed)) )
		{
		case 3:
			rotate = 180;
			break;
		case 6:
			rotate = 90;
			break;
		case 8:
			rotate = 270;
			break;
		default:
			rotate = 0;
			break;
		}
		if( rotate )
			xasprintf(&m.rotation, "%d", rotate);
	}

	if( ed->size )
	{
		/* We might need to verify that the thumbnail is 160x160 or smaller */
		if( ed->size > 12000 )
		{
			imsrc = image_new_from_jpeg(NULL, 0, (char *)ed->data, ed->size, 1, ROTATE_NONE);
			if( imsrc )
			{
 				if( (imsrc->width <= 160) && (imsrc->height <= 160) )
					thumb = 1;
				image_free(imsrc);
			}
		}
		else
		{
			thumb = 1;
			//- 20130708 Sungmin add
			if(ed->data && ed->size)
			{
				char* art_file;
				if( !thumb_cache_exists(path, &art_file) )
				{
					char cache_dir[MAXPATHLEN];
					strncpyt(cache_dir, art_file, sizeof(cache_dir));
					make_dir(dirname(cache_dir), S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);

					FILE *thumb = fopen(art_file, "wb");
					//DPRINTF(E_WARN, L_METADATA, " * cache_dir: %s\n", cache_dir);
					//DPRINTF(E_WARN, L_METADATA, " * thumbnail: %s\n", art_file);
					if(thumb)
					{
						fwrite(ed->data, 1, ed->size, thumb);
						fclose(thumb);
					}
				}
				free(art_file);
			}
		}
	}
	//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * thumbnail: %d\n", thumb);

	exif_data_unref(ed);

no_exifdata:
	/* If SOF parsing fails, then fall through to reading the JPEG data with libjpeg to get the resolution */
	if( image_get_jpeg_resolution(path, &width, &height) != 0 || !width || !height )
	{
		infile = fopen(path, "r");
		if( infile )
		{
			cinfo.err = jpeg_std_error(&jerr);
			jerr.error_exit = libjpeg_error_handler;
			jpeg_create_decompress(&cinfo);
			if( setjmp(setjmp_buffer) )
				goto error;
			jpeg_stdio_src(&cinfo, infile);
			jpeg_read_header(&cinfo, TRUE);
			jpeg_start_decompress(&cinfo);
			width = cinfo.output_width;
			height = cinfo.output_height;
			error:
			jpeg_destroy_decompress(&cinfo);
			fclose(infile);
		}
	}
	//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * resolution: %dx%d\n", width, height);

	if( !width || !height )
	{
		free_metadata(&m, free_flags);
		return 0;
	}
	if( width <= 640 && height <= 480 )
		m.dlna_pn = strdup("JPEG_SM");
	else if( width <= 1024 && height <= 768 )
		m.dlna_pn = strdup("JPEG_MED");
	else if( (width <= 4096 && height <= 4096) || !GETFLAG(DLNA_STRICT_MASK) )
		m.dlna_pn = strdup("JPEG_LRG");
	xasprintf(&m.resolution, "%dx%d", width, height);

	ret = sql_exec(db, "INSERT into DETAILS"
	                   " (PATH, TITLE, SIZE, TIMESTAMP, DATE, RESOLUTION,"
	                    " ROTATION, THUMBNAIL, CREATOR, DLNA_PN, MIME) "
	                   "VALUES"
	                   " (%Q, '%q', %lld, %ld, %Q, %Q, %Q, %d, %Q, %Q, %Q);",
	                   path, name, (long long)file.st_size, file.st_mtime, m.date, m.resolution,
	                   m.rotation, thumb, m.creator, m.dlna_pn, m.mime);
	if( ret != SQLITE_OK )
	{
		fprintf(stderr, "Error inserting details for '%s'!\n", path);
		ret = 0;
	}
	else
	{
		ret = sqlite3_last_insert_rowid(db);
	}
	free_metadata(&m, free_flags);

	return ret;
}
示例#9
0
int64_t
GetAudioMetadata(const char *path, char *name)
{
	char type[4];
	static char lang[6] = { '\0' };
	struct stat file;
	int64_t ret;
	char *esc_tag;
	int i;
	int64_t album_art = 0;
	struct song_metadata song;
	metadata_t m;
	uint32_t free_flags = FLAG_MIME|FLAG_DURATION|FLAG_DLNA_PN|FLAG_DATE;
	memset(&m, '\0', sizeof(metadata_t));

	if ( stat(path, &file) != 0 )
		return 0;
	strip_ext(name);

	if( ends_with(path, ".mp3") )
	{
		strcpy(type, "mp3");
		m.mime = strdup("audio/mpeg");
	}
	else if( ends_with(path, ".m4a") || ends_with(path, ".mp4") ||
	         ends_with(path, ".aac") || ends_with(path, ".m4p") )
	{
		strcpy(type, "aac");
		m.mime = strdup("audio/mp4");
	}
	else if( ends_with(path, ".3gp") )
	{
		strcpy(type, "aac");
		m.mime = strdup("audio/3gpp");
	}
	else if( ends_with(path, ".wma") || ends_with(path, ".asf") )
	{
		strcpy(type, "asf");
		m.mime = strdup("audio/x-ms-wma");
	}
	else if( ends_with(path, ".flac") || ends_with(path, ".fla") || ends_with(path, ".flc") )
	{
		strcpy(type, "flc");
		m.mime = strdup("audio/x-flac");
	}
	else if( ends_with(path, ".wav") )
	{
		strcpy(type, "wav");
		m.mime = strdup("audio/x-wav");
	}
	else if( ends_with(path, ".ogg") || ends_with(path, ".oga") )
	{
		strcpy(type, "ogg");
		m.mime = strdup("audio/ogg");
	}
	else if( ends_with(path, ".pcm") )
	{
		strcpy(type, "pcm");
		m.mime = strdup("audio/L16");
	}
	else
	{
		DPRINTF(E_WARN, L_GENERAL, "Unhandled file extension on %s\n", path);
		return 0;
	}

	if( !(*lang) )
	{
		if( !getenv("LANG") )
			strcpy(lang, "en_US");
		else
			strncpyt(lang, getenv("LANG"), sizeof(lang));
	}

	if( readtags((char *)path, &song, &file, lang, type) != 0 )
	{
		DPRINTF(E_WARN, L_GENERAL, "Cannot extract tags from %s!\n", path);
        	freetags(&song);
		free_metadata(&m, free_flags);
		return 0;
	}

	if( song.dlna_pn )
		m.dlna_pn = strdup(song.dlna_pn);
	if( song.year )
		xasprintf(&m.date, "%04d-01-01", song.year);
	xasprintf(&m.duration, "%d:%02d:%02d.%03d",
	                      (song.song_length/3600000),
	                      (song.song_length/60000%60),
	                      (song.song_length/1000%60),
	                      (song.song_length%1000));
	if( song.title && *song.title )
	{
		m.title = trim(song.title);
		if( (esc_tag = escape_tag(m.title, 0)) )
		{
			free_flags |= FLAG_TITLE;
			m.title = esc_tag;
		}
	}
	else
	{
		m.title = name;
	}
	for( i=ROLE_START; i<N_ROLE; i++ )
	{
		if( song.contributor[i] && *song.contributor[i] )
		{
			m.creator = trim(song.contributor[i]);
			if( strlen(m.creator) > 48 )
			{
				m.creator = strdup("Various Artists");
				free_flags |= FLAG_CREATOR;
			}
			else if( (esc_tag = escape_tag(m.creator, 0)) )
			{
				m.creator = esc_tag;
				free_flags |= FLAG_CREATOR;
			}
			m.artist = m.creator;
			break;
		}
	}
	/* If there is a band associated with the album, use it for virtual containers. */
	if( (i != ROLE_BAND) && (i != ROLE_ALBUMARTIST) )
	{
	        if( song.contributor[ROLE_BAND] && *song.contributor[ROLE_BAND] )
		{
			i = ROLE_BAND;
			m.artist = trim(song.contributor[i]);
			if( strlen(m.artist) > 48 )
			{
				m.artist = strdup("Various Artists");
				free_flags |= FLAG_ARTIST;
			}
			else if( (esc_tag = escape_tag(m.artist, 0)) )
			{
				m.artist = esc_tag;
				free_flags |= FLAG_ARTIST;
			}
		}
	}
	if( song.album && *song.album )
	{
		m.album = trim(song.album);
		if( (esc_tag = escape_tag(m.album, 0)) )
		{
			free_flags |= FLAG_ALBUM;
			m.album = esc_tag;
		}
	}
	if( song.genre && *song.genre )
	{
		m.genre = trim(song.genre);
		if( (esc_tag = escape_tag(m.genre, 0)) )
		{
			free_flags |= FLAG_GENRE;
			m.genre = esc_tag;
		}
	}
	if( song.comment && *song.comment )
	{
		m.comment = trim(song.comment);
		if( (esc_tag = escape_tag(m.comment, 0)) )
		{
			free_flags |= FLAG_COMMENT;
			m.comment = esc_tag;
		}
	}

	album_art = find_album_art(path, song.image, song.image_size);

	ret = sql_exec(db, "INSERT into DETAILS"
	                   " (PATH, SIZE, TIMESTAMP, DURATION, CHANNELS, BITRATE, SAMPLERATE, DATE,"
	                   "  TITLE, CREATOR, ARTIST, ALBUM, GENRE, COMMENT, DISC, TRACK, DLNA_PN, MIME, ALBUM_ART) "
	                   "VALUES"
	                   " (%Q, %lld, %ld, '%s', %d, %d, %d, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %d, %d, %Q, '%s', %lld);",
	                   path, (long long)file.st_size, file.st_mtime, m.duration, song.channels, song.bitrate, song.samplerate, m.date,
	                   m.title, m.creator, m.artist, m.album, m.genre, m.comment, song.disc, song.track,
	                   m.dlna_pn, song.mime?song.mime:m.mime, album_art);
	if( ret != SQLITE_OK )
	{
		fprintf(stderr, "Error inserting details for '%s'!\n", path);
		ret = 0;
	}
	else
	{
		ret = sqlite3_last_insert_rowid(db);
	}
        freetags(&song);
	free_metadata(&m, free_flags);

	return ret;
}
示例#10
0
文件: user.c 项目: dborca/mc
char *
expand_format (struct WEdit *edit_widget, char c, int quote)
{
    WPanel *panel = NULL;
    char *(*quote_func) (const char *, int);
    char *fname;
    char *result;
    char c_lc;

    if (c == '%')
	return g_strdup ("%");

    if (edit_one_file != NULL)
	fname = edit_widget->filename;
    else {
	if (islower ((unsigned char) c))
	    panel = current_panel;
	else {
	    if (get_other_type () != view_listing)
		return g_strdup ("");
	    panel = other_panel;
	}
	fname = panel->dir.list[panel->selected].fname;
    }

    if (quote)
	quote_func = name_quote;
    else
	quote_func = fake_name_quote;

    c_lc = tolower ((unsigned char) c);

    switch (c_lc) {
    case 'f':
    case 'p':
	return (*quote_func) (fname, 0);
    case 'x':
	return (*quote_func) (extension (fname), 0);
    case 'd':
	{
	    char *cwd;
	    char *qstr;

	    cwd = g_malloc(MC_MAXPATHLEN + 1);

	    if (panel)
		g_strlcpy(cwd, panel->cwd, MC_MAXPATHLEN + 1);
	    else
		mc_get_current_wd(cwd, MC_MAXPATHLEN + 1);

	    qstr = (*quote_func) (cwd, 0);

	    g_free (cwd);

	    return qstr;
	}
    case 'i':			/* indent equal number cursor position in line */
	if (edit_widget)
	    return g_strnfill (edit_widget->curs_col, ' ');
	break;
    case 'y':			/* syntax type */
	if (edit_widget && edit_widget->syntax_type)
	    return g_strdup (edit_widget->syntax_type);
	break;
    case 'k':			/* block file name */
    case 'b':			/* block file name / strip extension */  {
	    if (edit_widget) {
		char *file = g_strconcat (home_dir, PATH_SEP_STR BLOCK_FILE, (char *) NULL);
		fname = (*quote_func) (file, 0);
		g_free (file);
		return fname;
	    } else if (c_lc == 'b') {
		return strip_ext ((*quote_func) (fname, 0));
	    }
	    break;
	}
    case 'e':			/* was "cooledit.error" */
	return g_strdup("/dev/null");
    case 'n':			/* strip extension in editor */
	if (edit_widget)
	    return strip_ext ((*quote_func) (fname, 0));
	break;
    case 'm':			/* menu file name */
	if (menu)
	    return (*quote_func) (menu, 0);
	break;
    case 's':
	if (!panel || !panel->marked)
	    return (*quote_func) (fname, 0);

	/* Fall through */

    case 't':
    case 'u':
	{
	    int length = 2, i;
	    char *block, *tmp;

	    if (!panel)
		return g_strdup ("");

	    for (i = 0; i < panel->count; i++)
		if (panel->dir.list[i].f.marked)
		    length += strlen (panel->dir.list[i].fname) + 1;	/* for space */

	    block = g_malloc (length * 2 + 1);
	    *block = 0;
	    for (i = 0; i < panel->count; i++)
		if (panel->dir.list[i].f.marked) {
		    strcat (block, tmp =
			    (*quote_func) (panel->dir.list[i].fname, 0));
		    g_free (tmp);
		    strcat (block, " ");
		    if (c_lc == 'u')
			do_file_mark (panel, i, 0);
		}
	    return block;
	}			/* sub case block */
    }				/* switch */
    result = g_strdup ("% ");
    result[1] = c;
    return result;
}
示例#11
0
static struct bstr strip_ext(struct bstr str)
{
    int dotpos = bstrrchr(str, '.');
    if (dotpos < 0)
        return str;
    return (struct bstr){str.start, dotpos};
}

static struct bstr get_ext(struct bstr s)
{
    int dotpos = bstrrchr(s, '.');
    if (dotpos < 0)
        return (struct bstr){NULL, 0};
    return bstr_splice(s, dotpos + 1, s.len);
}

struct subfn {
    int priority;
    char *fname;
};

static int compare_sub_priority(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    if (s1->priority > s2->priority)
        return -1;
    if (s1->priority < s2->priority)
        return 1;
    return strcoll(s1->fname, s2->fname);
}

static struct bstr guess_lang_from_filename(struct bstr name)
{
    if (name.len < 2)
        return (struct bstr){NULL, 0};

    int n = 0;
    int i = name.len - 1;

    if (name.start[i] == ')' || name.start[i] == ']')
        i--;
    while (i >= 0 && isalpha(name.start[i])) {
        n++;
        if (n > 3)
            return (struct bstr){NULL, 0};
        i--;
    }
    if (n < 2)
        return (struct bstr){NULL, 0};
    return (struct bstr){name.start + i + 1, n};
}

struct sub_list {
    struct subfn subs[MAX_SUBTITLE_FILES];
    int sid;
    void *ctx;
};

/**
 * @brief Append all the subtitles in the given path matching fname
 * @param opts MPlayer options
 * @param slist pointer to the subtitles list tallocated
 * @param nsub pointer to the number of subtitles
 * @param path Look for subtitles in this directory
 * @param fname Subtitle filename (pattern)
 * @param limit_fuzziness Ignore flag when sub_fuziness == 2
 */
static void append_dir_subtitles(struct MPOpts *opts,
                                 struct subfn **slist, int *nsub,
                                 struct bstr path, const char *fname,
                                 int limit_fuzziness)
{
    char *sub_exts[] = {"utf", "utf8", "utf-8", "sub", "srt", "smi", "rt", "txt", "ssa", "aqt", "jss", "js", "ass", NULL};
    void *tmpmem = talloc_new(NULL);
    FILE *f;
    assert(strlen(fname) < 1e6);

    struct bstr f_fname = bstr0(mp_basename(fname));
    struct bstr f_fname_noext = bstrdup(tmpmem, strip_ext(f_fname));
    bstr_lower(f_fname_noext);
    struct bstr f_fname_trim = bstr_strip(f_fname_noext);

    // 0 = nothing
    // 1 = any subtitle file
    // 2 = any sub file containing movie name
    // 3 = sub file containing movie name and the lang extension
    char *path0 = bstrdup0(tmpmem, path);
    DIR *d = opendir(path0);
    if (!d)
        goto out;
    mp_msg(MSGT_SUBREADER, MSGL_V, "Load subtitles in %.*s\n", BSTR_P(path));
    struct dirent *de;
    while ((de = readdir(d))) {
        struct bstr dename = bstr0(de->d_name);
        void *tmpmem2 = talloc_new(tmpmem);

        // retrieve various parts of the filename
        struct bstr tmp_fname_noext = bstrdup(tmpmem2, strip_ext(dename));
        bstr_lower(tmp_fname_noext);
        struct bstr tmp_fname_ext = get_ext(dename);
        struct bstr tmp_fname_trim = bstr_strip(tmp_fname_noext);

        // If it's a .sub, check if there is a .idx with the same name. If
        // there is one, it's certainly a vobsub so we skip it.
        if (bstrcasecmp(tmp_fname_ext, bstr0("sub")) == 0) {
            char *idxname = talloc_asprintf(tmpmem2, "%.*s.idx",
                                            (int)tmp_fname_noext.len,
                                            de->d_name);
            char *idx = mp_path_join(tmpmem2, path, bstr0(idxname));
            f = fopen(idx, "rt");
            if (f) {
                fclose(f);
                goto next_sub;
            }
        }

        // does it end with a subtitle extension?
#ifdef CONFIG_ICONV
#ifdef CONFIG_ENCA
        int i = (sub_cp && strncasecmp(sub_cp, "enca", 4) != 0) ? 3 : 0;
#else
        int i = sub_cp ? 3 : 0;
#endif
#else
        int i = 0;
#endif
        while (1) {
            if (!sub_exts[i])
                goto next_sub;
            if (bstrcasecmp(bstr0(sub_exts[i]), tmp_fname_ext) == 0)
                break;
            i++;
        }

        // we have a (likely) subtitle file
        int prio = 0;
        if (opts->sub_lang) {
            if (bstr_startswith(tmp_fname_trim, f_fname_trim)) {
                struct bstr lang = guess_lang_from_filename(tmp_fname_trim);
                if (lang.len) {
                    for (int n = 0; opts->sub_lang[n]; n++) {
                        if (bstr_startswith(lang,
                                            bstr0(opts->sub_lang[n]))) {
                            prio = 4; // matches the movie name + lang extension
                            break;
                        }
                    }
                }
            }
        }
        if (!prio && bstrcmp(tmp_fname_trim, f_fname_trim) == 0)
            prio = 3; // matches the movie name
        if (!prio && bstr_find(tmp_fname_trim, f_fname_trim) >= 0
            && sub_match_fuzziness >= 1)
            prio = 2; // contains the movie name
        if (!prio) {
            // doesn't contain the movie name
            // don't try in the mplayer subtitle directory
            if (!limit_fuzziness && sub_match_fuzziness >= 2) {
                prio = 1;
            }
        }

        mp_msg(MSGT_SUBREADER, MSGL_DBG2, "Potential sub file: "
               "\"%s\"  Priority: %d\n", de->d_name, prio);
        if (prio) {
            prio += prio;
#ifdef CONFIG_ICONV
            if (i < 3) // prefer UTF-8 coded
                prio++;
#endif
            char *subpath = mp_path_join(*slist, path, dename);
            if ((f = fopen(subpath, "rt"))) {
                MP_GROW_ARRAY(*slist, *nsub);
                struct subfn *sub = *slist + (*nsub)++;

                fclose(f);
                sub->priority = prio;
                sub->fname    = subpath;
            } else
                talloc_free(subpath);
        }

    next_sub:
        talloc_free(tmpmem2);
    }
    closedir(d);

 out:
    talloc_free(tmpmem);
}

char **find_text_subtitles(struct MPOpts *opts, const char *fname)
{
    char **subnames = NULL;
    struct subfn *slist = talloc_array_ptrtype(NULL, slist, 1);
    int n = 0;

    // Load subtitles from current media directory
    append_dir_subtitles(opts, &slist, &n, mp_dirname(fname), fname, 0);

    // Load subtitles in dirs specified by sub-paths option
    if (opts->sub_paths) {
        for (int i = 0; opts->sub_paths[i]; i++) {
            char *path = mp_path_join(slist, mp_dirname(fname),
                                      bstr0(opts->sub_paths[i]));
            append_dir_subtitles(opts, &slist, &n, bstr0(path), fname, 0);
        }
    }

    // Load subtitles in ~/.mplayer/sub limiting sub fuzziness
    char *mp_subdir = get_path("sub/");
    if (mp_subdir)
        append_dir_subtitles(opts, &slist, &n, bstr0(mp_subdir), fname, 1);
    free(mp_subdir);

    // Sort subs by priority and append them
    qsort(slist, n, sizeof(*slist), compare_sub_priority);

    subnames = talloc_array_ptrtype(NULL, subnames, n);
    for (int i = 0; i < n; i++)
        subnames[i] = talloc_strdup(subnames, slist[i].fname);

    talloc_free(slist);
    return subnames;
}

char **find_vob_subtitles(struct MPOpts *opts, const char *fname)
{
    char **vobs = talloc_array_ptrtype(NULL, vobs, 1);
    int n = 0;

    // Potential vobsub in the media directory
    struct bstr bname = bstr0(mp_basename(fname));
    int pdot = bstrrchr(bname, '.');
    if (pdot >= 0)
        bname.len = pdot;
    vobs[n++] = mp_path_join(vobs, mp_dirname(fname), bname);

    // Potential vobsubs in directories specified by sub-paths option
    if (opts->sub_paths) {
        for (int i = 0; opts->sub_paths[i]; i++) {
            char *path = mp_path_join(NULL, mp_dirname(fname),
                                      bstr0(opts->sub_paths[i]));
            MP_GROW_ARRAY(vobs, n);
            vobs[n++] = mp_path_join(vobs, bstr0(path), bname);
            talloc_free(path);
        }
    }

    // Potential vobsub in ~/.mplayer/sub
    char *mp_subdir = get_path("sub/");
    if (mp_subdir) {
        MP_GROW_ARRAY(vobs, n);
        vobs[n++] = mp_path_join(vobs, bstr0(mp_subdir), bname);
    }

    free(mp_subdir);
    MP_RESIZE_ARRAY(NULL, vobs, n);
    return vobs;
}
示例#12
0
文件: main.c 项目: DeltaYang/wine
static void do_name (const char *arg)
{
  globals.dll_name = strip_ext (arg);
}
示例#13
0
char *
expand_format (struct WEdit *edit_widget, char c, gboolean do_quote)
{
    WPanel *panel = NULL;
    char *(*quote_func) (const char *, int);
    char *fname = NULL;
    char *result;
    char c_lc;

#ifndef USE_INTERNAL_EDIT
    (void) edit_widget;
#endif

    if (c == '%')
        return g_strdup ("%");

    if (mc_run_mode == MC_RUN_FULL)
    {
        if (g_ascii_islower ((gchar) c))
            panel = current_panel;
        else
        {
            if (get_other_type () != view_listing)
                return g_strdup ("");
            panel = other_panel;
        }
        fname = panel->dir.list[panel->selected].fname;
    }
#ifdef USE_INTERNAL_EDIT
    else if (mc_run_mode == MC_RUN_EDITOR)
        fname = (char *) edit_get_file_name (edit_widget);
#endif

    if (do_quote)
        quote_func = name_quote;
    else
        quote_func = fake_name_quote;

    c_lc = g_ascii_tolower ((gchar) c);

    switch (c_lc)
    {
    case 'f':
    case 'p':
        return (*quote_func) (fname, 0);
    case 'x':
        return (*quote_func) (extension (fname), 0);
    case 'd':
        {
            char *cwd;
            char *qstr;

            cwd = g_malloc (MC_MAXPATHLEN + 1);

            if (panel)
                g_strlcpy (cwd, panel->cwd, MC_MAXPATHLEN + 1);
            else
                mc_get_current_wd (cwd, MC_MAXPATHLEN + 1);

            qstr = (*quote_func) (cwd, 0);

            g_free (cwd);

            return qstr;
        }
    case 'i':                  /* indent equal number cursor position in line */
#ifdef USE_INTERNAL_EDIT
        if (edit_widget)
            return g_strnfill (edit_get_curs_col (edit_widget), ' ');
#endif
        break;
    case 'y':                  /* syntax type */
#ifdef USE_INTERNAL_EDIT
        if (edit_widget)
        {
            const char *syntax_type = edit_get_syntax_type (edit_widget);
            if (syntax_type != NULL)
                return g_strdup (syntax_type);
        }
#endif
        break;
    case 'k':                  /* block file name */
    case 'b':                  /* block file name / strip extension */
        {
#ifdef USE_INTERNAL_EDIT
            if (edit_widget)
            {
                char *file = concat_dir_and_file (mc_config_get_cache_path (), EDIT_BLOCK_FILE);
                fname = (*quote_func) (file, 0);
                g_free (file);
                return fname;
            }
#endif
            if (c_lc == 'b')
                return strip_ext ((*quote_func) (fname, 0));
            break;
        }
    case 'n':                  /* strip extension in editor */
#ifdef USE_INTERNAL_EDIT
        if (edit_widget)
            return strip_ext ((*quote_func) (fname, 0));
#endif
        break;
    case 'm':                  /* menu file name */
        if (menu)
            return (*quote_func) (menu, 0);
        break;
    case 's':
        if (!panel || !panel->marked)
            return (*quote_func) (fname, 0);

        /* Fall through */

    case 't':
    case 'u':
        {
            int length = 2, i;
            char *block, *tmp;

            if (!panel)
                return g_strdup ("");

            for (i = 0; i < panel->count; i++)
                if (panel->dir.list[i].f.marked)
                    length += strlen (panel->dir.list[i].fname) + 1;    /* for space */

            block = g_malloc (length * 2 + 1);
            *block = 0;
            for (i = 0; i < panel->count; i++)
                if (panel->dir.list[i].f.marked)
                {
                    tmp = (*quote_func) (panel->dir.list[i].fname, 0);
                    strcat (block, tmp);
                    g_free (tmp);
                    strcat (block, " ");
                    if (c_lc == 'u')
                        do_file_mark (panel, i, 0);
                }
            return block;
        }                       /* sub case block */
    }                           /* switch */
    result = g_strdup ("% ");
    result[1] = c;
    return result;
}
示例#14
0
int
FileSelector ()
{
    u32 p, wp, ph, wh;
    signed char a, c;
    int haverom = 0;
    int redraw = 1;
    int selectit = 0;
	float mag = 0;
	float mag2 = 0;
	u16 ang = 0;
	u16 ang2 = 0;
	int scroll_delay = 0;
	bool move_selection = 0;
	#define SCROLL_INITIAL_DELAY	15
	#define SCROLL_LOOP_DELAY		4
    
    while (haverom == 0)    
    {
        if (redraw)
            ShowFiles (offset, selection);
        redraw = 0;

		VIDEO_WaitVSync();	// slow things down a bit so we don't overread the pads
		
        p = PAD_ButtonsDown (0);
		ph = PAD_ButtonsHeld (0);
#ifdef HW_RVL
		wp = WPAD_ButtonsDown (0);
		wh = WPAD_ButtonsHeld (0);
		wpad_get_analogues(0, &mag, &ang, &mag2, &ang2);		// get joystick info from wii expansions
#else
		wp = 0;
		wh = 0;
#endif
		a = PAD_StickY (0);
		c = PAD_SubStickX (0);
        
		/*** Check for exit combo ***/
		if ( (c < -70) || (wp & WPAD_BUTTON_HOME) || (wp & WPAD_CLASSIC_BUTTON_HOME) ) return 0;
		
		/*** Check buttons, perform actions ***/
        if ( (p & PAD_BUTTON_A) || selectit || (wp & (WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A)) )
        {
            if ( selectit )
                selectit = 0;
            if (filelist[selection].flags)                        /*** This is directory ***/
            {
                if (loadtype == LOAD_SDC || loadtype == LOAD_USB)
                {
                    /* memorize last entries list, actual root directory and selection for next access */
					if (loadtype == LOAD_SDC)
						haveSDdir = 1;
					else
						haveUSBdir = 1;
                    
                    /* update current directory and set new entry list if directory has changed */
                    int status = updateFATdirname();
                    if (status == 1)	// ok, open directory
                    {
                        maxfiles = parseFATdirectory();
                        if (!maxfiles)
                        {
                            WaitPrompt ((char*) "Error reading directory !");
                            haverom   = 1; // quit SD menu
                            if (loadtype == LOAD_SDC)  // reset everything at next access
								haveSDdir = 0;
							else
								haveUSBdir = 0;
                        }
                    }
                    else if (status == -1)	// directory name too long
                    {
                        haverom   = 1; // quit SD menu
                        if (loadtype == LOAD_SDC)  // reset everything at next access
							haveSDdir = 0;
						else
							haveUSBdir = 0;
                    }
                }
                else
                {
                    if ( (strcmp (filelist[selection].filename, "..") == 0)
                        &&  ((unsigned int)rootdir == filelist[selection].offset) )
                        return 0;
                    else
                    {
                        rootdir = filelist[selection].offset;
                        rootdirlength = filelist[selection].length;
                        offset = selection = 0;
                        maxfiles = parsedirectory ();
                    }
                }
            }
            else	// this is a file
            {
                rootdir = filelist[selection].offset;
                rootdirlength = filelist[selection].length;
				
				/*** store the filename (used for sram/freeze naming) ***/
				strip_ext(filelist[selection].filename, Memory.ROMFilename);	// store stripped filename in Memory.ROMFilename
                
                switch (loadtype)
                {
                    case LOAD_DVD:
                        /*** Now load the DVD file to it's offset ***/
                        ARAM_ROMSIZE = LoadDVDFile (Memory.ROM);
                        break;
                    
                    case LOAD_SMB:
                        /*** Load from SMB ***/
                        ARAM_ROMSIZE = LoadSMBFile (filelist[selection].filename,
                             filelist[selection].length);
                        break;
                    
					case LOAD_USB:
                    case LOAD_SDC:
                        /*** Load from SD Card ***/
                        /* memorize last entries list, actual root directory and selection for next access */
                        haveSDdir = 1;
                        ARAM_ROMSIZE = LoadSDFile (filelist[selection].filename,
                                         filelist[selection].length);
                        break;
                }
                
                if (ARAM_ROMSIZE > 0)
                {
                    hasloaded = 1;
                    Memory.LoadROM ("BLANK.SMC");
                
                    Memory.LoadSRAM ("BLANK");
                    haverom = 1;
                    
                    return 1;
                }
                else
                {
                    WaitPrompt((char*) "Error loading ROM!");
                }
            }
            redraw = 1;
        }	// End of A
        if ( (p & PAD_BUTTON_B) || (wp & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)) )
        {
            while ( (PAD_ButtonsDown(0) & PAD_BUTTON_B) 
#ifdef HW_RVL
					|| (WPAD_ButtonsDown(0) & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)) 
#endif
					)
                VIDEO_WaitVSync();
            //if ((strcmp(filelist[1].filename,"..") == 0) && (strlen (filelist[0].filename) != 0))
			if ( strcmp(filelist[0].filename,"..") == 0 ) 
			{
				selection = 0;
				selectit = 1;
			}
			else if ( strcmp(filelist[1].filename,"..") == 0 ) 
			{
                selection = selectit = 1;
			} else {
                return 0;
			}
        }	// End of B
        if ( ((p | ph) & PAD_BUTTON_DOWN) || ((wp | wh) & (WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN)) || (a < -PADCAL) || (mag>JOY_THRESHOLD && (ang>130 && ang<230)) )
        {
			if ( (p & PAD_BUTTON_DOWN) || (wp & (WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN)) ) { /*** Button just pressed ***/
				scroll_delay = SCROLL_INITIAL_DELAY;	// reset scroll delay.
				move_selection = 1;	//continue (move selection)
			} 
			else if (scroll_delay == 0) { 		/*** Button is held ***/
				scroll_delay = SCROLL_LOOP_DELAY;
				move_selection = 1;	//continue (move selection)
			} else {
				scroll_delay--;	// wait
			}
				
			if (move_selection)
			{
	            selection++;
	            if (selection == maxfiles)
	                selection = offset = 0;
	            if ((selection - offset) >= PAGESIZE)
	                offset += PAGESIZE;
	            redraw = 1;
				move_selection = 0;
			}
        }	// End of down
        if ( ((p | ph) & PAD_BUTTON_UP) || ((wp | wh) & (WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP)) || (a > PADCAL) || (mag>JOY_THRESHOLD && (ang>300 || ang<50)) )
        {	
			if ( (p & PAD_BUTTON_UP) || (wp & (WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP)) ) { /*** Button just pressed***/
				scroll_delay = SCROLL_INITIAL_DELAY;	// reset scroll delay.
				move_selection = 1;	//continue (move selection)
			} 
			else if (scroll_delay == 0) { 		/*** Button is held ***/
				scroll_delay = SCROLL_LOOP_DELAY;
				move_selection = 1;	//continue (move selection)
			} else {
				scroll_delay--;	// wait
			}
			
			if (move_selection)
			{
	            selection--;
	            if (selection < 0) {
	                selection = maxfiles - 1;
	                offset = selection - PAGESIZE + 1;
	            }
	            if (selection < offset)
	                offset -= PAGESIZE;
	            if (offset < 0)
	                offset = 0;
	            redraw = 1;
				move_selection = 0;
			}
        }	// End of Up
        if ( (p & PAD_BUTTON_LEFT) || (wp & (WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT)) )
        {
            /*** Go back a page ***/
            selection -= PAGESIZE;
            if (selection < 0)
            {
                selection = maxfiles - 1;
                offset = selection - PAGESIZE + 1;
            }
            if (selection < offset)
                offset -= PAGESIZE;
            if (offset < 0)
                offset = 0;
            redraw = 1;
        }
        if ( (p & PAD_BUTTON_RIGHT) || (wp & (WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT)) )
        {
            /*** Go forward a page ***/
            selection += PAGESIZE;
            if (selection > maxfiles - 1)
                selection = offset = 0;
            if ((selection - offset) >= PAGESIZE)
                offset += PAGESIZE;
            redraw = 1;
        }
    }
    return 0;
}
示例#15
0
char *
expand_format (struct WEdit *edit_widget, char c, gboolean do_quote)
{
    WPanel *panel = NULL;
    char *(*quote_func) (const char *, int);
    char *fname = NULL;
    char *result;
    char c_lc;

#ifndef USE_INTERNAL_EDIT
    (void) edit_widget;
#endif

    if (c == '%')
        return g_strdup ("%");

    switch (mc_global.mc_run_mode)
    {
    case MC_RUN_FULL:
        if (g_ascii_islower ((gchar) c))
            panel = current_panel;
        else
        {
            if (get_other_type () != view_listing)
                return g_strdup ("");
            panel = other_panel;
        }
        fname = g_strdup (panel->dir.list[panel->selected].fname);
        break;

#ifdef USE_INTERNAL_EDIT
    case MC_RUN_EDITOR:
        fname = edit_get_file_name (edit_widget);
        break;
#endif

    default:
        /* other modes don't use formats */
        return g_strdup ("");
    }

    if (do_quote)
        quote_func = name_quote;
    else
        quote_func = fake_name_quote;

    c_lc = g_ascii_tolower ((gchar) c);

    switch (c_lc)
    {
    case 'f':
    case 'p':
        result = (*quote_func) (fname, 0);
        goto ret;
    case 'x':
        result = (*quote_func) (extension (fname), 0);
        goto ret;
    case 'd':
        {
            char *cwd;
            char *qstr;

            if (panel)
                cwd = g_strdup (vfs_path_as_str (panel->cwd_vpath));
            else
                cwd = vfs_get_current_dir ();

            qstr = (*quote_func) (cwd, 0);

            g_free (cwd);

            result = qstr;
            goto ret;
        }
    case 'i':                  /* indent equal number cursor position in line */
#ifdef USE_INTERNAL_EDIT
        if (edit_widget)
        {
            result = g_strnfill (edit_get_curs_col (edit_widget), ' ');
            goto ret;
        }
#endif
        break;
    case 'y':                  /* syntax type */
#ifdef USE_INTERNAL_EDIT
        if (edit_widget)
        {
            const char *syntax_type = edit_get_syntax_type (edit_widget);
            if (syntax_type != NULL)
            {
                result = g_strdup (syntax_type);
                goto ret;
            }
        }
#endif
        break;
    case 'k':                  /* block file name */
    case 'b':                  /* block file name / strip extension */
        {
#ifdef USE_INTERNAL_EDIT
            if (edit_widget)
            {
                char *file;

                file = mc_config_get_full_path (EDIT_BLOCK_FILE);
                result = (*quote_func) (file, 0);
                g_free (file);
                goto ret;
            }
#endif
            if (c_lc == 'b')
            {
                result = strip_ext ((*quote_func) (fname, 0));
                goto ret;
            }
            break;
        }
    case 'n':                  /* strip extension in editor */
#ifdef USE_INTERNAL_EDIT
        if (edit_widget)
        {
            result = strip_ext ((*quote_func) (fname, 0));
            goto ret;
        }
#endif
        break;
    case 'm':                  /* menu file name */
        if (menu)
        {
            result = (*quote_func) (menu, 0);
            goto ret;
        }
        break;
    case 's':
        if (!panel || !panel->marked)
        {
            result = (*quote_func) (fname, 0);
            goto ret;
        }

        /* Fall through */

    case 't':
    case 'u':
        {
            GString *block;
            int i;

            if (panel == NULL)
            {
                result = g_strdup ("");
                goto ret;
            }

            block = g_string_sized_new (16);

            for (i = 0; i < panel->dir.len; i++)
                if (panel->dir.list[i].f.marked)
                {
                    char *tmp;

                    tmp = (*quote_func) (panel->dir.list[i].fname, 0);
                    g_string_append (block, tmp);
                    g_string_append_c (block, ' ');
                    g_free (tmp);

                    if (c_lc == 'u')
                        do_file_mark (panel, i, 0);
                }
            result = g_string_free (block, FALSE);
            goto ret;
        }                       /* sub case block */
    }                           /* switch */
    result = g_strdup ("% ");
    result[1] = c;
  ret:
    g_free (fname);
    return result;
}
示例#16
0
int64_t
GetAudioMetadata(const char *path, char *name)
{
	char type[4];
	static char lang[6] = { '\0' };
	struct stat file;
	int64_t ret;
	char *esc_tag;
	int i;
	int64_t album_art = 0;
	struct song_metadata song;
	metadata_t m;
	uint32_t free_flags = FLAG_MIME|FLAG_DURATION|FLAG_DLNA_PN|FLAG_DATE;
	memset(&m, '\0', sizeof(metadata_t));

	if ( stat(path, &file) != 0 )
		return 0;
	strip_ext(name);

	if( ends_with(path, ".mp3") )
	{
		strcpy(type, "mp3");
		m.mime = strdup("audio/mpeg");
	}
	else if( ends_with(path, ".m4a") || ends_with(path, ".mp4") ||
	         ends_with(path, ".aac") || ends_with(path, ".m4p") )
	{
		strcpy(type, "aac");
		m.mime = strdup("audio/mp4");
	}
	else if( ends_with(path, ".3gp") )
	{
		strcpy(type, "aac");
		m.mime = strdup("audio/3gpp");
	}
	else if( ends_with(path, ".wma") || ends_with(path, ".asf") )
	{
		strcpy(type, "asf");
		m.mime = strdup("audio/x-ms-wma");
	}
	else if( ends_with(path, ".flac") || ends_with(path, ".fla") || ends_with(path, ".flc") )
	{
		strcpy(type, "flc");
		m.mime = strdup("audio/x-flac");
	}
	else if( ends_with(path, ".wav") )
	{
		strcpy(type, "wav");
		m.mime = strdup("audio/x-wav");
	}
	else if( ends_with(path,".oga") || ends_with(path,".ogg"))
	{
		/* The .ogg/.oga file extensions present something of a problem.
		 * ".ogg" has been deprecated in favor of ".oga" for some time, but
		 * many applications still only recognize ".ogg".
		 *
		 * This examines the file and causes .ogg to be presented for any naked
		 * Vorbis file (MIME type audio/ogg; codecs=vorbis) and .oga
		 * (audio/ogg) to be used for everything else.  This is in line with
		 * the official ogg naming conventions and, hopefully, makes for a
		 * resonable compromise.
		 */
		uint8_t oggtestbuf[35];
		FILE *oggfile = fopen (path, "rb");

		if (oggfile == (FILE *)NULL)
		{
			DPRINTF(E_ERROR, L_METADATA, "Error opening %s\n", path);
			return 0;
		}

		if (fread (oggtestbuf, 1, 35, oggfile) != 35)
		{
			DPRINTF(E_WARN, L_METADATA, "Premature EOF on %s\n", path);
			fclose (oggfile);
			return 0;
		}
		fclose (oggfile);

		if (memcmp (&oggtestbuf[28], "\x01vorbis", 7))
			m.mime = strdup ("audio/ogg");
		else
			m.mime = strdup ("audio/ogg; codecs=vorbis");

		strcpy(type, "ogg");
	}
	else if ( ends_with(path, ".opus") )
	{
		strcpy(type,"ops");
		m.mime = strdup("audio/ogg; codecs=opus");
	}
#if 0
	/* Not supported yet, and probably won't be. */
	else if( ends_with(path, ".ogx") )
	{
		strcpy(type, "ogx");
		m.mime = strdup("application/ogg");
	}
#endif
	else if( ends_with(path, ".pcm") )
	{
		strcpy(type, "pcm");
		m.mime = strdup("audio/L16");
	}
	else
	{
		DPRINTF(E_WARN, L_METADATA, "Unhandled file extension on %s\n", path);
		return 0;
	}

	if( !(*lang) )
	{
		if( !getenv("LANG") )
			strcpy(lang, "en_US");
		else
			strncpyt(lang, getenv("LANG"), sizeof(lang));
	}

	if( readtags((char *)path, &song, &file, lang, type) != 0 )
	{
		DPRINTF(E_WARN, L_METADATA, "Cannot extract tags from %s!\n", path);
        	freetags(&song);
		free_metadata(&m, free_flags);
		return 0;
	}

	if( song.dlna_pn )
		m.dlna_pn = strdup(song.dlna_pn);
	if( song.year )
		xasprintf(&m.date, "%04d-01-01", song.year);
	xasprintf(&m.duration, "%d:%02d:%02d.%03d",
	                      (song.song_length/3600000),
	                      (song.song_length/60000%60),
	                      (song.song_length/1000%60),
	                      (song.song_length%1000));
	if( song.title && *song.title )
	{
		m.title = trim(song.title);
		if( (esc_tag = escape_tag(m.title, 0)) )
		{
			free_flags |= FLAG_TITLE;
			m.title = esc_tag;
		}
	}
	else
	{
		m.title = name;
	}
	for( i = ROLE_START; i < N_ROLE; i++ )
	{
		if( song.contributor[i] && *song.contributor[i] )
		{
			m.creator = trim(song.contributor[i]);
			if( strlen(m.creator) > 48 )
			{
				m.creator = strdup("Various Artists");
				free_flags |= FLAG_CREATOR;
			}
			else if( (esc_tag = escape_tag(m.creator, 0)) )
			{
				m.creator = esc_tag;
				free_flags |= FLAG_CREATOR;
			}
			m.artist = m.creator;
			break;
		}
	}
	/* If there is a album artist or band associated with the album,
	   use it for virtual containers. */
	if( i < ROLE_ALBUMARTIST )
	{
		for( i = ROLE_ALBUMARTIST; i <= ROLE_BAND; i++ )
		{
	        	if( song.contributor[i] && *song.contributor[i] )
				break;
		}
	        if( i <= ROLE_BAND )
		{
			m.artist = trim(song.contributor[i]);
			if( strlen(m.artist) > 48 )
			{
				m.artist = strdup("Various Artists");
				free_flags |= FLAG_ARTIST;
			}
			else if( (esc_tag = escape_tag(m.artist, 0)) )
			{
				m.artist = esc_tag;
				free_flags |= FLAG_ARTIST;
			}
		}
	}
	if( song.album && *song.album )
	{
		m.album = trim(song.album);
		if( (esc_tag = escape_tag(m.album, 0)) )
		{
			free_flags |= FLAG_ALBUM;
			m.album = esc_tag;
		}
	}
	if( song.genre && *song.genre )
	{
		m.genre = trim(song.genre);
		if( (esc_tag = escape_tag(m.genre, 0)) )
		{
			free_flags |= FLAG_GENRE;
			m.genre = esc_tag;
		}
	}
	if( song.comment && *song.comment )
	{
		m.comment = trim(song.comment);
		if( (esc_tag = escape_tag(m.comment, 0)) )
		{
			free_flags |= FLAG_COMMENT;
			m.comment = esc_tag;
		}
	}

	album_art = find_album_art(path, song.image, song.image_size);

	ret = sql_exec(db, "INSERT into DETAILS"
	                   " (PATH, SIZE, TIMESTAMP, DURATION, CHANNELS, BITRATE, SAMPLERATE, DATE,"
	                   "  TITLE, CREATOR, ARTIST, ALBUM, GENRE, COMMENT, DISC, TRACK, DLNA_PN, MIME, ALBUM_ART) "
	                   "VALUES"
	                   " (%Q, %lld, %lld, '%s', %d, %d, %d, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %d, %d, %Q, '%s', %lld);",
	                   path, (long long)file.st_size, (long long)file.st_mtime, m.duration, song.channels, song.bitrate,
	                   song.samplerate, m.date, m.title, m.creator, m.artist, m.album, m.genre, m.comment, song.disc,
	                   song.track, m.dlna_pn, song.mime?song.mime:m.mime, album_art);
	if( ret != SQLITE_OK )
	{
		DPRINTF(E_ERROR, L_METADATA, "Error inserting details for '%s'!\n", path);
		ret = 0;
	}
	else
	{
		ret = sqlite3_last_insert_rowid(db);
	}
        freetags(&song);
	free_metadata(&m, free_flags);

	return ret;
}
示例#17
0
//------------------------------main-------------------------------------------
int main(int argc, char *argv[])
{
  ArchDesc      AD;             // Architecture Description object
  globalAD = &AD;

  // ResourceMark  mark;
  ADLParser    *ADL_Parse;      // ADL Parser object to parse AD file

  // Check for proper arguments
  if( argc == 1 ) usage(AD);    // No arguments?  Then print usage

  // Read command line arguments and file names
  for( int i = 1; i < argc; i++ ) { // For all arguments
    register char *s = argv[i]; // Get option/filename

    if( *s++ == '-' ) {         // It's a flag? (not a filename)
      if( !*s ) {               // Stand-alone `-' means stdin
        //********** INSERT CODE HERE **********
      } else while (*s != '\0') { // While have flags on option
        switch (*s++) {         // Handle flag
        case 'd':               // Debug flag
          AD._dfa_debug += 1;   // Set Debug Flag
          break;
        case 'g':               // Debug ad location flag
          AD._adlocation_debug += 1;       // Set Debug ad location Flag
          break;
        case 'o':               // No Output Flag
          AD._no_output ^= 1;   // Toggle no_output flag
          break;
        case 'q':               // Quiet Mode Flag
          AD._quiet_mode ^= 1;  // Toggle quiet_mode flag
          break;
        case 'w':               // Disable Warnings Flag
          AD._disable_warnings ^= 1; // Toggle disable_warnings flag
          break;
        case 'T':               // Option to make DFA as many subroutine calls.
          AD._dfa_small += 1;   // Set Mode Flag
          break;
        case 'c': {             // Set C++ Output file name
          AD._CPP_file._name = s;
          const char *base = strip_ext(strdup(s));
          AD._CPP_CLONE_file._name    = base_plus_suffix(base,"_clone.cpp");
          AD._CPP_EXPAND_file._name   = base_plus_suffix(base,"_expand.cpp");
          AD._CPP_FORMAT_file._name   = base_plus_suffix(base,"_format.cpp");
          AD._CPP_GEN_file._name      = base_plus_suffix(base,"_gen.cpp");
          AD._CPP_MISC_file._name     = base_plus_suffix(base,"_misc.cpp");
          AD._CPP_PEEPHOLE_file._name = base_plus_suffix(base,"_peephole.cpp");
          AD._CPP_PIPELINE_file._name = base_plus_suffix(base,"_pipeline.cpp");
          s += strlen(s);
          break;
        }
        case 'h':               // Set C++ Output file name
          AD._HPP_file._name = s; s += strlen(s);
          break;
        case 'v':               // Set C++ Output file name
          AD._VM_file._name = s; s += strlen(s);
          break;
        case 'a':               // Set C++ Output file name
          AD._DFA_file._name = s;
          AD._bug_file._name = s;
          s += strlen(s);
          break;
        case '#':               // Special internal debug flag
          AD._adl_debug++;      // Increment internal debug level
          break;
        case 's':               // Output which instructions are cisc-spillable
          AD._cisc_spill_debug = true;
          break;
        case 'D':               // Flag Definition
          {
            char* flag = s;
            s += strlen(s);
            char* def = strchr(flag, '=');
            if (def == NULL)  def = (char*)"1";
            else              *def++ = '\0';
            AD.set_preproc_def(flag, def);
          }
          break;
        case 'U':               // Flag Un-Definition
          {
            char* flag = s;
            s += strlen(s);
            AD.set_preproc_def(flag, NULL);
          }
          break;
        default:                // Unknown option
          usage(AD);            // So print usage and exit
        }                       // End of switch on options...
      }                         // End of while have options...

    } else {                    // Not an option; must be a filename
      AD._ADL_file._name = argv[i]; // Set the input filename

      // // Files for storage, based on input file name
      const char *base = strip_ext(strdup(argv[i]));
      char       *temp = base_plus_suffix("dfa_",base);
      AD._DFA_file._name = base_plus_suffix(temp,".cpp");
      delete temp;
      temp = base_plus_suffix("ad_",base);
      AD._CPP_file._name          = base_plus_suffix(temp,".cpp");
      AD._CPP_CLONE_file._name    = base_plus_suffix(temp,"_clone.cpp");
      AD._CPP_EXPAND_file._name   = base_plus_suffix(temp,"_expand.cpp");
      AD._CPP_FORMAT_file._name   = base_plus_suffix(temp,"_format.cpp");
      AD._CPP_GEN_file._name      = base_plus_suffix(temp,"_gen.cpp");
      AD._CPP_MISC_file._name     = base_plus_suffix(temp,"_misc.cpp");
      AD._CPP_PEEPHOLE_file._name = base_plus_suffix(temp,"_peephole.cpp");
      AD._CPP_PIPELINE_file._name = base_plus_suffix(temp,"_pipeline.cpp");
      AD._HPP_file._name = base_plus_suffix(temp,".hpp");
      delete temp;
      temp = base_plus_suffix("adGlobals_",base);
      AD._VM_file._name = base_plus_suffix(temp,".hpp");
      delete temp;
      temp = base_plus_suffix("bugs_",base);
      AD._bug_file._name = base_plus_suffix(temp,".out");
      delete temp;
    }                           // End of files vs options...
  }                             // End of while have command line arguments

  // Open files used to store the matcher and its components
  if (AD.open_files() == 0) return 1; // Open all input/output files

  // Build the File Buffer, Parse the input, & Generate Code
  FileBuff  ADL_Buf(&AD._ADL_file, AD); // Create a file buffer for input file

  // Get pointer to legal text at the beginning of AD file.
  // It will be used in generated ad files.
  char* legal_text;
  int legal_sz = get_legal_text(ADL_Buf, &legal_text);

  ADL_Parse = new ADLParser(ADL_Buf, AD); // Create a parser to parse the buffer
  ADL_Parse->parse();           // Parse buffer & build description lists

  if( AD._dfa_debug >= 1 ) {    // For higher debug settings, print dump
    AD.dump();
  }

  delete ADL_Parse;             // Delete parser

  // Verify that the results of the parse are consistent
  AD.verify();

  // Prepare to generate the result files:
  AD.generateMatchLists();
  AD.identify_unique_operands();
  AD.identify_cisc_spill_instructions();
  AD.identify_short_branches();
  // Make sure every file starts with a copyright:
  AD.addSunCopyright(legal_text, legal_sz, AD._HPP_file._fp);           // .hpp
  AD.addSunCopyright(legal_text, legal_sz, AD._CPP_file._fp);           // .cpp
  AD.addSunCopyright(legal_text, legal_sz, AD._CPP_CLONE_file._fp);     // .cpp
  AD.addSunCopyright(legal_text, legal_sz, AD._CPP_EXPAND_file._fp);    // .cpp
  AD.addSunCopyright(legal_text, legal_sz, AD._CPP_FORMAT_file._fp);    // .cpp
  AD.addSunCopyright(legal_text, legal_sz, AD._CPP_GEN_file._fp);       // .cpp
  AD.addSunCopyright(legal_text, legal_sz, AD._CPP_MISC_file._fp);      // .cpp
  AD.addSunCopyright(legal_text, legal_sz, AD._CPP_PEEPHOLE_file._fp);  // .cpp
  AD.addSunCopyright(legal_text, legal_sz, AD._CPP_PIPELINE_file._fp);  // .cpp
  AD.addSunCopyright(legal_text, legal_sz, AD._VM_file._fp);            // .hpp
  AD.addSunCopyright(legal_text, legal_sz, AD._DFA_file._fp);           // .cpp
  // Add include guards for all .hpp files
  AD.addIncludeGuardStart(AD._HPP_file, "GENERATED_ADFILES_AD_HPP");        // .hpp
  AD.addIncludeGuardStart(AD._VM_file, "GENERATED_ADFILES_ADGLOBALS_HPP");  // .hpp
  // Add includes
  AD.addInclude(AD._CPP_file, "precompiled.hpp");
  AD.addInclude(AD._CPP_file, "adfiles", get_basename(AD._VM_file._name));
  AD.addInclude(AD._CPP_file, "adfiles", get_basename(AD._HPP_file._name));
  AD.addInclude(AD._CPP_file, "memory/allocation.inline.hpp");
  AD.addInclude(AD._CPP_file, "asm/macroAssembler.inline.hpp");
  AD.addInclude(AD._CPP_file, "code/compiledIC.hpp");
  AD.addInclude(AD._CPP_file, "code/nativeInst.hpp");
  AD.addInclude(AD._CPP_file, "code/vmreg.inline.hpp");
  AD.addInclude(AD._CPP_file, "gc/shared/collectedHeap.inline.hpp");
  AD.addInclude(AD._CPP_file, "oops/compiledICHolder.hpp");
  AD.addInclude(AD._CPP_file, "oops/markOop.hpp");
  AD.addInclude(AD._CPP_file, "oops/method.hpp");
  AD.addInclude(AD._CPP_file, "oops/oop.inline.hpp");
  AD.addInclude(AD._CPP_file, "opto/cfgnode.hpp");
  AD.addInclude(AD._CPP_file, "opto/locknode.hpp");
  AD.addInclude(AD._CPP_file, "opto/opcodes.hpp");
  AD.addInclude(AD._CPP_file, "opto/regalloc.hpp");
  AD.addInclude(AD._CPP_file, "opto/regmask.hpp");
  AD.addInclude(AD._CPP_file, "opto/runtime.hpp");
  AD.addInclude(AD._CPP_file, "runtime/biasedLocking.hpp");
  AD.addInclude(AD._CPP_file, "runtime/sharedRuntime.hpp");
  AD.addInclude(AD._CPP_file, "runtime/stubRoutines.hpp");
  AD.addInclude(AD._CPP_file, "utilities/growableArray.hpp");
  AD.addInclude(AD._HPP_file, "memory/allocation.hpp");
  AD.addInclude(AD._HPP_file, "code/nativeInst.hpp");
  AD.addInclude(AD._HPP_file, "opto/machnode.hpp");
  AD.addInclude(AD._HPP_file, "opto/node.hpp");
  AD.addInclude(AD._HPP_file, "opto/regalloc.hpp");
  AD.addInclude(AD._HPP_file, "opto/subnode.hpp");
  AD.addInclude(AD._HPP_file, "opto/vectornode.hpp");
  AD.addInclude(AD._CPP_CLONE_file, "precompiled.hpp");
  AD.addInclude(AD._CPP_CLONE_file, "adfiles", get_basename(AD._HPP_file._name));
  AD.addInclude(AD._CPP_EXPAND_file, "precompiled.hpp");
  AD.addInclude(AD._CPP_EXPAND_file, "adfiles", get_basename(AD._HPP_file._name));
  AD.addInclude(AD._CPP_FORMAT_file, "precompiled.hpp");
  AD.addInclude(AD._CPP_FORMAT_file, "adfiles", get_basename(AD._HPP_file._name));
  AD.addInclude(AD._CPP_GEN_file, "precompiled.hpp");
  AD.addInclude(AD._CPP_GEN_file, "adfiles", get_basename(AD._HPP_file._name));
  AD.addInclude(AD._CPP_GEN_file, "opto/cfgnode.hpp");
  AD.addInclude(AD._CPP_GEN_file, "opto/locknode.hpp");
  AD.addInclude(AD._CPP_MISC_file, "precompiled.hpp");
  AD.addInclude(AD._CPP_MISC_file, "adfiles", get_basename(AD._HPP_file._name));
  AD.addInclude(AD._CPP_PEEPHOLE_file, "precompiled.hpp");
  AD.addInclude(AD._CPP_PEEPHOLE_file, "adfiles", get_basename(AD._HPP_file._name));
  AD.addInclude(AD._CPP_PIPELINE_file, "precompiled.hpp");
  AD.addInclude(AD._CPP_PIPELINE_file, "adfiles", get_basename(AD._HPP_file._name));
  AD.addInclude(AD._DFA_file, "precompiled.hpp");
  AD.addInclude(AD._DFA_file, "adfiles", get_basename(AD._HPP_file._name));
  AD.addInclude(AD._DFA_file, "opto/cfgnode.hpp");  // Use PROB_MAX in predicate.
  AD.addInclude(AD._DFA_file, "opto/matcher.hpp");
  AD.addInclude(AD._DFA_file, "opto/opcodes.hpp");
  AD.addInclude(AD._DFA_file, "opto/convertnode.hpp");
  // Make sure each .cpp file starts with include lines:
  // files declaring and defining generators for Mach* Objects (hpp,cpp)
  // Generate the result files:
  // enumerations, class definitions, object generators, and the DFA
  // file containing enumeration of machine operands & instructions (hpp)
  AD.addPreHeaderBlocks(AD._HPP_file._fp);        // .hpp
  AD.buildMachOperEnum(AD._HPP_file._fp);         // .hpp
  AD.buildMachOpcodesEnum(AD._HPP_file._fp);      // .hpp
  AD.buildMachRegisterNumbers(AD._VM_file._fp);   // VM file
  AD.buildMachRegisterEncodes(AD._HPP_file._fp);  // .hpp file
  AD.declareRegSizes(AD._HPP_file._fp);           // .hpp
  AD.build_pipeline_enums(AD._HPP_file._fp);      // .hpp
  // output definition of class "State"
  AD.defineStateClass(AD._HPP_file._fp);          // .hpp
  // file declaring the Mach* classes derived from MachOper and MachNode
  AD.declareClasses(AD._HPP_file._fp);
  // declare and define maps: in the .hpp and .cpp files respectively
  AD.addSourceBlocks(AD._CPP_file._fp);           // .cpp
  AD.addHeaderBlocks(AD._HPP_file._fp);           // .hpp
  AD.buildReduceMaps(AD._HPP_file._fp, AD._CPP_file._fp);
  AD.buildMustCloneMap(AD._HPP_file._fp, AD._CPP_file._fp);
  // build CISC_spilling oracle and MachNode::cisc_spill() methods
  AD.build_cisc_spill_instructions(AD._HPP_file._fp, AD._CPP_file._fp);
  // define methods for machine dependent State, MachOper, and MachNode classes
  AD.defineClasses(AD._CPP_file._fp);
  AD.buildMachOperGenerator(AD._CPP_GEN_file._fp);// .cpp
  AD.buildMachNodeGenerator(AD._CPP_GEN_file._fp);// .cpp
  // define methods for machine dependent instruction matching
  AD.buildInstructMatchCheck(AD._CPP_file._fp);  // .cpp
  // define methods for machine dependent frame management
  AD.buildFrameMethods(AD._CPP_file._fp);         // .cpp
  AD.generate_needs_clone_jvms(AD._CPP_file._fp);

  // do this last:
  AD.addPreprocessorChecks(AD._CPP_file._fp);     // .cpp
  AD.addPreprocessorChecks(AD._CPP_CLONE_file._fp);     // .cpp
  AD.addPreprocessorChecks(AD._CPP_EXPAND_file._fp);    // .cpp
  AD.addPreprocessorChecks(AD._CPP_FORMAT_file._fp);    // .cpp
  AD.addPreprocessorChecks(AD._CPP_GEN_file._fp);       // .cpp
  AD.addPreprocessorChecks(AD._CPP_MISC_file._fp);      // .cpp
  AD.addPreprocessorChecks(AD._CPP_PEEPHOLE_file._fp);  // .cpp
  AD.addPreprocessorChecks(AD._CPP_PIPELINE_file._fp);  // .cpp

  // define the finite automata that selects lowest cost production
  AD.buildDFA(AD._DFA_file._fp);
  // Add include guards for all .hpp files
  AD.addIncludeGuardEnd(AD._HPP_file, "GENERATED_ADFILES_AD_HPP");        // .hpp
  AD.addIncludeGuardEnd(AD._VM_file, "GENERATED_ADFILES_ADGLOBALS_HPP");  // .hpp

  AD.close_files(0);               // Close all input/output files

  // Final printout and statistics
  // cout << program;

  if( AD._dfa_debug & 2 ) {    // For higher debug settings, print timing info
    //    Timer t_stop;
    //    Timer t_total = t_stop - t_start; // Total running time
    //    cerr << "\n---Architecture Description Totals---\n";
    //    cerr << ", Total lines: " << TotalLines;
    //    float l = TotalLines;
    //    cerr << "\nTotal Compilation Time: " << t_total << "\n";
    //    float ft = (float)t_total;
    //    if( ft > 0.0 ) fprintf(stderr,"Lines/sec: %#5.2f\n", l/ft);
  }
  return (AD._syntax_errs + AD._semantic_errs + AD._internal_errs); // Bye Bye!!
}
示例#18
0
static struct bstr strip_ext(struct bstr str)
{
    int dotpos = bstrrchr(str, '.');
    if (dotpos < 0)
        return str;
    return (struct bstr){str.start, dotpos};
}

static struct bstr get_ext(struct bstr s)
{
    int dotpos = bstrrchr(s, '.');
    if (dotpos < 0)
        return (struct bstr){NULL, 0};
    return bstr_splice(s, dotpos + 1, s.len);
}

static int compare_sub_filename(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    return strcoll(s1->fname, s2->fname);
}

static int compare_sub_priority(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    if (s1->priority > s2->priority)
        return -1;
    if (s1->priority < s2->priority)
        return 1;
    return strcoll(s1->fname, s2->fname);
}

static struct bstr guess_lang_from_filename(struct bstr name)
{
    if (name.len < 2)
        return (struct bstr){NULL, 0};

    int n = 0;
    int i = name.len - 1;

    if (name.start[i] == ')' || name.start[i] == ']')
        i--;
    while (i >= 0 && isalpha(name.start[i])) {
        n++;
        if (n > 3)
            return (struct bstr){NULL, 0};
        i--;
    }
    if (n < 2)
        return (struct bstr){NULL, 0};
    return (struct bstr){name.start + i + 1, n};
}

/**
 * @brief Append all the subtitles in the given path matching fname
 * @param opts MPlayer options
 * @param slist pointer to the subtitles list tallocated
 * @param nsub pointer to the number of subtitles
 * @param path Look for subtitles in this directory
 * @param fname Subtitle filename (pattern)
 * @param limit_fuzziness Ignore flag when sub_fuziness == 2
 */
static void append_dir_subtitles(struct MPOpts *opts,
                                 struct subfn **slist, int *nsub,
                                 struct bstr path, const char *fname,
                                 int limit_fuzziness)
{
    void *tmpmem = talloc_new(NULL);

    if (mp_is_url(bstr0(fname)))
        goto out;

    struct bstr f_fname = bstr0(mp_basename(fname));
    struct bstr f_fname_noext = bstrdup(tmpmem, strip_ext(f_fname));
    bstr_lower(f_fname_noext);
    struct bstr f_fname_trim = bstr_strip(f_fname_noext);

    // 0 = nothing
    // 1 = any subtitle file
    // 2 = any sub file containing movie name
    // 3 = sub file containing movie name and the lang extension
    char *path0 = bstrdup0(tmpmem, path);
    DIR *d = opendir(path0);
    if (!d)
        goto out;
    mp_msg(MSGT_SUBREADER, MSGL_V, "Load subtitles in %.*s\n", BSTR_P(path));
    struct dirent *de;
    while ((de = readdir(d))) {
        struct bstr dename = bstr0(de->d_name);
        void *tmpmem2 = talloc_new(tmpmem);

        // retrieve various parts of the filename
        struct bstr tmp_fname_noext = bstrdup(tmpmem2, strip_ext(dename));
        bstr_lower(tmp_fname_noext);
        struct bstr tmp_fname_ext = get_ext(dename);
        struct bstr tmp_fname_trim = bstr_strip(tmp_fname_noext);

        // does it end with a subtitle extension?
        if (!is_sub_ext(tmp_fname_ext))
            goto next_sub;

        // we have a (likely) subtitle file
        int prio = 0;
        char *found_lang = NULL;
        if (opts->sub_lang) {
            if (bstr_startswith(tmp_fname_trim, f_fname_trim)) {
                struct bstr lang = guess_lang_from_filename(tmp_fname_trim);
                if (lang.len) {
                    for (int n = 0; opts->sub_lang[n]; n++) {
                        if (bstr_startswith0(lang, opts->sub_lang[n])) {
                            prio = 4; // matches the movie name + lang extension
                            found_lang = opts->sub_lang[n];
                            break;
                        }
                    }
                }
            }
        }
        if (!prio && bstrcmp(tmp_fname_trim, f_fname_trim) == 0)
            prio = 3; // matches the movie name
        if (!prio && bstr_find(tmp_fname_trim, f_fname_trim) >= 0
            && opts->sub_match_fuzziness >= 1)
            prio = 2; // contains the movie name
        if (!prio) {
            // doesn't contain the movie name
            // don't try in the mplayer subtitle directory
            if (!limit_fuzziness && opts->sub_match_fuzziness >= 2) {
                prio = 1;
            }
        }

        mp_msg(MSGT_SUBREADER, MSGL_DBG2, "Potential sub file: "
               "\"%s\"  Priority: %d\n", de->d_name, prio);
        if (prio) {
            prio += prio;
            char *subpath = mp_path_join(*slist, path, dename);
            if (mp_path_exists(subpath)) {
                MP_GROW_ARRAY(*slist, *nsub);
                struct subfn *sub = *slist + (*nsub)++;

                // annoying and redundant
                if (strncmp(subpath, "./", 2) == 0)
                    subpath += 2;

                sub->priority = prio;
                sub->fname    = subpath;
                sub->lang     = found_lang;
            } else
                talloc_free(subpath);
        }

    next_sub:
        talloc_free(tmpmem2);
    }
    closedir(d);

 out:
    talloc_free(tmpmem);
}

static bool case_endswith(const char *s, const char *end)
{
    size_t len = strlen(s);
    size_t elen = strlen(end);
    return len >= elen && strcasecmp(s + len - elen, end) == 0;
}

// Drop .sub file if .idx file exists.
// Assumes slist is sorted by compare_sub_filename.
static void filter_subidx(struct subfn **slist, int *nsub)
{
    const char *prev = NULL;
    for (int n = 0; n < *nsub; n++) {
        const char *fname = (*slist)[n].fname;
        if (case_endswith(fname, ".idx")) {
            prev = fname;
        } else if (case_endswith(fname, ".sub")) {
            if (prev && strncmp(prev, fname, strlen(fname) - 4) == 0)
                (*slist)[n].priority = -1;
        }
    }
    for (int n = *nsub - 1; n >= 0; n--) {
        if ((*slist)[n].priority < 0)
            MP_TARRAY_REMOVE_AT(*slist, *nsub, n);
    }
}

// Return a list of subtitles found, sorted by priority.
// Last element is terminated with a fname==NULL entry.
struct subfn *find_text_subtitles(struct MPOpts *opts, const char *fname)
{
    struct subfn *slist = talloc_array_ptrtype(NULL, slist, 1);
    int n = 0;

    // Load subtitles from current media directory
    append_dir_subtitles(opts, &slist, &n, mp_dirname(fname), fname, 0);

    // Load subtitles in dirs specified by sub-paths option
    if (opts->sub_paths) {
        for (int i = 0; opts->sub_paths[i]; i++) {
            char *path = mp_path_join(slist, mp_dirname(fname),
                                      bstr0(opts->sub_paths[i]));
            append_dir_subtitles(opts, &slist, &n, bstr0(path), fname, 0);
        }
    }

    // Load subtitles in ~/.mpv/sub limiting sub fuzziness
    char *mp_subdir = mp_find_user_config_file("sub/");
    if (mp_subdir)
        append_dir_subtitles(opts, &slist, &n, bstr0(mp_subdir), fname, 1);
    talloc_free(mp_subdir);

    // Sort by name for filter_subidx()
    qsort(slist, n, sizeof(*slist), compare_sub_filename);

    filter_subidx(&slist, &n);

    // Sort subs by priority and append them
    qsort(slist, n, sizeof(*slist), compare_sub_priority);

    struct subfn z = {0};
    MP_TARRAY_APPEND(NULL, slist, n, z);

    return slist;
}
示例#19
0
char *
check_for_album_file(char * dir, const char * path)
{
	char * file = malloc(PATH_MAX);
	struct album_art_name_s * album_art_name;
	image * imsrc = NULL;
	int width=0, height=0;
	char * art_file;

	/* First look for file-specific cover art */
	sprintf(file, "%s.cover.jpg", path);
	if( access(file, R_OK) == 0 )
	{
		if( art_cache_exists(file, &art_file) )
			goto existing_file;
		free(art_file);
		imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1);
		if( imsrc )
			goto found_file;
	}
	sprintf(file, "%s", path);
	strip_ext(file);
	strcat(file, ".jpg");
	if( access(file, R_OK) == 0 )
	{
		if( art_cache_exists(file, &art_file) )
			goto existing_file;
		free(art_file);
		imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1);
		if( imsrc )
			goto found_file;
	}

	/* Then fall back to possible generic cover art file names */
	for( album_art_name = album_art_names; album_art_name; album_art_name = album_art_name->next )
	{
		sprintf(file, "%s/%s", dir, album_art_name->name);
		if( access(file, R_OK) == 0 )
		{
			if( art_cache_exists(file, &art_file) )
			{
existing_file:
				free(file);
				return art_file;
			}
			free(art_file);
			imsrc = image_new_from_jpeg(file, 1, NULL, 0, 1);
			if( !imsrc )
				continue;
found_file:
			width = imsrc->width;
			height = imsrc->height;
			if( width > 160 || height > 160 )
			{
				art_file = file;
				file = save_resized_album_art(imsrc, art_file);
				free(art_file);
			}
			image_free(imsrc);
			return(file);
		}
	}
	free(file);
	return NULL;
}
示例#20
0
int64_t
GetVideoMetadata(const char *path, char *name)
{
	struct stat file;
	int ret, i;
	struct tm *modtime;
	AVFormatContext *ctx = NULL;
	AVCodecContext *ac = NULL, *vc = NULL;
	int audio_stream = -1, video_stream = -1;
	enum audio_profiles audio_profile = PROFILE_AUDIO_UNKNOWN;
	char fourcc[4];
	int64_t album_art = 0;
	char nfo[MAXPATHLEN], *ext;
	struct song_metadata video;
	metadata_t m;
	uint32_t free_flags = 0xFFFFFFFF;
	char *path_cpy, *basepath;

	memset(&m, '\0', sizeof(m));
	memset(&video, '\0', sizeof(video));

	//DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing video %s...\n", name);
	if ( stat(path, &file) != 0 )
		return 0;
	strip_ext(name);
	//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size);

	ret = lav_open(&ctx, path);
	if( ret != 0 )
	{
		char err[128];
		av_strerror(ret, err, sizeof(err));
		DPRINTF(E_WARN, L_METADATA, "Opening %s failed! [%s]\n", path, err);
		return 0;
	}
	//dump_format(ctx, 0, NULL, 0);
	for( i=0; i<ctx->nb_streams; i++)
	{
		if( audio_stream == -1 &&
		    ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO )
		{
			audio_stream = i;
			ac = ctx->streams[audio_stream]->codec;
			continue;
		}
		else if( video_stream == -1 &&
			 ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO )
		{
			video_stream = i;
			vc = ctx->streams[video_stream]->codec;
			continue;
		}
	}
	path_cpy = strdup(path);
	basepath = basename(path_cpy);
	if( !vc )
	{
		/* This must not be a video file. */
		lav_close(ctx);
		if( !is_audio(path) )
			DPRINTF(E_DEBUG, L_METADATA, "File %s does not contain a video stream.\n", basepath);
		free(path_cpy);
		return 0;
	}

	if( ac )
	{
		aac_object_type_t aac_type = AAC_INVALID;
		switch( ac->codec_id )
		{
			case CODEC_ID_MP3:
				audio_profile = PROFILE_AUDIO_MP3;
				break;
			case CODEC_ID_AAC:
				if( !ac->extradata_size ||
				    !ac->extradata )
				{
					DPRINTF(E_DEBUG, L_METADATA, "No AAC type\n");
				}
				else
				{
					uint8_t data;
					memcpy(&data, ac->extradata, 1);
					aac_type = data >> 3;
				}
				switch( aac_type )
				{
					/* AAC Low Complexity variants */
					case AAC_LC:
					case AAC_LC_ER:
						if( ac->sample_rate < 8000 ||
						    ac->sample_rate > 48000 )
						{
							DPRINTF(E_DEBUG, L_METADATA, "Unsupported AAC: sample rate is not 8000 < %d < 48000\n",
								ac->sample_rate);
							break;
						}
						/* AAC @ Level 1/2 */
						if( ac->channels <= 2 &&
						    ac->bit_rate <= 576000 )
							audio_profile = PROFILE_AUDIO_AAC;
						else if( ac->channels <= 6 &&
							 ac->bit_rate <= 1440000 )
							audio_profile = PROFILE_AUDIO_AAC_MULT5;
						else
							DPRINTF(E_DEBUG, L_METADATA, "Unhandled AAC: %d channels, %d bitrate\n",
								ac->channels,
								ac->bit_rate);
						break;
					default:
						DPRINTF(E_DEBUG, L_METADATA, "Unhandled AAC type [%d]\n", aac_type);
						break;
				}
				break;
			case CODEC_ID_AC3:
			case CODEC_ID_DTS:
				audio_profile = PROFILE_AUDIO_AC3;
				break;
			case CODEC_ID_WMAV1:
			case CODEC_ID_WMAV2:
				/* WMA Baseline: stereo, up to 48 KHz, up to 192,999 bps */
				if ( ac->bit_rate <= 193000 )
					audio_profile = PROFILE_AUDIO_WMA_BASE;
				/* WMA Full: stereo, up to 48 KHz, up to 385 Kbps */
				else if ( ac->bit_rate <= 385000 )
					audio_profile = PROFILE_AUDIO_WMA_FULL;
				break;
			#if LIBAVCODEC_VERSION_INT > ((51<<16)+(50<<8)+1)
			case CODEC_ID_WMAPRO:
				audio_profile = PROFILE_AUDIO_WMA_PRO;
				break;
			#endif
			case CODEC_ID_MP2:
				audio_profile = PROFILE_AUDIO_MP2;
				break;
			case CODEC_ID_AMR_NB:
				audio_profile = PROFILE_AUDIO_AMR;
				break;
			default:
				if( (ac->codec_id >= CODEC_ID_PCM_S16LE) &&
				    (ac->codec_id < CODEC_ID_ADPCM_IMA_QT) )
					audio_profile = PROFILE_AUDIO_PCM;
				else
					DPRINTF(E_DEBUG, L_METADATA, "Unhandled audio codec [0x%X]\n", ac->codec_id);
				break;
		}
		xasprintf(&m.frequency, "%u", ac->sample_rate);
		#if LIBAVCODEC_VERSION_INT < (52<<16)
		xasprintf(&m.bps, "%u", ac->bits_per_sample);
		#else
		xasprintf(&m.bps, "%u", ac->bits_per_coded_sample);
		#endif
		xasprintf(&m.channels, "%u", ac->channels);
	}
	if( vc )
	{
		int off;
		int duration, hours, min, sec, ms;
		ts_timestamp_t ts_timestamp = NONE;
		DPRINTF(E_DEBUG, L_METADATA, "Container: '%s' [%s]\n", ctx->iformat->name, basepath);
		xasprintf(&m.resolution, "%dx%d", vc->width, vc->height);
		if( ctx->bit_rate > 8 )
			xasprintf(&m.bitrate, "%u", ctx->bit_rate / 8);
		if( ctx->duration > 0 ) {
			duration = (int)(ctx->duration / AV_TIME_BASE);
			hours = (int)(duration / 3600);
			min = (int)(duration / 60 % 60);
			sec = (int)(duration % 60);
			ms = (int)(ctx->duration / (AV_TIME_BASE/1000) % 1000);
			xasprintf(&m.duration, "%d:%02d:%02d.%03d", hours, min, sec, ms);
		}

		/* NOTE: The DLNA spec only provides for ASF (WMV), TS, PS, and MP4 containers.
		 * Skip DLNA parsing for everything else. */
		if( strcmp(ctx->iformat->name, "avi") == 0 )
		{
			xasprintf(&m.mime, "video/x-msvideo");
			if( vc->codec_id == CODEC_ID_MPEG4 )
			{
        			fourcc[0] = vc->codec_tag     & 0xff;
			        fourcc[1] = vc->codec_tag>>8  & 0xff;
		        	fourcc[2] = vc->codec_tag>>16 & 0xff;
			        fourcc[3] = vc->codec_tag>>24 & 0xff;
				if( memcmp(fourcc, "XVID", 4) == 0 ||
				    memcmp(fourcc, "DX50", 4) == 0 ||
				    memcmp(fourcc, "DIVX", 4) == 0 )
					xasprintf(&m.creator, "DiVX");
			}
		}
示例#21
0
static int64_t
_get_png_metadata (const char *path, char *name)
{
	FILE *file;
	uint32_t width=0, height=0;
	int thumb=0;
	int got_header = 0;
	struct stat statbuf;
	int64_t ret;
	metadata_t m;
	uint8_t tagbuf[8];
	uint32_t free_flags = 0;

	memset(&m, '\0', sizeof(metadata_t));

	if ( stat(path, &statbuf) != 0 )
		return 0;
	strip_ext(name);

	if ((file = fopen (path, "rb")) == (FILE *)NULL)
	{
		DPRINTF (E_ERROR, L_METADATA, "Error opening \"%s\": %s\n",
				path, strerror (errno));
		return 0;
	}

	if (fread (tagbuf, 1, 8, file) != 8)
	{
		fclose (file);
		return 0;
	}

	if (memcmp (tagbuf, PNG_ID, PNG_ID_LEN))
	{
		DPRINTF (E_WARN, L_METADATA,
				"\"%s\" not a PNG file.\n", path);
		fclose (file);
		return 0;
	}

	/* Go through the chunks */

	for (;;)
	{
		int32_t chunksize;
		char *chunkname[5];
		uint8_t *buf;

		if ((fread (tagbuf, 1, 8, file)) != 8)
		{
			DPRINTF (E_WARN, L_METADATA,
					"%s: Premature EOF.\n", path);
			fclose (file);
			free_metadata(&m, free_flags);
			return 0;
		}
		chunksize = BE32 (&tagbuf[0]);
		memcpy (chunkname, &tagbuf[4], 4);
		chunkname[4] = '\x00';

		if (!memcmp (&tagbuf[4], "IEND", 4))
		{
			break;
		}
		else if (chunksize <= 0)
		{
			if (fseek (file, 4, SEEK_CUR))
			{
				DPRINTF (E_WARN, L_METADATA,
						"%s: Seek error.\n", path);
				fclose (file);
				free_metadata(&m, free_flags);
				return 0;
			}
			continue;
		}
		else if (!memcmp (&tagbuf[4], "IHDR", 4)) {
			if ((buf = _png_readchunk (file, chunksize)) == NULL)
			{
				fclose (file);
				free_metadata(&m, free_flags);
				return 0;
			}
			got_header = 1;

			/* width and height are 32-bit BE starting at offset 0 */
			width = BE32 (&buf[0]);
			height = BE32 (&buf[4]);
			free (buf);
			continue;
		}
		else if (!memcmp (&tagbuf[4], "tIME", 4))
		{
			if ((buf = _png_readchunk (file, chunksize)) == NULL)
			{
				fclose (file);
				free_metadata(&m, free_flags);
				return 0;
			}
			if (free_flags & FLAG_DATE)
				free (m.date);

			xasprintf (&m.date, "%04d-%02d-%02dT%02d:%02d:%02d",
					(int)(buf[0]<<8 | buf[1]),
					(int)buf[2], (int)buf[3],
					(int)buf[4], (int)buf[5], (int)buf[6]);
			free_flags |= FLAG_DATE;
			free (buf);
			continue;
		}
		else if (!memcmp (&tagbuf[4], "tEXt", 4) ||
				!memcmp (&tagbuf[4], "iTXt", 4))
		{
			int international = !memcmp (&tagbuf[4], "iTXt", 4),
					remaining = chunksize;
			char *keyword, *value;
			uint8_t *textp;
			int l;

			if ((buf = _png_readchunk (file, chunksize)) == NULL)
			{
				fclose (file);
				free_metadata(&m, free_flags);
				return 0;
			}

			textp = buf;
			keyword = (char *)buf;
			l = strlen (keyword) + 1;
			textp += l;
			if ((remaining -= l) <= 0)
				goto textdone;

			if (international)
			{
				char *lang;

				if (*textp)
					/* compressed */
					goto textdone;

				textp += 2;
				if ((remaining -= 2) <= 0)
					goto textdone;

				/* language */
				lang = (char *)textp;
				l = strlen (lang) + 1;
				textp += l;
				if ((remaining -= l) <= 0)
					goto textdone;

				/* translated keyword */
				l = strlen ((char *)textp) + 1;
				textp += l;
				if ((remaining -= l) <= 0)
					goto textdone;
			}

			/* whatever's left is the value */
			if ((value = malloc (remaining + 1)) == (char *)NULL)
			{
				DPRINTF (E_ERROR, L_METADATA, "Allocation error.\n");
				free (buf);
				fclose (file);
				free_metadata(&m, free_flags);
				return 0;
			}

			memcpy (value, textp, remaining);
			value[remaining] = '\0';

			if (!strcmp (keyword, "Title"))
			{
				if (free_flags & FLAG_TITLE)
					free (m.title);
				m.title = value;
				free_flags |= FLAG_TITLE;
			}
			else if (!strcmp (keyword, "Author"))
			{
				if (free_flags & FLAG_CREATOR)
					free (m.creator);
				m.creator = value;
				free_flags |= FLAG_CREATOR;
			}
			else
			{
				free (value);
			}

textdone:
			free (buf);
		}
		else
		{
			/* move on to the next chunk */
			if (fseek (file, chunksize+4, SEEK_CUR))
			{
				DPRINTF (E_WARN, L_METADATA,
						"%s: Seek error.\n", path);
				fclose (file);
				free_metadata(&m, free_flags);
				return 0;
			}
		}
	}
	fclose (file);

	if (!got_header)
	{
		DPRINTF (E_WARN, L_METADATA,
				"%s: No PNG header.\n", path);
		free_metadata (&m, free_flags);
		return 0;
	}

	xasprintf(&m.resolution, "%dx%d", (int)width, (int)height);
	m.rotation = 0;
	thumb = 0;
	m.dlna_pn = NULL;
	m.mime = strdup("image/png");
	free_flags |= (FLAG_MIME | FLAG_RESOLUTION);

	if (!(free_flags & FLAG_TITLE))
		m.title = strdup (name);
	free_flags |= FLAG_TITLE;

	DPRINTF (E_MAXDEBUG, L_METADATA,
			"Processed \"%s\":\n  Name: %s\n  Resolution: %s\n",
			path, name, m.resolution);

	ret = sql_exec(db, "INSERT into DETAILS"
	                   " (PATH, TITLE, SIZE, TIMESTAMP, DATE, RESOLUTION,"
	                    " ROTATION, THUMBNAIL, CREATOR, DLNA_PN, MIME) "
	                   "VALUES"
	                   " (%Q, '%q', %lld, %lld, %Q, %Q, %u, %d, %Q, %Q, %Q);",
	                   path, m.title, (long long)statbuf.st_size,
					   (long long)statbuf.st_mtime, m.date, m.resolution,
					   m.rotation, thumb, m.creator, m.dlna_pn, m.mime);
	if( ret != SQLITE_OK )
	{
		DPRINTF(E_ERROR, L_METADATA, "Error inserting details for '%s'!\n", path);
		ret = 0;
	}
	else
	{
		ret = sqlite3_last_insert_rowid(db);
	}
	free_metadata(&m, free_flags);

	return ret;
}
示例#22
0
static struct bstr strip_ext(struct bstr str)
{
    int dotpos = bstrrchr(str, '.');
    if (dotpos < 0)
        return str;
    return (struct bstr){str.start, dotpos};
}

static struct bstr get_ext(struct bstr s)
{
    int dotpos = bstrrchr(s, '.');
    if (dotpos < 0)
        return (struct bstr){NULL, 0};
    return bstr_splice(s, dotpos + 1, s.len);
}

bool mp_might_be_subtitle_file(const char *filename)
{
    return test_ext(get_ext(bstr0(filename))) == STREAM_SUB;
}

static int compare_sub_filename(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    return strcoll(s1->fname, s2->fname);
}

static int compare_sub_priority(const void *a, const void *b)
{
    const struct subfn *s1 = a;
    const struct subfn *s2 = b;
    if (s1->priority > s2->priority)
        return -1;
    if (s1->priority < s2->priority)
        return 1;
    return strcoll(s1->fname, s2->fname);
}

static struct bstr guess_lang_from_filename(struct bstr name)
{
    if (name.len < 2)
        return (struct bstr){NULL, 0};

    int n = 0;
    int i = name.len - 1;

    if (name.start[i] == ')' || name.start[i] == ']')
        i--;
    while (i >= 0 && mp_isalpha(name.start[i])) {
        n++;
        if (n > 3)
            return (struct bstr){NULL, 0};
        i--;
    }
    if (n < 2)
        return (struct bstr){NULL, 0};
    return (struct bstr){name.start + i + 1, n};
}

static void append_dir_subtitles(struct mpv_global *global,
                                 struct subfn **slist, int *nsub,
                                 struct bstr path, const char *fname,
                                 int limit_fuzziness)
{
    void *tmpmem = talloc_new(NULL);
    struct MPOpts *opts = global->opts;
    struct mp_log *log = mp_log_new(tmpmem, global->log, "find_files");

    if (mp_is_url(bstr0(fname)))
        goto out;

    struct bstr f_fname = bstr0(mp_basename(fname));
    struct bstr f_fname_noext = bstrdup(tmpmem, strip_ext(f_fname));
    bstr_lower(f_fname_noext);
    struct bstr f_fname_trim = bstr_strip(f_fname_noext);

    // 0 = nothing
    // 1 = any subtitle file
    // 2 = any sub file containing movie name
    // 3 = sub file containing movie name and the lang extension
    char *path0 = bstrdup0(tmpmem, path);
    DIR *d = opendir(path0);
    if (!d)
        goto out;
    mp_verbose(log, "Loading external files in %.*s\n", BSTR_P(path));
    struct dirent *de;
    while ((de = readdir(d))) {
        struct bstr dename = bstr0(de->d_name);
        void *tmpmem2 = talloc_new(tmpmem);

        // retrieve various parts of the filename
        struct bstr tmp_fname_noext = bstrdup(tmpmem2, strip_ext(dename));
        bstr_lower(tmp_fname_noext);
        struct bstr tmp_fname_ext = get_ext(dename);
        struct bstr tmp_fname_trim = bstr_strip(tmp_fname_noext);

        // check what it is (most likely)
        int type = test_ext(tmp_fname_ext);
        char **langs = NULL;
        int fuzz = -1;
        switch (type) {
        case STREAM_SUB:
            langs = opts->sub_lang;
            fuzz = opts->sub_auto;
            break;
        case STREAM_AUDIO:
            langs = opts->audio_lang;
            fuzz = opts->audiofile_auto;
            break;
        }

        if (fuzz < 0)
            goto next_sub;

        // we have a (likely) subtitle file
        int prio = 0;
        char *found_lang = NULL;
        if (langs) {
            if (bstr_startswith(tmp_fname_trim, f_fname_trim)) {
                struct bstr lang = guess_lang_from_filename(tmp_fname_trim);
                if (lang.len) {
                    for (int n = 0; langs[n]; n++) {
                        if (bstr_startswith0(lang, langs[n])) {
                            prio = 4; // matches the movie name + lang extension
                            found_lang = langs[n];
                            break;
                        }
                    }
                }
            }
        }
        if (!prio && bstrcmp(tmp_fname_trim, f_fname_trim) == 0)
            prio = 3; // matches the movie name
        if (!prio && bstr_find(tmp_fname_trim, f_fname_trim) >= 0 && fuzz >= 1)
            prio = 2; // contains the movie name
        if (!prio) {
            // doesn't contain the movie name
            // don't try in the mplayer subtitle directory
            if (!limit_fuzziness && fuzz >= 2) {
                prio = 1;
            }
        }

        mp_dbg(log, "Potential external file: \"%s\"  Priority: %d\n",
               de->d_name, prio);

        if (prio) {
            prio += prio;
            char *subpath = mp_path_join(*slist, path, dename);
            if (mp_path_exists(subpath)) {
                MP_GROW_ARRAY(*slist, *nsub);
                struct subfn *sub = *slist + (*nsub)++;

                // annoying and redundant
                if (strncmp(subpath, "./", 2) == 0)
                    subpath += 2;

                sub->type     = type;
                sub->priority = prio;
                sub->fname    = subpath;
                sub->lang     = found_lang;
            } else
                talloc_free(subpath);
        }

    next_sub:
        talloc_free(tmpmem2);
    }
    closedir(d);

 out:
    talloc_free(tmpmem);
}

static bool case_endswith(const char *s, const char *end)
{
    size_t len = strlen(s);
    size_t elen = strlen(end);
    return len >= elen && strcasecmp(s + len - elen, end) == 0;
}

// Drop .sub file if .idx file exists.
// Assumes slist is sorted by compare_sub_filename.
static void filter_subidx(struct subfn **slist, int *nsub)
{
    const char *prev = NULL;
    for (int n = 0; n < *nsub; n++) {
        const char *fname = (*slist)[n].fname;
        if (case_endswith(fname, ".idx")) {
            prev = fname;
        } else if (case_endswith(fname, ".sub")) {
            if (prev && strncmp(prev, fname, strlen(fname) - 4) == 0)
                (*slist)[n].priority = -1;
        }
    }
    for (int n = *nsub - 1; n >= 0; n--) {
        if ((*slist)[n].priority < 0)
            MP_TARRAY_REMOVE_AT(*slist, *nsub, n);
    }
}

// Return a list of subtitles and audio files found, sorted by priority.
// Last element is terminated with a fname==NULL entry.
struct subfn *find_external_files(struct mpv_global *global, const char *fname)
{
    struct MPOpts *opts = global->opts;
    struct subfn *slist = talloc_array_ptrtype(NULL, slist, 1);
    int n = 0;

    // Load subtitles from current media directory
    append_dir_subtitles(global, &slist, &n, mp_dirname(fname), fname, 0);

    if (opts->sub_auto >= 0) {
        // Load subtitles in dirs specified by sub-paths option
        if (opts->sub_paths) {
            for (int i = 0; opts->sub_paths[i]; i++) {
                char *path = mp_path_join(slist, mp_dirname(fname),
                                        bstr0(opts->sub_paths[i]));
                append_dir_subtitles(global, &slist, &n, bstr0(path), fname, 0);
            }
        }

        // Load subtitles in ~/.mpv/sub limiting sub fuzziness
        char *mp_subdir = mp_find_config_file(NULL, global, "sub/");
        if (mp_subdir)
            append_dir_subtitles(global, &slist, &n, bstr0(mp_subdir), fname, 1);
        talloc_free(mp_subdir);
    }

    // Sort by name for filter_subidx()
    qsort(slist, n, sizeof(*slist), compare_sub_filename);

    filter_subidx(&slist, &n);

    // Sort subs by priority and append them
    qsort(slist, n, sizeof(*slist), compare_sub_priority);

    struct subfn z = {0};
    MP_TARRAY_APPEND(NULL, slist, n, z);

    return slist;
}
示例#23
0
文件: user.c 项目: malikcjm/mc-nt
char *expand_format (char c, int quote)
{
    WPanel *panel;
    char *(*quote_func)(const char *, int);

    if (quote)
    quote_func = name_quote;
    else
    quote_func = fake_name_quote;

    if (c == '%')
    return strdup ("%");

    if (islower (c))
    panel = cpanel;
    else {
    if (get_other_type () == view_listing){
        panel = other_panel;
    } else
        return strdup ("");
    }
    if (!panel)
    panel = cpanel;

    c = tolower (c);

    switch (c){
    case 'f':
    case 'p': return (*quote_func) (panel->dir.list [panel->selected].fname, 0);
    case 'b':
    return strip_ext((*quote_func) (panel->dir.list [panel->selected].fname, 0));
    case 'd': return (*quote_func) (panel->cwd, 0);
    case 's':
    if (!panel->marked)
        return (*quote_func) (panel->dir.list [panel->selected].fname, 0);

    /* Fall through */

    case 't':
    case 'u':
    {
    int length = 2, i;
    char *block, *tmp;

    for (i = 0; i < panel->count; i++)
        if (panel->dir.list [i].f.marked)
        length += strlen (panel->dir.list [i].fname) + 1;

    block = xmalloc (length*2+1, "expand_format");
    *block = 0;
    for (i = 0; i < panel->count; i++)
        if (panel->dir.list [i].f.marked){
        strcat (block, tmp = (*quote_func) (panel->dir.list [i].fname, 0));
        free (tmp);
        strcat (block, " ");
        if (c == 'u')
            do_file_mark (panel, i, 0);
        }
    return block;
    } /* sub case block */
    } /* switch */
    return strdup ("");
}