initial commit
authorSvjatoslav Agejenko <n0@n0-Aspire-8920.(none)>
Mon, 17 Dec 2012 21:24:16 +0000 (23:24 +0200)
committerSvjatoslav Agejenko <n0@n0-Aspire-8920.(none)>
Mon, 17 Dec 2012 21:24:16 +0000 (23:24 +0200)
60 files changed:
.classpath [new file with mode: 0755]
.gitignore [new file with mode: 0755]
.project [new file with mode: 0755]
.settings/org.eclipse.jdt.core.prefs [new file with mode: 0755]
.settings/org.eclipse.jdt.ui.prefs [new file with mode: 0755]
.settings/org.eclipse.m2e.core.prefs [new file with mode: 0755]
.settings/org.maven.ide.eclipse.prefs [new file with mode: 0755]
COPYING [new file with mode: 0755]
README [new file with mode: 0644]
TODO [new file with mode: 0755]
doc/index.html [new file with mode: 0755]
install [new file with mode: 0755]
meviz [new file with mode: 0755]
pom.xml [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/Main.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/Module.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/Bitrate.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/CommandlineHandler.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/Encoder.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/EncodingOptions.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/EncodingPlan.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/EncodingTask.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/FormatsRegistry.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Avi2Ogv.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Converter.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Jpeg2Png.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Mp42Ogv.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Mts2Mkv.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Mts2Mp4.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Ogg2Mp3.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Ogg2Wav.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Png2Tiff.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Tiff2Png.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/meviz/encoder/converters/Wav2mp3.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/grabmemcard/Main.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/AbstractIndexer.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/meviz/htmlindexer/CommandlineHandler.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/Constants.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/FileSortComparator.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/meviz/htmlindexer/FilesystemIndexer.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/ImageFormatError.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/IndexingOptions.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/Layout.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/Main.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/meviz/htmlindexer/Utils.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/layouts/MixedLayout.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/Dimension.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/DirectoryMetadata.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/MetadadaHelper.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/AbstractFile.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/DirectoryFile.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/GeneralFile.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/Picture.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/renamer/CommandlineHandler.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/renamer/Main.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/renamer/RenamingOptions.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/textsplitter/CommandlineHandler.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/textsplitter/Main.java [new file with mode: 0755]
src/main/java/eu/svjatoslav/meviz/textsplitter/TextSplittingOptions.java [new file with mode: 0755]
src/main/resources/log4j.xml [new file with mode: 0755]

diff --git a/.classpath b/.classpath
new file mode 100755 (executable)
index 0000000..72d2ee9
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" output="target/classes" path="src/main/java">
+               <attributes>
+                       <attribute name="optional" value="true"/>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
+               <attributes>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+       <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+               <attributes>
+                       <attribute name="optional" value="true"/>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
+               <attributes>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+               <attributes>
+                       <attribute name="maven.pomderived" value="true"/>
+               </attributes>
+       </classpathentry>
+       <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/.gitignore b/.gitignore
new file mode 100755 (executable)
index 0000000..2f7896d
--- /dev/null
@@ -0,0 +1 @@
+target/
diff --git a/.project b/.project
new file mode 100755 (executable)
index 0000000..c37e774
--- /dev/null
+++ b/.project
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>meviz</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.maven.ide.eclipse.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.m2e.core.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.m2e.core.maven2Nature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.maven.ide.eclipse.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100755 (executable)
index 0000000..3d8336b
--- /dev/null
@@ -0,0 +1,292 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
new file mode 100755 (executable)
index 0000000..28778fe
--- /dev/null
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=12
diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs
new file mode 100755 (executable)
index 0000000..ff7698f
--- /dev/null
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=false
+version=1
diff --git a/.settings/org.maven.ide.eclipse.prefs b/.settings/org.maven.ide.eclipse.prefs
new file mode 100755 (executable)
index 0000000..3707fa5
--- /dev/null
@@ -0,0 +1,8 @@
+#Tue May 31 02:56:21 EEST 2011
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/COPYING b/COPYING
new file mode 100755 (executable)
index 0000000..10828e0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,341 @@
+
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..e8e6bc3
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+See "doc" directory for project documentation.
diff --git a/TODO b/TODO
new file mode 100755 (executable)
index 0000000..e803ab8
--- /dev/null
+++ b/TODO
@@ -0,0 +1,18 @@
+TODO:
+
+* integrate:
+       jheora
+       jogg and jorbis from jcraft
+
+
+* possibility to delete original files after conversion
+* possibility to get rid of the terminal window when encoding videos
+* possibility to use parent directory name in the file renamer tool
+
+HTML generator:
+       * video thumbnails      
+       
+       * possibility to go back multiple levels        
+
+       * sitemap generation
+       
diff --git a/doc/index.html b/doc/index.html
new file mode 100755 (executable)
index 0000000..0307371
--- /dev/null
@@ -0,0 +1,43 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta
+    http-equiv="Content-Type"
+    content="text/html; charset=UTF-8">
+<title>MeWiz</title>
+</head>
+<body>
+    <h1>MeWiz - Media Wizard</h1>
+    <a href="http://php.svjatoslav.eu/gitweb/?p=meviz.git;a=snapshot;h=HEAD;sf=tgz">Download</a>
+    &nbsp;&nbsp;
+    <a href="http://svjatoslav.eu/static/gitbrowse/meviz/doc/index.html">Online homepage</a>
+    &nbsp;&nbsp;
+    <a href="http://svjatoslav.eu/programs.jsp">Other applications hosted on svjatoslav.eu</a>
+    <pre>
+<b>Program author:</b>
+    Svjatoslav Agejenko
+    Homepage: <a href="http://svjatoslav.eu">http://svjatoslav.eu</a>
+    Email: <a href="mailto:svjatoslav@svjatoslav.eu">svjatoslav@svjatoslav.eu</a>
+
+This software is distributed under <a href="http://www.gnu.org/licenses/gpl-2.0.html">GNU GENERAL PUBLIC LICENSE Version 2</a>.
+
+<h2>Introdution</h2>
+
+The idea is to have something like a Swiss army knife of various tools
+for audio, video, photo editing/conversion.
+
+
+Current functionality:
+
+    * Acts as unified frontend for linux commandline tools for
+      audio, video and photo conversion.
+
+    * Generates HTML listing for directory content with image thumbnails and embedded video player
+      for OGV video. <a href="http://svjatoslav.eu/static/events/index.html">Example generated listing.</a> 
+
+    * Batch file rename.
+    
+
+    </pre>
+</body>
+</html>
\ No newline at end of file
diff --git a/install b/install
new file mode 100755 (executable)
index 0000000..d7e9a04
--- /dev/null
+++ b/install
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+sudo apt-get install "maven"
+sudo apt-get install "lame"
+sudo apt-get install "vorbis-tools"
+sudo apt-get install "imagemagick"
+sudo apt-get install "ffmpeg2theora"
+sudo apt-get install "libav-tools"
+
+# this provides "avconv" commandline universal media conversion utility
+sudo apt-get install "libav-tools"
+
+mvn clean
+mvn package
+
+sudo mkdir /opt/meviz
+sudo cp target/meviz-1.0-SNAPSHOT.jar /opt/meviz/
+sudo cp meviz /opt/meviz/
+sudo ln -s /opt/meviz/meviz /usr/bin/
+
diff --git a/meviz b/meviz
new file mode 100755 (executable)
index 0000000..5283cb8
--- /dev/null
+++ b/meviz
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+set -f
+
+java -Xmx4000m -XX:MaxPermSize=2024m -jar /opt/meviz/meviz-1.0-SNAPSHOT.jar $@
+
diff --git a/pom.xml b/pom.xml
new file mode 100755 (executable)
index 0000000..ee43dc4
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,138 @@
+<project
+    xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>eu.svjatoslav</groupId>
+    <artifactId>meviz</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+    <name>meviz</name>
+    <description>media wizard</description>
+
+    <organization>
+        <name>svjatoslav.eu</name>
+        <url>http://svjatoslav.eu</url>
+    </organization>
+
+    <dependencies>
+        <dependency>
+            <groupId>eu.svjatoslav</groupId>
+            <artifactId>svjatoslavcommons</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.16</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>eu.svjatoslav.meviz.Main</mainClass>
+                        </manifest>
+                    </archive>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+
+                <executions>
+
+                    <execution>
+                        <id>package-jar-with-dependencies</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <appendAssemblyId>false</appendAssemblyId>
+                            <descriptorRefs>
+                                <descriptorRef>jar-with-dependencies</descriptorRef>
+                            </descriptorRefs>
+                            <archive>
+                                <manifest>
+                                    <mainClass>eu.svjatoslav.meviz.Main</mainClass>
+                                </manifest>
+                            </archive>
+                        </configuration>
+                    </execution>
+
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.3.2</version>
+                <configuration>
+                    <source>1.6</source>
+                    <target>1.6</target>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>2.2.1</version>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>2.9</version>
+                <executions>
+                    <execution>
+                        <id>attach-javadocs</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+        </plugins>
+
+        <extensions>
+            <extension>
+                <groupId>org.apache.maven.wagon</groupId>
+                <artifactId>wagon-ssh</artifactId>
+                <version>2.2</version>
+            </extension>
+        </extensions>
+
+    </build>
+
+    <distributionManagement>
+        <snapshotRepository>
+            <id>svjatoslav.eu</id>
+            <name>svjatoslav.eu</name>
+            <url>scp://svjatoslav.eu:7022/var/lib/tomcat6/_svjatoslav.eu/static/maven</url>
+        </snapshotRepository>
+    </distributionManagement>
+
+    <repositories>
+        <repository>
+            <id>svjatoslav.eu</id>
+            <name>Svjatoslav repository</name>
+            <url>http://svjatoslav.eu/static/maven/</url>
+        </repository>
+    </repositories>
+
+</project>
diff --git a/src/main/java/eu/svjatoslav/meviz/Main.java b/src/main/java/eu/svjatoslav/meviz/Main.java
new file mode 100755 (executable)
index 0000000..58ae6b7
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz;
+
+import java.util.ArrayList;
+
+import eu.svjatoslav.meviz.encoder.Encoder;
+
+public class Main {
+
+       public static ArrayList<Module> modules;
+
+       public static String[] getRemainingOptions(final String[] options) {
+               final String[] remainingOptions = new String[options.length - 1];
+
+               for (int i = 1; i < options.length; i++)
+                       remainingOptions[i - 1] = options[i];
+
+               return remainingOptions;
+       };
+
+       public static void initModules() {
+               modules = new ArrayList<Module>();
+
+               modules.add(new Encoder());
+               modules.add(new eu.svjatoslav.meviz.htmlindexer.Main());
+               modules.add(new eu.svjatoslav.meviz.renamer.Main());
+               modules.add(new eu.svjatoslav.meviz.grabmemcard.Main());
+               modules.add(new eu.svjatoslav.meviz.textsplitter.Main());
+
+       }
+
+       public static void main(final String[] args) throws Exception {
+
+               initModules();
+
+               if (args.length < 1)
+                       showHelp();
+               else if (args[0].equals("help")) {
+                       if (args.length != 2)
+                               showHelp();
+                       else {
+
+                               for (final Module module : modules)
+                                       if (args[1].equals(module.getModuleCommand())) {
+                                               module.showCommandlineHelp();
+                                               return;
+                                       }
+
+                               System.out.println("Error: unrecognized module by name:"
+                                               + args[1] + "\n");
+                               showHelp();
+
+                       }
+               } else {
+
+                       for (final Module module : modules)
+                               if (args[0].equals(module.getModuleCommand())) {
+                                       module.run(getRemainingOptions(args));
+                                       return;
+                               }
+
+                       System.out.println("Error: unrecognized commandline option:"
+                                       + args[0] + "\n");
+                       showHelp();
+               }
+
+       }
+
+       public static void showHelp() {
+               final StringBuffer buffer = new StringBuffer();
+
+               buffer.append("Commandline options: \n"
+                               + "help\n    show this help screen \n\n");
+
+               buffer.append("help <module>\n    show module specific help screen\n\n");
+
+               buffer.append("Available modules:\n\n");
+
+               for (final Module module : modules) {
+                       buffer.append(module.getModuleCommand() + "\n");
+                       buffer.append("    " + module.getDescription() + "\n\n");
+               }
+
+               System.out.println(buffer.toString());
+       }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/Module.java b/src/main/java/eu/svjatoslav/meviz/Module.java
new file mode 100755 (executable)
index 0000000..797aa1d
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz;
+
+public interface Module {
+
+    public String getDescription();
+
+    public String getModuleCommand();
+
+    public void run(String args[]) throws Exception;
+
+    public void showCommandlineHelp();
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/Bitrate.java b/src/main/java/eu/svjatoslav/meviz/encoder/Bitrate.java
new file mode 100755 (executable)
index 0000000..fb1481d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder;
+
+import eu.svjatoslav.commons.commandline.parameterparser.Argument;
+
+public class Bitrate implements Argument {
+    @Override
+    public String describeFormat() {
+        return "Target bitrate [LOW / MEDIUM / HIGH]";
+    }
+
+    @Override
+    public boolean validate(final String value) {
+        try {
+            bitrate.valueOf(value);
+        } catch (final IllegalArgumentException exception) {
+            return false;
+        }
+
+        return true;
+    }
+
+    static public enum bitrate {
+        LOW, MEDIUM, HIGH
+    };
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/CommandlineHandler.java b/src/main/java/eu/svjatoslav/meviz/encoder/CommandlineHandler.java
new file mode 100755 (executable)
index 0000000..fd9d9e9
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder;
+
+import eu.svjatoslav.commons.commandline.parameterparser.Parameter;
+import eu.svjatoslav.commons.commandline.parameterparser.Parser;
+
+public class CommandlineHandler {
+
+    Parameter outputFormatParameter = new Parameter(true, true, true,
+            new eu.svjatoslav.commons.commandline.parameterparser.arguments.String(), "Encoding output format.", "-o",
+            "--output-format");
+
+    Parameter terminalParameter = new Parameter("Enable popup terminal.", "--terminal");
+
+    Parameter testParameter = new Parameter("Simulate file encoding.", "-t", "--test");
+
+    Parameter recursiveParameter = new Parameter("Enable recursive mode.", "-r", "--recursive");
+
+    Parameter inputPatternParameter = new Parameter(true, true, true,
+            new eu.svjatoslav.commons.commandline.parameterparser.arguments.String(), "File input pattern.", "-i",
+            "--input-pattern");
+
+    Parameter workingDirectoryParameter = new Parameter(false, true, true,
+            new eu.svjatoslav.commons.commandline.parameterparser.arguments.ExistingDirectory(), "Working directory.",
+            "-w", "--working-directory");
+
+    Parameter videoBitrateParameter = new Parameter(false, true, false, new Bitrate(), "Video bitrate.", "-v",
+            "--video-bitrate");
+
+    public Parser initParser() {
+        final Parser parser = new Parser();
+
+        parser.addParameter(recursiveParameter);
+
+        parser.addParameter(testParameter);
+
+        parser.addParameter(terminalParameter);
+
+        parser.addParameter(outputFormatParameter);
+
+        parser.addParameter(inputPatternParameter);
+
+        parser.addParameter(workingDirectoryParameter);
+
+        parser.addParameter(videoBitrateParameter);
+
+        return parser;
+    }
+
+    /**
+     * @return {@link EncodingOptions} if commandline arguments were
+     *         successfully parsed, or <code>null</code> if parsing error
+     *         occurred.
+     */
+    public EncodingOptions parseCommandlineArguments(final String[] args) {
+
+        final EncodingOptions options = new EncodingOptions();
+
+        final Parser parser = initParser();
+        parser.parse(args);
+
+        if (recursiveParameter.isParameterSpecified())
+            options.recursive = true;
+
+        if (terminalParameter.isParameterSpecified())
+            options.terminal = true;
+
+        if (testParameter.isParameterSpecified())
+            options.testOnly = true;
+
+        if (outputFormatParameter.isParameterSpecified()) {
+            options.outputFormats.addAll(outputFormatParameter.getArgumentsAsStrings());
+        }
+
+        if (workingDirectoryParameter.isParameterSpecified()) {
+            options.workingDirectory = workingDirectoryParameter.getArgumentsAsFiles().get(0);
+        }
+
+        if (inputPatternParameter.isParameterSpecified()) {
+            options.inputPatterns.addAll(inputPatternParameter.getArgumentsAsStrings());
+        }
+
+        if (videoBitrateParameter.isParameterSpecified()) {
+
+            try {
+                options.videoBitrate = Bitrate.bitrate.valueOf(videoBitrateParameter.getArgumentAsString()
+                        .toUpperCase());
+            } catch (final Exception e) {
+                System.out.println("Invalid video bitrate. Valid values are: LOW, MEDIUM, HIGH.");
+                return null;
+            }
+        }
+
+        return options;
+    }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/Encoder.java b/src/main/java/eu/svjatoslav/meviz/encoder/Encoder.java
new file mode 100755 (executable)
index 0000000..3b2f043
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder;
+
+import java.io.File;
+import java.util.List;
+
+import eu.svjatoslav.commons.file.FilePathParser;
+import eu.svjatoslav.commons.string.WildCardMatcher;
+import eu.svjatoslav.meviz.Module;
+import eu.svjatoslav.meviz.encoder.converters.Converter;
+
+public class Encoder implements Module {
+
+       public FormatsRegistry encoderRegistry = new FormatsRegistry();
+
+       public EncodingOptions encodingOptions;
+
+       public EncodingPlan encodingPlan;
+
+       CommandlineHandler commandlineHandler = new CommandlineHandler();
+
+       /**
+        * Generate encoding plan
+        * 
+        * @param sourceFile
+        *            Source directory of file
+        */
+       public void compileEncodingPlan(final File sourceFile) {
+               if (!sourceFile.exists()) {
+                       System.out.println("Error: file \"" + sourceFile.getAbsolutePath()
+                                       + "\" does not exist.");
+                       return;
+               }
+
+               if (sourceFile.isDirectory()) {
+                       // handle directory
+                       for (final File subFile : sourceFile.listFiles())
+                               if (subFile.isDirectory()) {
+                                       if (encodingOptions.recursive)
+                                               compileEncodingPlan(subFile);
+                               } else
+                                       compileEncodingPlan(subFile);
+               } else if (sourceFile.isFile())
+                       if (fileMatchesInputPattern(sourceFile)) {
+
+                               // System.out.println("Processing file: " +
+                               // file.getAbsolutePath());
+
+                               final String sourceFileExtension = FilePathParser
+                                               .getFileExtension(sourceFile);
+
+                               // encode source file into every desired target format
+                               for (final String targetFormat : encodingOptions.outputFormats) {
+
+                                       // construct target file
+                                       final File targetFile = getTargetFile(sourceFile,
+                                                       targetFormat);
+
+                                       // System.out.println("target path: " +
+                                       // targetFilePath.toString());
+
+                                       if (!targetFile.exists()) {
+
+                                               final List<eu.svjatoslav.meviz.encoder.converters.Converter> formats = encoderRegistry
+                                                               .getEncoders(sourceFileExtension, targetFormat);
+
+                                               if (formats.size() == 0)
+                                                       System.out
+                                                                       .println("Error: no encoders found to convert file \""
+                                                                                       + sourceFile.getAbsolutePath()
+                                                                                       + "\" into "
+                                                                                       + targetFormat
+                                                                                       + " format.");
+                                               else if (formats.size() > 1)
+                                                       System.out
+                                                                       .println("Error: Encoders piping not yet supported to convert file \""
+                                                                                       + sourceFile.getAbsolutePath()
+                                                                                       + "\" into "
+                                                                                       + targetFormat
+                                                                                       + " format.");
+                                               else {
+                                                       final Converter chosenFormat = formats.get(0);
+                                                       final EncodingTask encodingTask = new EncodingTask(
+                                                                       sourceFile, targetFile, chosenFormat);
+
+                                                       if (encodingOptions.terminal
+                                                                       || chosenFormat.isTerminalMandatory())
+                                                               encodingTask.setUseTerminal(true);
+                                                       encodingPlan.scheduleTask(encodingTask);
+                                               }
+                                       }
+                               }
+                       }
+
+       }
+
+       /**
+        * @param file
+        *            single file candidate to potentially be encoded
+        * 
+        * @return <code>true</code> if file shall be encoded.
+        */
+       public boolean fileMatchesInputPattern(final File file) {
+               final String fileName = file.getName().toLowerCase();
+
+               for (final String inputPattern : encodingOptions.inputPatterns)
+                       if (WildCardMatcher.match(fileName, inputPattern.toLowerCase()))
+                               return true;
+
+               return false;
+       }
+
+       @Override
+       public String getDescription() {
+               return "Convert between various media formats.";
+       }
+
+       @Override
+       public String getModuleCommand() {
+               return "encode";
+       }
+
+       private File getTargetFile(final File sourceFile, final String targetFormat) {
+               final StringBuffer targetFilePath = new StringBuffer();
+               targetFilePath.append(sourceFile.getParent());
+               targetFilePath.append("/");
+               targetFilePath.append(FilePathParser
+                               .getFileNameWithoutExtension(sourceFile));
+               targetFilePath.append(".");
+               targetFilePath.append(targetFormat);
+
+               return new File(targetFilePath.toString());
+       }
+
+       @Override
+       public void run(final String[] args) {
+
+               // parse incoming commandline arguments
+               encodingOptions = commandlineHandler.parseCommandlineArguments(args);
+
+               if (encodingOptions == null) {
+                       showCommandlineHelp();
+                       return;
+               }
+
+               encodingPlan = new EncodingPlan();
+
+               compileEncodingPlan(encodingOptions.workingDirectory);
+
+               if (!encodingOptions.testOnly)
+                       try {
+                               encodingPlan.execute(encodingOptions);
+                       } catch (final Exception exception) {
+                               exception.printStackTrace();
+                       }
+
+       }
+
+       @Override
+       public void showCommandlineHelp() {
+               commandlineHandler.initParser().showHelp();
+               System.out.println("Example commands:");
+               System.out
+                               .println("    Convert all MTS files in the current directory into MP4's.");
+               System.out.println("        meviz encode -o mp4 -i *.MTS");
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/EncodingOptions.java b/src/main/java/eu/svjatoslav/meviz/encoder/EncodingOptions.java
new file mode 100755 (executable)
index 0000000..d9df4bd
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class EncodingOptions {
+
+    public Bitrate.bitrate videoBitrate = Bitrate.bitrate.MEDIUM;
+
+    public Bitrate audioBitrate;
+
+    public boolean recursive;
+
+    public boolean terminal;
+
+    public boolean testOnly;
+
+    public File workingDirectory = new File(System.getProperty("user.dir"));
+
+    List<String> outputFormats = new ArrayList<String>();
+
+    List<String> inputPatterns = new ArrayList<String>();
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/EncodingPlan.java b/src/main/java/eu/svjatoslav/meviz/encoder/EncodingPlan.java
new file mode 100755 (executable)
index 0000000..f23fbdb
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class EncodingPlan {
+
+    public ArrayList<EncodingTask> encodingTasks = new ArrayList<EncodingTask>();
+
+    public void execute(final EncodingOptions encodingOptions) throws IOException {
+        for (final EncodingTask task : encodingTasks) {
+
+            try {
+                String command = task.getCommand(encodingOptions);
+
+                if (task.doUseTerminal()) {
+                    command = "xterm -e '" + command + "'";
+                }
+
+                System.out.println("Executing command: " + command);
+
+                final Runtime run = Runtime.getRuntime();
+                Process pr;
+                pr = run.exec(new String[] { "/bin/bash", "-c", command });
+
+                pr.waitFor();
+
+            } catch (final Exception e) {
+                System.out.println(e.toString());
+                e.printStackTrace();
+            }
+
+        }
+
+    }
+
+    public void scheduleTask(final EncodingTask encodingTask) {
+        encodingTasks.add(encodingTask);
+    };
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/EncodingTask.java b/src/main/java/eu/svjatoslav/meviz/encoder/EncodingTask.java
new file mode 100755 (executable)
index 0000000..9db5d92
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.converters.Converter;
+
+public class EncodingTask {
+
+    /**
+     * Source file to encode
+     */
+    private final File source;
+
+    /**
+     * Target file.
+     */
+    private final File target;
+
+    private final Converter converter;
+
+    private boolean useTerminal;
+
+    public EncodingTask(final File source, final File destination,
+            final eu.svjatoslav.meviz.encoder.converters.Converter converter) {
+
+        this.source = source;
+        target = destination;
+        this.converter = converter;
+
+    }
+
+    /**
+     * @return the useTerminal
+     */
+    public boolean doUseTerminal() {
+        return useTerminal;
+    }
+
+    public String getCommand(final EncodingOptions encodingOptions) {
+        return converter.getCommand(source, target, encodingOptions);
+    }
+
+    /**
+     * @param useTerminal
+     *            the useTerminal to set
+     */
+    public void setUseTerminal(final boolean useTerminal) {
+        this.useTerminal = useTerminal;
+    }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/FormatsRegistry.java b/src/main/java/eu/svjatoslav/meviz/encoder/FormatsRegistry.java
new file mode 100755 (executable)
index 0000000..ab794c3
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import eu.svjatoslav.meviz.encoder.converters.Avi2Ogv;
+import eu.svjatoslav.meviz.encoder.converters.Converter;
+import eu.svjatoslav.meviz.encoder.converters.Jpeg2Png;
+import eu.svjatoslav.meviz.encoder.converters.Mp42Ogv;
+import eu.svjatoslav.meviz.encoder.converters.Mts2Mkv;
+import eu.svjatoslav.meviz.encoder.converters.Mts2Mp4;
+import eu.svjatoslav.meviz.encoder.converters.Ogg2Mp3;
+import eu.svjatoslav.meviz.encoder.converters.Ogg2Wav;
+import eu.svjatoslav.meviz.encoder.converters.Png2Tiff;
+import eu.svjatoslav.meviz.encoder.converters.Tiff2Png;
+import eu.svjatoslav.meviz.encoder.converters.Wav2mp3;
+
+public class FormatsRegistry {
+
+    public ArrayList<Converter> encoders = new ArrayList<Converter>();
+
+    public FormatsRegistry() {
+       // video conversion
+        registerEncoder(new Avi2Ogv());
+        registerEncoder(new Mp42Ogv());
+        registerEncoder(new Mts2Mp4());
+        registerEncoder(new Mts2Mkv());
+
+        // image conversion
+        registerEncoder(new Jpeg2Png());
+        registerEncoder(new Png2Tiff());
+        registerEncoder(new Tiff2Png());
+
+        // audio conversion
+        registerEncoder(new Ogg2Wav());
+        registerEncoder(new Wav2mp3());
+        registerEncoder(new Ogg2Mp3());
+    }
+
+    public List<Converter> getEncoders(final String sourceFormat, final String targetFormat) {
+
+        final String sourceFormatLowerCase = sourceFormat.toLowerCase();
+        final String targetFormatLowerCase = targetFormat.toLowerCase();
+
+        final ArrayList<Converter> encoders = new ArrayList<Converter>();
+
+        for (final Converter encoder : this.encoders) {
+            if (encoder.getSourceFileExtension().equals(sourceFormatLowerCase)) {
+                if (encoder.getTargetFileExtension().equals(targetFormatLowerCase)) {
+                    encoders.add(encoder);
+                    return encoders;
+                }
+            }
+        }
+
+        return encoders;
+    }
+
+    public void registerEncoder(final Converter encoder) {
+        encoders.add(encoder);
+    }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Avi2Ogv.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Avi2Ogv.java
new file mode 100755 (executable)
index 0000000..acb3624
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class Avi2Ogv implements Converter {
+
+       @Override
+       public String getCommand(final File inputFile, final File targetFile,
+                       final EncodingOptions options) {
+
+               return "ffmpeg2theora \"" + inputFile.getAbsolutePath() + "\" -o \""
+                               + targetFile.getAbsolutePath()
+                               + "\" --optimize --videobitrate 3000 --width 800";
+       }
+
+       @Override
+       public String getSourceFileExtension() {
+               return "avi";
+       }
+
+       @Override
+       public String getTargetFileExtension() {
+               return "ogv";
+       }
+
+       @Override
+       public boolean isTerminalMandatory() {
+
+               return false;
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Converter.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Converter.java
new file mode 100755 (executable)
index 0000000..d39cf79
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public interface Converter {
+
+    public String getCommand(File inputFile, File targetFile, EncodingOptions options);
+
+    public String getSourceFileExtension();
+
+    public String getTargetFileExtension();
+
+    /**
+     * For some reasons some encoders require terminal to run. Until this is
+     * resolved, encoder can request for terminal using this method.
+     */
+    public boolean isTerminalMandatory();
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Jpeg2Png.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Jpeg2Png.java
new file mode 100755 (executable)
index 0000000..cb66bf5
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class Jpeg2Png implements Converter {
+
+    @Override
+    public String getCommand(final File inputFile, final File targetFile, final EncodingOptions options) {
+        return "convert \"" + inputFile.getAbsolutePath() + "\" \""
+        + targetFile.getAbsolutePath() + "\"";
+    }
+
+    @Override
+    public String getSourceFileExtension() {
+        return "jpeg";
+    }
+
+    @Override
+    public String getTargetFileExtension() {
+        return "png";
+    }
+
+    @Override
+    public boolean isTerminalMandatory() {
+        return false;
+    }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Mp42Ogv.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Mp42Ogv.java
new file mode 100755 (executable)
index 0000000..59f4922
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class Mp42Ogv implements Converter {
+
+    @Override
+    public String getCommand(final File inputFile, final File targetFile, final EncodingOptions options) {
+        return "ffmpeg2theora \"" + inputFile.getAbsolutePath() + "\" -o \"" + targetFile.getAbsolutePath()
+                + "\" --optimize --videobitrate 3000 --width 800";
+    }
+
+    @Override
+    public String getSourceFileExtension() {
+        return "mp4";
+    }
+
+    @Override
+    public String getTargetFileExtension() {
+        return "ogv";
+    }
+
+    @Override
+    public boolean isTerminalMandatory() {
+        return true;
+    }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Mts2Mkv.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Mts2Mkv.java
new file mode 100644 (file)
index 0000000..1fdab94
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class Mts2Mkv implements Converter {
+
+    @Override
+    public String getCommand(final File inputFile, final File targetFile, final EncodingOptions options) {
+
+        return "ffmpeg -i \"" + inputFile.getAbsolutePath() + "\" -vcodec copy -acodec copy \""
+                + targetFile.getAbsolutePath() + "\"";
+    }
+
+    @Override
+    public String getSourceFileExtension() {
+        return "mts";
+    }
+
+    @Override
+    public String getTargetFileExtension() {
+        return "mkv";
+    }
+
+    @Override
+    public boolean isTerminalMandatory() {
+        return true;
+    }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Mts2Mp4.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Mts2Mp4.java
new file mode 100755 (executable)
index 0000000..011282f
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class Mts2Mp4 implements Converter {
+
+       @Override
+       public String getCommand(final File inputFile, final File targetFile,
+                       final EncodingOptions options) {
+               //
+               // int videoBitrate;
+               //
+               // switch (options.videoBitrate) {
+               // case LOW:
+               // videoBitrate = 3000;
+               // break;
+               //
+               // case MEDIUM:
+               // videoBitrate = 7000;
+               // break;
+               //
+               // case HIGH:
+               // videoBitrate = 15000;
+               // break;
+               //
+               // default:
+               // throw new RuntimeException("Video bitrate: " + options.videoBitrate
+               // + " is not supported.");
+               // }
+
+               // convert
+               final String codecParams = "-acodec libmp3lame -vcodec libx264 -b 3500k -b:a 192k";
+
+               // pass through
+               // final String codecParams = "-acodec copy -vcodec copy";
+
+               return "avconv -i \"" + inputFile.getAbsolutePath() + "\" "
+                               + codecParams + " \"" + targetFile.getAbsolutePath() + "\"";
+       }
+
+       @Override
+       public String getSourceFileExtension() {
+               return "mts";
+       }
+
+       @Override
+       public String getTargetFileExtension() {
+               return "mp4";
+       }
+
+       @Override
+       public boolean isTerminalMandatory() {
+               return true;
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Ogg2Mp3.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Ogg2Mp3.java
new file mode 100755 (executable)
index 0000000..1d5401d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class Ogg2Mp3 implements Converter {
+
+    @Override
+    public String getCommand(final File inputFile, final File targetFile, final EncodingOptions options) {
+        return "avconv -i \"" + inputFile.getAbsolutePath() + "\" \"" + targetFile.getAbsolutePath() + "\"";
+    }
+
+    @Override
+    public String getSourceFileExtension() {
+        return "ogg";
+    }
+
+    @Override
+    public String getTargetFileExtension() {
+        return "mp3";
+    }
+
+    @Override
+    public boolean isTerminalMandatory() {
+        return false;
+    }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Ogg2Wav.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Ogg2Wav.java
new file mode 100755 (executable)
index 0000000..49b989b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class Ogg2Wav implements Converter {
+
+    @Override
+    public String getCommand(final File inputFile, final File targetFile, final EncodingOptions options) {
+
+        return "oggdec \"" + inputFile.getAbsolutePath() + "\" -o \"" + targetFile.getAbsolutePath() + "\"";
+
+    }
+
+    @Override
+    public String getSourceFileExtension() {
+        return "ogg";
+    }
+
+    @Override
+    public String getTargetFileExtension() {
+        return "wav";
+    }
+
+    @Override
+    public boolean isTerminalMandatory() {
+        return true;
+    }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Png2Tiff.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Png2Tiff.java
new file mode 100644 (file)
index 0000000..ccf7e57
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class Png2Tiff implements Converter {
+
+
+    @Override
+    public String getCommand(final File inputFile, final File targetFile, final EncodingOptions options) {
+        return "convert \"" + inputFile.getAbsolutePath() + "\" \""
+        + targetFile.getAbsolutePath() + "\"";
+    }
+
+    @Override
+    public String getSourceFileExtension() {
+        return "tiff";
+    }
+
+    @Override
+    public String getTargetFileExtension() {
+        return "png";
+    }
+
+    @Override
+    public boolean isTerminalMandatory() {
+        return false;
+    }
+
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Tiff2Png.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Tiff2Png.java
new file mode 100644 (file)
index 0000000..fbbaee8
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class Tiff2Png implements Converter {
+
+
+    @Override
+    public String getCommand(final File inputFile, final File targetFile, final EncodingOptions options) {
+        return "convert \"" + inputFile.getAbsolutePath() + "\" \""
+        + targetFile.getAbsolutePath() + "\"";
+    }
+
+    @Override
+    public String getSourceFileExtension() {
+        return "png";
+    }
+
+    @Override
+    public String getTargetFileExtension() {
+        return "tiff";
+    }
+
+    @Override
+    public boolean isTerminalMandatory() {
+        return false;
+    }
+
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/encoder/converters/Wav2mp3.java b/src/main/java/eu/svjatoslav/meviz/encoder/converters/Wav2mp3.java
new file mode 100755 (executable)
index 0000000..ec67f0f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.encoder.converters;
+
+import java.io.File;
+
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class Wav2mp3 implements Converter {
+
+       @Override
+       public String getCommand(final File inputFile, final File targetFile,
+                       final EncodingOptions options) {
+
+               final String codecParams = "-b:a 192k";
+
+               return "avconv -i \"" + inputFile.getAbsolutePath() + "\" "
+                               + codecParams + " \"" + targetFile.getAbsolutePath() + "\"";
+       }
+
+       @Override
+       public String getSourceFileExtension() {
+               return "wav";
+       }
+
+       @Override
+       public String getTargetFileExtension() {
+               return "mp3";
+       }
+
+       @Override
+       public boolean isTerminalMandatory() {
+               return false;
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/grabmemcard/Main.java b/src/main/java/eu/svjatoslav/meviz/grabmemcard/Main.java
new file mode 100755 (executable)
index 0000000..d7f866e
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.grabmemcard;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import eu.svjatoslav.commons.file.CommonPathResolver;
+import eu.svjatoslav.commons.file.FilePathParser;
+import eu.svjatoslav.meviz.Module;
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+import eu.svjatoslav.meviz.encoder.EncodingPlan;
+import eu.svjatoslav.meviz.encoder.EncodingTask;
+import eu.svjatoslav.meviz.encoder.converters.Converter;
+import eu.svjatoslav.meviz.encoder.converters.Mts2Mp4;
+
+public class Main implements Module {
+
+       @Override
+       public String getDescription() {
+               return "Convenience helper to retrieve contents of inserted memory card.";
+       }
+
+       public File[] getDiskVideos(final File file) {
+               final String videosPath = file.getAbsolutePath()
+                               + "/AVCHD/BDMV/STREAM/";
+               final File videosDirectory = new File(videosPath);
+
+               if (!videosDirectory.exists())
+                       return new File[0];
+
+               return videosDirectory.listFiles();
+       }
+
+       public String getDoubleDigit(final int value) {
+               String valueString = Integer.toString(value);
+               if (valueString.length() == 1)
+                       valueString = "0" + valueString;
+               return valueString;
+       };
+
+       @Override
+       public String getModuleCommand() {
+               return "grabmemcard";
+       }
+
+       @SuppressWarnings("deprecation")
+       public File getTargetDirectory() {
+               final Date now = new Date();
+               final GregorianCalendar calendar = new GregorianCalendar();
+
+               final StringBuffer directoryName = new StringBuffer();
+               directoryName.append(calendar.get(GregorianCalendar.YEAR) + "."
+                               + getDoubleDigit(calendar.get(GregorianCalendar.MONTH) + 1)
+                               + "."
+                               + getDoubleDigit(calendar.get(GregorianCalendar.DAY_OF_MONTH))
+                               + " ");
+
+               directoryName.append(getDoubleDigit(now.getHours()) + ":"
+                               + getDoubleDigit(now.getMinutes()) + ":"
+                               + getDoubleDigit(now.getSeconds()));
+
+               final String targetDirectoryPath = CommonPathResolver
+                               .getDesktopDirectory().getAbsolutePath()
+                               + "/"
+                               + directoryName.toString() + "/";
+
+               System.out.println("Target directory path: " + targetDirectoryPath);
+
+               return new File(targetDirectoryPath);
+       }
+
+       @Override
+       public void run(final String[] args) throws IOException {
+
+               final File targetDirectory = getTargetDirectory();
+               targetDirectory.mkdirs();
+
+               final Converter converter = new Mts2Mp4();
+               final EncodingPlan encodingPlan = new EncodingPlan();
+
+               final File file = new File("/media");
+
+               for (final File insertedDisk : file.listFiles()) {
+                       final File[] diskVideos = getDiskVideos(insertedDisk);
+
+                       for (final File sourceFile : diskVideos) {
+
+                               // compute target file path
+                               final StringBuffer targetFilePath = new StringBuffer();
+                               targetFilePath.append(targetDirectory.getAbsolutePath());
+                               targetFilePath.append("/");
+                               targetFilePath.append(FilePathParser
+                                               .getFileNameWithoutExtension(sourceFile));
+                               targetFilePath.append(".mp4");
+                               final File targetFile = new File(targetFilePath.toString());
+
+                               final EncodingTask encodingTask = new EncodingTask(sourceFile,
+                                               targetFile, converter);
+                               encodingPlan.scheduleTask(encodingTask);
+                       }
+               }
+
+               final EncodingOptions options = new EncodingOptions();
+
+               encodingPlan.execute(options);
+       }
+
+       @Override
+       public void showCommandlineHelp() {
+               System.out.println("memory card grabber has no commandline options");
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/AbstractIndexer.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/AbstractIndexer.java
new file mode 100644 (file)
index 0000000..cc8f159
--- /dev/null
@@ -0,0 +1,60 @@
+package eu.svjatoslav.meviz.htmlindexer;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+
+import eu.svjatoslav.meviz.htmlindexer.metadata.Dimension;
+import eu.svjatoslav.meviz.htmlindexer.metadata.DirectoryMetadata;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.AbstractFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.DirectoryFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.GeneralFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.Picture;
+
+public abstract class AbstractIndexer {
+
+       public void compileHtml(final Layout layout,
+                       final DirectoryMetadata directory)
+                       throws UnsupportedEncodingException {
+
+               for (final AbstractFile file : directory.getFiles())
+                       if (file instanceof GeneralFile) {
+                               final String fileExtension = file.getFileExtension();
+
+                               if ("ogv".equals(fileExtension))
+                                       layout.enlistOgv((GeneralFile) file);
+                               else
+                                       layout.enlistFile(file);
+
+                       } else if (file instanceof Picture)
+                               layout.enlistImage(file);
+                       else if (file instanceof DirectoryFile)
+                               layout.enlistDirectory(file);
+
+       }
+
+       public abstract String getThumbnailPath(Picture picture,
+                       final Dimension desiredDimension);
+
+       public static boolean isImage(final String fileExtension) {
+               for (final String ext : Constants.SUPPORTED_IMAGE_EXTENSIONS)
+                       if (ext.equals(fileExtension))
+                               return true;
+               return false;
+       }
+
+       public static boolean isOgv(final String fileExtension) {
+               return fileExtension.equalsIgnoreCase("ogv");
+       }
+
+       public static boolean shallFileBeIndexed(final File file) {
+
+               if (file.getName().startsWith("."))
+                       return false;
+               if (file.getName().startsWith("index"))
+                       if (file.getName().endsWith(".html"))
+                               return false;
+
+               return true;
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/CommandlineHandler.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/CommandlineHandler.java
new file mode 100755 (executable)
index 0000000..6095673
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer;
+
+import java.io.File;
+
+import eu.svjatoslav.commons.commandline.parameterparser.Parameter;
+import eu.svjatoslav.commons.commandline.parameterparser.Parser;
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class CommandlineHandler {
+
+    Parameter galleryNameParameter = new Parameter(false, true, false,
+            new eu.svjatoslav.commons.commandline.parameterparser.arguments.String(), "Gallery title. (default is: "
+                    + Constants.DEFAULT_GALLERY_TITLE + ").", "-t", "--gallery-title");
+
+    Parameter workingDirectoryParameter = new Parameter(false, true, true,
+            new eu.svjatoslav.commons.commandline.parameterparser.arguments.String(), "Working directory.", "-w",
+            "--working-directory");
+
+    public Parser initParser() {
+
+        final Parser parser = new Parser();
+        parser.addParameter(galleryNameParameter);
+        parser.addParameter(workingDirectoryParameter);
+
+        return parser;
+    }
+
+    /**
+     * @return {@link EncodingOptions} if commandline arguments were
+     *         successfully parsed, or <code>null</code> if parsing error
+     *         occurred.
+     */
+    public IndexingOptions parseCommandlineArguments(final String[] args) {
+
+        final IndexingOptions options = new IndexingOptions();
+
+        final Parser parser = initParser();
+        if (!parser.parse(args)) {
+            return null;
+        }
+
+        if (galleryNameParameter.isParameterSpecified()) {
+            options.galleryTitle = galleryNameParameter.getArgumentsAsStrings().get(0);
+        }
+
+        if (workingDirectoryParameter.isParameterSpecified()) {
+            options.workingDirectory = workingDirectoryParameter.getArgumentsAsFiles().get(0);
+        } else {
+            options.workingDirectory = new File(System.getProperty("user.dir"));
+        }
+
+        return options;
+    }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/Constants.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/Constants.java
new file mode 100755 (executable)
index 0000000..3167f3b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer;
+
+public class Constants {
+
+       public static final String DEFAULT_GALLERY_TITLE = "Gallery";
+
+       public static final String METADATA_FILE_NAME = "metadata_6.dat";
+
+       public static final String THUMBNAILS_DIRECTORY_NAME = ".thumbnails";
+
+       /**
+        * If this string is found within index.html then it is assumed that the
+        * file is generated by current utility and therefore is safe to overwrite
+        * with the newer version.
+        * 
+        * TODO: possibility of multiple patterns shall be present, to allow easy
+        * migration
+        * 
+        * TODO: a safer way shall be used for detection, like specific pattern also
+        * in specific place within a file
+        */
+       public static final String HTML_MAGIC_STRING = "DirListGen";
+
+       public static final String HTML_MEMO = "Directory Listing Generator by Svjatoslav Agejenko. E-mail: svjatoslav@svjatoslav.eu, homepage: http://svjatoslav.eu";
+
+       public static final String[] SUPPORTED_IMAGE_EXTENSIONS = { "jpg", "jpeg",
+                       "png", "gif" };
+
+       public static final String THUMBNAIL_VERSION = "2";
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/FileSortComparator.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/FileSortComparator.java
new file mode 100644 (file)
index 0000000..b7ecef7
--- /dev/null
@@ -0,0 +1,14 @@
+package eu.svjatoslav.meviz.htmlindexer;
+
+import java.util.Comparator;
+
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.AbstractFile;
+
+public class FileSortComparator implements Comparator<AbstractFile> {
+
+       @Override
+       public int compare(final AbstractFile o1, final AbstractFile o2) {
+               return o1.fileName.compareTo(o2.fileName);
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/FilesystemIndexer.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/FilesystemIndexer.java
new file mode 100755 (executable)
index 0000000..9c8c877
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.HashSet;
+
+import org.apache.log4j.Logger;
+
+import eu.svjatoslav.commons.file.IOHelper;
+import eu.svjatoslav.meviz.htmlindexer.layouts.MixedLayout;
+import eu.svjatoslav.meviz.htmlindexer.metadata.Dimension;
+import eu.svjatoslav.meviz.htmlindexer.metadata.DirectoryMetadata;
+import eu.svjatoslav.meviz.htmlindexer.metadata.MetadadaHelper;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.AbstractFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.DirectoryFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.GeneralFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.Picture;
+
+/**
+ * Main class of HTML indexer.
+ */
+
+public class FilesystemIndexer extends AbstractIndexer {
+
+       public static final Logger logger = Logger
+                       .getLogger(FilesystemIndexer.class);
+
+       private final HashSet<String> validMetadataFiles = new HashSet<String>();
+
+       private final File directoryToIndex;
+
+       private String thumbnailsPath;
+
+       private File metadataFile;
+
+       private DirectoryMetadata metadata;
+
+       private final IndexingOptions indexingOptions;
+
+       private final String[] pathElements;
+
+       private HashSet<Layout> layouts;
+
+       public FilesystemIndexer(final File directoryToIndex,
+                       final IndexingOptions indexingOptions, final String[] pathElements)
+                       throws IOException, ImageFormatError {
+
+               this.directoryToIndex = directoryToIndex;
+               this.indexingOptions = indexingOptions;
+               this.pathElements = pathElements;
+
+               if (!directoryToIndex.canRead())
+                       return;
+
+               validMetadataFiles.add(Constants.METADATA_FILE_NAME);
+
+               initializeThumbnailsDirectory();
+               loadOrCreateMetadata();
+
+               initializeLayouts();
+
+               updateMetadata();
+
+               metadata.removeUnusedMetadataEntries();
+
+               generateHtmlFromMetadata(layouts);
+
+               removeUnusedThumbnailFiles();
+
+               // save directory metadata
+               if (metadata.changed)
+                       MetadadaHelper.saveDirectoryMetadata(metadataFile, metadata);
+
+       }
+
+       public boolean canWriteIndexFile(final File indexFile)
+                       throws FileNotFoundException, IOException {
+               boolean canWriteIndexFile = false;
+
+               if (indexFile.exists()) {
+                       // if file already exists, make sure that we can overwrite
+                       // it
+                       final FileReader fileReader = new FileReader(indexFile);
+                       final BufferedReader reader = new BufferedReader(fileReader);
+
+                       parseFile: {
+                               while (true) {
+                                       final String line = reader.readLine();
+
+                                       if (line == null)
+                                               break parseFile;
+
+                                       if (line.contains(Constants.HTML_MAGIC_STRING)) {
+                                               canWriteIndexFile = true;
+                                               break parseFile;
+                                       }
+                               }
+                       }
+
+                       reader.close();
+                       fileReader.close();
+               } else
+                       canWriteIndexFile = true;
+               return canWriteIndexFile;
+       }
+
+       public void cleanupUnusedMetadataFiles() {
+               final File thumbnailsDirectory = new File(thumbnailsPath);
+
+               for (final File file : thumbnailsDirectory.listFiles())
+                       if (!validMetadataFiles.contains(file.getName()))
+                               file.delete();
+       }
+
+       public void generateHtmlFromMetadata(final HashSet<Layout> layouts) {
+               // Generate HTML from metadata
+               for (final Layout layout : layouts) {
+
+                       final String indexFilePath = directoryToIndex.getAbsolutePath()
+                                       + "/index" + layout.getFileNameSuffix() + ".html";
+
+                       try {
+
+                               final File indexFile = new File(indexFilePath);
+                               if (canWriteIndexFile(indexFile)) {
+
+                                       indexForLayout(layout);
+
+                                       IOHelper.overwriteFileIfContentDiffers(indexFile, layout
+                                                       .getHtml().getBytes());
+                               }
+                       } catch (final Exception e) {
+                               logger.error("Error writing index file to:" + indexFilePath, e);
+                       }
+               }
+       }
+
+       public String[] getSubPath(final File file) {
+
+               final String[] subPath = new String[pathElements.length + 1];
+
+               for (int i = 0; i < pathElements.length; i++)
+                       subPath[i] = pathElements[i];
+
+               subPath[pathElements.length] = file.getName();
+               return subPath;
+       }
+
+       @Override
+       public String getThumbnailPath(final Picture picture,
+                       final Dimension desiredDimension) {
+
+               // in case thumbnail size was equal to original, then return original
+               // file path
+               if (picture.getDimensions().equals(desiredDimension))
+                       return picture.fileName;
+
+               final String thumbnailFileName = picture
+                               .getRelativeThumbnailFileName(desiredDimension);
+
+               validMetadataFiles.add(thumbnailFileName);
+               final File thumbnailFile = new File(thumbnailsPath + thumbnailFileName);
+
+               if (!thumbnailFile.exists()) {
+
+                       final File originalFile = new File(
+                                       directoryToIndex.getAbsolutePath() + "/" + picture.fileName);
+
+                       // generate new thumbnail
+                       Picture.makeThumbnail(originalFile, thumbnailFile,
+                                       desiredDimension.getAwtDimension());
+               }
+               return Constants.THUMBNAILS_DIRECTORY_NAME + "/" + thumbnailFileName;
+       }
+
+       public void indexForLayout(final Layout layout)
+                       throws UnsupportedEncodingException {
+
+               for (final AbstractFile abstractFile : metadata.getFiles())
+                       if (abstractFile instanceof GeneralFile) {
+
+                               if (isOgv(abstractFile.getFileExtension()))
+                                       layout.enlistOgv(abstractFile);
+                               else
+                                       layout.enlistFile(abstractFile);
+
+                       } else if (abstractFile instanceof Picture)
+                               layout.enlistImage(abstractFile);
+                       else if (abstractFile instanceof DirectoryFile)
+                               layout.enlistDirectory(abstractFile);
+
+       }
+
+       public void initializeLayouts() {
+               layouts = new HashSet<Layout>();
+               layouts.add(new MixedLayout());
+
+               for (final Layout layout : layouts)
+                       layout.init(indexingOptions.galleryTitle, pathElements, this);
+       }
+
+       public void initializeThumbnailsDirectory() {
+               // initialize thumbnails directory
+               thumbnailsPath = directoryToIndex.getAbsolutePath() + "/"
+                               + Constants.THUMBNAILS_DIRECTORY_NAME + "/";
+
+               // ensure thumbnails directory exists
+               final File thumbnailsDirectory = new File(thumbnailsPath);
+               if (!thumbnailsDirectory.exists())
+                       thumbnailsDirectory.mkdirs();
+       }
+
+       public void loadOrCreateMetadata() {
+               metadataFile = new File(thumbnailsPath + Constants.METADATA_FILE_NAME);
+
+               metadata = MetadadaHelper.initDirectoryMetadata(metadataFile);
+       }
+
+       private void removeUnusedThumbnailFiles() {
+
+               final File thumbnailsDirectory = new File(thumbnailsPath);
+
+               for (final File file : thumbnailsDirectory.listFiles())
+                       if (!validMetadataFiles.contains(file.getName()))
+                               file.delete();
+
+       }
+
+       public void updateMetadata() throws IOException, ImageFormatError {
+
+               final File[] directoryContent = directoryToIndex.listFiles();
+
+               for (final File file : directoryContent)
+                       if (shallFileBeIndexed(file)) {
+
+                               metadata.ensureFileMetainfoIsUpToDate(directoryToIndex, file);
+
+                               if (file.isDirectory())
+                                       new FilesystemIndexer(file, indexingOptions,
+                                                       getSubPath(file));
+                       }
+       }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/ImageFormatError.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/ImageFormatError.java
new file mode 100755 (executable)
index 0000000..7d40bf4
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer;
+
+public class ImageFormatError extends Exception {
+
+    private static final long serialVersionUID = 4037233564457071385L;
+
+    public ImageFormatError(final String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/IndexingOptions.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/IndexingOptions.java
new file mode 100755 (executable)
index 0000000..354aaed
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer;
+
+import java.io.File;
+
+public class IndexingOptions {
+
+    File workingDirectory;
+
+    String galleryTitle = Constants.DEFAULT_GALLERY_TITLE;
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/Layout.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/Layout.java
new file mode 100755 (executable)
index 0000000..510e7ad
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer;
+
+import java.io.UnsupportedEncodingException;
+
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.AbstractFile;
+
+/**
+ * In order to have possibility of several different layouts per directory.
+ * Universal interface is defined.
+ * 
+ * Layout implementation is responsible for actual HTML generation.
+ */
+
+public interface Layout {
+
+       /**
+        * Enlist directory.
+        */
+       public void enlistDirectory(AbstractFile directory);
+
+       /**
+        * Enlist simple file.
+        */
+       public void enlistFile(AbstractFile file);
+
+       /**
+        * Enlist image file.
+        */
+       public void enlistImage(AbstractFile picture);
+
+       /**
+        * Enlist video in OGV format.
+        * 
+        * @throws UnsupportedEncodingException
+        */
+       public void enlistOgv(AbstractFile file)
+                       throws UnsupportedEncodingException;
+
+       /**
+        * Return layout specific suffix that will be appended between
+        * index(suffix).html of generated file. This way multiple layouts can
+        * coexist in the same directory, each residing in its own HTML file.
+        */
+       public String getFileNameSuffix();
+
+       /**
+        * After necessary files have been enlisted for particular directory, use
+        * this method to retrieve generated HTML result.
+        */
+       public String getHtml();
+
+       /**
+        * Initialize layout for particular directory.
+        */
+       public void init(String galleryTitle, String[] path,
+                       final AbstractIndexer indexer);
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/Main.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/Main.java
new file mode 100644 (file)
index 0000000..94a2253
--- /dev/null
@@ -0,0 +1,52 @@
+package eu.svjatoslav.meviz.htmlindexer;
+
+import eu.svjatoslav.meviz.Module;
+
+public class Main implements Module {
+
+       CommandlineHandler commandlineHandler = new CommandlineHandler();
+
+       IndexingOptions indexingOptions;
+
+       /** {@inheritDoc} */
+       @Override
+       public String getDescription() {
+               return "Generate HTML listing of directories.";
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public String getModuleCommand() {
+               return "index";
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public void run(final String[] args) throws Exception {
+
+               indexingOptions = commandlineHandler.parseCommandlineArguments(args);
+
+               if (indexingOptions == null) {
+                       showCommandlineHelp();
+                       return;
+               }
+
+               new FilesystemIndexer(indexingOptions.workingDirectory,
+                               indexingOptions, new String[] {});
+
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public void showCommandlineHelp() {
+               commandlineHandler.initParser().showHelp();
+       }
+
+       // public static void main(final String[] args) throws Exception {
+       //
+       // final Main main = new Main();
+       // main.run(new String[] { "-w", "/home/n0/Desktop/testGallery/" });
+       //
+       // }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/Utils.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/Utils.java
new file mode 100755 (executable)
index 0000000..b21f8e9
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.zip.CRC32;
+
+import javax.imageio.ImageIO;
+
+public class Utils {
+
+    private static File lastLoadedFile;
+
+    private static BufferedImage lastLoadedBufferedImage;
+
+    /**
+     * Load image into {@link BufferedImage} and return it. Caches last loaded
+     * image to speed up subsequent loading attempts.
+     * 
+     * @throws ImageFormatError
+     * @throws IOException
+     */
+    public static BufferedImage getBufferedImage(final File file) throws ImageFormatError, IOException {
+        if (file.equals(lastLoadedFile)) {
+            return lastLoadedBufferedImage;
+        }
+
+        System.out.println("Loading image: " + file.getPath());
+        lastLoadedBufferedImage = ImageIO.read(file);
+        lastLoadedFile = file;
+
+        if (lastLoadedBufferedImage == null)
+            throw new ImageFormatError("File: " + file + " is not a valid image.");
+
+        return lastLoadedBufferedImage;
+    }
+
+    public static String getStringCrcAsHex(final String input) {
+
+        // create a new CRC-calculating object
+        final CRC32 crc = new CRC32();
+
+        // loop, calculating CRC for each byte of the string
+        // There is no CRC16.update(byte[]) method.
+        for (final byte b : input.getBytes()) {
+            crc.update(b);
+        }
+
+        // note use crc.value, not crc.getValue()
+        final String hex = Integer.toHexString((int) crc.getValue()).toUpperCase();
+
+        // System.out.println("Input string: " + input);
+        // System.out.println("Result: " + hex);
+
+        return hex;
+    }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/layouts/MixedLayout.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/layouts/MixedLayout.java
new file mode 100755 (executable)
index 0000000..f54b72f
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer.layouts;
+
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import eu.svjatoslav.commons.file.FilePathParser;
+import eu.svjatoslav.commons.network.UrlParamEncoder;
+import eu.svjatoslav.meviz.htmlindexer.AbstractIndexer;
+import eu.svjatoslav.meviz.htmlindexer.Constants;
+import eu.svjatoslav.meviz.htmlindexer.Layout;
+import eu.svjatoslav.meviz.htmlindexer.metadata.Dimension;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.AbstractFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.GeneralFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.Picture;
+
+public class MixedLayout implements Layout {
+
+       Logger logger = Logger.getLogger(MixedLayout.class);
+
+       StringBuffer dirHtml = new StringBuffer();
+
+       StringBuffer filesHtml = new StringBuffer();
+
+       String galleryTitle;
+
+       String[] path;
+
+       public static final String encoding = "UTF-8";
+
+       int currentColumn = 0;
+
+       int horizontalColumnsLimit = 2;
+
+       private AbstractIndexer indexer;
+
+       public void columnAdded() {
+               currentColumn++;
+               if (currentColumn > horizontalColumnsLimit) {
+
+                       currentColumn = 0;
+
+                       filesHtml.append("</TR>\n");
+               }
+       }
+
+       @Override
+       public void enlistDirectory(final AbstractFile directory) {
+               dirHtml.append("<TR>");
+               dirHtml.append("<TD><b><a href=\"" + directory.fileName
+                               + "/index.html\"> ==&gt; " + directory.fileName
+                               + "</a></b></TD>");
+               dirHtml.append("</TR>\n");
+
+       }
+
+       @Override
+       public void enlistFile(final AbstractFile file) {
+               finishRow();
+
+               final String fullFileName = file.fileName;
+
+               filesHtml.append("<TR>\n");
+               filesHtml.append("    <TD colspan=\""
+                               + String.valueOf(horizontalColumnsLimit) + "\"><a href=\""
+                               + UrlParamEncoder.encode(fullFileName) + "\">" + fullFileName
+                               + "</a>\n");
+               filesHtml.append("&nbsp;&nbsp;("
+                               + FilePathParser.getFileSizeDescription(file.getFileLength())
+                               + ")</TD>\n");
+               filesHtml.append("</TR>\n");
+
+       }
+
+       @Override
+       public void enlistImage(final AbstractFile abstractFile) {
+               try {
+
+                       final Picture picture = (Picture) abstractFile;
+
+                       final Dimension imageSize = picture.getDimensions();
+
+                       final List<Dimension> recommendedDimensions = Picture
+                                       .getThumbnailDimensions(imageSize);
+
+                       Dimension listingDimension = new Dimension(500, 500);
+
+                       if (listingDimension.width > imageSize.width)
+                               if (listingDimension.height > imageSize.height)
+                                       listingDimension = imageSize;
+
+                       final String listingThumbnailPath = indexer.getThumbnailPath(
+                                       picture, listingDimension);
+
+                       startcolumn();
+
+                       filesHtml.append("<TD><center><a href=\""
+                                       + UrlParamEncoder.encode(picture.fileName) + "\">\n");
+
+                       filesHtml.append("<img border=\"0\" src=\""
+                                       + UrlParamEncoder.encode(listingThumbnailPath)
+                                       + "\"/></a>\n");
+                       filesHtml.append("<br/><b>"
+                                       + FilePathParser
+                                                       .getFileNameWithoutExtension(picture.fileName)
+                                       + "</b><br/>(");
+
+                       int count = 0;
+                       for (final Dimension dimension : recommendedDimensions) {
+                               count++;
+                               if (count > 1)
+                                       filesHtml.append(", ");
+                               filesHtml.append("<a href=\""
+                                               + UrlParamEncoder.encode(indexer.getThumbnailPath(
+                                                               picture, dimension)) + "\">");
+                               filesHtml.append(dimension.width + "x" + dimension.height);
+                               filesHtml.append("</a>");
+                       }
+
+                       filesHtml.append(")</TD>\n");
+
+                       columnAdded();
+
+               } catch (final Exception e) {
+                       logger.error(
+                                       "Error generating thumbnails for image file: "
+                                                       + e.toString()
+                                                       + ", thumbnail generation skipped, enlisting as ordinary file instead.",
+                                       e);
+                       enlistFile(abstractFile);
+               }
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public void enlistOgv(final AbstractFile abstractFile)
+                       throws UnsupportedEncodingException {
+
+               final GeneralFile file = (GeneralFile) abstractFile;
+
+               finishRow();
+
+               filesHtml
+                               .append("<TR style=\"background-color: #404040; text-align: center\">\n");
+               filesHtml.append("<TD style=\"text-align: center\" colspan=\""
+                               + String.valueOf(horizontalColumnsLimit) + "\">\n");
+
+               filesHtml.append("<video controls=\"controls\" tabindex=\"0\">\n");
+               filesHtml
+                               .append("<source type=\"video/ogg\" codecs=\"theora, vorbis\" src=\""
+                                               + UrlParamEncoder.encode(file.fileName) + "\">\n");
+               filesHtml.append("</source>\n");
+
+               // if browser cannot play video directry, fall back to java Applet
+               filesHtml
+                               .append("<applet code=\"com.fluendo.player.Cortado.class\" archive=\"http://theora.org/cortado.jar\" width=\"800\" height=\"600\">\n");
+               filesHtml.append("    <param name=\"url\" value=\""
+                               + UrlParamEncoder.encode(file.fileName) + "\"/>\n");
+               filesHtml.append("    <param name=\"keepAspect\" value=\"true\"/>\n");
+               filesHtml.append("    <param name=\"autoPlay\" value=\"false\"/>\n");
+               filesHtml.append("</applet>\n");
+
+               filesHtml.append("</video>\n");
+
+               filesHtml.append("<br/>\n");
+
+               filesHtml
+                               .append("Video: <b>"
+                                               + FilePathParser
+                                                               .getFileNameWithoutExtension(file.fileName)
+                                               + "<b/>  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
+               filesHtml.append("<a href=\"" + UrlParamEncoder.encode(file.fileName)
+                               + "\">download as OGV</a>\n");
+
+               filesHtml.append("</TD></TR>\n");
+
+       }
+
+       public void finishRow() {
+
+               if (currentColumn == 0)
+                       return;
+
+               while (currentColumn <= horizontalColumnsLimit) {
+                       filesHtml.append("<TD></TD>");
+                       currentColumn++;
+               }
+               filesHtml.append("</TR>\n");
+               currentColumn = 0;
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public String getFileNameSuffix() {
+               return "";
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public String getHtml() {
+
+               // assemble final page HTML
+               final StringBuffer finalHtml = new StringBuffer();
+
+               // page header
+               finalHtml.append("<HTML>\n");
+               finalHtml.append("<HEAD>\n");
+               finalHtml
+                               .append("    <meta HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\"/>\n");
+               finalHtml.append("</HEAD>\n");
+               finalHtml
+                               .append("<BODY bgcolor=\"#000000\" alink=\"#50ffff\" link=\"#50ffff\" vlink=\"#ff50ff\" text=\"#ffffff\">\n");
+               finalHtml.append("<!-- " + Constants.HTML_MAGIC_STRING + " -->\n");
+               finalHtml.append("<!-- " + Constants.HTML_MEMO + " -->\n");
+               finalHtml.append("<FONT color=\"#ffffff\">\n");
+               finalHtml.append("<CENTER><H1>" + galleryTitle + "</H1>\n");
+
+               finalHtml.append("<H2>");
+               for (final String p : path)
+                       finalHtml.append(" / " + p);
+               finalHtml.append("</H2></CENTER>\n");
+
+               // append directory listing
+               finalHtml.append("<TABLE>\n");
+
+               if (path.length > 0) {
+                       finalHtml.append("<TR>");
+                       finalHtml
+                                       .append("<TD><b><a href=\"../index.html\"> &lt;== ..</a></b></TD>");
+                       finalHtml.append("</TR>\n");
+               }
+
+               finalHtml.append(dirHtml.toString());
+               finalHtml.append("\n<TR><TD><br></TD></TR>\n");
+               finalHtml.append("</TABLE>\n");
+
+               // append file listing
+
+               finishRow();
+               finalHtml.append("<TABLE width=\"1100\">\n");
+               finalHtml.append(filesHtml.toString());
+               finalHtml.append("\n</TABLE>\n");
+
+               finalHtml.append("</font></BODY></HTML>\n");
+
+               return finalHtml.toString();
+       }
+
+       @Override
+       public void init(final String galleryTitle, final String[] path,
+                       final AbstractIndexer indexer) {
+               this.indexer = indexer;
+               this.galleryTitle = galleryTitle;
+               this.path = path;
+       }
+
+       public void startcolumn() {
+               if (currentColumn == 0) {
+                       filesHtml.append("<TR>");
+                       currentColumn = 1;
+               }
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/Dimension.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/Dimension.java
new file mode 100755 (executable)
index 0000000..7841783
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer.metadata;
+
+import java.io.Serializable;
+
+/**
+ * Corresponds to single image dimensions.
+ */
+
+public class Dimension implements Serializable, Comparable<Dimension> {
+
+    private static final long serialVersionUID = -1039288266937331829L;
+
+    public int width;
+    public int height;
+
+    public Dimension() {
+        width = 0;
+        height = 0;
+    }
+
+    public Dimension(final Dimension origial) {
+        width = origial.width;
+        height = origial.height;
+    }
+
+    public Dimension(final int width, final int height) {
+        this.width = width;
+        this.height = height;
+    }
+
+    @Override
+    public int compareTo(final Dimension anotherDimension) {
+        if (width < anotherDimension.width)
+            return -1;
+        if (width > anotherDimension.width)
+            return 1;
+
+        if (height < anotherDimension.height)
+            return -1;
+        if (height > anotherDimension.height)
+            return 1;
+
+        return 0;
+    }
+
+    public boolean equals(final Dimension anotherDimension) {
+        if (compareTo(anotherDimension) == 0)
+            return true;
+        return false;
+    }
+
+    public int getArea() {
+        return width * height;
+    }
+
+    public java.awt.Dimension getAwtDimension() {
+        return new java.awt.Dimension(width, height);
+    }
+
+    public Dimension getScaled(final double multiplicationFactor) {
+        final Dimension result = new Dimension();
+
+        result.width = (int) ((width) * multiplicationFactor);
+        result.height = (int) ((height) * multiplicationFactor);
+
+        return result;
+    }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/DirectoryMetadata.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/DirectoryMetadata.java
new file mode 100755 (executable)
index 0000000..574da98
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer.metadata;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import eu.svjatoslav.commons.file.FilePathParser;
+import eu.svjatoslav.meviz.htmlindexer.AbstractIndexer;
+import eu.svjatoslav.meviz.htmlindexer.FileSortComparator;
+import eu.svjatoslav.meviz.htmlindexer.ImageFormatError;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.AbstractFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.DirectoryFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.GeneralFile;
+import eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes.Picture;
+
+/**
+ * Corresponds to single filesystem directory.
+ */
+public class DirectoryMetadata implements Serializable {
+
+       private static final long serialVersionUID = 3526489102725366334L;
+
+       private final HashMap<String, AbstractFile> fileNameToFileMap = new HashMap<String, AbstractFile>();
+
+       public transient boolean changed;
+
+       /**
+        * Performs cleanup of directory model. In particular removes metadata for
+        * images that no longer exist in the filesystem.
+        */
+       public void cleanup() {
+               final Iterator<AbstractFile> fileIterator = fileNameToFileMap.values()
+                               .iterator();
+
+               while (fileIterator.hasNext()) {
+                       final AbstractFile file = fileIterator.next();
+
+                       if (!file.isMetaInfoVerified())
+                               fileIterator.remove();
+               }
+       }
+
+       public void ensureFileMetainfoIsUpToDate(final File parentDirectory,
+                       final File file) throws IOException, ImageFormatError {
+
+               final String fileName = file.getName();
+
+               if (fileNameToFileMap.containsKey(fileName)) {
+                       final boolean metainfoUpdated = fileNameToFileMap.get(fileName)
+                                       .ensureFileMetainfoIsUpToDate(parentDirectory);
+
+                       if (metainfoUpdated)
+                               changed = true;
+               } else
+                       registerFile(parentDirectory, file);
+
+       }
+
+       public AbstractFile getFile(final String fileName) throws IOException {
+               return fileNameToFileMap.get(fileName);
+       }
+
+       public Collection<AbstractFile> getFiles() {
+
+               final ArrayList<AbstractFile> files = new ArrayList<AbstractFile>(
+                               fileNameToFileMap.values());
+
+               Collections.sort(files, new FileSortComparator());
+
+               return files;
+       }
+
+       public Dimension getImageDimensions(final String fileName)
+                       throws IOException, ImageFormatError {
+
+               return ((Picture) getFile(fileName)).getDimensions();
+       }
+
+       public AbstractFile registerFile(final File parentDirectory, final File file)
+                       throws IOException, ImageFormatError {
+
+               final String fileName = file.getName();
+
+               final AbstractFile abstractFile;
+
+               if (file.isDirectory())
+                       abstractFile = new DirectoryFile(parentDirectory, fileName);
+               else {
+                       final String fileExtension = FilePathParser.getFileExtension(
+                                       fileName).toLowerCase();
+
+                       if (AbstractIndexer.isImage(fileExtension))
+                               abstractFile = new Picture(parentDirectory, fileName);
+                       else
+                               abstractFile = new GeneralFile(parentDirectory, fileName);
+               }
+
+               fileNameToFileMap.put(fileName, abstractFile);
+
+               changed = true;
+
+               return abstractFile;
+       }
+
+       public void removeUnusedMetadataEntries() {
+
+               for (final String key : new HashSet<String>(fileNameToFileMap.keySet()))
+                       if (!fileNameToFileMap.get(key).isMetaInfoVerified()) {
+                               fileNameToFileMap.remove(key);
+                               changed = true;
+                       }
+
+       }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/MetadadaHelper.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/MetadadaHelper.java
new file mode 100644 (file)
index 0000000..0877a98
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer.metadata;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.log4j.Logger;
+
+import eu.svjatoslav.commons.file.IOHelper;
+
+public class MetadadaHelper {
+
+       public static final Logger logger = Logger.getLogger(MetadadaHelper.class);
+
+       /**
+        * Load previously generated or initialize new directory metadata.
+        */
+       public static DirectoryMetadata initDirectoryMetadata(
+                       final File metadataFile) {
+
+               if (!metadataFile.exists())
+                       return new DirectoryMetadata();
+               else
+                       try {
+
+                               final ObjectInputStream in = new ObjectInputStream(
+                                               new FileInputStream(metadataFile));
+                               final DirectoryMetadata directory = (DirectoryMetadata) in
+                                               .readObject();
+                               in.close();
+
+                               return directory;
+
+                       } catch (final Exception exception) {
+                               logger.error("Cannot load existing directory metadata.",
+                                               exception);
+
+                               return new DirectoryMetadata();
+                       }
+       }
+
+       public static void saveDirectoryMetadata(final File persistanceFile,
+                       final DirectoryMetadata directory) throws IOException {
+               // serialize directory metadata into byte array
+               final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+
+               final ObjectOutputStream out = new ObjectOutputStream(
+                               byteArrayOutputStream);
+               out.writeObject(directory);
+               out.close();
+
+               // store byte array into file
+               IOHelper.saveToFile(persistanceFile,
+                               byteArrayOutputStream.toByteArray());
+       }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/AbstractFile.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/AbstractFile.java
new file mode 100644 (file)
index 0000000..fb6e0a8
--- /dev/null
@@ -0,0 +1,92 @@
+package eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+
+import eu.svjatoslav.commons.file.FilePathParser;
+
+public abstract class AbstractFile implements Serializable {
+
+       private static final long serialVersionUID = -2547388204667088033L;
+
+       /**
+        * File name relative to the immediate parent directory.
+        */
+       public final String fileName;
+
+       /**
+        * File length in bytes.
+        */
+       private long fileLength;
+
+       private transient boolean metaInfoVerified;
+
+       public AbstractFile(final File parentDirectory, final String fileName)
+                       throws IOException {
+               this.fileName = fileName;
+               ensureFileMetainfoIsUpToDate(parentDirectory);
+       }
+
+       /**
+        * @return <code>true</code> if file metadata was updated.
+        */
+       public boolean ensureFileMetainfoIsUpToDate(final File parentDirectory)
+                       throws IOException {
+               if (!isMetainfoUpToDate(parentDirectory)) {
+                       fileLength = getFile(parentDirectory).length();
+                       updateFileMetainfo(parentDirectory);
+                       metaInfoVerified = true;
+                       return true;
+               }
+               return false;
+       };
+
+       public boolean fileExists(final File parentDirectory) {
+               return getFile(parentDirectory).exists();
+       }
+
+       public File getFile(final File parentDirectory) {
+               return new File(parentDirectory.getAbsolutePath(), fileName);
+       }
+
+       public String getFileExtension() {
+               return FilePathParser.getFileExtension(fileName);
+       }
+
+       public long getFileLength() {
+               return fileLength;
+       }
+
+       private boolean isMetainfoUpToDate(final java.io.File parentDirectory)
+                       throws IOException {
+
+               if (metaInfoVerified)
+                       return true;
+
+               final File file = getFile(parentDirectory);
+
+               // first check that file exists at all
+               if (!file.exists()) {
+                       System.out.println(file);
+                       throw new RuntimeException("Picture file by name \"" + fileName
+                                       + "\" does not exist in the parent directory \""
+                                       + parentDirectory.getAbsolutePath() + "\"");
+               }
+
+               // check that file length is the same as before
+               if (file.length() != fileLength)
+                       return false;
+
+               metaInfoVerified = true;
+               return true;
+       }
+
+       public boolean isMetaInfoVerified() {
+               return metaInfoVerified;
+       }
+
+       protected abstract void updateFileMetainfo(final File parentDirectory)
+                       throws IOException;
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/DirectoryFile.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/DirectoryFile.java
new file mode 100644 (file)
index 0000000..7c53e79
--- /dev/null
@@ -0,0 +1,20 @@
+package eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes;
+
+import java.io.File;
+import java.io.IOException;
+
+public class DirectoryFile extends AbstractFile {
+
+       private static final long serialVersionUID = 2387153281300820532L;
+
+       public DirectoryFile(final File parentDirectory, final String fileName)
+                       throws IOException {
+               super(parentDirectory, fileName);
+       }
+
+       @Override
+       protected void updateFileMetainfo(final File parentDirectory)
+                       throws IOException {
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/GeneralFile.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/GeneralFile.java
new file mode 100644 (file)
index 0000000..f4d6657
--- /dev/null
@@ -0,0 +1,20 @@
+package eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes;
+
+import java.io.File;
+import java.io.IOException;
+
+public class GeneralFile extends AbstractFile {
+
+       private static final long serialVersionUID = -2373609481729401415L;
+
+       public GeneralFile(final File parentDirectory, final String fileName)
+                       throws IOException {
+               super(parentDirectory, fileName);
+       }
+
+       @Override
+       protected void updateFileMetainfo(final File parentDirectory)
+                       throws IOException {
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/Picture.java b/src/main/java/eu/svjatoslav/meviz/htmlindexer/metadata/fileTypes/Picture.java
new file mode 100755 (executable)
index 0000000..02a29b9
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.htmlindexer.metadata.fileTypes;
+
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+import java.awt.image.FilteredImageSource;
+import java.awt.image.ImageFilter;
+import java.awt.image.ImageProducer;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+import javax.swing.ImageIcon;
+
+import eu.svjatoslav.commons.file.FilePathParser;
+import eu.svjatoslav.meviz.htmlindexer.Constants;
+import eu.svjatoslav.meviz.htmlindexer.ImageFormatError;
+import eu.svjatoslav.meviz.htmlindexer.Utils;
+import eu.svjatoslav.meviz.htmlindexer.metadata.Dimension;
+
+public class Picture extends AbstractFile {
+
+       private static final long serialVersionUID = -4156533490858298387L;
+
+       /**
+        * Picture dimensions.
+        */
+       private Dimension dimensions;
+
+       public Picture(final File parentDirectory, final String fileName)
+                       throws IOException, ImageFormatError {
+               super(parentDirectory, fileName);
+       }
+
+       private String computeThumbnailHash(final Dimension targetDimension) {
+
+               // compute new thumbnails hash number
+               final String forMagicHash = fileName + " "
+                               + String.valueOf(targetDimension.width) + " "
+                               + String.valueOf(targetDimension.height) + " "
+                               + String.valueOf(getFileLength()) + " "
+                               + Constants.THUMBNAIL_VERSION;
+
+               // System.out.println("Computing hash from: " + forMagicHash);
+               return Utils.getStringCrcAsHex(forMagicHash);
+       }
+
+       public Dimension getDimensions() {
+               return dimensions;
+       };
+
+       /**
+        * Get thumbnail file name for this image and desired thumbnail dimensions
+        * relative to designated thumbnails directory within parent directory.
+        */
+       public String getRelativeThumbnailFileName(final Dimension targetDimension) {
+               return FilePathParser.getFileNameWithoutExtension(fileName) + " ("
+                               + computeThumbnailHash(targetDimension) + ").jpeg";
+       }
+
+       @Override
+       public void updateFileMetainfo(final File parentDirectory)
+                       throws IOException {
+               BufferedImage image;
+               try {
+                       image = Utils.getBufferedImage(getFile(parentDirectory));
+               } catch (final ImageFormatError e) {
+                       throw new RuntimeException(e);
+               }
+               dimensions = new Dimension(image.getWidth(), image.getHeight());
+       }
+
+       /**
+        * Actual returned target thumbnail size will be adjusted from desired one
+        * by attempting to generate as large as possible thumbnail, while not
+        * exceeding provided thumbnail width and height, and preserving aspect
+        * ratio of original image.
+        */
+       public static java.awt.Dimension getTargetThumbnailDimension(
+                       final java.awt.Dimension originalImageDimension,
+                       final java.awt.Dimension desiredTargetDimension) {
+
+               final double thumbWidthToHeightRatio = (double) desiredTargetDimension.width
+                               / (double) desiredTargetDimension.height;
+               final double inputImageWidthToHeightRatio = (double) originalImageDimension.width
+                               / (double) originalImageDimension.height;
+
+               if (thumbWidthToHeightRatio < inputImageWidthToHeightRatio) {
+
+                       final java.awt.Dimension result = new java.awt.Dimension(
+                                       desiredTargetDimension.width,
+                                       (int) (desiredTargetDimension.width / inputImageWidthToHeightRatio));
+
+                       return result;
+               } else {
+
+                       final java.awt.Dimension result = new java.awt.Dimension(
+                                       (int) (desiredTargetDimension.height * inputImageWidthToHeightRatio),
+                                       desiredTargetDimension.height);
+
+                       return result;
+               }
+       }
+
+       /**
+        * Propose list of thumbnail dimensions.
+        */
+       public static List<Dimension> getThumbnailDimensions(Dimension current) {
+               final ArrayList<Dimension> result = new ArrayList<Dimension>();
+               result.add(current);
+
+               while (current.getArea() > 100000) {
+                       current = current.getScaled(0.5d);
+                       result.add(current);
+               }
+
+               return result;
+
+       }
+
+       public static void makeThumbnail(final File inputFile,
+                       final File outputFile,
+                       final java.awt.Dimension preferredTargetDimensions) {
+
+               try {
+
+                       final BufferedImage inputImage = Utils.getBufferedImage(inputFile);
+
+                       final java.awt.Dimension sourceImageDimension = new java.awt.Dimension(
+                                       inputImage.getWidth(), inputImage.getHeight());
+
+                       final java.awt.Dimension targetDimensions = getTargetThumbnailDimension(
+                                       sourceImageDimension, preferredTargetDimensions);
+
+                       final OutputStream out = new FileOutputStream(outputFile);
+
+                       final Image scaledImage = scaleImage(inputImage,
+                                       targetDimensions.width, targetDimensions.height);
+
+                       final BufferedImage bufferedImage = new BufferedImage(
+                                       scaledImage.getWidth(null), scaledImage.getHeight(null),
+                                       BufferedImage.TYPE_INT_RGB);
+
+                       final Graphics2D g = bufferedImage.createGraphics();
+                       g.drawImage(scaledImage, 0, 0, null);
+                       g.dispose();
+
+                       ImageIO.write(bufferedImage, "jpg", out);
+                       out.close();
+
+               } catch (final Exception exception) {
+                       System.out.println(exception.toString());
+                       exception.printStackTrace();
+               }
+       }
+
+       /**
+        * @return new image scaled to desired dimensions
+        */
+       public static Image scaleImage(final Image srcImage, final int width,
+                       final int height) {
+
+               ImageFilter filter;
+               filter = new java.awt.image.AreaAveragingScaleFilter(width, height);
+
+               final ImageProducer prod = new FilteredImageSource(
+                               srcImage.getSource(), filter);
+
+               final Image newImage = Toolkit.getDefaultToolkit().createImage(prod);
+
+               final ImageIcon imageIcon = new ImageIcon(newImage);
+               return imageIcon.getImage();
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/renamer/CommandlineHandler.java b/src/main/java/eu/svjatoslav/meviz/renamer/CommandlineHandler.java
new file mode 100755 (executable)
index 0000000..1c559c7
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.renamer;
+
+import java.io.File;
+
+import eu.svjatoslav.commons.commandline.parameterparser.Parameter;
+import eu.svjatoslav.commons.commandline.parameterparser.Parser;
+import eu.svjatoslav.meviz.encoder.EncodingOptions;
+
+public class CommandlineHandler {
+
+       Parameter recursiveParameter = new Parameter("Enable recursive mode.",
+                       "-r", "--recursive");
+
+       Parameter testParameter = new Parameter(
+                       "Simulate renaming (no changes will be actually done).", "-t",
+                       "--test");
+
+       Parameter outputPatternParameter = new Parameter(
+                       true,
+                       true,
+                       true,
+                       new eu.svjatoslav.commons.commandline.parameterparser.arguments.String(),
+                       "Output pattern.", "-o", "--output-pattern");
+
+       Parameter inputPatternParameter = new Parameter(
+                       true,
+                       true,
+                       true,
+                       new eu.svjatoslav.commons.commandline.parameterparser.arguments.String(),
+                       "File input pattern.", "-i", "--input-pattern");
+
+       Parameter workingDirectoryParameter = new Parameter(
+                       false,
+                       true,
+                       true,
+                       new eu.svjatoslav.commons.commandline.parameterparser.arguments.ExistingDirectory(),
+                       "Working directory.", "-w", "--working-directory");
+
+       public Parser initParser() {
+
+               final Parser parser = new Parser();
+               parser.addParameter(recursiveParameter);
+               parser.addParameter(testParameter);
+               parser.addParameter(outputPatternParameter);
+               parser.addParameter(inputPatternParameter);
+               parser.addParameter(workingDirectoryParameter);
+
+               return parser;
+       }
+
+       /**
+        * @return {@link EncodingOptions} if commandline arguments were
+        *         successfully parsed, or <code>null</code> if parsing error
+        *         occurred.
+        */
+       public RenamingOptions parseCommandlineArguments(final String[] args) {
+
+               final RenamingOptions options = new RenamingOptions();
+
+               final Parser parser = initParser();
+               if (!parser.parse(args))
+                       return null;
+
+               if (testParameter.isParameterSpecified())
+                       options.testOnly = true;
+
+               if (recursiveParameter.isParameterSpecified())
+                       options.recursive = true;
+
+               if (outputPatternParameter.isParameterSpecified())
+                       options.outputPattern = outputPatternParameter
+                                       .getArgumentsAsStrings().get(0);
+
+               if (workingDirectoryParameter.isParameterSpecified())
+                       options.targetDirectory = workingDirectoryParameter
+                                       .getArgumentsAsFiles().get(0);
+               else
+                       options.targetDirectory = new File(System.getProperty("user.dir"));
+
+               if (inputPatternParameter.isParameterSpecified())
+                       options.inputPatterns.addAll(inputPatternParameter
+                                       .getArgumentsAsStrings());
+
+               return options;
+       }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/renamer/Main.java b/src/main/java/eu/svjatoslav/meviz/renamer/Main.java
new file mode 100755 (executable)
index 0000000..fff4b39
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.renamer;
+
+import java.io.File;
+
+import eu.svjatoslav.commons.string.WildCardMatcher;
+import eu.svjatoslav.meviz.Module;
+
+public class Main implements Module {
+
+       CommandlineHandler commandlineHandler = new CommandlineHandler();
+
+       public int processedFilesCount;
+
+       RenamingOptions options;
+
+       /**
+        * Verify that program has enough information to start executing
+        * 
+        * @return true if all is ok, false if errors were found
+        */
+       public boolean checkThatThereIsEnoughDataToProceed() {
+               if (options.inputPatterns.size() == 0) {
+                       System.out.println("Error: no input patterns given.");
+                       return false;
+               }
+
+               if (options.outputPattern == null) {
+                       System.out.println("Error: no output pattern given.");
+                       return false;
+               }
+
+               return true;
+       }
+
+       public boolean fileMatchesInputPattern(final File file) {
+               final String fileName = file.getName();
+
+               for (final String inputPattern : options.inputPatterns)
+                       if (WildCardMatcher.match(fileName, inputPattern))
+                               return true;
+
+               return false;
+       }
+
+       @Override
+       public String getDescription() {
+               return "Mass rename files according to given pattern.";
+       }
+
+       @Override
+       public String getModuleCommand() {
+               return "rename";
+       };
+
+       public void handleFile(final File file) {
+               if (!file.exists()) {
+                       System.out.println("Error: file \"" + file.getAbsolutePath()
+                                       + "\" does not exist.");
+                       return;
+               }
+
+               if (file.isDirectory()) {
+                       for (final File subFile : file.listFiles())
+                               if (subFile.isDirectory()) {
+                                       if (options.recursive)
+                                               handleFile(subFile);
+                               } else
+                                       handleFile(subFile);
+               } else if (file.isFile())
+                       if (fileMatchesInputPattern(file)) {
+
+                               final StringBuffer targetFilePath = new StringBuffer();
+
+                               targetFilePath.append(file.getParent());
+                               targetFilePath.append("/");
+
+                               for (int i = 0; i < options.outputPattern.length(); i++) {
+
+                                       final char c = options.outputPattern.charAt(i);
+
+                                       if (c == '*')
+                                               targetFilePath.append(file.getName());
+                                       else if (c == '%') {
+
+                                               final String processedFileCountString = String
+                                                               .valueOf(processedFilesCount);
+
+                                               for (int j = 0; j < (5 - processedFileCountString
+                                                               .length()); j++)
+                                                       targetFilePath.append(0);
+
+                                               targetFilePath.append(processedFileCountString);
+                                               processedFilesCount++;
+                                       } else if (c == '_')
+                                               targetFilePath.append(" ");
+                                       else
+                                               targetFilePath.append(c);
+                               }
+
+                               final File targetFile = new File(targetFilePath.toString());
+
+                               if (!options.testOnly) {
+
+                                       if (targetFile.exists())
+                                               System.out
+                                                               .println("Renaming aborted because target file: "
+                                                                               + targetFile.getAbsolutePath()
+                                                                               + " already exists.");
+                                       else
+                                               file.renameTo(targetFile);
+
+                               } else {
+                                       System.out.println("About to rename file: "
+                                                       + file.getAbsolutePath());
+                                       System.out.println("into: " + targetFile.getAbsolutePath());
+                               }
+                       }
+
+       }
+
+       public void rename() {
+               handleFile(options.targetDirectory);
+       }
+
+       @Override
+       public void run(final String[] args) {
+
+               options = commandlineHandler.parseCommandlineArguments(args);
+
+               if (options == null) {
+                       showCommandlineHelp();
+                       return;
+               }
+
+               if (checkThatThereIsEnoughDataToProceed()) {
+
+                       System.out.println("Renaming using input patterns: ");
+                       for (final String inputPattern : options.inputPatterns)
+                               System.out.println("    " + inputPattern);
+
+                       rename();
+               } else
+                       showCommandlineHelp();
+       }
+
+       @Override
+       public void showCommandlineHelp() {
+               commandlineHandler.initParser().showHelp();
+               System.out.println("");
+               System.out.println("Output pattern special symbols:");
+               System.out.println("    % - file number");
+               System.out.println("    * - original file name");
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/renamer/RenamingOptions.java b/src/main/java/eu/svjatoslav/meviz/renamer/RenamingOptions.java
new file mode 100755 (executable)
index 0000000..a9a1c04
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.renamer;
+
+import java.io.File;
+import java.util.ArrayList;
+
+public class RenamingOptions {
+
+    public ArrayList<String> inputPatterns = new ArrayList<String>();
+
+    public boolean recursive = false;
+
+    public boolean testOnly = false;
+
+    public String outputPattern;
+
+    public File targetDirectory;
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/textsplitter/CommandlineHandler.java b/src/main/java/eu/svjatoslav/meviz/textsplitter/CommandlineHandler.java
new file mode 100755 (executable)
index 0000000..1364a13
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.textsplitter;
+
+import java.io.File;
+
+import eu.svjatoslav.commons.commandline.parameterparser.Parameter;
+import eu.svjatoslav.commons.commandline.parameterparser.Parser;
+
+public class CommandlineHandler {
+
+       Parameter recursiveParameter = new Parameter("Enable recursive mode.",
+                       "-r", "--recursive");
+
+       Parameter inputPatternParameter = new Parameter(
+                       true,
+                       true,
+                       true,
+                       new eu.svjatoslav.commons.commandline.parameterparser.arguments.String(),
+                       "File input pattern.", "-i", "--input-pattern");
+
+       Parameter workingDirectoryParameter = new Parameter(
+                       false,
+                       true,
+                       true,
+                       new eu.svjatoslav.commons.commandline.parameterparser.arguments.ExistingDirectory(),
+                       "Working directory.", "-w", "--working-directory");
+
+       public Parser initParser() {
+
+               final Parser parser = new Parser();
+               parser.addParameter(recursiveParameter);
+               parser.addParameter(inputPatternParameter);
+               parser.addParameter(workingDirectoryParameter);
+
+               return parser;
+       }
+
+       public TextSplittingOptions parseCommandlineArguments(final String[] args) {
+
+               final TextSplittingOptions options = new TextSplittingOptions();
+
+               final Parser parser = initParser();
+               if (!parser.parse(args))
+                       return null;
+
+               if (recursiveParameter.isParameterSpecified())
+                       options.recursive = true;
+
+               if (workingDirectoryParameter.isParameterSpecified())
+                       options.targetDirectory = workingDirectoryParameter
+                                       .getArgumentsAsFiles().get(0);
+               else
+                       options.targetDirectory = new File(System.getProperty("user.dir"));
+
+               if (inputPatternParameter.isParameterSpecified())
+                       options.inputPatterns.addAll(inputPatternParameter
+                                       .getArgumentsAsStrings());
+
+               return options;
+       }
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/textsplitter/Main.java b/src/main/java/eu/svjatoslav/meviz/textsplitter/Main.java
new file mode 100755 (executable)
index 0000000..9a52d55
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.textsplitter;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import eu.svjatoslav.commons.file.FilePathParser;
+import eu.svjatoslav.commons.string.CuttableString;
+import eu.svjatoslav.commons.string.WildCardMatcher;
+import eu.svjatoslav.meviz.Module;
+
+public class Main implements Module {
+
+       public static final int targetLineLength = 200;
+
+       public static final int maxSplittedLines = 3;
+
+       public static final String splitLinePrefix = "    ";
+
+       CommandlineHandler commandlineHandler = new CommandlineHandler();
+
+       TextSplittingOptions options;
+
+       public boolean fileMatchesInputPattern(final File file) {
+               final String fileName = file.getName().toLowerCase();
+
+               for (final String inputPattern : options.inputPatterns)
+                       if (WildCardMatcher.match(fileName, inputPattern.toLowerCase()))
+                               return true;
+
+               return false;
+       }
+
+       @Override
+       public String getDescription() {
+               return "Split text with long lines into multiple shorter lines.";
+       }
+
+       @Override
+       public String getModuleCommand() {
+               return "splittext";
+       }
+
+       private File getTargetFile(final File sourceFile) {
+               final StringBuffer targetFilePath = new StringBuffer();
+               targetFilePath.append(sourceFile.getParent());
+               targetFilePath.append("/");
+               targetFilePath.append(FilePathParser
+                               .getFileNameWithoutExtension(sourceFile));
+
+               targetFilePath.append(".fixedLengh");
+
+               // add file extension
+               {
+                       final String fileExtension = FilePathParser
+                                       .getFileExtension(sourceFile);
+
+                       if (fileExtension.length() > 0)
+                               targetFilePath.append("." + fileExtension);
+               }
+               return new File(targetFilePath.toString());
+       }
+
+       public void processDirectory(final File directory) {
+
+               for (final File subFile : directory.listFiles())
+                       if (subFile.isDirectory()) {
+                               if (options.recursive)
+                                       processDirectory(subFile);
+                       } else if (fileMatchesInputPattern(subFile))
+                               try {
+                                       processFile(subFile);
+                               } catch (final IOException exception) {
+                                       System.out.println("Error processing file: "
+                                                       + subFile.getAbsolutePath());
+                                       System.out.println("   exception: "
+                                                       + exception.getMessage());
+                               }
+
+       }
+
+       public void processFile(final File file) throws IOException {
+               final File targetFile = getTargetFile(file);
+
+               final BufferedReader bufferedReader = new BufferedReader(
+                               new FileReader(file));
+
+               final BufferedWriter bufferedWriter = new BufferedWriter(
+                               new FileWriter(targetFile));
+
+               while (true) {
+                       final String readLine = bufferedReader.readLine();
+                       if (readLine == null)
+                               break;
+
+                       if (readLine.length() <= targetLineLength)
+                               bufferedWriter.write(readLine + "\n");
+                       else {
+
+                               final CuttableString cuttableString = new CuttableString(
+                                               readLine);
+
+                               bufferedWriter.write(cuttableString.cutLeft(targetLineLength)
+                                               + "\n");
+
+                               int splittedLinesCount = 0;
+
+                               while (!cuttableString.isEmpty()) {
+                                       splittedLinesCount++;
+                                       if (splittedLinesCount >= maxSplittedLines)
+                                               break;
+
+                                       bufferedWriter.write(splitLinePrefix
+                                                       + cuttableString.cutLeft(targetLineLength
+                                                                       - splitLinePrefix.length()) + "\n");
+                               }
+                       }
+
+               }
+
+               bufferedReader.close();
+               bufferedWriter.close();
+       }
+
+       @Override
+       public void run(final String[] args) throws IOException {
+
+               options = commandlineHandler.parseCommandlineArguments(args);
+
+               if (options == null) {
+                       showCommandlineHelp();
+                       return;
+               }
+
+               processDirectory(options.targetDirectory);
+
+       }
+
+       @Override
+       public void showCommandlineHelp() {
+               commandlineHandler.initParser().showHelp();
+       }
+
+}
diff --git a/src/main/java/eu/svjatoslav/meviz/textsplitter/TextSplittingOptions.java b/src/main/java/eu/svjatoslav/meviz/textsplitter/TextSplittingOptions.java
new file mode 100755 (executable)
index 0000000..fb0cb99
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Meviz - Various tools collection to work with multimedia.
+ * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+package eu.svjatoslav.meviz.textsplitter;
+
+import java.io.File;
+import java.util.ArrayList;
+
+public class TextSplittingOptions {
+
+    public ArrayList<String> inputPatterns = new ArrayList<String>();
+
+    public boolean recursive = false;
+
+    public boolean testOnly = false;
+
+    public String outputPattern;
+
+    public File targetDirectory;
+
+}
diff --git a/src/main/resources/log4j.xml b/src/main/resources/log4j.xml
new file mode 100755 (executable)
index 0000000..a9b5a88
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
+<log4j:configuration>
+       <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
+               <layout class="org.apache.log4j.PatternLayout">
+                       <param name="ConversionPattern" value="%d{ABSOLUTE} 
+      %5p %c{1}:%L - %m%n" />
+
+               </layout>
+       </appender>
+       <root>
+               <priority value="info"></priority>
+               <!-- <priority value="debug"></priority> -->
+               <appender-ref ref="stdout" />
+       </root>
+</log4j:configuration>
\ No newline at end of file