From ff081934d3f79e659ca14c93b147028b59880ee8 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Sat, 5 Feb 2005 00:00:00 +0100 Subject: [PATCH] version 0.31 * a flag was added to avoid parsing twice the hardlinked files (patch by Andreas Neuper) * Makefile was improved to easily build packages --- CHANGELOG | 4 ++ Makefile | 16 ++++++++ README | 2 +- debian/changelog | 6 +++ debian/compat | 1 + debian/control | 13 +++++++ debian/copyright | 16 ++++++++ debian/docs | 1 + debian/rules | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ fapg.1 | 16 +++----- fapg.c | 82 ++++++++++++++++++++++++++++++++++++--- rpm/fapg.spec | 30 +++++++++++++++ 12 files changed, 269 insertions(+), 17 deletions(-) create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/docs create mode 100755 debian/rules create mode 100644 rpm/fapg.spec diff --git a/CHANGELOG b/CHANGELOG index ff59438..5a79507 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ Change log file for FAPG +version 0.31 (2005-02-05) + * a flag was added to avoid parsing twice the hardlinked files (patch by Andreas Neuper) + * Makefile was improved to easily build packages + version 0.30 (2004-10-12) * selection by genre was added (thank you Andreas Neuper) * MP2 files are parsed for mp3 headers (thank you Andreas Neuper) diff --git a/Makefile b/Makefile index 990ae9c..0403744 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +VER = 0.31 PRE = /usr/local BIN = $(PRE)/bin DOC = $(PRE)/share/doc/fapg @@ -8,6 +9,8 @@ fapg:fapg.c genres.h clean: rm -f fapg + rm -f build-stamp configure-stamp debian/fapg.substvars debian/files + rm -rf debian/fapg rpm/BUILD rpm/SPECS rpm/SOURCES rpm/SRPMS rpm/RPMS install:fapg mkdir -p $(BIN) $(DOC) $(MAN) @@ -19,3 +22,16 @@ uninstall: rm -f $(BIN)/fapg rm -rf $(DOC) rm -f $(MAN)/fapg.1 + +tar: clean + cd .. && tar zcvf fapg-$(VER).tar.gz fapg-$(VER) + +rpm: tar + mkdir -p rpm/BUILD rpm/SPECS rpm/SOURCES rpm/SRPMS rpm/RPMS + rpm -ta ../fapg-$(VER).tar.gz --define "_topdir `pwd`/rpm" + cp rpm/*/*.rpm rpm/*/*/*.rpm .. + +deb: clean + dpkg-buildpackage -us -uc -rfakeroot + +dist: tar rpm deb \ No newline at end of file diff --git a/README b/README index 7904dd2..849d150 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -FAPG 0.30 (Fast Audio Playlist Generator) +FAPG 0.31 (Fast Audio Playlist Generator) site: http://royale.zerezo.com/fapg/ mail: royale@zerezo.com diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..6d703b0 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +fapg (0.31-1) unstable; urgency=low + + * Initial Release. + + -- Antoine Jacquet Sat, 5 Feb 2005 20:23:49 +0100 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +4 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..40a02c6 --- /dev/null +++ b/debian/control @@ -0,0 +1,13 @@ +Source: fapg +Section: sound +Priority: optional +Maintainer: Antoine Jacquet +Build-Depends: debhelper (>= 4.0.0) +Standards-Version: 3.6.1 + +Package: fapg +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Fast Audio Playlist Generator + FAPG is a tool to generate list of audio files (Wav, MP3, Ogg, etc) + in various formats (M3U, PLS, HTML, etc). diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..bd7f9d3 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,16 @@ +This package was debianized by Antoine Jacquet on +Sat, 5 Feb 2005 20:23:49 +0100. + +It was downloaded from: http://royale.zerezo.com/fapg/ + +Upstream Author: Antoine Jacquet + +Copyright (C) 2002-2004 Antoine Jacquet + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +On Debian GNU/Linux systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e845566 --- /dev/null +++ b/debian/docs @@ -0,0 +1 @@ +README diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..3e34bae --- /dev/null +++ b/debian/rules @@ -0,0 +1,99 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + + + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + #docbook-to-man debian/fapg.sgml > fapg.1 + + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/fapg. + $(MAKE) install PRE=$(CURDIR)/debian/fapg/usr + rm $(CURDIR)/debian/fapg/usr/share/doc/fapg/COPYING + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs CHANGELOG + dh_installdocs + dh_installexamples +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_python +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/fapg.1 b/fapg.1 index e909bdb..a9af76f 100644 --- a/fapg.1 +++ b/fapg.1 @@ -7,19 +7,13 @@ fapg \- Fast Audio Playlist Generator .SH SYNOPSIS -.B fapg [-b|--backslash] [-d|--debug] [-f|--format=m3u|pls|html] [-g|--genre -.I #:#:... -.B ] [-o|--output= -.I /path/to/file.m3u -.B ] [-p|--prefix= -.I /the/prefix -.B ] [-r|--recursive] [-w|--windows] [-x|--exclude -.I #:#:... +.B fapg [ +.I options .B ] .I /path/to/mp3/dir1 .B [ .I /path/to/mp3/dir2 -.B ...] +.B ... ] .SH DESCRIPTION .B fapg @@ -41,7 +35,9 @@ Display useful messages if the program fails ;) .IP -f|--format=m3u|pls|html Choose which format of playlist you want to generate (default is m3u). .IP -g|--genre=#:#:... -Choose which genres (numerical values only) will be included in the generated playlist (default is all). +Choose which genres (numerical values only) will be included in the generated playlist (default is all). +.IP -n|--nohardlink +Avoid to parse twice the files because of hardlinks. .IP -o|--output=/path/to/file.m3u Choose the name of the playlist file to generate (default behavior is to display on standard output). diff --git a/fapg.c b/fapg.c index e75235e..8a6667d 100644 --- a/fapg.c +++ b/fapg.c @@ -1,5 +1,5 @@ /* - * FAPG version 0.30 + * FAPG version 0.31 * * FAPG means Fast Audio Playlist Generator. * It is a tool to generate list of audio files (Wav, MP3, Ogg, etc) @@ -36,6 +36,7 @@ #include #include #include +#include #include "genres.h" #define MP3_BASE 1024 @@ -47,6 +48,7 @@ int format=0; /* 0 = m3u ; 1 = pls ; 2 = html */ char *genrelist=NULL; unsigned char *prefix=""; int recursive=0; +int avoidhlinked=0; int separator='/'; int skip=0; int windows=0; @@ -65,19 +67,20 @@ unsigned char unix2dos[256]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,2 void usage() { - fprintf(stderr,"Usage >> fapg [-b|--backslash] [-d|--debug] [-f|--format=m3u|pls|html] [-g|--genre=#:#:...] [-o|--output=/path/to/file.m3u] [-p|--prefix=/the/prefix] [-r|--recursive] [-w|--windows] [-x|--exclude=#:#:...] /path/to/mp3/dir1 [/path/to/mp3/dir2 ...]\n"); + fprintf(stderr,"Usage >> fapg [-b|--backslash] [-d|--debug] [-f|--format=m3u|pls|html] [-g|--genre=#:#:...] [-n|--nohardlink] [-o|--output=/path/to/file.m3u] [-p|--prefix=/the/prefix] [-r|--recursive] [-w|--windows] [-x|--exclude=#:#:...] /path/to/mp3/dir1 [/path/to/mp3/dir2 ...]\n"); exit(1); } void parse_options(int argc,char **argv) { - static char const short_options[]="bdf:g:o:p:rwx:"; + static char const short_options[]="bdf:g:lo:np:rwx:"; static struct option long_options[]= { {"backslash",no_argument,NULL,'b'}, {"debug",no_argument,NULL,'d'}, {"format",required_argument,NULL,'f'}, {"genre",required_argument,NULL,'g'}, + {"nohardlink",no_argument,NULL,'n'}, {"output",required_argument,NULL,'o'}, {"prefix",required_argument,NULL,'p'}, {"recursive",no_argument,NULL,'r'}, @@ -116,6 +119,9 @@ void parse_options(int argc,char **argv) } } break; + case 'n': + avoidhlinked=1; + break; case 'o': close(1); if (fopen(optarg,"w")==NULL) { fprintf(stderr,"Error >> unable to open output file : %s\n",optarg); exit(2); } @@ -473,6 +479,69 @@ void parse_mpc(unsigned char *file) fclose(fic); } +#define FSN 8 +#define MAXINO (1<<22) +#define INOTYP unsigned long +#define regbit_qry(x,y) ( x[( (y) / sizeof(INOTYP) )] & 1<<( (y) % sizeof(INOTYP) ) ) +#define regbit_set(x,y) ( x[( (y) / sizeof(INOTYP) )] |= 1<<( (y) % sizeof(INOTYP) ) ) + +int hlink_check(struct stat*info) +{ + /* + * for speed this subroutine should only be called + * - if the file has more than one hardlink + * - if the file is a resolved softlink + */ + /* the persistent variables */ + static INOTYP *list[FSN]; + static dev_t name[FSN]; + /* some temporary variables */ + int fsn, is_registered=0; + + /* assertions - in case parameters are lowered for less memory usage */ + assert(fsnst_ino)/sizeof(INOTYP)st_dev)) && (name[fsn]!=0) ; fsn++); + + /* if file system is not registered yet, do it and leave */ + if( name[fsn] == 0 ) + { + name[fsn] = (info->st_dev); + /* provide space for the bitmap that maps the inodes of this file system */ + list[fsn] = (INOTYP*)calloc(MAXINO,sizeof(INOTYP)); + /* no comparison is needed in empty lists ... return */ + if(debug) fprintf(stderr, "Debug >> Linked >> Init List %04x @mem %04lx\n", (int)name[fsn], (long)&list[fsn] ); + } else + { + /* this looks more complicated than it really is */ + /* the idea is very simple: + * provide a bitmap that maps all inodes of a file system + * to mark all files that have already been visited. + * If it is already visited, do not add it to the playlist + */ + /* + * The difficulty is as follows: + * struct inode_bitmap { char registered:1; } bitmap[1<st_ino) ) ) is_registered=1; + else regbit_set( list[fsn], (info->st_ino) ); + /* + * the debug expression is more complicated then the working stuff + */ + if(debug) + fprintf(stderr, "Debug >> Linked >> DEV %04x INO %06x => " + "list[%02x][%04x] = %04x & %04x --> %s registered\n", + (int)info->st_dev, (int)info->st_ino, fsn, (int)((info->st_ino)/sizeof(INOTYP)), + (int)list[fsn][(info->st_ino)/sizeof(INOTYP)], + 1<<((info->st_ino)%sizeof(INOTYP)), is_registered?"Already":"Not" ); + } + return is_registered; +} + void parse_directory(unsigned char *path) { int i,n; @@ -505,7 +574,8 @@ void parse_directory(unsigned char *path) sprintf(newpath,"%s/%s",path,namelist[i]->d_name); if (stat(newpath,&infos)!=0) { fprintf(stderr,"Warning >> can't stat file : %s\n",newpath); continue; } if (recursive && S_ISDIR(infos.st_mode) && strcmp(namelist[i]->d_name,".")!=0 && strcmp(namelist[i]->d_name,"..")!=0) parse_directory(newpath); - if (S_ISREG(infos.st_mode)) + /* hlink_check() might be applied more selective ... avoidhlink is only a simple prereq */ + if (S_ISREG(infos.st_mode) && ! ( avoidhlinked && hlink_check(&infos) ) ) { unsigned char ext[5]; int j; @@ -572,7 +642,7 @@ int main(int argc,char **argv) printf("[playlist]%s",eol); break; case 2: - printf("%s%s%s%s%sPlaylist generated by FAPG 0.30%s%s%s%s%s%s%s

