author | Michael Krelin <hacker@klever.net> | 2011-03-19 20:14:26 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2011-03-19 20:14:26 (UTC) |
commit | b6859c0f505b79a246955ab06763392871459e22 (patch) (side-by-side diff) | |
tree | fd85af38d44c7ff5af1eb687d6446d8c49a19bc8 | |
parent | 5ca0d6a85c438ea75dc2795aca5176e3b31e89f0 (diff) | |
download | iii-b6859c0f505b79a246955ab06763392871459e22.zip iii-b6859c0f505b79a246955ab06763392871459e22.tar.gz iii-b6859c0f505b79a246955ab06763392871459e22.tar.bz2 |
iii-extract-riff-chunk manpage and more date bumps
Signed-off-by: Michael Krelin <hacker@klever.net>
-rw-r--r-- | doc/Makefile.am | 2 | ||||
-rw-r--r-- | doc/iii-extract-riff-chunk.1 | 79 | ||||
-rw-r--r-- | doc/iiid.8.in | 2 | ||||
-rw-r--r-- | src/iii-extract-riff-chunk.cc | 2 |
4 files changed, 82 insertions, 3 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am index e171b0b..63079ee 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,6 +1,6 @@ -man_MANS=iiid.8 +man_MANS=iiid.8 iii-extract-riff-chunk.1 doc_DATA = 000000000000.conf pkglib_SCRIPTS = on-upload-photo.bash tag-photo.bash clean-local: rm -f iiid.8 diff --git a/doc/iii-extract-riff-chunk.1 b/doc/iii-extract-riff-chunk.1 new file mode 100644 index 0000000..5a9afeb --- a/dev/null +++ b/doc/iii-extract-riff-chunk.1 @@ -0,0 +1,79 @@ +.TH iii-extract-riff-chunk 1 "March 19th, 2011" "iii" "Klever Group (http://www.klever.net/)" +.hla en + +.SH NAME + +iii-extract-riff-chunk \- utility to extract chunks from RIFF files + +.SH SYNOPSYS + +\fBiii-extract-riff-chunk\fR +[\fB-h\fR] [\fB--help\fR] [\fB--usage\fR] +[\fB-V\fR] [\fB--version\fR] +[\fB-L\fR] [\fB--license\fR] +[\fB-1\fR] [\fB--first\fR] +<avi-file> <chunk-path> + +.SH DESCRIPTION + +The utility is designed to assist in extracting chunk from RIFF files. The main +(and only) reason why it was developed is to sort video files created by camera +by date. + +.SH OPTIONS + +.TP +\fB-1\fR, \fB--first\fR +Stop after extracting the first matching chunk. +.TP +\fB-h\fR, \fB--help\fR, \fB--usage\fR +Display short usage instructions and exit. +.TP +\fB-V\fR, \fB--version\fR +Report version and exit. +.TP +\fB-L\fR, \fB--license\fR +Show licensing terms. + +.SH EXAMPLE + +The command line invokation + +\fBiii-extract-riff-chunk DSC_0001.AVI '/RIFF.AVI /LIST.ncdt/nctg'\fR +| dd bs=1 skip=82 count=19 2>/dev/null + +produces output + +YYYY:MM:DD HH:MM:SS + +at least for my Nikon D90 recorded AVI files. + +.SH AUTHOR + +Written by Michael Krelin <hacker@klever.net> + +.SH COPYRIGHT + +Copyright (c) 2009-2011 Klever Group (http://www.klever.net/) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +.SH BUGS + +You tell me. Send reports to <iii-bugs@klever.net> diff --git a/doc/iiid.8.in b/doc/iiid.8.in index 533ed18..30476f7 100644 --- a/doc/iiid.8.in +++ b/doc/iiid.8.in @@ -1,106 +1,106 @@ -.TH iiid 8 "March 8th, 2009" "iiid(8)" "Klever Group (http://www.klever.net/)" +.TH iiid 8 "March 8th, 2009" "iii" "Klever Group (http://www.klever.net/)" .hla en .SH NAME iiid \- An eye-fi card management daemon .SH SYNOPSYS \fBiiid\fR [\fB-h\fR] [\fB--help\fR] [\fB--usage\fR] [\fB-V\fR] [\fB--version\fR] [\fB-L\fR] [\fB--license\fR] [\fB-p\fR \fIport\fR] [\fB--port=\fR\fIport\fR] .SH DESCRIPTION iiid daemon is a minimalistic open source eye-fi management daemon implementation. It is listening for incoming connections and accepts files from eye-fi card, optionally invoking scripts to sort out files or send out notifications. .SH OPTIONS .TP \fB-p\fR \fIport\fR, \fB--port=\fR\fIport\fR Set the port to listen to. You're not likely to ever need to change this, perhaps for debugging purpose or if you want to proxy connections. .TP \fB-h\fR, \fB--help\fR, \fB--usage\fR Display short usage instructions and exit. .TP \fB-V\fR, \fB--version\fR Report version and exit. .TP \fB-L\fR, \fB--license\fR Show licensing terms. .SH EXIT STATUS The daemon isn't supposed to exit at this point, but, like most executables, it returns zero in case of success, non-zero otherwise. .SH FILES .TP @sysconfdir@/iii/\fBXXXXXXXXXXXX.conf/fR Upon successfull connection, the daemon reads the configuration from this file, where XXXXXXXXXXXX is the macaddress of your eyefi card. You can lookup the mac address of your card in your Mac/Windows Settings.xml file. Be sure to remove dashes from it. .SH CONFIGURATION OPTIONS .TP \fBtargetdir\fR = "\fI/var/lib/iii/%s/\fR" Sets the target directory for uploaded files. If the \fI%s\fR placeholder is present in the string, it is replaced with card mac address. .TP \fBuploadkey\fR = "\fIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\fR" The upload key as seen in Mac/Windows Settings.xml file. .TP \fBon-start-session\fR = "\fIlogger iii-StartSession ${EYEFI_MACADDRESS} ${EYEFI_TRANSFER_MODE} ${EYEFI_TRANSFERMODETIMESTAMP}\fR" The command to execute on \fBStartSession\fR request. The command receives some information via environment variables. .TP \fBon-upload-photo\fR = "\fIlogger iii-UploadPhoto ${EYEFI_MACADDRESS} ${EYEFI_UPLOADED}\fR" The command to execute after successfull photo upload. The information about the card mac address and uploaded file name is passed via environment variables. .TP \fBon-mark-last-photo-in-roll\fR = "\fIlogger iii-MarkLastPhotoInRoll ${EYEFI_MACADDRESS} ${EYEFI_MERGEDELTA}\fR" The command to execute on \fBMarkLastPhotoInRoll\fR request. The information about request is passed via environment variables. .TP \fBumask\fR = \fI002\fR The file mode creation mask. .SH AUTHOR Written by Michael Krelin <hacker@klever.net> .SH COPYRIGHT Copyright (c) 2009-2011 Klever Group (http://www.klever.net/) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. .SH BUGS You tell me. Send reports to <iii-bugs@klever.net> diff --git a/src/iii-extract-riff-chunk.cc b/src/iii-extract-riff-chunk.cc index 3a06db2..d53170d 100644 --- a/src/iii-extract-riff-chunk.cc +++ b/src/iii-extract-riff-chunk.cc @@ -1,246 +1,246 @@ /* vim:set sw=8 nosi noai cin cino=:0,l1,g0: */ #include <stdint.h> #include <stdlib.h> #include <getopt.h> #include <cstring> #include <iostream> #include <fstream> #include <stdexcept> #include <cassert> #include <list> #include <string> #include <iterator> #include "config.h" #define PHEADER \ PACKAGE " Version " VERSION "\n" \ - "Copyright (c) 2009-2010 Klever Group" + "Copyright (c) 2009-2011 Klever Group" typedef uint32_t fourcc_type; enum fourcc_value { fourcc_RIFF = 0x46464952, fourcc_AVI = 0x20495641, fourcc_LIST = 0x5453494c, fourcc_hdrl = 0x6c726468, fourcc_strl = 0x6c727473, fourcc_ncdt = 0x7464636e, fourcc_ncvr = 0x7276636e, fourcc_nctg = 0x6774636e, fourcc_ncth = 0x6874636e }; fourcc_type str2fourcc(const char *str) { fourcc_type rv = 0; return *(fourcc_type*)strncpy((char*)&rv,str,sizeof(rv)); } const std::string fourcc2str(fourcc_type fcc) { char rv[sizeof(fcc)+1]; *(fourcc_type*)rv = fcc; rv[sizeof(fcc)]=0; return rv; } #pragma pack(1) struct riff_sized_head { fourcc_type fourcc; uint32_t size; }; #pragma pack() class exceptional_success : public std::exception { }; struct riff { struct chunk_type { riff_sized_head head; uint32_t left; chunk_type(riff& r) { r.read(&head); left = head.size; } }; std::istream *in; typedef std::list<chunk_type> chunks_type; chunks_type chunks; riff(std::istream& i) : in(&i) { } protected: int begin_chunk() { chunks.push_back( chunk_type(*this) ); return chunks.size(); } void end_chunk(int level) { assert(in); assert(chunks.size()==level); std::streamsize o = chunks.back().left; chunks.pop_back(); if(!o) return; in->seekg(o,std::ios::cur); for(chunks_type::iterator i=chunks.begin(),ie=chunks.end() ;i!=ie; (i++)->left -= o) ; } void read(void *p,size_t n) { assert(in); if( (!chunks.empty()) && chunks.back().left < n) throw std::runtime_error("attempt to read beyond the end of chunk"); if(!in->read((char*)p,n)) throw std::runtime_error("failed to read()"); std::streamsize gc = in->gcount(); for(chunks_type::iterator i=chunks.begin(),ie=chunks.end();i!=ie;++i) { i->left -= gc; assert(i->left >= 0); } if(gc!=n) throw std::runtime_error("incomplete read()"); } template<typename T> void read(T* v) { read(v,sizeof(*v)); } friend class scoped_chunk; }; struct scoped_chunk { riff& rs; int level; riff::chunks_type::reverse_iterator chunk_iterator; scoped_chunk(riff& rs_) : rs(rs_), level(rs.begin_chunk()), chunk_iterator(rs.chunks.rbegin()) { } ~scoped_chunk() { rs.end_chunk(level); } riff::chunk_type& chunk() { return *chunk_iterator; } fourcc_type get_chunk_id() { return chunk().head.fourcc; } bool has(uint32_t bytes=1) { return chunk().left >= bytes; } template<typename T> T read() { T rv; rs.read(&rv); return rv; } template<typename T> void read(T& t) { rs.read(&t); } void read(void *p,size_t n) { rs.read(p,n); } }; struct chunk_path_type : public std::list<std::string> { chunk_path_type() { } chunk_path_type(const char *str) { for(const char *p0=str,*p1=strchr(p0,'/');p0;p1=p1?strchr(p0=++p1,'/'):(p0=0)) if(p0!=p1) push_back( p1? std::string(p0,p1-p0) : std::string(p0) ); } }; struct chunk_walker { riff& r; chunk_path_type path; chunk_walker(riff& r_) : r(r_) { } void shoot(scoped_chunk& chunk) { riff::chunk_type& c = chunk.chunk(); while(c.left) { static char tmp[512]; int r = (c.left<sizeof(tmp)) ? c.left : sizeof(tmp) ; chunk.read(tmp,r); std::cout.write(tmp,r); } if(first) throw exceptional_success(); } void walk_chunks() { scoped_chunk chunk(r); std::string pc = fourcc2str(chunk.get_chunk_id()); bool list = false; switch(chunk.get_chunk_id()) { case fourcc_RIFF: case fourcc_LIST: list = true; pc += '.'; pc += fourcc2str(chunk.read<fourcc_type>()); break; } path.push_back(pc); std::pair<chunk_path_type::const_iterator,chunk_path_type::const_iterator> mm = std::mismatch(path.begin(),path.end(),target.begin()); bool dive = list; if(mm.first==path.end()) { if(mm.second==target.end()) { shoot(chunk); dive = false; } }else{ assert(mm.second!=target.end()); dive = false; } if(dive) while(chunk.has()) walk_chunks(); path.pop_back(); } chunk_path_type target; chunk_walker& set_target(chunk_path_type t) { target = t; return *this; } bool first; chunk_walker& set_oneshot(bool os) { first = true; return *this; } }; void usage(char **argv) { std::cerr << PHEADER << std::endl << std::endl << ' ' << argv[0] << " [options] <avi-file> <chunk-path>" << std::endl << std::endl << " -h, --help,\n" " --usage display this text\n" " -V, --version display version information\n" " -L, --license show license\n" "\n" "Example: " << argv[0] << " DSC_0001.AVI '/RIFF.AVI /LIST.ncdt/nctg' \\\n" "\t\t| dd bs=1 skip=82 count=19 2>/dev/null\n" "Output: YYYY:MM:DD HH:MM:SS (for Nikon-recorded AVI)" << std::endl << std::endl; exit(0); } int main(int argc,char **argv) try { bool first = false; for(;;) { static struct option opts[] = { { "first", no_argument, 0, '1' }, { "help", no_argument, 0, 'h' }, { "usage", no_argument, 0, 'h' }, { "version", no_argument, 0, 'V' }, { "license", no_argument, 0, 'L' }, { NULL, 0, 0, 0 } }; int c = getopt_long(argc,argv,"1hVL",opts,NULL); if(c==-1) break; switch(c) { case 'h': usage(argv); break; case 'V': std::cerr << VERSION << std::endl; exit(0); break; case 'L': extern const char *COPYING; std::cerr << COPYING << std::endl; exit(0); break; case '1': first = true; break; default: std::cerr << "Huh?" << std::endl; exit(1); break; } } if(optind!=(argc-2)) usage(argv); std::ifstream i(argv[optind],std::ios::in); if(!i) { std::cerr << "Failed to open file '" << argv[optind] << "'" << std::endl; exit(1); } riff rs(i); chunk_walker(rs) .set_target(chunk_path_type(argv[++optind])) .set_oneshot(first) .walk_chunks(); return 0; }catch(exceptional_success&) { return 0; }catch(std::exception &e) { std::cerr << "oops: " << e.what() << std::endl; return 1; } |