Playlist

%s%s%s%s",eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol); + printf("%s%s%s%s%sPlaylist generated by FAPG 0.31%s%s%s%s%s%s%s

Playlist

%s%s
EntryArtistTitleLength
%s%s",eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol,eol); break; } for (;optind%s%s

Playlist generated by FAPG 0.30

%s%s%s%s",eol,eol,eol,eol,eol,eol); + printf("
EntryArtistTitleLength
%s%s

Playlist generated by FAPG 0.31

%s%s%s%s",eol,eol,eol,eol,eol,eol); break; } if (genrelist) free(genrelist); diff --git a/rpm/fapg.spec b/rpm/fapg.spec new file mode 100644 index 0000000..16243da --- /dev/null +++ b/rpm/fapg.spec @@ -0,0 +1,30 @@ +Name: fapg +Summary: Fast Audio Playlist Generator +Version: 0.31 +Release: 1 +Source: http://royale.zerezo.com/%{name}/%{name}-%{version}.tar.gz +Group: Applications/Multimedia +License: GPL +BuildRoot: %{_tmppath}/%{name}-%{version}-root + +%description +FAPG is a tool to generate list of audio files (Wav, MP3, Ogg, etc) +in various formats (M3U, PLS, HTML, etc). + +%prep +%setup -q + +%build +make + +%install +make install PRE=$RPM_BUILD_ROOT/usr + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,0755) +%doc COPYING README +%{_bindir}/fapg +%{_mandir}/man1/fapg.1.gz -- 2.20.1