├── .clang-format ├── .gitignore ├── LICENSE ├── MANUAL.md ├── README.md ├── ROADMAP.md ├── bundle.sh ├── meson.build ├── res ├── html │ ├── main.css │ └── main.html ├── img │ ├── accept.png │ ├── close.png │ ├── closeblack.png │ ├── max.png │ ├── minus.png │ ├── next.png │ ├── pause.png │ ├── play.png │ ├── plus.png │ ├── prev.png │ ├── settings.png │ ├── sidebar.png │ └── up.png ├── mmfm.desktop └── mmfm.png ├── screenshot.png ├── src ├── kinetic_ui │ ├── egl │ │ ├── ku_gl.c │ │ ├── ku_gl_atlas.c │ │ ├── ku_gl_floatbuffer.c │ │ └── ku_gl_shader.c │ ├── handler │ │ ├── vh_anim.c │ │ ├── vh_button.c │ │ ├── vh_cv_body.c │ │ ├── vh_cv_evnt.c │ │ ├── vh_cv_scrl.c │ │ ├── vh_drag.c │ │ ├── vh_key.c │ │ ├── vh_knob.c │ │ ├── vh_roll.c │ │ ├── vh_slider.c │ │ ├── vh_table.c │ │ ├── vh_tbl_body.c │ │ ├── vh_tbl_evnt.c │ │ ├── vh_tbl_head.c │ │ ├── vh_tbl_scrl.c │ │ ├── vh_textinput.c │ │ └── vh_touch.c │ ├── ku_bitmap.c │ ├── ku_connector_wayland.c │ ├── ku_css.c │ ├── ku_draw.c │ ├── ku_event.c │ ├── ku_fontconfig.c │ ├── ku_gen_css.c │ ├── ku_gen_html.c │ ├── ku_gen_textstyle.c │ ├── ku_gen_type.c │ ├── ku_html.c │ ├── ku_png.c │ ├── ku_recorder.c │ ├── ku_rect.c │ ├── ku_renderer_egl.c │ ├── ku_renderer_soft.c │ ├── ku_text.c │ ├── ku_view.c │ ├── ku_window.c │ └── texture │ │ ├── tg_css.c │ │ ├── tg_knob.c │ │ ├── tg_scaledimg.c │ │ └── tg_text.c ├── media_coder │ └── coder.c ├── media_player │ ├── clock.c │ ├── decoder.c │ ├── framequeue.c │ ├── mediaplayer.c │ └── packetqueue.c ├── mmfm │ ├── config.c │ ├── filemanager.c │ ├── kvlist.c │ ├── mmfm.c │ ├── pdf.c │ └── ui.c ├── mt_core │ ├── mt_channel.c │ ├── mt_log.c │ ├── mt_map.c │ ├── mt_memory.c │ ├── mt_number.c │ ├── mt_path.c │ ├── mt_string.c │ ├── mt_time.c │ ├── mt_vector.c │ ├── mt_wrapper.c │ └── utf8.h ├── mt_core_ext │ ├── ku_bitmap_ext.c │ ├── mt_map_ext.c │ └── mt_string_ext.c ├── mt_core_test │ ├── mt_channel_test.c │ ├── mt_core_test.c │ ├── mt_map_test.c │ ├── mt_memory_test.c │ ├── mt_path_test.c │ ├── mt_string_test.c │ └── mt_vector_test.c ├── mt_math │ ├── mt_math_2d.c │ ├── mt_math_3d.c │ ├── mt_matrix_3d.c │ ├── mt_matrix_4d.c │ ├── mt_vector_2d.c │ ├── mt_vector_3d.c │ └── mt_vector_4d.c └── mt_math_test │ └── mt_math_2d_test.c ├── svg ├── accept.svg ├── close.svg ├── maximize.svg ├── minus.svg ├── next.svg ├── play.svg ├── plus.svg ├── prev.svg ├── sidebar.svg ├── terminus.otb └── up.svg ├── tst ├── file_delete_test │ ├── files_master │ │ ├── .emacs hidden invalid file │ │ ├── .fehbg executable invalid file │ │ ├── ADELE nocover nometa.aac │ │ ├── MOTHER nocover nometa.opus │ │ ├── folder1 │ │ │ ├── NOINLOVE cover meta.mp3 │ │ │ └── szurke patas.odt │ │ ├── folder2 │ │ │ ├── PHEV-MY14-5_Maintenance Schedule.pdf │ │ │ └── ROYKSOPP nocover nometa.mp4 │ │ └── screenshots │ │ │ ├── placeholder │ │ │ ├── screenshot000.png │ │ │ ├── screenshot001.png │ │ │ └── screenshot002.png │ └── session.rec ├── file_info_test │ ├── files_master │ │ ├── .emacs hidden invalid file │ │ ├── .fehbg executable invalid file │ │ ├── ADELE nocover nometa.aac │ │ ├── MOTHER nocover nometa.opus │ │ ├── folder1 │ │ │ ├── Airspeeder.png │ │ │ ├── NOINLOVE cover meta.mp3 │ │ │ └── szurke patas.odt │ │ ├── folder2 │ │ │ ├── PHEV-MY14-5_Maintenance Schedule.pdf │ │ │ └── ROYKSOPP nocover nometa.mp4 │ │ └── screenshots │ │ │ ├── placeholder │ │ │ ├── screenshot000.png │ │ │ ├── screenshot001.png │ │ │ ├── screenshot002.png │ │ │ ├── screenshot003.png │ │ │ └── screenshot004.png │ └── session.rec ├── file_ops_test │ ├── files_master │ │ ├── .emacs hidden invalid file │ │ ├── .fehbg executable invalid file │ │ ├── ADELE nocover nometa.aac │ │ ├── MOTHER nocover nometa.opus │ │ ├── folder1 │ │ │ ├── Airspeeder.png │ │ │ ├── NOINLOVE cover meta.mp3 │ │ │ ├── szurke patas.odt │ │ │ └── testf │ │ │ │ ├── .emacs hidden invalid file │ │ │ │ └── .fehbg executable invalid file │ │ ├── folder2 │ │ │ ├── PHEV-MY14-5_Maintenance Schedule.pdf │ │ │ └── ROYKSOPP nocover nometa.mp4 │ │ └── screenshots │ │ │ ├── placeholder │ │ │ ├── screenshot000.png │ │ │ ├── screenshot001.png │ │ │ ├── screenshot002.png │ │ │ ├── screenshot003.png │ │ │ ├── screenshot004.png │ │ │ ├── screenshot005.png │ │ │ ├── screenshot006.png │ │ │ ├── screenshot007.png │ │ │ └── screenshot008.png │ └── session.rec ├── file_play_test │ ├── files_master │ │ ├── .emacs hidden invalid file │ │ ├── .fehbg executable invalid file │ │ ├── ADELE nocover nometa.aac │ │ ├── MOTHER nocover nometa.opus │ │ ├── folder1 │ │ │ ├── Airspeeder.png │ │ │ ├── NOINLOVE cover meta.mp3 │ │ │ └── szurke patas.odt │ │ ├── folder2 │ │ │ ├── PHEV-MY14-5_Maintenance Schedule.pdf │ │ │ └── ROYKSOPP nocover nometa.mp4 │ │ └── screenshots │ │ │ ├── placeholder │ │ │ └── screenshot000.png │ └── session.rec ├── file_view_test │ ├── files_master │ │ ├── .emacs hidden invalid file │ │ ├── .fehbg executable invalid file │ │ ├── ADELE nocover nometa.aac │ │ ├── MOTHER nocover nometa.opus │ │ ├── folder1 │ │ │ ├── Airspeeder.png │ │ │ ├── NOINLOVE cover meta.mp3 │ │ │ └── szurke patas.odt │ │ ├── folder2 │ │ │ ├── PHEV-MY14-5_Maintenance Schedule.pdf │ │ │ └── ROYKSOPP nocover nometa.mp4 │ │ └── screenshots │ │ │ ├── placeholder │ │ │ ├── screenshot000.png │ │ │ ├── screenshot001.png │ │ │ ├── screenshot002.png │ │ │ ├── screenshot003.png │ │ │ ├── screenshot004.png │ │ │ ├── screenshot005.png │ │ │ ├── screenshot006.png │ │ │ ├── screenshot007.png │ │ │ └── screenshot008.png │ └── session.rec ├── record.sh ├── replay.sh ├── rerecord.sh ├── run.sh └── test_files │ ├── .emacs hidden invalid file │ ├── .fehbg executable invalid file │ ├── ADELE nocover nometa.aac │ ├── MOTHER nocover nometa.opus │ ├── folder1 │ ├── Airspeeder.png │ ├── NOINLOVE cover meta.mp3 │ └── szurke patas.odt │ ├── folder2 │ ├── PHEV-MY14-5_Maintenance Schedule.pdf │ └── ROYKSOPP nocover nometa.mp4 │ └── screenshots │ └── placeholder └── wlr-layer-shell-unstable-v1.xml /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -2 5 | AlignAfterOpenBracket: AlwaysBreak 6 | AlignConsecutiveAssignments: true 7 | AlignConsecutiveDeclarations: true 8 | AlignEscapedNewlines: Right 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: true 13 | AllowShortCaseLabelsOnASingleLine: true 14 | AllowShortFunctionsOnASingleLine: false 15 | #AllowShortIfStatementsOnASingleLine: AllIfsAndElse 16 | AllowShortLoopsOnASingleLine: true 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: true 20 | AlwaysBreakTemplateDeclarations: MultiLine 21 | BinPackArguments: false 22 | BinPackParameters: false 23 | BraceWrapping: 24 | AfterClass: false 25 | AfterControlStatement: false 26 | AfterEnum: false 27 | AfterFunction: true 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: false 31 | AfterUnion: false 32 | AfterExternBlock: false 33 | BeforeCatch: false 34 | BeforeElse: false 35 | IndentBraces: false 36 | SplitEmptyFunction: true 37 | SplitEmptyRecord: true 38 | SplitEmptyNamespace: true 39 | BreakBeforeBinaryOperators: None 40 | BreakBeforeBraces: Allman 41 | BreakBeforeInheritanceComma: false 42 | BreakInheritanceList: BeforeColon 43 | BreakBeforeTernaryOperators: true 44 | BreakConstructorInitializersBeforeComma: false 45 | BreakConstructorInitializers: BeforeColon 46 | BreakAfterJavaFieldAnnotations: false 47 | BreakStringLiterals: true 48 | ColumnLimit: 0 49 | CommentPragmas: '^ IWYU pragma:' 50 | CompactNamespaces: false 51 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 52 | ConstructorInitializerIndentWidth: 4 53 | ContinuationIndentWidth: 4 54 | Cpp11BracedListStyle: true 55 | DerivePointerAlignment: false 56 | DisableFormat: false 57 | ExperimentalAutoDetectBinPacking: false 58 | FixNamespaceComments: true 59 | ForEachMacros: 60 | - foreach 61 | - Q_FOREACH 62 | - BOOST_FOREACH 63 | IncludeBlocks: Preserve 64 | IncludeCategories: 65 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 66 | Priority: 3 67 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 68 | Priority: 2 69 | - Regex: '.*' 70 | Priority: 1 71 | IncludeIsMainRegex: '(Test)?$' 72 | IndentCaseLabels: true 73 | IndentPPDirectives: BeforeHash 74 | IndentWidth: 4 75 | IndentWrappedFunctionNames: false 76 | JavaScriptQuotes: Leave 77 | JavaScriptWrapImports: true 78 | KeepEmptyLinesAtTheStartOfBlocks: true 79 | MacroBlockBegin: '' 80 | MacroBlockEnd: '' 81 | MaxEmptyLinesToKeep: 1 82 | NamespaceIndentation: None 83 | ObjCBinPackProtocolList: Auto 84 | ObjCBlockIndentWidth: 2 85 | ObjCSpaceAfterProperty: false 86 | ObjCSpaceBeforeProtocolList: true 87 | PenaltyBreakAssignment: 2 88 | PenaltyBreakBeforeFirstCallParameter: 19 89 | PenaltyBreakComment: 300 90 | PenaltyBreakFirstLessLess: 120 91 | PenaltyBreakString: 1000 92 | PenaltyBreakTemplateDeclaration: 10 93 | PenaltyExcessCharacter: 1000000 94 | PenaltyReturnTypeOnItsOwnLine: 60 95 | PointerAlignment: Left 96 | ReflowComments: true 97 | SortIncludes: true 98 | SortUsingDeclarations: true 99 | SpaceAfterCStyleCast: true 100 | SpaceAfterTemplateKeyword: true 101 | SpaceBeforeAssignmentOperators: true 102 | SpaceBeforeCpp11BracedList: false 103 | SpaceBeforeCtorInitializerColon: true 104 | SpaceBeforeInheritanceColon: true 105 | SpaceBeforeParens: ControlStatements 106 | SpaceBeforeRangeBasedForLoopColon: true 107 | SpaceInEmptyParentheses: false 108 | SpacesBeforeTrailingComments: 1 109 | SpacesInAngles: false 110 | SpacesInContainerLiterals: true 111 | SpacesInCStyleCastParentheses: false 112 | SpacesInParentheses: false 113 | SpacesInSquareBrackets: false 114 | Standard: Cpp11 115 | StatementMacros: 116 | - Q_UNUSED 117 | - QT_REQUIRE_VERSION 118 | TabWidth: 8 119 | UseTab: ForContinuationAndIndentation 120 | ... 121 | 122 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /MANUAL.md: -------------------------------------------------------------------------------- 1 | # MultiMedia File Manager User Guide 2 | 3 | Welcome to Multimedia File Manager! I put a lot of effort in the making of this application and I hope that using this application fills your heart with warmth, pride and childlike joy! 4 | 5 | ## Table of contents 6 | 7 | 1. First start 8 | 2. The main interface 9 | 3. The main toolbar 10 | 4. The file browser 11 | 5. The file info browser 12 | 6. The content toolbar 13 | 7. The content viewer 14 | 8. The file operations context menu 15 | 9. Controlling the application 16 | 10. Handling the file browser 17 | 11. Command line arguments 18 | 12. Customizing the user interface 19 | 20 | ## 1. First start 21 | 22 | Open a terminal window or your favorite application launcher and type 23 | 24 | ``` 25 | mmfm 26 | ``` 27 | 28 | The application will show you the contents of the current folder. 29 | 30 | ## 2. The Main Interface 31 | 32 | MMFM's main user interface has five main parts : 33 | 34 | - The main toolbar 35 | - The file browser 36 | - The file info browser 37 | - The content toolbar 38 | - The content viewer 39 | 40 | ## 3. The main toolbar 41 | 42 | Elements from left to right : 43 | 44 | 1. close application button 45 | 2. about/help button 46 | 3. progress info field 47 | 4. the sidebar( file info/clipboard ) toggle button 48 | 5. the maximize button 49 | 50 | ## 4. The file browser 51 | 52 | The file browser shows all files in the current directory. Use the mouse or the arrow keys to navigate through files. Single click or move over a file with the arrow keys to view it. Double click on the double dot or press enter on it to go up a directory. 53 | 54 | ## 5. The file info browser 55 | 56 | The file info browser shows all information about the currently selected file. To make it visible click on the file info browser button on the toolbar next to the maximize button. 57 | 58 | ## 6. The content toolbar 59 | 60 | Elements from left to right : 61 | 62 | 1. previous page button 63 | 2. next page button 64 | 3. play/pause button 65 | 4. progress bar 66 | 5. zoom in button 67 | 6. zoom out button 68 | 69 | ## 7. The content viewer 70 | 71 | The content viewer shows the currently selected media. Press +/- buttons to zoom in/out, or use the scroll wheel of the mouse, or use pinch gestures on the touchpad to zoom in/out, or use the zoom in/out buttons in the content toolbar. Press space or the play/pause button to toggle auto play. 72 | 73 | ## 8. The file operations context menu ## 74 | 75 | Elements from top to bottom : 76 | 77 | 1. Create folder button 78 | 2. Rename button 79 | 3. Delete button 80 | 4. Send to clipboard button 81 | 5. Paste using copy button 82 | 6. Paste using move button 83 | 7. Reset clipboard button 84 | 85 | ## 9. Controlling the application 86 | 87 | **To exit the application** 88 | Click on the close application button 89 | 90 | **To maximize/minimize the application** 91 | Click on the maximize button 92 | 93 | ## 10. Handling the file browser 94 | 95 | **To scroll the song list** 96 | a. scroll over the list 97 | b. click on the invisible scrollbar area on the right edge of the song list ( vertical ) or bottom edge of the song list ( horizontal ) 98 | c. drag on the invisible scrollbar area on the right edge of the song list ( vertical ) or bottom edge of the song list ( horizontal ) 99 | 100 | **To resize the column** 101 | Drag on the right edge of the header cell you want to resize. 102 | 103 | **To rearrange the columns** 104 | Drag and drop the header cell onto an other cell 105 | 106 | ## 11. Command line arguments 107 | 108 | ``` 109 | -c --config= [config file] use config file for session 110 | -r --resources= [resources folder] use resources dir for session 111 | -s --record= [recorder file] record session to file 112 | -p --replay= [recorder file] replay session from file 113 | -f --frame= [widthxheight] initial window dimension 114 | ``` 115 | 116 | ## 12. Customizing the user interface 117 | 118 | The user interface uses html for structure description and css for design description. The location of the two file is under settings. Feel free to modify them, but beware, the html/css parser is very strict, follow strictly the original files syntax to achieve success. Also some parts are generated from code and cannot be set by css, I will wire out those parts soon. -------------------------------------------------------------------------------- /ROADMAP.md: -------------------------------------------------------------------------------- 1 | # MultiMedia File Manager 2 | 3 | - drag and drop not working 4 | - external file drag and drop 5 | - delete accept + enter belep a folderbe ha az kovetkezik 6 | - switchable texture smoothing for preview 7 | - kurzor valtozzon at column move eseten 8 | - play button active amikor mnme kene 9 | - hold gesture to image scroller also 10 | - first drag and drop doesn't work 11 | - drag and drop from clipboard 12 | - CTRL + drag from clipboard - move 13 | - save autoplay state 14 | - file list ordering head click 15 | - store table states 16 | - left right arrow scroll in scroll views 17 | - get dimensions before image,pdf, video load, resize preview 18 | - slow click rename 19 | - test scaling 20 | - copy/paste text from wayland clipboard 21 | - text file load/seek, hexa view, fix meretu chunkokat olvasson 22 | - linelist component, text fileoknak es hexa viewnak 23 | - pause/play felvillano ikon over preview 24 | - visualization level gombok, kep, oszcilloszkop, binaris 25 | - search bar 26 | - shortcutok config fileba vagy kulon fileba 27 | - listen for folder change event 28 | - HEIF/HEVC/mpts play error 29 | - korusos videok nem jatszodnak le 30 | 31 | - video on github page 32 | - tech video, automated ui/full test, logban meg a leakek is lathatoak 33 | 34 | - show raw html/css switch without any code 35 | - legalso elem ne legyen felig takarva cursor down eseten 36 | - input text scroll or wrap 37 | - dirty rect drawing for debugging 38 | - time based animations 39 | - unified css for all applications to make global styling easier 40 | 41 | - Extracts all stream and metadata info from multimedia files, also shows the raw hexa/ASCII bytes of the file if needed 42 | - Works without a window manager for super hackers 43 | - Frequency and scope analyzer visualizers for audio conent 44 | 45 | KineticUI is a UI renderer / UI component framework I created to bring MacOS level UI and UX to UNIX-like operating systems. It does kinetic scrolling, hold on two finger touch, edge bounce, zoom on pinch, glyph animations and much more. But one of it's most important feature is deterministic session recording and replaying to automate UI and functional testing. If you create screenshots during session recording with the built-in screenshot tool, those screenshots will be re-created during session replay and you can compare them for changes. If there is no random, time-bound or backgrounud thread-bound information in the screemshots then they should be identical on pixel-level. Check out MultiMedia File Manager ( www.github.com/milgra/mmfm ), Visual Music Player ( www.github.com/milgra/vmp ) , Sway Overview ( www.github.com/milgra/sov ) or Wayland Control Panel (www.github.com/milgra/wcp ) to see KineticUI in action! -------------------------------------------------------------------------------- /bundle.sh: -------------------------------------------------------------------------------- 1 | rm -rf mmfm.app 2 | mkdir mmfm.app 3 | mkdir -p mmfm.app/bin 4 | mkdir -p mmfm.app/lib 5 | mkdir -p mmfm.app/res 6 | ldd build/mmfm | awk '{print $3}' | xargs -I {} cp {} mmfm.app/lib/ 7 | rm mmfm.app/lib/libc.so.* 8 | rm mmfm.app/lib/libm.so.* 9 | cp -R build/mmfm mmfm.app/bin/ 10 | cp -R res/html mmfm.app/res/ 11 | cp -R res/img mmfm.app/res/ 12 | cp res/mmfm.desktop mmfm.app/ 13 | cp res/mmfm.png mmfm.app/ 14 | echo 'PTH=$(dirname $(readlink -f $0))' > mmfm.app/mmfm 15 | echo "LD_LIBRARY_PATH=\$PTH/lib \$PTH/bin/mmfm -r \$PTH/res" >> mmfm.app/mmfm 16 | chmod +x mmfm.app/mmfm 17 | tar czf mmfm.app.tar.gz mmfm.app 18 | -------------------------------------------------------------------------------- /res/img/accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/accept.png -------------------------------------------------------------------------------- /res/img/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/close.png -------------------------------------------------------------------------------- /res/img/closeblack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/closeblack.png -------------------------------------------------------------------------------- /res/img/max.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/max.png -------------------------------------------------------------------------------- /res/img/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/minus.png -------------------------------------------------------------------------------- /res/img/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/next.png -------------------------------------------------------------------------------- /res/img/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/pause.png -------------------------------------------------------------------------------- /res/img/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/play.png -------------------------------------------------------------------------------- /res/img/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/plus.png -------------------------------------------------------------------------------- /res/img/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/prev.png -------------------------------------------------------------------------------- /res/img/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/settings.png -------------------------------------------------------------------------------- /res/img/sidebar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/sidebar.png -------------------------------------------------------------------------------- /res/img/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/img/up.png -------------------------------------------------------------------------------- /res/mmfm.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Terminal=false 5 | Exec=/usr/local/bin/mmfm 6 | Name=Multimedia File Manager 7 | Comment=mmfm 8 | Icon=/usr/local/share/mmfm/mmfm.png -------------------------------------------------------------------------------- /res/mmfm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/res/mmfm.png -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/screenshot.png -------------------------------------------------------------------------------- /src/kinetic_ui/egl/ku_gl_floatbuffer.c: -------------------------------------------------------------------------------- 1 | #ifndef ku_floatbuffer_h 2 | #define ku_floatbuffer_h 3 | 4 | #include "mt_memory.c" 5 | #include 6 | #include 7 | 8 | typedef struct ku_floatbuffer_t ku_floatbuffer_t; 9 | struct ku_floatbuffer_t 10 | { 11 | GLfloat* data; 12 | size_t pos; 13 | size_t cap; 14 | char changed; 15 | }; 16 | 17 | ku_floatbuffer_t* ku_floatbuffer_new(void); 18 | void ku_floatbuffer_del(void* fb); 19 | void ku_floatbuffer_reset(ku_floatbuffer_t* fb); 20 | void ku_floatbuffer_add(ku_floatbuffer_t* fb, GLfloat* data, size_t count); 21 | 22 | #endif 23 | 24 | #if __INCLUDE_LEVEL__ == 0 25 | 26 | void ku_floatbuffer_desc(void* p, int level) 27 | { 28 | printf("fb"); 29 | } 30 | 31 | void ku_floatbuffer_desc_data(void* p, int level) 32 | { 33 | printf("fb data"); 34 | } 35 | 36 | ku_floatbuffer_t* ku_floatbuffer_new() 37 | { 38 | ku_floatbuffer_t* fb = CAL(sizeof(ku_floatbuffer_t), ku_floatbuffer_del, ku_floatbuffer_desc); 39 | fb->data = CAL(sizeof(GLfloat) * 10, NULL, ku_floatbuffer_desc_data); 40 | fb->pos = 0; 41 | fb->cap = 10; 42 | 43 | return fb; 44 | } 45 | 46 | void ku_floatbuffer_del(void* pointer) 47 | { 48 | ku_floatbuffer_t* fb = pointer; 49 | REL(fb->data); 50 | } 51 | 52 | void ku_floatbuffer_reset(ku_floatbuffer_t* fb) 53 | { 54 | fb->pos = 0; 55 | } 56 | 57 | void ku_floatbuffer_expand(ku_floatbuffer_t* fb) 58 | { 59 | assert(fb->cap < SIZE_MAX / 2); 60 | fb->cap *= 2; 61 | fb->data = mt_memory_realloc(fb->data, sizeof(void*) * fb->cap); 62 | } 63 | 64 | void ku_floatbuffer_add(ku_floatbuffer_t* fb, GLfloat* data, size_t count) 65 | { 66 | while (fb->pos + count >= fb->cap) ku_floatbuffer_expand(fb); 67 | memcpy(fb->data + fb->pos, data, sizeof(GLfloat) * count); 68 | fb->pos += count; 69 | fb->changed = 1; 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /src/kinetic_ui/egl/ku_gl_shader.c: -------------------------------------------------------------------------------- 1 | #ifndef ku_gl_shader_h 2 | #define ku_gl_shader_h 3 | 4 | #include 5 | 6 | typedef struct _glsha_t 7 | { 8 | GLuint name; 9 | GLint uni_loc[13]; 10 | } glsha_t; 11 | 12 | glsha_t ku_gl_shader_create( 13 | const char* vertex_source, 14 | const char* fragment_source, 15 | int attribute_locations_length, 16 | const char** attribute_structure, 17 | int uniform_locations_length, 18 | const char** uniform_structure); 19 | 20 | #endif 21 | 22 | #if __INCLUDE_LEVEL__ == 0 23 | 24 | #include 25 | 26 | GLuint ku_gl_shader_compile(GLenum type, const GLchar* source) 27 | { 28 | GLint status, logLength, realLength; 29 | GLuint shader = 0; 30 | 31 | status = 0; 32 | shader = glCreateShader(type); 33 | 34 | if (shader > 0) 35 | { 36 | glShaderSource(shader, 1, &source, NULL); 37 | glCompileShader(shader); 38 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); 39 | 40 | if (logLength > 0) 41 | { 42 | GLchar log[logLength]; 43 | 44 | glGetShaderInfoLog(shader, logLength, &realLength, log); 45 | 46 | printf("Shader compile log: %s\n", log); 47 | } 48 | 49 | glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 50 | 51 | if (status != GL_TRUE) 52 | return 0; 53 | } 54 | else 55 | printf("Cannot create shader\n"); 56 | 57 | return shader; 58 | } 59 | 60 | int ku_gl_shader_link(GLuint program) 61 | { 62 | GLint status, logLength, realLength; 63 | 64 | glLinkProgram(program); 65 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); 66 | 67 | if (logLength > 0) 68 | { 69 | GLchar log[logLength]; 70 | glGetProgramInfoLog(program, logLength, &realLength, log); 71 | printf("Program link log : %i %s\n", realLength, log); 72 | } 73 | 74 | glGetProgramiv(program, GL_LINK_STATUS, &status); 75 | if (status == GL_TRUE) 76 | return 1; 77 | return 0; 78 | } 79 | 80 | glsha_t ku_gl_shader_create( 81 | const char* vertex_source, 82 | const char* fragment_source, 83 | int attribute_locations_length, 84 | const char** attribute_structure, 85 | int uniform_locations_length, 86 | const char** uniform_structure) 87 | { 88 | glsha_t sh = {0}; 89 | 90 | sh.name = glCreateProgram(); 91 | 92 | GLuint vertex_shader = ku_gl_shader_compile(GL_VERTEX_SHADER, vertex_source); 93 | if (vertex_shader == 0) printf("Failed to compile vertex shader : %s\n", vertex_source); 94 | 95 | GLuint fragment_shader = ku_gl_shader_compile(GL_FRAGMENT_SHADER, fragment_source); 96 | if (fragment_shader == 0) printf("Failed to compile fragment shader : %s\n", fragment_source); 97 | 98 | glAttachShader(sh.name, vertex_shader); 99 | glAttachShader(sh.name, fragment_shader); 100 | 101 | for (int index = 0; index < attribute_locations_length; index++) 102 | { 103 | const GLchar* name = attribute_structure[index]; 104 | glBindAttribLocation(sh.name, index, name); 105 | } 106 | 107 | int success = ku_gl_shader_link(sh.name); 108 | 109 | if (success == 1) 110 | { 111 | for (int index = 0; index < uniform_locations_length; index++) 112 | { 113 | const GLchar* name = uniform_structure[index]; 114 | GLint location = glGetUniformLocation(sh.name, name); 115 | sh.uni_loc[index] = location; 116 | } 117 | } 118 | else 119 | printf("Failed to link shader program\n"); 120 | 121 | if (vertex_shader > 0) 122 | { 123 | glDetachShader(sh.name, vertex_shader); 124 | glDeleteShader(vertex_shader); 125 | } 126 | 127 | if (fragment_shader > 0) 128 | { 129 | glDetachShader(sh.name, fragment_shader); 130 | glDeleteShader(fragment_shader); 131 | } 132 | 133 | return sh; 134 | } 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /src/kinetic_ui/handler/vh_cv_body.c: -------------------------------------------------------------------------------- 1 | /* content view body */ 2 | 3 | #ifndef vh_cv_body_h 4 | #define vh_cv_body_h 5 | 6 | #include "ku_view.c" 7 | 8 | typedef struct _vh_cv_body_t 9 | { 10 | void* userdata; 11 | 12 | ku_view_t* content; 13 | float cw; // content width 14 | float ch; // content height 15 | float px; 16 | float py; 17 | float zoom; 18 | } vh_cv_body_t; 19 | 20 | void vh_cv_body_attach( 21 | ku_view_t* view, 22 | void* userdata); 23 | 24 | void vh_cv_body_set_content_size( 25 | ku_view_t* view, 26 | int cw, 27 | int ch); 28 | 29 | void vh_cv_body_move( 30 | ku_view_t* view, 31 | float dx, 32 | float dy); 33 | 34 | void vh_cv_body_zoom( 35 | ku_view_t* view, 36 | float s, 37 | int x, 38 | int y); 39 | 40 | void vh_cv_body_reset( 41 | ku_view_t* view); 42 | 43 | void vh_cv_body_hjump( 44 | ku_view_t* view, 45 | float dx); 46 | 47 | void vh_cv_body_vjump( 48 | ku_view_t* view, 49 | int topindex); 50 | 51 | #endif 52 | 53 | #if __INCLUDE_LEVEL__ == 0 54 | 55 | #include "tg_scaledimg.c" 56 | 57 | void vh_cv_body_del(void* p) 58 | { 59 | } 60 | 61 | void vh_cv_body_desc(void* p, int level) 62 | { 63 | printf("vh_cv_body"); 64 | } 65 | 66 | void vh_cv_body_attach( 67 | ku_view_t* view, 68 | void* userdata) 69 | { 70 | assert(view->evt_han == NULL && view->evt_han_data == NULL); 71 | 72 | vh_cv_body_t* vh = CAL(sizeof(vh_cv_body_t), vh_cv_body_del, vh_cv_body_desc); 73 | vh->userdata = userdata; 74 | vh->content = view->views->data[0]; 75 | vh->zoom = 1.0; 76 | 77 | vh->cw = 1; 78 | vh->ch = 1; 79 | 80 | view->evt_han_data = vh; 81 | } 82 | 83 | void vh_cv_body_set_content_size( 84 | ku_view_t* view, 85 | int cw, 86 | int ch) 87 | { 88 | vh_cv_body_t* vh = view->evt_han_data; 89 | 90 | vh->cw = cw; 91 | vh->ch = ch; 92 | 93 | ku_rect_t lf = view->frame.local; // local frame 94 | 95 | float cr = (float) ch / (float) cw; // content aspect ratio 96 | 97 | /* fit width first */ 98 | 99 | float nw = lf.w; 100 | float nh = nw * cr; 101 | 102 | vh->zoom = (float) nw / cw; 103 | 104 | if (nh > lf.h) 105 | { 106 | cr = lf.h / nh; 107 | 108 | nh = lf.h; 109 | nw *= cr; 110 | vh->zoom = (float) nh / ch; 111 | } 112 | 113 | ku_rect_t frame = vh->content->frame.local; 114 | frame.x = (lf.w - nw) / 2.0; 115 | frame.y = (lf.h - nh) / 2.0; 116 | frame.w = nw; 117 | frame.h = nh; 118 | 119 | ku_view_set_frame(vh->content, frame); 120 | 121 | tg_scaledimg_set_content_size(vh->content, cw, ch); 122 | tg_scaledimg_gen(vh->content); 123 | } 124 | 125 | void vh_cv_body_move( 126 | ku_view_t* view, 127 | float dx, 128 | float dy) 129 | { 130 | vh_cv_body_t* vh = view->evt_han_data; 131 | 132 | ku_rect_t frame = vh->content->frame.local; 133 | frame.x += dx; 134 | frame.y += dy; 135 | ku_view_set_frame(vh->content, frame); 136 | } 137 | 138 | void vh_cv_body_zoom( 139 | ku_view_t* view, 140 | float z, 141 | int x, 142 | int y) 143 | { 144 | vh_cv_body_t* vh = view->evt_han_data; 145 | 146 | ku_rect_t gf = vh->content->frame.global; 147 | ku_rect_t lf = vh->content->frame.local; 148 | 149 | /* partial width and height from mouse position */ 150 | 151 | float pw = (float) x - gf.x; 152 | float ph = (float) y - gf.y; 153 | 154 | /* ratios */ 155 | 156 | float rw = pw / gf.w; 157 | float rh = ph / gf.h; 158 | 159 | vh->zoom = z; 160 | if (vh->zoom < 0.001) 161 | vh->zoom = 0.001; 162 | 163 | float nw = vh->cw * vh->zoom; 164 | float nh = vh->ch * vh->zoom; 165 | 166 | lf.x = (float) x - rw * nw - view->frame.global.x; 167 | lf.y = (float) y - rh * nh - view->frame.global.y; 168 | lf.w = nw; 169 | lf.h = nh; 170 | 171 | ku_view_set_frame(vh->content, lf); 172 | tg_scaledimg_gen(vh->content); 173 | } 174 | 175 | void vh_cv_body_reset( 176 | ku_view_t* view) 177 | { 178 | } 179 | 180 | void vh_cv_body_hjump( 181 | ku_view_t* view, 182 | float x) 183 | { 184 | } 185 | 186 | void vh_cv_body_vjump( 187 | ku_view_t* view, 188 | int topindex) 189 | { 190 | } 191 | 192 | #endif 193 | -------------------------------------------------------------------------------- /src/kinetic_ui/handler/vh_drag.c: -------------------------------------------------------------------------------- 1 | #ifndef vh_drag_h 2 | #define vh_drag_h 3 | 4 | #include "ku_event.c" 5 | #include "ku_view.c" 6 | 7 | enum vh_drag_event_id 8 | { 9 | VH_DRAG_MOVE, 10 | VH_DRAG_DROP 11 | }; 12 | 13 | typedef struct _vh_drag_t vh_drag_t; 14 | 15 | typedef struct _vh_drag_event_t 16 | { 17 | enum vh_drag_event_id id; 18 | vh_drag_t* vh; 19 | ku_view_t* view; 20 | ku_view_t* dragged_view; 21 | } vh_drag_event_t; 22 | 23 | struct _vh_drag_t 24 | { 25 | void (*on_event)(vh_drag_event_t); 26 | ku_view_t* dragged_view; 27 | }; 28 | 29 | void vh_drag_attach(ku_view_t* view, void (*on_event)(vh_drag_event_t)); 30 | void vh_drag_drag(ku_view_t* view, ku_view_t* item); 31 | 32 | #endif 33 | 34 | #if __INCLUDE_LEVEL__ == 0 35 | 36 | int vh_drag_evt(ku_view_t* view, ku_event_t ev) 37 | { 38 | if (ev.type == KU_EVENT_MOUSE_MOVE && ev.drag) 39 | { 40 | vh_drag_t* vh = view->evt_han_data; 41 | 42 | if (vh->dragged_view) 43 | { 44 | ku_rect_t frame = vh->dragged_view->frame.local; 45 | frame.x = ev.x - frame.w / 2; 46 | frame.y = ev.y - frame.h / 2; 47 | ku_view_set_frame(vh->dragged_view, frame); 48 | 49 | vh_drag_event_t event = {.id = VH_DRAG_MOVE, .vh = vh, .view = view, .dragged_view = vh->dragged_view}; 50 | if (vh->on_event) 51 | (*vh->on_event)(event); 52 | } 53 | 54 | return 1; 55 | } 56 | if (ev.type == KU_EVENT_MOUSE_UP && ev.drag) 57 | { 58 | vh_drag_t* vh = view->evt_han_data; 59 | 60 | if (vh->dragged_view) 61 | { 62 | vh_drag_event_t event = {.id = VH_DRAG_DROP, .vh = vh, .view = view, .dragged_view = vh->dragged_view}; 63 | if (vh->on_event) 64 | (*vh->on_event)(event); 65 | 66 | REL(vh->dragged_view); 67 | vh->dragged_view = NULL; 68 | } 69 | 70 | return 1; 71 | } 72 | 73 | return 0; 74 | } 75 | 76 | void vh_drag_del(void* p) 77 | { 78 | vh_drag_t* vh = p; 79 | 80 | if (vh->dragged_view) REL(vh->dragged_view); 81 | } 82 | 83 | void vh_drag_desc(void* p, int level) 84 | { 85 | } 86 | 87 | void vh_drag_attach(ku_view_t* view, void (*on_event)(vh_drag_event_t)) 88 | { 89 | assert(view->evt_han == NULL && view->evt_han_data == NULL); 90 | 91 | vh_drag_t* vh = CAL(sizeof(vh_drag_t), vh_drag_del, vh_drag_desc); 92 | vh->on_event = on_event; 93 | 94 | view->evt_han_data = vh; 95 | view->evt_han = vh_drag_evt; 96 | } 97 | 98 | void vh_drag_drag(ku_view_t* view, ku_view_t* item) 99 | { 100 | vh_drag_t* vh = view->evt_han_data; 101 | 102 | if (vh->dragged_view) 103 | { 104 | REL(vh->dragged_view); 105 | vh->dragged_view = NULL; 106 | } 107 | if (item) 108 | { 109 | vh->dragged_view = RET(item); 110 | } 111 | } 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /src/kinetic_ui/handler/vh_key.c: -------------------------------------------------------------------------------- 1 | #ifndef vh_key_h 2 | #define vh_key_h 3 | 4 | #include "ku_view.c" 5 | 6 | typedef struct _vh_key_t vh_key_t; 7 | 8 | typedef struct _vh_key_event_t 9 | { 10 | ku_event_t ev; 11 | vh_key_t* vh; 12 | ku_view_t* view; 13 | } vh_key_event_t; 14 | 15 | struct _vh_key_t 16 | { 17 | int (*on_event)(vh_key_event_t event); 18 | }; 19 | 20 | void vh_key_add(ku_view_t* view, int (*on_event)(vh_key_event_t)); 21 | 22 | #endif 23 | 24 | #if __INCLUDE_LEVEL__ == 0 25 | 26 | int vh_key_evt(ku_view_t* view, ku_event_t ev) 27 | { 28 | int cancel = 0; 29 | if (ev.type == KU_EVENT_KEY_DOWN) 30 | { 31 | vh_key_t* vh = view->evt_han_data; 32 | vh_key_event_t event = {.ev = ev, .vh = vh, .view = view}; 33 | if (vh->on_event) 34 | cancel = (*vh->on_event)(event); 35 | } 36 | 37 | return cancel; 38 | } 39 | 40 | void vh_key_del(void* p) 41 | { 42 | } 43 | 44 | void vh_key_desc(void* p, int level) 45 | { 46 | printf("vh_key"); 47 | } 48 | 49 | void vh_key_add(ku_view_t* view, int (*on_event)(vh_key_event_t)) 50 | { 51 | assert(view->evt_han == NULL && view->evt_han_data == NULL); 52 | 53 | vh_key_t* vh = CAL(sizeof(vh_key_t), vh_key_del, vh_key_desc); 54 | vh->on_event = on_event; 55 | 56 | view->evt_han_data = vh; 57 | view->evt_han = vh_key_evt; 58 | } 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/kinetic_ui/handler/vh_knob.c: -------------------------------------------------------------------------------- 1 | #ifndef vh_knob_h 2 | #define vh_knob_h 3 | 4 | #include "ku_view.c" 5 | 6 | void vh_knob_add(ku_view_t* view, void (*ratio_changed)(ku_view_t* view, float ratio)); 7 | 8 | #endif 9 | 10 | #if __INCLUDE_LEVEL__ == 0 11 | 12 | #include "ku_draw.c" 13 | #include "tg_knob.c" 14 | #include 15 | 16 | typedef struct _vh_knob_t 17 | { 18 | float angle; 19 | char* id; 20 | 21 | void (*ratio_changed)(ku_view_t* view, float ratio); 22 | } vh_knob_t; 23 | 24 | int vh_knob_evt(ku_view_t* view, ku_event_t ev) 25 | { 26 | int cancel = 1; 27 | if (ev.type == KU_EVENT_MOUSE_DOWN || (ev.type == KU_EVENT_MOUSE_MOVE && ev.drag)) 28 | { 29 | vh_knob_t* vh = view->evt_han_data; 30 | 31 | float dx = ev.x - (view->frame.global.x + view->frame.global.w / 2.0); 32 | float dy = ev.y - (view->frame.global.y + view->frame.global.h / 2.0); 33 | float angle = atan2(dy, dx); 34 | float r = sqrt(dx * dx + dy * dy); 35 | 36 | if (angle < 0) 37 | angle += 6.28; 38 | 39 | if (r < view->frame.global.w / 2.0) 40 | { 41 | tg_knob_set_angle(view, angle); 42 | (*vh->ratio_changed)(view, angle); 43 | } 44 | } 45 | else if (ev.type == KU_EVENT_SCROLL) 46 | { 47 | vh_knob_t* vh = view->evt_han_data; 48 | tg_knob_t* tg = view->tex_gen_data; 49 | 50 | float angle = tg->angle - ev.dy / 50.0; 51 | 52 | if (angle < 0) 53 | angle += 6.28; 54 | 55 | if (tg->angle < 3 * 3.14 / 2 && tg->angle > 3.14 && angle > 3 * 3.14 / 2) 56 | angle = tg->angle; 57 | if (tg->angle > 3 * 3.14 / 2 && tg->angle < 2 * 3.14 && angle < 3 * 3.14 / 2) 58 | angle = tg->angle; 59 | 60 | if (angle > 6.28) 61 | angle -= 6.28; 62 | tg_knob_set_angle(view, angle); 63 | (*vh->ratio_changed)(view, angle); 64 | } 65 | 66 | return cancel; 67 | } 68 | 69 | void vh_knob_desc(void* p, int level) 70 | { 71 | printf("vh_knob"); 72 | } 73 | 74 | void vh_knob_add(ku_view_t* view, void (*ratio_changed)(ku_view_t* view, float ratio)) 75 | { 76 | assert(view->evt_han == NULL && view->evt_han_data == NULL); 77 | 78 | vh_knob_t* vh = CAL(sizeof(vh_knob_t), NULL, vh_knob_desc); 79 | 80 | vh->ratio_changed = ratio_changed; 81 | 82 | view->evt_han_data = vh; 83 | view->evt_han = vh_knob_evt; 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/kinetic_ui/handler/vh_roll.c: -------------------------------------------------------------------------------- 1 | #ifndef vh_roll_h 2 | #define vh_roll_h 3 | 4 | #include "ku_event.c" 5 | #include "ku_view.c" 6 | 7 | enum vh_roll_event_id 8 | { 9 | VH_ROLL_IN, 10 | VH_ROLL_OUT 11 | }; 12 | 13 | typedef struct _vh_roll_t vh_roll_t; 14 | 15 | typedef struct _vh_roll_event_t 16 | { 17 | enum vh_roll_event_id id; 18 | vh_roll_t* vh; 19 | ku_view_t* view; 20 | } vh_roll_event_t; 21 | 22 | struct _vh_roll_t 23 | { 24 | char active; 25 | void (*on_event)(vh_roll_event_t); 26 | }; 27 | 28 | void vh_roll_add(ku_view_t* view, void (*on_event)(vh_roll_event_t)); 29 | 30 | #endif 31 | 32 | #if __INCLUDE_LEVEL__ == 0 33 | 34 | int vh_roll_evt(ku_view_t* view, ku_event_t ev) 35 | { 36 | if (ev.type == KU_EVENT_MOUSE_MOVE) 37 | { 38 | vh_roll_t* vh = view->evt_han_data; 39 | ku_rect_t frame = view->frame.global; 40 | 41 | if (!vh->active) 42 | { 43 | if (ev.x >= frame.x && 44 | ev.x <= frame.x + frame.w && 45 | ev.y >= frame.y && 46 | ev.y <= frame.y + frame.h) 47 | { 48 | vh->active = 1; 49 | 50 | vh_roll_event_t event = {.id = VH_ROLL_IN, .view = view, .vh = vh}; 51 | if (vh->on_event) 52 | (*vh->on_event)(event); 53 | } 54 | } 55 | } 56 | else if (ev.type == KU_EVENT_MOUSE_MOVE_OUT) 57 | { 58 | vh_roll_t* vh = view->evt_han_data; 59 | ku_rect_t frame = view->frame.global; 60 | 61 | if (vh->active) 62 | { 63 | if (ev.x < frame.x || 64 | ev.x > frame.x + frame.w || 65 | ev.y < frame.y || 66 | ev.y > frame.y + frame.h) 67 | { 68 | vh->active = 0; 69 | vh_roll_event_t event = {.id = VH_ROLL_OUT, .view = view, .vh = vh}; 70 | if (vh->on_event) 71 | (*vh->on_event)(event); 72 | } 73 | } 74 | } 75 | 76 | return 1; 77 | } 78 | 79 | void vh_roll_del(void* p) 80 | { 81 | } 82 | 83 | void vh_roll_desc(void* p, int level) 84 | { 85 | printf("vh_roll"); 86 | } 87 | 88 | void vh_roll_add(ku_view_t* view, void (*on_event)(vh_roll_event_t)) 89 | { 90 | assert(view->evt_han == NULL && view->evt_han_data == NULL); 91 | 92 | vh_roll_t* vh = CAL(sizeof(vh_roll_t), vh_roll_del, vh_roll_desc); 93 | vh->on_event = on_event; 94 | 95 | view->evt_han_data = vh; 96 | view->evt_han = vh_roll_evt; 97 | } 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/kinetic_ui/handler/vh_slider.c: -------------------------------------------------------------------------------- 1 | #ifndef vh_slider_h 2 | #define vh_slider_h 3 | 4 | #include "ku_view.c" 5 | 6 | typedef struct _vh_slider_t vh_slider_t; 7 | 8 | typedef struct _vh_slider_event_t 9 | { 10 | vh_slider_t* vh; 11 | ku_view_t* view; 12 | float ratio; 13 | } vh_slider_event_t; 14 | 15 | struct _vh_slider_t 16 | { 17 | float ratio; 18 | char enabled; 19 | void (*on_event)(vh_slider_event_t); 20 | }; 21 | 22 | void vh_slider_add(ku_view_t* view, void (*on_event)(vh_slider_event_t)); 23 | void vh_slider_set(ku_view_t* view, float ratio); 24 | float vh_slider_get_ratio(ku_view_t* view); 25 | void vh_slider_set_enabled(ku_view_t* view, int flag); 26 | 27 | #endif 28 | 29 | #if __INCLUDE_LEVEL__ == 0 30 | 31 | #include "vh_anim.c" 32 | #include 33 | 34 | int vh_slider_evt(ku_view_t* view, ku_event_t ev) 35 | { 36 | vh_slider_t* vh = view->evt_han_data; 37 | 38 | if (vh->enabled) 39 | { 40 | if (ev.type == KU_EVENT_MOUSE_DOWN || (ev.type == KU_EVENT_MOUSE_MOVE && ev.drag)) 41 | { 42 | float dx = ev.x - view->frame.global.x; 43 | vh->ratio = dx / view->frame.global.w; 44 | 45 | ku_view_t* bar = view->views->data[0]; 46 | ku_rect_t frame = bar->frame.local; 47 | frame.w = dx; 48 | ku_view_set_frame(bar, frame); 49 | 50 | vh_slider_event_t event = {.view = view, .ratio = vh->ratio, .vh = vh}; 51 | if (vh->on_event) 52 | (*vh->on_event)(event); 53 | } 54 | else if (ev.type == KU_EVENT_SCROLL) 55 | { 56 | float ratio = vh->ratio - ev.dx / 50.0; 57 | 58 | if (ratio < 0) 59 | ratio = 0; 60 | if (ratio > 1) 61 | ratio = 1; 62 | 63 | vh->ratio = ratio; 64 | ku_view_t* bar = view->views->data[0]; 65 | ku_rect_t frame = bar->frame.local; 66 | frame.w = view->frame.global.w * vh->ratio; 67 | ku_view_set_frame(bar, frame); 68 | 69 | vh_slider_event_t event = {.view = view, .ratio = vh->ratio, .vh = vh}; 70 | if (vh->on_event) 71 | (*vh->on_event)(event); 72 | } 73 | } 74 | 75 | return 0; 76 | } 77 | 78 | void vh_slider_set(ku_view_t* view, float ratio) 79 | { 80 | vh_slider_t* vh = view->evt_han_data; 81 | vh->ratio = ratio; 82 | ku_view_t* bar = view->views->data[0]; 83 | ku_rect_t frame = bar->frame.local; 84 | frame.w = view->frame.global.w * vh->ratio; 85 | ku_view_set_frame(bar, frame); 86 | } 87 | 88 | float vh_slider_get_ratio(ku_view_t* view) 89 | { 90 | vh_slider_t* vh = view->evt_han_data; 91 | return vh->ratio; 92 | } 93 | 94 | void vh_slider_desc(void* p, int level) 95 | { 96 | printf("vh_slider"); 97 | } 98 | 99 | void vh_slider_del(void* p) 100 | { 101 | } 102 | 103 | void vh_slider_add(ku_view_t* view, void (*on_event)(vh_slider_event_t)) 104 | { 105 | assert(view->evt_han == NULL && view->evt_han_data == NULL); 106 | 107 | vh_slider_t* vh = CAL(sizeof(vh_slider_t), vh_slider_del, vh_slider_desc); 108 | vh->on_event = on_event; 109 | vh->enabled = 1; 110 | 111 | view->evt_han_data = vh; 112 | view->evt_han = vh_slider_evt; 113 | 114 | ku_view_t* bar = view->views->data[0]; 115 | vh_anim_add(bar, NULL, NULL); 116 | } 117 | 118 | void vh_slider_set_enabled(ku_view_t* view, int flag) 119 | { 120 | vh_slider_t* vh = view->evt_han_data; 121 | 122 | if (flag) 123 | { 124 | if (vh->enabled == 0) 125 | { 126 | ku_view_t* bar = view->views->data[0]; 127 | vh_anim_alpha(bar, 0.3, 1.0, 10, AT_LINEAR); 128 | } 129 | } 130 | else 131 | { 132 | if (vh->enabled == 1) 133 | { 134 | ku_view_t* bar = view->views->data[0]; 135 | vh_anim_alpha(bar, 1.0, 0.3, 10, AT_LINEAR); 136 | } 137 | } 138 | 139 | vh->enabled = flag; 140 | } 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /src/kinetic_ui/handler/vh_touch.c: -------------------------------------------------------------------------------- 1 | #ifndef vh_touch_h 2 | #define vh_touch_h 3 | 4 | #include "ku_view.c" 5 | 6 | typedef struct _vh_touch_t vh_touch_t; 7 | 8 | enum vh_touch_event_id 9 | { 10 | VH_TOUCH_EVENT 11 | }; 12 | 13 | typedef struct _vh_touch_event_t 14 | { 15 | enum vh_touch_event_id id; 16 | vh_touch_t* vh; 17 | ku_view_t* view; 18 | } vh_touch_event_t; 19 | 20 | struct _vh_touch_t 21 | { 22 | int (*on_event)(vh_touch_event_t); 23 | }; 24 | 25 | void vh_touch_add(ku_view_t* view, int (*on_event)(vh_touch_event_t)); 26 | 27 | #endif 28 | 29 | #if __INCLUDE_LEVEL__ == 0 30 | 31 | #include "ku_event.c" 32 | 33 | int vh_touch_evt(ku_view_t* view, ku_event_t ev) 34 | { 35 | int cancel = 0; 36 | if (ev.type == KU_EVENT_MOUSE_DOWN) 37 | { 38 | vh_touch_t* vh = view->evt_han_data; 39 | vh_touch_event_t event = {.id = VH_TOUCH_EVENT, .vh = vh, .view = view}; 40 | if (vh->on_event) 41 | cancel = (*vh->on_event)(event); 42 | } 43 | 44 | return cancel; 45 | } 46 | 47 | void vh_touch_del(void* p) 48 | { 49 | /* vh_touch_t* vh = p; */ 50 | } 51 | 52 | void vh_touch_desc(void* p, int level) 53 | { 54 | printf("vh_touch"); 55 | } 56 | 57 | void vh_touch_add(ku_view_t* view, int (*on_event)(vh_touch_event_t)) 58 | { 59 | assert(view->evt_han == NULL && view->evt_han_data == NULL); 60 | 61 | vh_touch_t* vh = CAL(sizeof(vh_touch_t), vh_touch_del, vh_touch_desc); 62 | vh->on_event = on_event; 63 | 64 | view->evt_han = vh_touch_evt; 65 | view->evt_han_data = vh; 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/kinetic_ui/ku_css.c: -------------------------------------------------------------------------------- 1 | /* 2 | Kinetic UI CSS parser 3 | Does pretty dumb parsing, error handling should be improved 4 | */ 5 | 6 | #ifndef ku_css_h 7 | #define ku_css_h 8 | 9 | /* TODO write tests */ 10 | 11 | #include "mt_log.c" 12 | #include "mt_map.c" 13 | #include "mt_string.c" 14 | #include "mt_vector.c" 15 | #include 16 | #include 17 | #include 18 | 19 | typedef struct _css_range_t 20 | { 21 | uint32_t pos; 22 | uint32_t len; 23 | } css_range_t; 24 | 25 | typedef struct _prop_t 26 | { 27 | css_range_t class; 28 | css_range_t key; 29 | css_range_t value; 30 | } prop_t; 31 | 32 | mt_map_t* ku_css_new(char* path); 33 | 34 | #endif 35 | 36 | #if __INCLUDE_LEVEL__ == 0 37 | 38 | #include "mt_string_ext.c" 39 | 40 | uint32_t ku_css_count_props(char* css) 41 | { 42 | int t = 0; // tag index 43 | char* c = css; 44 | while (*c) 45 | { 46 | if (*c == ':') 47 | t++; 48 | c++; 49 | } 50 | return t; 51 | } 52 | 53 | void ku_css_analyze_classes(char* css, prop_t* props) 54 | { 55 | int start = -1; 56 | // char in_l = 0; // in line 57 | uint32_t index = 0; 58 | css_range_t class = {0}; 59 | int in_str = 0; 60 | char* c = css; 61 | while (*c) 62 | { 63 | if (*c == '}' || *c == ' ' || *c == '\r' || *c == '\n') 64 | { 65 | if (c - css - 1 == start) start = c - css; // skip starting empty chars 66 | } 67 | else if (*c == '"') // class name 68 | { 69 | in_str = 1 - in_str; 70 | } 71 | else if (*c == '{') // class name 72 | { 73 | class.pos = start + 1; 74 | class.len = c - css - start - 2; 75 | while (*(css + class.pos + class.len) == ' ') class.len--; 76 | class.len++; 77 | start = c - css; 78 | } 79 | else if (*c == ':' && !in_str) // property name 80 | { 81 | props[index].class = class; 82 | props[index].key.pos = start + 1; 83 | props[index].key.len = c - css - start - 1; 84 | start = c - css; 85 | } 86 | else if (*c == ';') // value name 87 | { 88 | props[index].class = class; 89 | props[index].value.pos = start + 1; 90 | props[index].value.len = c - css - start - 1; 91 | 92 | start = c - css; 93 | index++; 94 | } 95 | 96 | c++; 97 | } 98 | } 99 | 100 | void ku_css_prop_desc(void* p, int level) 101 | { 102 | printf("html prop_t"); 103 | } 104 | 105 | prop_t* ku_css_new_parse(char* css) 106 | { 107 | uint32_t cnt = ku_css_count_props(css); 108 | prop_t* props = CAL(sizeof(prop_t) * (cnt + 1), NULL, ku_css_prop_desc); // REL 1 109 | 110 | ku_css_analyze_classes(css, props); 111 | 112 | for (uint32_t i = 0; i < cnt; i++) 113 | { 114 | // prop_t p = props[i]; 115 | // printf("extracted prop %.*s %.*s %.*s\n", p.class.len, css + p.class.pos, p.key.len, css + p.key.pos, p.value.len, css + p.value.pos); 116 | } 117 | 118 | return props; 119 | } 120 | 121 | mt_map_t* ku_css_new(char* filepath) 122 | { 123 | mt_map_t* styles = MNEW(); // REL 2 124 | char* css = mt_string_new_file(filepath); // REL 0 125 | 126 | if (css) 127 | { 128 | prop_t* view_styles = ku_css_new_parse(css); // REL 1 129 | prop_t* props = view_styles; 130 | 131 | while ((*props).class.len > 0) 132 | { 133 | prop_t t = *props; 134 | char* cls = CAL(sizeof(char) * t.class.len + 1, NULL, mt_string_describe); // REL 3 135 | char* key = CAL(sizeof(char) * t.key.len + 1, NULL, mt_string_describe); // REL 4 136 | char* val = CAL(sizeof(char) * t.value.len + 1, NULL, mt_string_describe); // REL 5 137 | 138 | memcpy(cls, css + t.class.pos, t.class.len); 139 | memcpy(key, css + t.key.pos, t.key.len); 140 | memcpy(val, css + t.value.pos, t.value.len); 141 | 142 | mt_map_t* style = MGET(styles, cls); 143 | if (style == NULL) 144 | { 145 | style = MNEW(); // REL 6 146 | MPUT(styles, cls, style); 147 | REL(style); // REL 6 148 | } 149 | MPUT(style, key, val); 150 | props += 1; 151 | REL(cls); // REL 3 152 | REL(key); // REL 4 153 | REL(val); // REL 5 154 | } 155 | 156 | REL(view_styles); 157 | REL(css); 158 | } 159 | else mt_log_error("Empty CSS descriptor"); 160 | 161 | return styles; 162 | } 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /src/kinetic_ui/ku_event.c: -------------------------------------------------------------------------------- 1 | #ifndef ku_event_h 2 | #define ku_event_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | enum evtype 9 | { 10 | KU_EVENT_EMPTY, 11 | KU_EVENT_FRAME, 12 | KU_EVENT_TIME, 13 | KU_EVENT_RESIZE, 14 | KU_EVENT_MOUSE_MOVE, 15 | KU_EVENT_MOUSE_DOWN, 16 | KU_EVENT_MOUSE_UP, 17 | KU_EVENT_MOUSE_MOVE_OUT, 18 | KU_EVENT_MOUSE_DOWN_OUT, 19 | KU_EVENT_MOUSE_UP_OUT, 20 | KU_EVENT_SCROLL, 21 | KU_EVENT_SCROLL_X_END, 22 | KU_EVENT_SCROLL_Y_END, 23 | KU_EVENT_KEY_DOWN, 24 | KU_EVENT_KEY_UP, 25 | KU_EVENT_TEXT, 26 | KU_EVENT_WINDOW_SHOWN, 27 | KU_EVENT_PINCH, 28 | KU_EVENT_HOLD_START, 29 | KU_EVENT_HOLD_END, 30 | KU_EVENT_STDIN, 31 | KU_EVENT_FOCUS, 32 | KU_EVENT_UNFOCUS, 33 | }; 34 | 35 | typedef struct _ku_event_t 36 | { 37 | int type; 38 | 39 | /* poiniter properties */ 40 | 41 | int x; // mouse coord x 42 | int y; // mouse coord y 43 | 44 | /* resize */ 45 | 46 | int w; // resize width 47 | int h; // resize height 48 | 49 | /* scroll */ 50 | 51 | float dx; // scroll x 52 | float dy; // scroll y 53 | 54 | /* pinch */ 55 | 56 | float ratio; // pinch ratio 57 | 58 | /* mouse */ 59 | 60 | int drag; // mouse drag 61 | int dclick; // double click 62 | int button; // mouse button id 63 | 64 | /* time */ 65 | 66 | uint32_t time; // milliseconds since start 67 | struct timespec time_unix; // unix timestamp 68 | float time_frame; // elapsed time since last frame 69 | uint32_t frame; // actual frame count 70 | 71 | /* keyboard */ 72 | 73 | uint32_t keycode; 74 | int repeat; // key event is coming from repeat 75 | 76 | int ctrl_down; // modifiers 77 | int shift_down; // modifiers 78 | 79 | char text[8]; 80 | 81 | /* window */ 82 | 83 | void* window; 84 | 85 | } ku_event_t; 86 | 87 | void ku_event_write(FILE* file, ku_event_t ev); 88 | ku_event_t ku_event_read(FILE* file); 89 | 90 | #endif 91 | 92 | #if __INCLUDE_LEVEL__ == 0 93 | 94 | #include "mt_log.c" 95 | 96 | /* frame type x y w h dx dy ratio drag dclick button time time_frame keycode repeat ctrl_down shift_down text */ 97 | char* ku_print_format = "%i %i %i %i %i %i %f %f %f %i %i %i %u %f %u %i %i %i '%s'\n"; 98 | char* ku_scan_format = "%i %i %i %i %i %i %f %f %f %i %i %i %u %f %u %i %i %i '%[^']'\n"; 99 | 100 | void ku_event_write(FILE* file, ku_event_t ev) 101 | { 102 | fprintf( 103 | file, 104 | ku_print_format, 105 | ev.frame, 106 | ev.type, 107 | ev.x, 108 | ev.y, 109 | ev.w, 110 | ev.h, 111 | ev.dx, 112 | ev.dy, 113 | ev.ratio, 114 | ev.drag, 115 | ev.dclick, 116 | ev.button, 117 | ev.time, 118 | ev.time_frame, 119 | ev.keycode, 120 | ev.repeat, 121 | ev.ctrl_down, 122 | ev.shift_down, 123 | ev.text[0] == '\0' ? "T" : ev.text); 124 | } 125 | 126 | ku_event_t ku_event_read(FILE* file) 127 | { 128 | ku_event_t ev = {0}; 129 | int res = fscanf( 130 | file, 131 | ku_scan_format, 132 | &ev.frame, 133 | &ev.type, 134 | &ev.x, 135 | &ev.y, 136 | &ev.w, 137 | &ev.h, 138 | &ev.dx, 139 | &ev.dy, 140 | &ev.ratio, 141 | &ev.drag, 142 | &ev.dclick, 143 | &ev.button, 144 | &ev.time, 145 | &ev.time_frame, 146 | &ev.keycode, 147 | &ev.repeat, 148 | &ev.ctrl_down, 149 | &ev.shift_down, 150 | &ev.text); 151 | 152 | if (res < 0) 153 | mt_log_error("Couldn't scanf file"); 154 | 155 | return ev; 156 | } 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /src/kinetic_ui/ku_fontconfig.c: -------------------------------------------------------------------------------- 1 | #ifndef ku_fontconfig_h 2 | #define ku_fontconfig_h 3 | 4 | char* ku_fontconfig_path(char* face_desc); 5 | void ku_fontconfig_delete(); 6 | 7 | #endif 8 | 9 | #if __INCLUDE_LEVEL__ == 0 10 | 11 | #include 12 | #ifdef __linux__ 13 | #include 14 | #endif 15 | 16 | // #define _POSIX_C_SOURCE 200112L 17 | #include "mt_map.c" 18 | #include "mt_memory.c" 19 | #include "mt_string.c" 20 | #include 21 | #include 22 | 23 | mt_map_t* ku_fontconfig_cache = NULL; 24 | 25 | char* ku_fontconfig_path(char* face_desc) 26 | { 27 | char* filename = NULL; 28 | if (face_desc) 29 | { 30 | if (ku_fontconfig_cache == NULL) 31 | ku_fontconfig_cache = MNEW(); 32 | filename = MGET(ku_fontconfig_cache, face_desc); 33 | 34 | if (filename == NULL) 35 | { 36 | char buff[PATH_MAX]; 37 | filename = mt_string_new_cstring(""); // REL 0 38 | char* command = mt_string_new_format(80, "fc-match \"%s\" --format=%%{file}", face_desc); // REL 1 39 | FILE* pipe = popen(command, "r"); // CLOSE 0 40 | while (fgets(buff, sizeof(buff), pipe) != NULL) filename = mt_string_append(filename, buff); 41 | pclose(pipe); // CLOSE 0 42 | REL(command); // REL 1 43 | 44 | MPUTR(ku_fontconfig_cache, face_desc, filename); 45 | } 46 | } 47 | return filename; 48 | } 49 | 50 | void ku_fontconfig_delete() 51 | { 52 | if (ku_fontconfig_cache) REL(ku_fontconfig_cache); 53 | ku_fontconfig_cache = NULL; 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/kinetic_ui/ku_gen_html.c: -------------------------------------------------------------------------------- 1 | #ifndef ku_gen_html_h 2 | #define ku_gen_html_h 3 | 4 | #include "mt_vector.c" 5 | 6 | void ku_gen_html_parse(char* htmlpath, mt_vector_t* views); 7 | 8 | #endif 9 | 10 | #if __INCLUDE_LEVEL__ == 0 11 | 12 | #include "ku_html.c" 13 | #include "ku_view.c" 14 | #include "mt_log.c" 15 | #include "mt_string_ext.c" 16 | 17 | void ku_gen_html_parse(char* htmlpath, mt_vector_t* views) 18 | { 19 | char* html = mt_string_new_file(htmlpath); // REL 0 20 | 21 | if (html != NULL) 22 | { 23 | tag_t* tags = ku_html_new(html); // REL 1 24 | tag_t* head = tags; 25 | 26 | while ((*tags).len > 0) 27 | { 28 | tag_t t = *tags; 29 | if (t.id.len > 0) 30 | { 31 | // extract id 32 | char* id = CAL(sizeof(char) * t.id.len + 1, NULL, mt_string_describe); // REL 0 33 | memcpy(id, html + t.id.pos + 1, t.id.len); 34 | ku_view_t* view = ku_view_new(id, (ku_rect_t){0}); // REL 1 35 | 36 | if (t.level > 0) 37 | { 38 | // add to parent 39 | ku_view_t* parent = views->data[t.parent]; 40 | ku_view_add_subview(parent, view); 41 | } 42 | 43 | if (t.class.len > 0) 44 | { 45 | // store css classes 46 | char* class = CAL(sizeof(char) * t.class.len + 1, NULL, mt_string_describe); // REL 0 47 | memcpy(class, html + t.class.pos + 1, t.class.len); 48 | ku_view_set_class(view, class); 49 | REL(class); 50 | } 51 | 52 | if (t.type.len > 0) 53 | { 54 | // store html stype 55 | char* type = CAL(sizeof(char) * t.type.len + 1, NULL, mt_string_describe); // REL 2 56 | memcpy(type, html + t.type.pos + 1, t.type.len); 57 | ku_view_set_type(view, type); 58 | REL(type); // REL 2 59 | } 60 | 61 | if (t.text.len > 0) 62 | { 63 | // store html stype 64 | char* text = CAL(sizeof(char) * t.text.len + 1, NULL, mt_string_describe); // REL 2 65 | memcpy(text, html + t.text.pos + 1, t.text.len); 66 | ku_view_set_text(view, text); 67 | REL(text); // REL 2 68 | } 69 | 70 | if (t.script.len > 0) 71 | { 72 | // store html stype 73 | char* script = CAL(sizeof(char) * t.script.len + 1, NULL, mt_string_describe); // REL 2 74 | memcpy(script, html + t.script.pos + 1, t.script.len); 75 | ku_view_set_script(view, script); 76 | REL(script); // REL 2 77 | } 78 | 79 | VADD(views, view); 80 | 81 | REL(id); // REL 0 82 | REL(view); // REL 1 83 | } 84 | else 85 | { 86 | static int divcnt = 0; 87 | char* divid = mt_string_new_format(10, "div%i", divcnt++); 88 | // idless view, probably 89 | ku_view_t* view = ku_view_new(divid, (ku_rect_t){0}); 90 | VADD(views, view); 91 | REL(view); 92 | REL(divid); 93 | } 94 | tags += 1; 95 | } 96 | 97 | // cleanup 98 | 99 | REL(head); // REL 1 100 | REL(html); // REL 0 101 | } 102 | else mt_log_error("No HTML description"); 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /src/kinetic_ui/ku_gen_textstyle.c: -------------------------------------------------------------------------------- 1 | #ifndef ku_gen_textstyle_h 2 | #define ku_gen_textstyle_h 3 | 4 | #include "ku_text.c" 5 | #include "ku_view.c" 6 | 7 | textstyle_t ku_gen_textstyle_parse(ku_view_t* view); 8 | void ku_gen_textstyle_force_font(char* path); 9 | 10 | #endif 11 | 12 | #if __INCLUDE_LEVEL__ == 0 13 | 14 | #include "ku_fontconfig.c" 15 | #include 16 | 17 | char* forced_font = NULL; 18 | 19 | textstyle_t ku_gen_textstyle_parse(ku_view_t* view) 20 | { 21 | textstyle_t style = {0}; 22 | 23 | if (forced_font) 24 | { 25 | strcpy(style.font, forced_font); 26 | } 27 | else 28 | { 29 | char* font = ku_fontconfig_path(view->style.font_family); 30 | if (font) 31 | strcpy(style.font, font); 32 | } 33 | 34 | style.size = view->style.font_size > 0 ? view->style.font_size : 15; 35 | 36 | style.align = view->style.text_align; 37 | style.valign = view->style.vertical_align; 38 | /* style.autosize = */ 39 | style.multiline = view->style.word_wrap == 1; 40 | style.line_height = view->style.line_height; 41 | 42 | style.margin = view->style.margin; 43 | if (view->style.margin_left < INT_MAX) 44 | style.margin_left = view->style.margin_left; 45 | if (view->style.margin_right < INT_MAX) 46 | style.margin_right = view->style.margin_right; 47 | if (view->style.margin_top < INT_MAX) 48 | style.margin_top = view->style.margin_top; 49 | if (view->style.margin_bottom < INT_MAX) 50 | style.margin_bottom = view->style.margin_bottom; 51 | 52 | style.textcolor = view->style.color; 53 | style.backcolor = view->style.background_color; 54 | 55 | return style; 56 | } 57 | 58 | void ku_gen_textstyle_force_font(char* path) 59 | { 60 | forced_font = RET(path); 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/kinetic_ui/ku_gen_type.c: -------------------------------------------------------------------------------- 1 | #ifndef ku_gen_type_h 2 | #define ku_gen_type_h 3 | 4 | #include "mt_vector.c" 5 | #include "vh_button.c" 6 | #include "vh_slider.c" 7 | 8 | void ku_gen_type_apply(mt_vector_t* views, int (*button_event)(vh_button_event_t), void (*slider_event)(vh_slider_event_t)); 9 | 10 | #endif 11 | 12 | #if __INCLUDE_LEVEL__ == 0 13 | 14 | #include "ku_view.c" 15 | #include "tg_css.c" 16 | #include "tg_text.c" 17 | 18 | void ku_gen_type_apply(mt_vector_t* views, int (*button_event)(vh_button_event_t), void (*slider_event)(vh_slider_event_t)) 19 | { 20 | for (size_t index = 0; index < views->length; index++) 21 | { 22 | ku_view_t* view = views->data[index]; 23 | 24 | if (view->type && strcmp(view->type, "label") == 0) 25 | { 26 | tg_text_add(view); 27 | tg_text_set1(view, view->text); 28 | } 29 | else if (view->style.background_color > 0 || view->style.border_color > 0) 30 | { 31 | tg_css_add(view); 32 | } 33 | else if (strlen(view->style.background_image) > 0) 34 | { 35 | tg_css_add(view); 36 | } 37 | 38 | if (view->type && strcmp(view->type, "button") == 0) 39 | { 40 | vh_button_add(view, VH_BUTTON_NORMAL, button_event); 41 | } 42 | else if (view->type && strcmp(view->type, "slider") == 0) 43 | { 44 | vh_slider_add(view, slider_event); 45 | } 46 | } 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/kinetic_ui/ku_recorder.c: -------------------------------------------------------------------------------- 1 | #ifndef ku_recorder_h 2 | #define ku_recorder_h 3 | 4 | #include "ku_event.c" 5 | 6 | void ku_recorder_init(void (*update)(ku_event_t)); 7 | void ku_recorder_destroy(); 8 | void ku_recorder_update(ku_event_t ev); 9 | void ku_recorder_record(char* path); 10 | void ku_recorder_replay(char* path); 11 | 12 | #endif 13 | 14 | #if __INCLUDE_LEVEL__ == 0 15 | 16 | #include "mt_vector.c" 17 | #include 18 | 19 | enum ku_recorder_mode_t 20 | { 21 | KU_REC_MODE_NORMAL, 22 | KU_REC_MODE_RECORD, 23 | KU_REC_MODE_REPLAY, 24 | }; 25 | 26 | struct ku_recorder_t 27 | { 28 | size_t index; 29 | FILE* file; 30 | mt_vector_t* eventqueue; 31 | void (*update)(ku_event_t); 32 | enum ku_recorder_mode_t mode; 33 | } kurec; 34 | 35 | void ku_recorder_init(void (*update)(ku_event_t)) 36 | { 37 | kurec.mode = KU_REC_MODE_NORMAL; 38 | kurec.update = update; 39 | kurec.eventqueue = VNEW(); 40 | } 41 | 42 | void ku_recorder_record(char* path) 43 | { 44 | kurec.mode = KU_REC_MODE_RECORD; 45 | FILE* file = fopen(path, "w"); 46 | if (!file) printf("evrec recorder : cannot open file %s\n", path); 47 | kurec.file = file; 48 | } 49 | 50 | void ku_recorder_replay(char* path) 51 | { 52 | kurec.mode = KU_REC_MODE_REPLAY; 53 | FILE* file = fopen(path, "r"); 54 | if (!file) 55 | printf("evrec player : cannot open file %s\n", path); 56 | 57 | kurec.file = file; 58 | 59 | while (1) 60 | { 61 | ku_event_t ev = ku_event_read(file); 62 | VADDR(kurec.eventqueue, HEAP(ev)); 63 | if (feof(file)) 64 | break; 65 | } 66 | 67 | printf("%li events read\n", kurec.eventqueue->length); 68 | } 69 | 70 | void ku_recorder_destroy() 71 | { 72 | if (kurec.file) fclose(kurec.file); 73 | if (kurec.eventqueue) REL(kurec.eventqueue); 74 | } 75 | 76 | void ku_recorder_update_record(ku_event_t ev) 77 | { 78 | /* normalize floats for deterministic movements during record/replay */ 79 | ev.dx = floor(ev.dx * 10000) / 10000; 80 | ev.dy = floor(ev.dy * 10000) / 10000; 81 | ev.ratio = floor(ev.ratio * 10000) / 10000; 82 | ev.time_frame = floor(ev.time_frame * 10000) / 10000; 83 | 84 | if (ev.type == KU_EVENT_FRAME || ev.type == KU_EVENT_TIME || ev.type == KU_EVENT_WINDOW_SHOWN) 85 | { 86 | /* record and send waiting events */ 87 | for (size_t index = 0; index < kurec.eventqueue->length; index++) 88 | { 89 | ku_event_t* event = (ku_event_t*) kurec.eventqueue->data[index]; 90 | event->frame = ev.frame; 91 | 92 | ku_event_write(kurec.file, *event); 93 | 94 | (*kurec.update)(*event); 95 | } 96 | 97 | mt_vector_reset(kurec.eventqueue); 98 | 99 | /* send frame event */ 100 | (*kurec.update)(ev); 101 | } 102 | else 103 | { 104 | /* queue event */ 105 | void* event = HEAP(ev); 106 | VADDR(kurec.eventqueue, event); 107 | } 108 | } 109 | 110 | void ku_recorder_update_replay(ku_event_t ev) 111 | { 112 | if (ev.type == KU_EVENT_FRAME || ev.type == KU_EVENT_WINDOW_SHOWN) 113 | { 114 | while (kurec.index < kurec.eventqueue->length) 115 | { 116 | ku_event_t* event = kurec.eventqueue->data[kurec.index]; 117 | 118 | if (event->frame < ev.frame) 119 | { 120 | kurec.index++; 121 | (*kurec.update)(*event); 122 | } 123 | else break; 124 | } 125 | 126 | (*kurec.update)(ev); 127 | } 128 | } 129 | 130 | void ku_recorder_update(ku_event_t ev) 131 | { 132 | if (kurec.mode == KU_REC_MODE_NORMAL) (*kurec.update)(ev); 133 | else if (kurec.mode == KU_REC_MODE_RECORD) ku_recorder_update_record(ev); 134 | else if (kurec.mode == KU_REC_MODE_REPLAY) ku_recorder_update_replay(ev); 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/kinetic_ui/ku_rect.c: -------------------------------------------------------------------------------- 1 | #ifndef ku_rect_h 2 | #define ku_rect_h 3 | 4 | /* TODO write tests */ 5 | 6 | typedef struct _ku_rect_t ku_rect_t; 7 | struct _ku_rect_t 8 | { 9 | float x; 10 | float y; 11 | float w; 12 | float h; 13 | }; 14 | 15 | int ku_rect_equals(ku_rect_t r1, ku_rect_t r2); 16 | ku_rect_t ku_rect_add(ku_rect_t r1, ku_rect_t r2); 17 | ku_rect_t ku_rect_is(ku_rect_t l, ku_rect_t r); 18 | void ku_rect_describe(ku_rect_t rect); 19 | 20 | #endif 21 | 22 | #if __INCLUDE_LEVEL__ == 0 23 | 24 | #include 25 | 26 | #define VMIN(X, Y) (((X) < (Y)) ? (X) : (Y)) 27 | #define VMAX(X, Y) (((X) > (Y)) ? (X) : (Y)) 28 | 29 | int ku_rect_equals(ku_rect_t r1, ku_rect_t r2) 30 | { 31 | return (r1.x == r2.x && r1.y == r2.y && r1.w == r2.w && r1.h == r2.h); 32 | } 33 | 34 | ku_rect_t ku_rect_add(ku_rect_t r1, ku_rect_t r2) 35 | { 36 | if (r1.w == 0 || r1.h == 0) return r2; 37 | if (r2.w == 0 || r2.h == 0) return r1; 38 | 39 | ku_rect_t res; 40 | 41 | res.x = VMIN(r1.x, r2.x); 42 | res.y = VMIN(r1.y, r2.y); 43 | 44 | float r1cx = r1.x + r1.w; 45 | float r1cy = r1.y + r1.h; 46 | float r2cx = r2.x + r2.w; 47 | float r2cy = r2.y + r2.h; 48 | 49 | res.w = r1cx < r2cx ? (r2cx - res.x) : (r1cx - res.x); 50 | res.h = r1cy < r2cy ? (r2cy - res.y) : (r1cy - res.y); 51 | 52 | return res; 53 | } 54 | 55 | ku_rect_t ku_rect_is(ku_rect_t l, ku_rect_t r) 56 | { 57 | ku_rect_t f = {0}; 58 | if (!(l.x + l.w < r.x || r.x + r.w < l.x || l.y + l.h < r.y || r.y + r.h < l.y)) 59 | { 60 | f.x = VMAX(l.x, r.x); 61 | f.y = VMAX(l.y, r.y); 62 | f.w = VMIN(r.x + r.w - f.x, l.x + l.w - f.x); 63 | f.h = VMIN(r.y + r.h - f.y, l.y + l.h - f.y); 64 | } 65 | 66 | return f; 67 | } 68 | 69 | void ku_rect_describe(ku_rect_t rect) 70 | { 71 | printf("%f %f %f %f\n", rect.x, rect.y, rect.w, rect.h); 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/kinetic_ui/ku_renderer_soft.c: -------------------------------------------------------------------------------- 1 | #ifndef ku_renderer_software_h 2 | #define ku_renderer_software_h 3 | 4 | #include "ku_bitmap.c" 5 | #include "ku_rect.c" 6 | #include "mt_vector.c" 7 | 8 | void ku_renderer_software_render(mt_vector_t* views, ku_bitmap_t* bitmap, ku_rect_t dirty); 9 | void ku_renderer_soft_screenshot(ku_bitmap_t* bitmap, char* path); 10 | 11 | #endif 12 | 13 | #if __INCLUDE_LEVEL__ == 0 14 | 15 | #include "ku_png.c" 16 | #include "ku_view.c" 17 | #include "mt_time.c" 18 | 19 | void ku_renderer_software_render(mt_vector_t* views, ku_bitmap_t* bitmap, ku_rect_t dirty) 20 | { 21 | /* cut out dirty rect */ 22 | 23 | /* ku_bitmap_cut(&mmfm.window->bitmap, (int) sum.x, (int) sum.y, (int) sum.w, (int) sum.h); */ 24 | 25 | /* draw dirty rect for debugging */ 26 | 27 | /* ku_bitmap_blend_rect(bitmap, (int) dirty.x, (int) dirty.y, (int) dirty.w, (int) dirty.h, 0x55FF0000); */ 28 | /* ku_wayland_draw_window(mmfm.window, 0, 0, mmfm.window->width, mmfm.window->height); */ 29 | 30 | /* we need to keep nested masks in mind */ 31 | 32 | static ku_rect_t masks[32] = {0}; 33 | static int maski = 0; 34 | 35 | masks[0] = dirty; 36 | 37 | /* draw views into bitmap */ 38 | 39 | for (size_t i = 0; i < views->length; i++) 40 | { 41 | ku_view_t* view = views->data[i]; 42 | 43 | if (view->style.masked) 44 | { 45 | dirty = ku_rect_is(masks[maski], view->frame.global); 46 | maski++; 47 | masks[maski] = dirty; 48 | /* printf("%s masked, dirty %f %f %f %f\n", view->id, dirty.x, dirty.y, dirty.w, dirty.h); */ 49 | } 50 | 51 | if (view->texture.bitmap) 52 | { 53 | ku_rect_t rect = view->frame.global; 54 | 55 | bmr_t dstmsk = ku_bitmap_is( 56 | (bmr_t){(int) dirty.x, (int) dirty.y, (int) (dirty.x + dirty.w), (int) (dirty.y + dirty.h)}, 57 | (bmr_t){0, 0, bitmap->w, bitmap->h}); 58 | 59 | bmr_t srcmsk = {0, 0, view->texture.bitmap->w, view->texture.bitmap->h}; 60 | 61 | /* if there is a region to draw, modify source mask */ 62 | 63 | if (view->frame.region.w > -1 && view->frame.region.h > -1) 64 | { 65 | srcmsk.x += view->frame.region.x; 66 | srcmsk.y += view->frame.region.y; 67 | srcmsk.z = srcmsk.x + view->frame.region.w; 68 | srcmsk.w = srcmsk.y + view->frame.region.h; 69 | } 70 | 71 | /* draw with shadow blur outlets in mind */ 72 | 73 | if (view->texture.transparent == 0 || i == 0) 74 | { 75 | ku_bitmap_insert( 76 | bitmap, 77 | dstmsk, 78 | view->texture.bitmap, 79 | srcmsk, 80 | rect.x - view->style.shadow_blur, 81 | rect.y - view->style.shadow_blur); 82 | } 83 | else 84 | { 85 | if (view->texture.alpha == 1.0) 86 | { 87 | ku_bitmap_blend( 88 | bitmap, 89 | dstmsk, 90 | view->texture.bitmap, 91 | srcmsk, 92 | rect.x - view->style.shadow_blur, 93 | rect.y - view->style.shadow_blur); 94 | } 95 | else 96 | { 97 | ku_bitmap_blend_with_alpha( 98 | bitmap, 99 | dstmsk, 100 | view->texture.bitmap, 101 | srcmsk, 102 | rect.x - view->style.shadow_blur, 103 | rect.y - view->style.shadow_blur, 104 | (255 - (int) (view->texture.alpha * 255.0))); 105 | } 106 | } 107 | } 108 | 109 | if (view->style.unmask) 110 | { 111 | maski--; 112 | dirty = masks[maski]; 113 | } 114 | } 115 | } 116 | 117 | void ku_renderer_soft_screenshot(ku_bitmap_t* bitmap, char* path) 118 | { 119 | ku_png_write(path, bitmap); 120 | } 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /src/kinetic_ui/texture/tg_css.c: -------------------------------------------------------------------------------- 1 | /* 2 | CSS texture generator 3 | Generates texture based on css style 4 | */ 5 | 6 | #ifndef texgen_css_h 7 | #define texgen_css_h 8 | 9 | #include "ku_bitmap.c" 10 | #include "ku_view.c" 11 | 12 | typedef struct _tg_css_t 13 | { 14 | char* id; 15 | char* path; 16 | ku_bitmap_t* bitmap; 17 | } tg_bitmap_t; 18 | 19 | void tg_css_add(ku_view_t* view); 20 | 21 | #endif 22 | 23 | #if __INCLUDE_LEVEL__ == 0 24 | 25 | #include "ku_draw.c" 26 | #include "ku_png.c" 27 | #include "mt_log.c" 28 | #include "mt_string.c" 29 | 30 | int tg_css_gen(ku_view_t* view) 31 | { 32 | if (view->frame.local.w >= 1.0 && 33 | view->frame.local.h >= 1.0) 34 | { 35 | if (strlen(view->style.background_image) > 0) 36 | { 37 | ku_bitmap_t* bm = view->texture.bitmap; 38 | 39 | if (bm == NULL || 40 | bm->w != (int) view->frame.local.w || 41 | bm->h != (int) view->frame.local.h) 42 | { 43 | bm = ku_bitmap_new((int) view->frame.local.w, (int) view->frame.local.h); // REL 0 44 | ku_view_set_texture_bmp(view, bm); 45 | REL(bm); 46 | } 47 | 48 | ku_png_load_into(view->style.background_image, bm); 49 | 50 | view->texture.transparent = 1; 51 | view->texture.changed = 0; 52 | view->texture.ready = 1; 53 | } 54 | else if (view->style.background_color) 55 | { 56 | uint32_t color = view->style.background_color; 57 | 58 | if ((color & 0xFF) < 0xFF || view->style.shadow_blur > 0 || view->style.border_radius > 0 || view->style.border_color > 0) 59 | view->texture.transparent = 1; 60 | else 61 | view->texture.transparent = 0; 62 | 63 | float w = view->frame.local.w + 2 * view->style.shadow_blur; 64 | float h = view->frame.local.h + 2 * view->style.shadow_blur; 65 | 66 | ku_bitmap_t* bm = view->texture.bitmap; 67 | 68 | if (bm == NULL || 69 | bm->w != (int) w || 70 | bm->h != (int) h) 71 | { 72 | bm = ku_bitmap_new((int) w, (int) h); // REL 0 73 | ku_view_set_texture_bmp(view, bm); 74 | REL(bm); 75 | } 76 | 77 | ku_bitmap_reset(bm); 78 | 79 | if (color > 0) 80 | ku_draw_rounded_rect(bm, 0, 0, w, h, view->style.border_radius, view->style.shadow_blur, color, view->style.shadow_color); 81 | 82 | if (view->style.border_width > 0) 83 | { 84 | ku_draw_border( 85 | bm, 86 | 0 + view->style.shadow_blur, 87 | 0 + view->style.shadow_blur, 88 | w - 2 * view->style.shadow_blur, 89 | h - 2 * view->style.shadow_blur, 90 | view->style.border_radius, 91 | view->style.border_width, 92 | view->style.border_color); 93 | } 94 | 95 | view->texture.changed = 1; 96 | view->texture.ready = 1; 97 | } 98 | } 99 | 100 | return 1; 101 | } 102 | 103 | void tg_css_add(ku_view_t* view) 104 | { 105 | if (view->tex_gen != NULL) 106 | mt_log_debug("Text generator already exist for view, cannot create a new one : %s", view->id); 107 | else 108 | { 109 | view->tex_gen = tg_css_gen; 110 | } 111 | } 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /src/kinetic_ui/texture/tg_knob.c: -------------------------------------------------------------------------------- 1 | 2 | #ifndef texgen_knob_h 3 | #define texgen_knob_h 4 | 5 | #include "ku_view.c" 6 | 7 | typedef struct _tg_knob_t 8 | { 9 | float angle; 10 | ku_bitmap_t* back; 11 | ku_bitmap_t* fore; 12 | } tg_knob_t; 13 | 14 | void tg_knob_add(ku_view_t* view); 15 | void tg_knob_set_angle(ku_view_t* view, float angle); 16 | 17 | #endif 18 | 19 | #if __INCLUDE_LEVEL__ == 0 20 | 21 | #include "ku_draw.c" 22 | 23 | int tg_knob_gen(ku_view_t* view) 24 | { 25 | tg_knob_t* tg = view->tex_gen_data; 26 | 27 | if (view->frame.local.w > 0 && view->frame.local.h > 0) 28 | { 29 | 30 | float dist0 = 5 * view->style.scale; 31 | float dist1 = 27 * view->style.scale; 32 | float dist8 = 28 * view->style.scale; 33 | float dist2 = 31 * view->style.scale; 34 | float dist3 = 35 * view->style.scale; 35 | 36 | if (view->texture.bitmap == NULL && view->frame.local.w > 0 && view->frame.local.h > 0) 37 | { 38 | ku_bitmap_t* bmp = ku_bitmap_new(view->frame.local.w, view->frame.local.h); // REL 0 39 | tg->back = ku_bitmap_new(view->frame.local.w, view->frame.local.h); // REL 1 40 | tg->fore = ku_bitmap_new(view->frame.local.w, view->frame.local.h); // REL 2 41 | 42 | uint32_t basecol = 0x454545FF; 43 | uint32_t outercol = 0x343434FF; 44 | uint32_t centercol = 0x676767FF; 45 | uint32_t shadowcol = 0xABABAB0A; 46 | 47 | /* ku_draw_arc_grad(tg->back, */ 48 | /* (view->frame.local.w - 1.0) / 2.0, */ 49 | /* (view->frame.local.h - 1.0) / 2.0, */ 50 | /* (view->frame.local.w / 2.0) - 3.0, */ 51 | /* (view->frame.local.w / 2.0), */ 52 | /* 0, */ 53 | /* 3.14 * 2, */ 54 | /* 0x00000044, */ 55 | /* 0); */ 56 | 57 | ku_draw_arc_grad(tg->back, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, 0, (view->frame.local.w / 2.0) - dist0, 0, 3.14 * 2, basecol, basecol); 58 | ku_draw_arc_grad(tg->back, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, dist1, dist3, 0, 3.14 * 2, outercol, outercol); 59 | ku_draw_arc_grad(tg->back, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, (view->frame.local.w / 2.0) - dist0, (view->frame.local.w / 2.0) - 2.0, 0, 3.14 * 2, shadowcol, 0x00000000); 60 | 61 | ku_draw_arc_grad(tg->fore, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, dist1, dist2, 0, 3.14 * 2, shadowcol, 0); 62 | ku_draw_arc_grad(tg->fore, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, 0, dist8, 0, 3.14 * 2, centercol, centercol); 63 | ku_view_set_texture_bmp(view, bmp); 64 | 65 | REL(bmp); // REL 0 66 | } 67 | 68 | if (tg->angle < 0) 69 | tg->angle += 6.28; 70 | 71 | ku_draw_insert(view->texture.bitmap, tg->back, 0, 0); 72 | 73 | if (tg->angle > 3.14 * 3 / 2) 74 | { 75 | ku_draw_arc_grad(view->texture.bitmap, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, dist1, dist3, 3.14 * 3 / 2, tg->angle, 0x999999FF, 0x999999FF); 76 | } 77 | else 78 | { 79 | ku_draw_arc_grad(view->texture.bitmap, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, dist1, dist3, 3.14 * 3 / 2, 6.28, 0x999999FF, 0x999999FF); 80 | ku_draw_arc_grad(view->texture.bitmap, (view->frame.local.w - 1.0) / 2.0, (view->frame.local.h - 1.0) / 2.0, dist1, dist3, 0, tg->angle, 0x999999FF, 0x999999FF); 81 | } 82 | 83 | ku_draw_blend_argb(view->texture.bitmap, 0, 0, tg->fore); 84 | view->texture.changed = 1; 85 | view->texture.ready = 1; 86 | } 87 | 88 | return 1; 89 | } 90 | 91 | void tg_knob_del(void* p) 92 | { 93 | tg_knob_t* tg = p; 94 | if (tg->back) REL(tg->back); 95 | if (tg->fore) REL(tg->fore); 96 | } 97 | 98 | void tg_knob_desc(void* p, int level) 99 | { 100 | printf("tg_knob"); 101 | } 102 | 103 | void tg_knob_add(ku_view_t* view) 104 | { 105 | assert(view->tex_gen == NULL); 106 | 107 | tg_knob_t* tg = CAL(sizeof(tg_knob_t), tg_knob_del, tg_knob_desc); 108 | tg->angle = 3 * 3.14 / 2; 109 | 110 | view->tex_gen_data = tg; 111 | view->tex_gen = tg_knob_gen; 112 | } 113 | 114 | void tg_knob_set_angle(ku_view_t* view, float angle) 115 | { 116 | tg_knob_t* tg = view->tex_gen_data; 117 | 118 | tg->angle = angle; 119 | view->texture.ready = 0; // force rerender 120 | } 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /src/kinetic_ui/texture/tg_scaledimg.c: -------------------------------------------------------------------------------- 1 | /* 2 | CSS texture generator 3 | Generates texture based on css style 4 | */ 5 | 6 | #ifndef texgen_scaledimg_h 7 | #define texgen_scaledimg_h 8 | 9 | #include "ku_bitmap.c" 10 | #include "ku_view.c" 11 | 12 | typedef struct _tg_scaledimg_t 13 | { 14 | int w; 15 | int h; 16 | } tg_scaledimg_t; 17 | 18 | void tg_scaledimg_add(ku_view_t* view, int w, int h); 19 | int tg_scaledimg_gen(ku_view_t* view); 20 | void tg_scaledimg_set_content_size(ku_view_t* view, int w, int h); 21 | 22 | #endif 23 | 24 | #if __INCLUDE_LEVEL__ == 0 25 | 26 | #include "ku_draw.c" 27 | #include "mt_string.c" 28 | 29 | int tg_scaledimg_gen(ku_view_t* view) 30 | { 31 | tg_scaledimg_t* gen = view->tex_gen_data; 32 | ku_bitmap_t* bm = view->texture.bitmap; 33 | 34 | /* just resize texture bitmap with the view */ 35 | 36 | if (bm == NULL || 37 | bm->w != (int) gen->w || 38 | bm->h != (int) gen->h) 39 | { 40 | bm = ku_bitmap_new_aligned((int) gen->w, (int) gen->h, 16); // REL 0 41 | 42 | ku_view_set_texture_bmp(view, bm); 43 | 44 | ku_draw_rect(bm, 0, 0, bm->w, bm->h, 0x00000000, 0); 45 | 46 | REL(bm); 47 | } 48 | 49 | view->texture.ready = 1; 50 | 51 | return 1; 52 | } 53 | 54 | void tg_scaledimg_set_content_size(ku_view_t* view, int w, int h) 55 | { 56 | tg_scaledimg_t* gen = view->tex_gen_data; 57 | 58 | gen->w = w; 59 | gen->h = h; 60 | } 61 | 62 | void tg_scaledimg_add(ku_view_t* view, int w, int h) 63 | { 64 | assert(view->tex_gen == NULL); 65 | 66 | tg_scaledimg_t* gen = CAL(sizeof(tg_scaledimg_t), NULL, NULL); 67 | gen->w = w; 68 | gen->h = h; 69 | 70 | view->tex_gen_data = gen; 71 | view->tex_gen = tg_scaledimg_gen; 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/kinetic_ui/texture/tg_text.c: -------------------------------------------------------------------------------- 1 | /* 2 | Text texture generator 3 | Shows text in view 4 | */ 5 | 6 | #ifndef texgen_text_h 7 | #define texgen_text_h 8 | 9 | #include "ku_text.c" 10 | #include "ku_view.c" 11 | 12 | typedef struct _tg_text_t 13 | { 14 | char* text; 15 | float scale; 16 | textstyle_t style; 17 | } tg_text_t; 18 | 19 | void tg_text_add(ku_view_t* view); 20 | void tg_text_set(ku_view_t* view, char* text, textstyle_t style); 21 | void tg_text_set1(ku_view_t* view, char* text); 22 | char* tg_text_get(ku_view_t* view); 23 | void tg_text_set_style(ku_view_t* view, textstyle_t style); 24 | 25 | #endif 26 | 27 | #if __INCLUDE_LEVEL__ == 0 28 | 29 | #include "ku_bitmap.c" 30 | #include "ku_draw.c" 31 | #include "ku_gen_textstyle.c" 32 | #include "mt_string.c" 33 | #include "tg_css.c" 34 | 35 | int tg_text_index = 0; 36 | 37 | int tg_text_gen(ku_view_t* view) 38 | { 39 | tg_text_t* gen = view->tex_gen_data; 40 | if (view->frame.local.w > 0 && view->frame.local.h > 0) 41 | { 42 | if (gen->scale != view->style.scale) 43 | { 44 | float ratio; 45 | if (gen->scale == 0.0) 46 | ratio = view->style.scale; 47 | else 48 | ratio = view->style.scale / gen->scale; 49 | gen->style.size *= ratio; 50 | gen->scale = view->style.scale; 51 | } 52 | 53 | ku_bitmap_t* fontmap = ku_bitmap_new((int) view->frame.local.w, (int) view->frame.local.h); // REL 0 54 | textstyle_t style = gen->style; 55 | 56 | if ((style.textcolor & 0xFF) < 0xFF || (style.backcolor & 0xFF) < 0xFF) 57 | view->texture.transparent = 1; 58 | else 59 | view->texture.transparent = 0; 60 | 61 | if ((gen->text != NULL) && strlen(gen->text) > 0) 62 | { 63 | ku_text_render(gen->text, style, fontmap); 64 | } 65 | else 66 | { 67 | ku_draw_rect(fontmap, 0, 0, fontmap->w, fontmap->h, style.backcolor, 0); 68 | } 69 | 70 | ku_view_set_texture_bmp(view, fontmap); 71 | 72 | REL(fontmap); // REL 0 73 | } 74 | 75 | return 1; 76 | } 77 | 78 | void tg_text_del(void* p) 79 | { 80 | tg_text_t* gen = p; 81 | if (gen->text) REL(gen->text); 82 | } 83 | 84 | void tg_text_desc(void* p, int level) 85 | { 86 | printf("tg_text"); 87 | } 88 | 89 | void tg_text_add(ku_view_t* view) 90 | { 91 | assert(view->tex_gen == NULL); 92 | 93 | tg_text_t* gen = CAL(sizeof(tg_text_t), tg_text_del, tg_text_desc); 94 | 95 | gen->text = NULL; // REL 1 96 | gen->scale = view->style.scale; 97 | gen->style = ku_gen_textstyle_parse(view); 98 | 99 | view->tex_gen_data = gen; 100 | view->tex_gen = tg_text_gen; 101 | } 102 | 103 | void tg_text_set1(ku_view_t* view, char* text) 104 | { 105 | tg_text_t* gen = view->tex_gen_data; 106 | 107 | if (gen->text) REL(gen->text); 108 | if (text) gen->text = mt_string_new_cstring(text); 109 | 110 | view->texture.ready = 0; 111 | } 112 | 113 | void tg_text_set(ku_view_t* view, char* text, textstyle_t style) 114 | { 115 | tg_text_t* gen = view->tex_gen_data; 116 | 117 | if (gen->text) REL(gen->text); 118 | if (text) gen->text = mt_string_new_cstring(text); 119 | 120 | gen->style = style; 121 | gen->style.size *= gen->scale; 122 | 123 | view->texture.ready = 0; 124 | } 125 | 126 | void tg_text_set_style(ku_view_t* view, textstyle_t style) 127 | { 128 | tg_text_t* gen = view->tex_gen_data; 129 | 130 | gen->style = style; 131 | gen->style.size *= gen->scale; 132 | view->texture.ready = 0; 133 | } 134 | 135 | char* tg_text_get(ku_view_t* view) 136 | { 137 | tg_text_t* gen = view->tex_gen_data; 138 | return gen->text; 139 | } 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /src/media_player/clock.c: -------------------------------------------------------------------------------- 1 | #ifndef clock_h 2 | #define clock_h 3 | 4 | #include "libavutil/opt.h" 5 | 6 | typedef struct Clock 7 | { 8 | double pts; /* clock base */ 9 | double pts_drift; /* clock base minus time at which we updated the clock */ 10 | double last_updated; 11 | 12 | double speed; 13 | int serial; /* clock is based on a packet with this serial */ 14 | int paused; 15 | int* queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */ 16 | } Clock; 17 | 18 | void clock_init(Clock* c, int* queue_serial); 19 | double clock_get(Clock* c); 20 | void clock_set(Clock* c, double pts, int serial); 21 | void clock_set_at(Clock* c, double pts, int serial, double time); 22 | void clock_set_speed(Clock* c, double speed); 23 | 24 | #endif 25 | 26 | #if __INCLUDE_LEVEL__ == 0 27 | 28 | #include "libavutil/time.h" 29 | #include "mt_log.c" 30 | 31 | void clock_init(Clock* c, int* queue_serial) 32 | { 33 | c->speed = 1.0; 34 | c->paused = 0; 35 | c->queue_serial = queue_serial; 36 | clock_set(c, NAN, -1); 37 | } 38 | 39 | double clock_get(Clock* c) 40 | { 41 | if (*c->queue_serial != c->serial) return NAN; 42 | 43 | if (c->paused) 44 | { 45 | return c->pts; 46 | } 47 | else 48 | { 49 | double time = av_gettime_relative() / 1000000.0; 50 | return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed); 51 | } 52 | } 53 | 54 | void clock_set(Clock* c, double pts, int serial) 55 | { 56 | double time = av_gettime_relative() / 1000000.0; 57 | clock_set_at(c, pts, serial, time); 58 | } 59 | 60 | void clock_set_at(Clock* c, double pts, int serial, double time) 61 | { 62 | c->pts = pts; 63 | c->last_updated = time; 64 | c->pts_drift = c->pts - time; 65 | c->serial = serial; 66 | 67 | // mt_log_debug("clock set at pts %f last upd %f drift %f", c->pts, c->last_updated, c->pts_drift); 68 | } 69 | 70 | void clock_set_speed(Clock* c, double speed) 71 | { 72 | clock_set(c, clock_get(c), c->serial); 73 | c->speed = speed; 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/mmfm/config.c: -------------------------------------------------------------------------------- 1 | #ifndef config_h 2 | #define config_h 3 | 4 | #include "mt_map.c" 5 | 6 | void config_init(); 7 | void config_destroy(); 8 | void config_read(char* path); 9 | void config_write(char* path); 10 | void config_set(char* key, char* value); 11 | char* config_get(char* key); 12 | int config_get_int(char* key); 13 | int config_get_bool(char* key); 14 | void config_set_bool(char* key, int val); 15 | 16 | #endif 17 | 18 | #if __INCLUDE_LEVEL__ == 0 19 | 20 | #include "filemanager.c" 21 | #include "kvlist.c" 22 | #include "mt_log.c" 23 | #include "mt_path.c" 24 | #include "mt_string.c" 25 | #include 26 | 27 | /* TODO separate permanent and temporary variables, write only permanent vars outs */ 28 | 29 | mt_map_t* confmap; 30 | 31 | void config_init() 32 | { 33 | confmap = MNEW(); // REL 0 34 | } 35 | 36 | void config_destroy() 37 | { 38 | REL(confmap); // REL 0 39 | } 40 | 41 | void config_read(char* path) 42 | { 43 | mt_map_t* data = MNEW(); // REL 0 44 | 45 | kvlist_read(path, data, "id"); 46 | 47 | mt_map_t* cfdb = MGET(data, "config"); 48 | 49 | if (cfdb) 50 | { 51 | mt_vector_t* keys = VNEW(); // REL 1 52 | mt_map_keys(cfdb, keys); 53 | 54 | for (size_t index = 0; index < keys->length; index++) 55 | { 56 | char* key = keys->data[index]; 57 | MPUT(confmap, key, MGET(cfdb, key)); 58 | } 59 | 60 | REL(keys); 61 | } 62 | 63 | REL(data); // REL 0 64 | } 65 | 66 | void config_write(char* path) 67 | { 68 | mt_map_t* data = MNEW(); // REL 0 69 | char* dirpath = mt_path_new_remove_last_component(path); // REL 1 70 | 71 | MPUTR(confmap, "id", mt_string_new_cstring("config")); // put id in config db 72 | MPUT(data, "id", confmap); // put config db in final data with same id 73 | 74 | int error = fm_create(dirpath, 0777); 75 | 76 | if (error == 0) 77 | { 78 | int res = kvlist_write(path, data); 79 | if (res < 0) 80 | mt_log_error("ERROR config_write cannot write config\n"); 81 | else 82 | mt_log_info("config written"); 83 | } 84 | else 85 | mt_log_error("ERROR config_write cannot create config path\n"); 86 | 87 | REL(dirpath); // REL 1 88 | REL(data); // REL 0 89 | } 90 | 91 | void config_set(char* key, char* value) 92 | { 93 | if (value) 94 | { 95 | char* str = mt_string_new_cstring(value); // REL 0 96 | MPUT(confmap, key, str); 97 | REL(str); // REL 0 98 | } 99 | else MDEL(confmap, key); 100 | } 101 | 102 | char* config_get(char* key) 103 | { 104 | return MGET(confmap, key); 105 | } 106 | 107 | int config_get_bool(char* key) 108 | { 109 | char* val = MGET(confmap, key); 110 | if (val && strcmp(val, "true") == 0) 111 | return 1; 112 | else 113 | return 0; 114 | } 115 | 116 | int config_get_int(char* key) 117 | { 118 | char* val = MGET(confmap, key); 119 | if (val) 120 | return atoi(val); 121 | else 122 | return 0; 123 | } 124 | 125 | void config_set_bool(char* key, int val) 126 | { 127 | if (val) 128 | { 129 | MPUTR(confmap, key, mt_string_new_cstring("true")); 130 | } 131 | else 132 | { 133 | MPUTR(confmap, key, mt_string_new_cstring("false")); 134 | } 135 | } 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/mmfm/kvlist.c: -------------------------------------------------------------------------------- 1 | #ifndef kvlist_h 2 | #define kvlist_h 3 | 4 | #include "mt_map.c" 5 | #include 6 | 7 | int kvlist_read(char* libpath, mt_map_t* db, char* keyfield); 8 | int kvlist_write(char* libpath, mt_map_t* db); 9 | 10 | #endif 11 | 12 | #if __INCLUDE_LEVEL__ == 0 13 | 14 | #include "mt_log.c" 15 | #include "mt_string.c" 16 | #include "mt_string_ext.c" 17 | #include 18 | 19 | int kvlist_read(char* libpath, mt_map_t* db, char* keyfield) 20 | { 21 | int retv = -1; 22 | char* dbstr = mt_string_new_file(libpath); // REL 0 23 | 24 | if (dbstr) 25 | { 26 | retv = 0; 27 | 28 | char* token = strtok(dbstr, "\n"); 29 | char* key = NULL; 30 | mt_map_t* map = MNEW(); // REL 1 31 | 32 | while (token) 33 | { 34 | if (key) 35 | { 36 | char* val = mt_string_new_cstring(token); 37 | MPUT(map, key, val); 38 | REL(key); 39 | REL(val); 40 | key = NULL; 41 | } 42 | else 43 | { 44 | if (token[0] == '-') 45 | { 46 | key = MGET(map, keyfield); 47 | MPUT(db, key, map); 48 | REL(map); // REL 1 49 | map = MNEW(); // REL 1 50 | key = NULL; 51 | } 52 | else 53 | key = mt_string_new_cstring(token); 54 | } 55 | token = strtok(NULL, "\n"); 56 | } 57 | 58 | REL(map); // REL 1 59 | REL(dbstr); // REL 0 60 | } 61 | else 62 | mt_log_debug("kvlist_read cannot read file %s", libpath); 63 | 64 | return retv; 65 | } 66 | 67 | int kvlist_write(char* libpath, mt_map_t* db) 68 | { 69 | int retv = -1; 70 | char* path = mt_string_new_format(PATH_MAX + NAME_MAX, "%snew", libpath); // REL 0 71 | FILE* file = fopen(path, "w"); // CLOSE 0 72 | 73 | if (file) 74 | { 75 | retv = 0; 76 | mt_vector_t* vals = VNEW(); // REL 1 77 | mt_map_values(db, vals); 78 | 79 | for (size_t vali = 0; vali < vals->length; vali++) 80 | { 81 | mt_map_t* entry = vals->data[vali]; 82 | mt_vector_t* keys = VNEW(); // REL 2 83 | 84 | mt_map_keys(entry, keys); 85 | 86 | for (size_t keyi = 0; keyi < keys->length; keyi++) 87 | { 88 | char* key = keys->data[keyi]; 89 | char* val = MGET(entry, key); 90 | 91 | if (fprintf(file, "%s\n", key) < 0) retv = -1; 92 | if (fprintf(file, "%s\n", val) < 0) retv = -1; 93 | } 94 | 95 | if (fprintf(file, "-\n") < 0) retv = -1; 96 | 97 | REL(keys); // REL 2 98 | 99 | if (retv < 0) break; 100 | } 101 | 102 | if (fclose(file) == EOF) retv = -1; // CLOSE 0 103 | 104 | REL(vals); // REL 1 105 | 106 | if (retv == 0) 107 | { 108 | if (rename(path, libpath) != 0) retv = -1; 109 | } 110 | else 111 | mt_log_error("ERROR kvlist_write cannot write file"); 112 | } 113 | else 114 | mt_log_error("ERROR kvlist_write cannot open file %s", path); 115 | 116 | REL(path); // REL 0 117 | 118 | return retv; 119 | } 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /src/mmfm/pdf.c: -------------------------------------------------------------------------------- 1 | #ifndef pdf_h 2 | #define pdf_h 3 | 4 | #include "ku_bitmap.c" 5 | 6 | int pdf_count(char* filename); 7 | ku_bitmap_t* pdf_render(char* filename, int page); 8 | 9 | #endif 10 | 11 | #if __INCLUDE_LEVEL__ == 0 12 | 13 | #include "mt_log.c" 14 | #include 15 | 16 | int pdf_count(char* filename) 17 | { 18 | char* input; 19 | float zoom, rotate; 20 | int page_number, page_count; 21 | fz_context* ctx; 22 | fz_document* doc; 23 | 24 | input = filename; 25 | page_number = 0; 26 | zoom = 200.0; 27 | rotate = 0.0; 28 | 29 | /* Create a context to hold the exception stack and various caches. */ 30 | ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); 31 | if (!ctx) mt_log_error("cannot create mupdf context\n"); 32 | 33 | /* Register the default file types to handle. */ 34 | fz_try(ctx) 35 | fz_register_document_handlers(ctx); 36 | fz_catch(ctx) 37 | { 38 | mt_log_error("cannot register document handlers: %s", fz_caught_message(ctx)); 39 | fz_drop_context(ctx); 40 | } 41 | 42 | /* Open the document. */ 43 | fz_try(ctx) 44 | doc = fz_open_document(ctx, input); 45 | fz_catch(ctx) 46 | { 47 | mt_log_error("cannot open document: %s", fz_caught_message(ctx)); 48 | fz_drop_context(ctx); 49 | } 50 | 51 | /* Count the number of pages. */ 52 | fz_try(ctx) 53 | page_count = fz_count_pages(ctx, doc); 54 | fz_catch(ctx) 55 | { 56 | mt_log_error("cannot count number of pages: %s", fz_caught_message(ctx)); 57 | fz_drop_document(ctx, doc); 58 | fz_drop_context(ctx); 59 | } 60 | 61 | return page_count; 62 | } 63 | 64 | ku_bitmap_t* pdf_render(char* filename, int page_number) 65 | { 66 | char* input; 67 | float zoom, rotate; 68 | fz_context* ctx; 69 | fz_document* doc; 70 | fz_pixmap* pix; 71 | fz_matrix ctm; 72 | int x, y; 73 | 74 | input = filename; 75 | zoom = 200.0; 76 | rotate = 0.0; 77 | 78 | /* Create a context to hold the exception stack and various caches. */ 79 | ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); 80 | if (!ctx) mt_log_error("cannot create mupdf context"); 81 | 82 | /* Register the default file types to handle. */ 83 | fz_try(ctx) 84 | fz_register_document_handlers(ctx); 85 | fz_catch(ctx) 86 | { 87 | mt_log_error("cannot register document handlers: %s", fz_caught_message(ctx)); 88 | fz_drop_context(ctx); 89 | } 90 | 91 | /* Open the document. */ 92 | fz_try(ctx) 93 | doc = fz_open_document(ctx, input); 94 | fz_catch(ctx) 95 | { 96 | mt_log_error("cannot open document: %s", fz_caught_message(ctx)); 97 | fz_drop_context(ctx); 98 | } 99 | 100 | /* Compute a transformation matrix for the zoom and rotation desired. */ 101 | /* The default resolution without scaling is 72 dpi. */ 102 | ctm = fz_scale(zoom / 100, zoom / 100); 103 | ctm = fz_pre_rotate(ctm, rotate); 104 | 105 | /* Render page to an RGB pixmap. */ 106 | fz_try(ctx) 107 | pix = fz_new_pixmap_from_page_number(ctx, doc, page_number, ctm, fz_device_rgb(ctx), 0); 108 | fz_catch(ctx) 109 | { 110 | mt_log_error("cannot render page: %s", fz_caught_message(ctx)); 111 | fz_drop_document(ctx, doc); 112 | fz_drop_context(ctx); 113 | } 114 | 115 | ku_bitmap_t* res = ku_bitmap_new(pix->w, pix->h); 116 | uint8_t* data = res->data; 117 | 118 | for (y = 0; y < pix->h; ++y) 119 | { 120 | unsigned char* p = &pix->samples[y * pix->stride]; 121 | for (x = 0; x < pix->w; ++x) 122 | { 123 | data[0] = p[0]; 124 | data[1] = p[1]; 125 | data[2] = p[2]; 126 | data[3] = 255; 127 | data += 4; 128 | p += pix->n; 129 | } 130 | } 131 | 132 | /* Clean up. */ 133 | fz_drop_pixmap(ctx, pix); 134 | fz_drop_document(ctx, doc); 135 | fz_drop_context(ctx); 136 | 137 | return res; 138 | } 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /src/mt_core/mt_channel.c: -------------------------------------------------------------------------------- 1 | /* 2 | One-way non-locking communication channel between threads 3 | If mtch_send returns 0, channel is full, send data again later 4 | If mtch_recv returns 0, channel is empty 5 | */ 6 | 7 | #ifndef mt_channel_h 8 | #define mt_channel_h 9 | 10 | #include "mt_memory.c" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | typedef struct mt_channel_t mt_channel_t; 18 | struct mt_channel_t 19 | { 20 | char* flags; 21 | void** boxes; 22 | 23 | uint32_t size; 24 | uint32_t rpos; // read position 25 | uint32_t wpos; // write position 26 | }; 27 | 28 | mt_channel_t* mt_channel_new(uint32_t size); 29 | void mt_channel_del(void* pointer); 30 | char mt_channel_send(mt_channel_t* ch, void* data); 31 | void* mt_channel_recv(mt_channel_t* ch); 32 | 33 | #endif 34 | 35 | #if __INCLUDE_LEVEL__ == 0 36 | 37 | void mt_channel_del(void* pointer) 38 | { 39 | assert(pointer != NULL); 40 | 41 | mt_channel_t* ch = pointer; 42 | 43 | REL(ch->flags); 44 | REL(ch->boxes); 45 | } 46 | 47 | void mt_channel_describe(void* p, int level) 48 | { 49 | mt_channel_t* ch = p; 50 | printf("mt_channel, size %u read pos %u write pos %u", ch->size, ch->rpos, ch->wpos); 51 | } 52 | 53 | void mt_channel_describe_flags(void* p, int level) 54 | { 55 | printf("mt_channel flags"); 56 | } 57 | 58 | void mt_channel_describe_boxes(void* p, int level) 59 | { 60 | printf("mt_channel boxes"); 61 | } 62 | 63 | mt_channel_t* mt_channel_new(uint32_t size) 64 | { 65 | mt_channel_t* ch = CAL(sizeof(mt_channel_t), mt_channel_del, mt_channel_describe); 66 | 67 | ch->flags = CAL(sizeof(char) * size, NULL, mt_channel_describe_flags); 68 | ch->boxes = CAL(sizeof(void*) * size, NULL, mt_channel_describe_boxes); 69 | ch->size = size; 70 | ch->rpos = 0; 71 | ch->wpos = 0; 72 | 73 | return ch; 74 | } 75 | 76 | char mt_channel_send(mt_channel_t* ch, void* data) 77 | { 78 | assert(ch != NULL); 79 | assert(data != NULL); 80 | 81 | // wait for the box to get empty 82 | 83 | if (ch->flags[ch->wpos] == 0) 84 | { 85 | /* swap these rows to cause a race condition and a failing test */ 86 | ch->boxes[ch->wpos] = data; // first store data 87 | ch->flags[ch->wpos] = 1; // then set flag, it doesn't have to be atomic, only the last bit counts 88 | 89 | ch->wpos += 1; // increment write index, doesn't have to be atomic, this thread uses it only 90 | if (ch->wpos == ch->size) 91 | ch->wpos = 0; 92 | 93 | return 1; 94 | } 95 | 96 | return 0; 97 | } 98 | 99 | void* mt_channel_recv(mt_channel_t* ch) 100 | { 101 | assert(ch != NULL); 102 | 103 | if (ch->flags[ch->rpos] == 1) 104 | { 105 | void* result = ch->boxes[ch->rpos]; 106 | 107 | ch->boxes[ch->rpos] = NULL; // empty box 108 | ch->flags[ch->rpos] = 0; // set flag, it doesn't have to be atomic, only the last bit counts 109 | 110 | ch->rpos += 1; // increment read index, it doesn't have to be atomic, this thread uses it only 111 | 112 | if (ch->rpos == ch->size) 113 | ch->rpos = 0; 114 | 115 | return result; 116 | } 117 | 118 | return NULL; 119 | } 120 | #endif 121 | -------------------------------------------------------------------------------- /src/mt_core/mt_number.c: -------------------------------------------------------------------------------- 1 | #ifndef mt_number_h 2 | #define mt_number_h 3 | 4 | #include 5 | 6 | typedef union 7 | { 8 | float floatv; 9 | int intv; 10 | uint32_t uint32v; 11 | } mt_number_t; 12 | 13 | mt_number_t* mt_number_new_float(float val); 14 | mt_number_t* mt_number_new_int(int val); 15 | mt_number_t* mt_number_new_uint32(uint32_t val); 16 | 17 | #endif 18 | 19 | #if __INCLUDE_LEVEL__ == 0 20 | 21 | #include "mt_memory.c" 22 | 23 | void mt_number_describe(void* p, int level) 24 | { 25 | mt_number_t* num = p; 26 | printf("num %f %i %u", num->floatv, num->intv, num->uint32v); 27 | } 28 | 29 | mt_number_t* mt_number_new_float(float val) 30 | { 31 | mt_number_t* res = CAL(sizeof(mt_number_t), NULL, mt_number_describe); 32 | res->floatv = val; 33 | return res; 34 | } 35 | 36 | mt_number_t* mt_number_new_int(int val) 37 | { 38 | mt_number_t* res = CAL(sizeof(mt_number_t), NULL, mt_number_describe); 39 | res->intv = val; 40 | return res; 41 | } 42 | 43 | mt_number_t* mt_number_new_uint32(uint32_t val) 44 | { 45 | mt_number_t* res = CAL(sizeof(mt_number_t), NULL, mt_number_describe); 46 | res->uint32v = val; 47 | return res; 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/mt_core/mt_time.c: -------------------------------------------------------------------------------- 1 | #ifndef _mt_time_h 2 | #define _mt_time_h 3 | 4 | void mt_time(char* id); 5 | 6 | #endif 7 | 8 | #if __INCLUDE_LEVEL__ == 0 9 | 10 | #include "mt_log.c" 11 | #include 12 | #include 13 | 14 | struct timeval mt_time_stamp; 15 | 16 | void mt_time(char* id) 17 | { 18 | if (id) 19 | { 20 | struct timeval ts; 21 | gettimeofday(&ts, NULL); 22 | mt_log_debug("%s time is %lu us", id, (ts.tv_sec - mt_time_stamp.tv_sec) * 1000000 + ts.tv_usec - mt_time_stamp.tv_usec); 23 | mt_time_stamp = ts; 24 | } 25 | else 26 | { 27 | gettimeofday(&mt_time_stamp, NULL); 28 | } 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/mt_core/mt_wrapper.c: -------------------------------------------------------------------------------- 1 | /* wraps a non-mtmemory managed pointer */ 2 | 3 | #ifndef mt_wrapper_h 4 | #define mt_wrapper_h 5 | 6 | #include 7 | 8 | typedef struct 9 | { 10 | void* data; 11 | } mt_wrapper_t; 12 | 13 | mt_wrapper_t* mt_wrapper_new(void* pointer); 14 | 15 | #endif 16 | 17 | #if __INCLUDE_LEVEL__ == 0 18 | 19 | #include "mt_memory.c" 20 | 21 | mt_wrapper_t* mt_wrapper_new(void* pointer) 22 | { 23 | mt_wrapper_t* res = CAL(sizeof(mt_wrapper_t), NULL, NULL); 24 | res->data = pointer; 25 | return res; 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/mt_core_ext/ku_bitmap_ext.c: -------------------------------------------------------------------------------- 1 | #ifndef bm_util_h 2 | #define bm_util_h 3 | 4 | #include "ku_bitmap.c" 5 | #include 6 | 7 | ku_bitmap_t* bm_new_flip_y(ku_bitmap_t* bm); 8 | void bm_write(ku_bitmap_t* bm, char* path); 9 | 10 | #endif 11 | 12 | #if __INCLUDE_LEVEL__ == 0 13 | 14 | ku_bitmap_t* bm_new_flip_y(ku_bitmap_t* bm) 15 | { 16 | ku_bitmap_t* tmp = ku_bitmap_new(bm->w, bm->h); 17 | for (int y = 0; y < bm->h; y++) 18 | { 19 | int src_y = bm->h - y - 1; 20 | memcpy(tmp->data + y * bm->w * 4, bm->data + src_y * bm->w * 4, bm->w * 4); 21 | } 22 | return tmp; 23 | } 24 | 25 | void bm_write(ku_bitmap_t* bm, char* path) 26 | { 27 | int w = bm->w; 28 | int h = bm->h; 29 | 30 | FILE* f; 31 | unsigned char* img = NULL; 32 | int filesize = 54 + 3 * w * h; // w is your image width, h is image height, both int 33 | 34 | img = (unsigned char*) malloc(3 * w * h); 35 | memset(img, 0, 3 * w * h); 36 | 37 | for (int i = 0; i < w; i++) 38 | { 39 | for (int j = 0; j < h; j++) 40 | { 41 | int index = j * w * 4 + i * 4; 42 | 43 | int x = i; 44 | int y = j; 45 | 46 | int r = bm->data[index]; 47 | int g = bm->data[index + 1]; 48 | int b = bm->data[index + 2]; 49 | 50 | if (r > 255) r = 255; 51 | if (g > 255) g = 255; 52 | if (b > 255) b = 255; 53 | 54 | img[(x + y * w) * 3 + 2] = (unsigned char) (r); 55 | img[(x + y * w) * 3 + 1] = (unsigned char) (g); 56 | img[(x + y * w) * 3 + 0] = (unsigned char) (b); 57 | } 58 | } 59 | 60 | unsigned char bmpfileheader[14] = {'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0}; 61 | unsigned char bmpinfoheader[40] = {40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0}; 62 | unsigned char bmppad[3] = {0, 0, 0}; 63 | 64 | bmpfileheader[2] = (unsigned char) (filesize); 65 | bmpfileheader[3] = (unsigned char) (filesize >> 8); 66 | bmpfileheader[4] = (unsigned char) (filesize >> 16); 67 | bmpfileheader[5] = (unsigned char) (filesize >> 24); 68 | 69 | bmpinfoheader[4] = (unsigned char) (w); 70 | bmpinfoheader[5] = (unsigned char) (w >> 8); 71 | bmpinfoheader[6] = (unsigned char) (w >> 16); 72 | bmpinfoheader[7] = (unsigned char) (w >> 24); 73 | bmpinfoheader[8] = (unsigned char) (h); 74 | bmpinfoheader[9] = (unsigned char) (h >> 8); 75 | bmpinfoheader[10] = (unsigned char) (h >> 16); 76 | bmpinfoheader[11] = (unsigned char) (h >> 24); 77 | 78 | f = fopen(path, "wb"); 79 | fwrite(bmpfileheader, 1, 14, f); 80 | fwrite(bmpinfoheader, 1, 40, f); 81 | for (int i = 0; i < h; i++) 82 | { 83 | fwrite(img + (w * (h - i - 1) * 3), 3, w, f); 84 | fwrite(bmppad, 1, (4 - (w * 3) % 4) % 4, f); 85 | } 86 | 87 | free(img); 88 | fclose(f); 89 | } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /src/mt_core_ext/mt_map_ext.c: -------------------------------------------------------------------------------- 1 | #ifndef mt_maputil_h 2 | #define mt_maputil_h 3 | 4 | #include "mt_map.c" 5 | #include "mt_string.c" 6 | 7 | typedef struct _mpair_t 8 | { 9 | char* key; 10 | char* value; 11 | } mpair_t; 12 | 13 | mt_map_t* mapu_pair(mpair_t pair); 14 | 15 | #endif 16 | 17 | #if __INCLUDE_LEVEL__ == 0 18 | 19 | mt_map_t* mapu_pair(mpair_t pair) 20 | { 21 | mt_map_t* result = MNEW(); 22 | char* str = mt_string_new_cstring(pair.value); // REL 0 23 | MPUT(result, pair.key, str); 24 | REL(str); // REL 0 25 | REL(pair.value); 26 | return result; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/mt_core_test/mt_channel_test.c: -------------------------------------------------------------------------------- 1 | #ifndef mt_channel_test_h 2 | #define mt_channel_test_h 3 | 4 | void mt_channel_test_main(); 5 | 6 | #endif 7 | 8 | #if __INCLUDE_LEVEL__ == 0 9 | 10 | #include "mt_channel.c" 11 | #include "mt_log.c" 12 | #include "mt_map.c" 13 | 14 | #define kChTestThreads 20 15 | #define kChTestMax 60000 16 | 17 | static int success = 1; 18 | 19 | void* send_test(void* chp) 20 | { 21 | mt_channel_t* ch = chp; 22 | uint32_t counter = 0; 23 | while (1) 24 | { 25 | if (success == 0) 26 | break; 27 | 28 | uint32_t* number = CAL(sizeof(uint32_t), NULL, NULL); 29 | *number = counter; 30 | char sent = mt_channel_send(ch, number); 31 | 32 | if (sent == 0) 33 | { 34 | REL(number); 35 | } 36 | else 37 | { 38 | counter += 1; 39 | if (counter == kChTestMax) 40 | break; 41 | } 42 | 43 | // struct timespec time; 44 | // time.tv_sec = 0; 45 | // time.tv_nsec = rand() % 100000; 46 | // nanosleep(&time , (struct timespec *)NULL); 47 | } 48 | 49 | return NULL; 50 | } 51 | 52 | void* recv_test(void* chp) 53 | { 54 | mt_channel_t* ch = chp; 55 | uint32_t last = 0; 56 | while (1) 57 | { 58 | if (success == 0) 59 | break; 60 | 61 | uint32_t* number = mt_channel_recv(ch); 62 | if (number != NULL) 63 | { 64 | if (*number != last) 65 | { 66 | success = 0; 67 | /* printf("index error!!! %u %u %i\n", *number, last, success); */ 68 | break; 69 | } 70 | 71 | REL(number); 72 | last += 1; 73 | 74 | if (last == kChTestMax) 75 | break; 76 | 77 | // struct timespec time; 78 | // time.tv_sec = 0; 79 | // time.tv_nsec = rand() % 100000; 80 | // nanosleep(&time , (struct timespec *)NULL); 81 | } 82 | } 83 | 84 | return NULL; 85 | } 86 | 87 | mt_channel_t** testarray; 88 | 89 | void mt_channel_test_main() 90 | { 91 | mt_log_debug("testing mt_channel"); 92 | 93 | testarray = CAL(sizeof(mt_channel_t) * kChTestThreads, NULL, NULL); 94 | 95 | pthread_t* threads = CAL(sizeof(pthread_t) * kChTestThreads * 2, NULL, NULL); 96 | 97 | uint32_t threadidx = 0; 98 | 99 | for (int index = 0; index < kChTestThreads; index++) 100 | { 101 | testarray[index] = mt_channel_new(100); 102 | pthread_create(&threads[threadidx++], NULL, send_test, testarray[index]); 103 | pthread_create(&threads[threadidx++], NULL, recv_test, testarray[index]); 104 | } 105 | 106 | for (uint32_t index = 0; index < threadidx; index++) 107 | { 108 | pthread_join(threads[index], NULL); 109 | } 110 | 111 | REL(threads); 112 | 113 | assert(success == 1); 114 | } 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /src/mt_core_test/mt_core_test.c: -------------------------------------------------------------------------------- 1 | #include "mt_channel_test.c" 2 | #include "mt_log.c" 3 | #include "mt_map_test.c" 4 | #include "mt_memory_test.c" 5 | #include "mt_path_test.c" 6 | #include "mt_string_test.c" 7 | #include "mt_vector_test.c" 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | mt_log_set_level(MT_LOG_DEBUG); 12 | 13 | mt_memory_test_main(); 14 | mt_vector_test_main(); 15 | mt_map_test_main(); 16 | mt_string_test_main(); 17 | mt_channel_test_main(); 18 | mt_path_test_main(); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /src/mt_core_test/mt_map_test.c: -------------------------------------------------------------------------------- 1 | #ifndef mt_map_test_h 2 | #define mt_map_test_h 3 | 4 | void mt_map_test_main(); 5 | 6 | #endif 7 | 8 | #if __INCLUDE_LEVEL__ == 0 9 | 10 | #include "mt_log.c" 11 | #include "mt_map.c" 12 | 13 | void mt_map_test_main() 14 | { 15 | char* text1 = "Test text 1"; 16 | char* text2 = "Test text 2"; 17 | 18 | char* ttext1 = mt_memory_stack_to_heap(strlen(text1) + 1, NULL, NULL, (char*) text1); 19 | char* ttext2 = mt_memory_stack_to_heap(strlen(text2) + 1, NULL, NULL, (char*) text2); 20 | 21 | /* checking if map is allocated correctly */ 22 | 23 | mt_log_debug("testing mt_map_new"); 24 | 25 | mt_map_t* map1 = mt_map_new(); 26 | 27 | assert(map1 != NULL); 28 | assert(map1->count == 0); 29 | 30 | /* checking if put works correctly */ 31 | 32 | mt_log_debug("testing mt_map_put"); 33 | 34 | mt_map_put(map1, "text1", ttext1); 35 | 36 | char* ctext1 = mt_map_get(map1, "text1"); 37 | 38 | assert(ttext1 == ctext1); 39 | 40 | /* checking if put release working correctly by checking retain counter */ 41 | 42 | mt_log_debug("testing mt_map_put_rel"); 43 | 44 | mt_map_put_rel(map1, "text2", ttext2); 45 | 46 | char* ctext2 = mt_map_get(map1, "text2"); 47 | 48 | assert(ttext2 == ctext2); 49 | assert(mt_memory_retaincount(ttext2) == 1); 50 | 51 | /* checking if map_keys working correctly */ 52 | 53 | mt_log_debug("testing mt_map_keys"); 54 | 55 | mt_vector_t* keys = mt_vector_new(); 56 | 57 | mt_map_keys(map1, keys); 58 | 59 | assert(keys->length == 2); 60 | 61 | for (size_t index = 0; index < keys->length; index++) 62 | { 63 | char* key = keys->data[index]; 64 | 65 | assert(strcmp(key, "text1") == 0 || strcmp(key, "text2") == 0); 66 | } 67 | 68 | REL(keys); 69 | 70 | /* checking if map_values working correctly */ 71 | 72 | mt_log_debug("testing mt_map_values"); 73 | 74 | mt_vector_t* vals = mt_vector_new(); 75 | 76 | mt_map_values(map1, vals); 77 | 78 | assert(vals->length == 2); 79 | 80 | for (size_t index = 0; index < vals->length; index++) 81 | { 82 | char* val = vals->data[index]; 83 | 84 | assert(val == ttext1 || val == ttext2); 85 | } 86 | 87 | REL(vals); 88 | 89 | /* checking if map_del working correctly */ 90 | 91 | mt_log_debug("testing mt_map_del"); 92 | 93 | mt_map_del(map1, "text2"); 94 | 95 | assert(map1->count == 1); 96 | assert(mt_map_get(map1, "text2") == NULL); 97 | 98 | /* checking if map_reset working correctly */ 99 | 100 | mt_log_debug("testing mt_map_reset"); 101 | 102 | mt_map_reset(map1); 103 | 104 | assert(map1->count == 0); 105 | 106 | /* cleanup, run with leak sanitizer on to check for hidden leaks */ 107 | 108 | REL(ttext1); 109 | REL(map1); 110 | } 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /src/mt_core_test/mt_memory_test.c: -------------------------------------------------------------------------------- 1 | #ifndef mt_memory_test_h 2 | #define mt_memory_test_h 3 | 4 | void mt_memory_test_main(); 5 | 6 | #endif 7 | 8 | #if __INCLUDE_LEVEL__ == 0 9 | 10 | #include "mt_log.c" 11 | #include "mt_memory.c" 12 | #include 13 | 14 | void test_alloc() 15 | { 16 | mt_log_debug("testing mt_memory_alloc"); 17 | 18 | char* atext = NULL; 19 | 20 | atext = mt_memory_alloc(sizeof(char) * 80, NULL, NULL); 21 | 22 | assert(atext != NULL); 23 | assert(mt_memory_retaincount(atext) == 1); 24 | 25 | mt_memory_release(atext); 26 | } 27 | 28 | void test_calloc() 29 | { 30 | mt_log_debug("testing mt_memory_calloc"); 31 | 32 | char* ctext = NULL; 33 | 34 | ctext = mt_memory_calloc(sizeof(char) * 80, NULL, NULL); 35 | 36 | assert(ctext != NULL); 37 | assert(mt_memory_retaincount(ctext) == 1); 38 | 39 | mt_memory_release(ctext); 40 | } 41 | 42 | void test_stack_to_heap() 43 | { 44 | mt_log_debug("testing mt_memory_stack_to_heap"); 45 | 46 | char* text = "This is a test string"; 47 | char* ttext = mt_memory_stack_to_heap(strlen(text) + 1, NULL, NULL, (char*) text); 48 | 49 | assert(ttext != NULL); 50 | assert(mt_memory_retaincount(ttext) == 1); 51 | assert(strcmp(ttext, text) == 0); 52 | 53 | mt_memory_release(ttext); 54 | } 55 | 56 | void test_realloc() 57 | { 58 | mt_log_debug("testing mt_memory_realloc"); 59 | 60 | char* text0 = "This is a test string"; 61 | char* text1 = "Another text string"; 62 | char* ttext = mt_memory_calloc(strlen(text0) + 1, NULL, NULL); 63 | memcpy(ttext, text0, strlen(text0)); 64 | 65 | ttext = mt_memory_realloc(ttext, strlen(text0) + strlen(text1) + 1); 66 | memcpy(ttext + strlen(text0), text1, strlen(text1)); 67 | 68 | assert(ttext != NULL); 69 | assert(mt_memory_retaincount(ttext) == 1); 70 | assert(strstr(ttext, text0) != NULL); 71 | assert(strstr(ttext, text1) != NULL); 72 | 73 | mt_memory_release(ttext); 74 | } 75 | 76 | int destruct_count = 1; 77 | 78 | void destruct() 79 | { 80 | destruct_count -= 1; 81 | } 82 | 83 | void test_destructor() 84 | { 85 | mt_log_debug("testing mt_memory descructor"); 86 | 87 | char* atext = NULL; 88 | 89 | atext = mt_memory_alloc(sizeof(char) * 80, destruct, NULL); 90 | 91 | assert(atext != NULL); 92 | assert(mt_memory_retaincount(atext) == 1); 93 | 94 | mt_memory_release(atext); 95 | 96 | assert(destruct_count == 0); 97 | } 98 | 99 | int describe_count = 1; 100 | 101 | void describe() 102 | { 103 | describe_count -= 1; 104 | } 105 | 106 | void test_descriptor() 107 | { 108 | mt_log_debug("testing mt_memory descriptor"); 109 | 110 | char* atext = NULL; 111 | 112 | atext = mt_memory_alloc(sizeof(char) * 80, NULL, describe); 113 | 114 | assert(atext != NULL); 115 | assert(mt_memory_retaincount(atext) == 1); 116 | 117 | mt_memory_describe(atext, 0); 118 | mt_memory_release(atext); 119 | 120 | assert(describe_count == 0); 121 | } 122 | 123 | /* run test with clang leak sanitizer */ 124 | 125 | void mt_memory_test_main() 126 | { 127 | test_alloc(); 128 | test_calloc(); 129 | test_stack_to_heap(); 130 | test_realloc(); 131 | test_destructor(); 132 | test_descriptor(); 133 | } 134 | 135 | #endif 136 | -------------------------------------------------------------------------------- /src/mt_core_test/mt_path_test.c: -------------------------------------------------------------------------------- 1 | #ifndef mt_path_test_h 2 | #define mt_path_test_h 3 | 4 | void mt_path_test_main(); 5 | 6 | #endif 7 | 8 | #if __INCLUDE_LEVEL__ == 0 9 | 10 | #include "mt_log.c" 11 | #include "mt_path.c" 12 | #include 13 | #include 14 | 15 | void mt_path_test_main() 16 | { 17 | /* checking if mt_path_new_format works */ 18 | 19 | mt_log_debug("testing mt_path_new_append"); 20 | 21 | char* path1 = mt_path_new_append("root", "exec/"); 22 | 23 | assert(strcmp(path1, "root/exec/") == 0); 24 | 25 | /* checking if mt_path_new_remove_last_component works */ 26 | 27 | mt_log_debug("testing mt_path_new_remove_last_component"); 28 | 29 | char* path2 = mt_path_new_remove_last_component("/home/milgra/whatever.ext"); 30 | 31 | assert(strcmp(path2, "/home/milgra/") == 0); 32 | 33 | /* checking if mt_path_new_extension works */ 34 | 35 | mt_log_debug("testing mt_path_new_extension"); 36 | 37 | char* path3 = mt_path_new_extension("/home/milgra/whatever.ext"); 38 | 39 | assert(strcmp(path3, "ext") == 0); 40 | 41 | /* checking if mt_path_new_filename works */ 42 | 43 | mt_log_debug("testing mt_path_new_filename"); 44 | 45 | char* path4 = mt_path_new_filename("/home/milgra/whatever.ext"); 46 | 47 | assert(strcmp(path4, "whatever") == 0); 48 | 49 | /* checking if mt_path_new_normalize works */ 50 | 51 | mt_log_debug("testing mt_path_new_normalize"); 52 | 53 | char* path5 = mt_path_new_normalize("//milcsi/../whatever.ext"); 54 | 55 | assert(strcmp(path5, "//whatever.ext")); 56 | 57 | REL(path1); 58 | REL(path2); 59 | REL(path3); 60 | REL(path4); 61 | REL(path5); 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/mt_core_test/mt_string_test.c: -------------------------------------------------------------------------------- 1 | #ifndef mt_string_test_h 2 | #define mt_string_test_h 3 | 4 | void mt_string_test_main(); 5 | 6 | #endif 7 | 8 | #if __INCLUDE_LEVEL__ == 0 9 | 10 | #include "mt_log.c" 11 | #include "mt_string.c" 12 | 13 | void mt_string_test_main() 14 | { 15 | /* char* str = "000 Állítólag svájcban"; */ 16 | 17 | /* checking if mt_string_new_format works */ 18 | 19 | mt_log_debug("testing mt_string_new_format"); 20 | 21 | char* str1 = mt_string_new_format(100, "%s-%i-%x", "milcsi", 100, 64); 22 | 23 | assert(strcmp(str1, "milcsi-100-40") == 0); 24 | 25 | /* checking if mt_string_new_cstring works */ 26 | 27 | mt_log_debug("testing mt_string_new_cstring"); 28 | 29 | char* str2 = mt_string_new_cstring("another cstring"); 30 | 31 | assert(strcmp(str2, "another cstring") == 0); 32 | 33 | /* checking if mt_string_new_substring works */ 34 | 35 | mt_log_debug("testing mt_string_new_substring"); 36 | 37 | char* str3 = mt_string_new_substring("another cstring", 3, 6); 38 | 39 | assert(strcmp(str3, "ther c") == 0); 40 | 41 | /* checking if mt_string_reset works */ 42 | 43 | mt_log_debug("testing mt_string_reset"); 44 | 45 | str1 = mt_string_reset(str1); 46 | 47 | assert(strlen(str1) == 0); 48 | 49 | /* checking if mt_string_append works */ 50 | 51 | mt_log_debug("testing mt_string_append"); 52 | 53 | str1 = mt_string_append(str1, "new string"); 54 | str1 = mt_string_append(str1, "|old string"); 55 | 56 | assert(strcmp(str1, "new string|old string") == 0); 57 | 58 | /* checking if mt_string_append works */ 59 | 60 | mt_log_debug("testing mt_string_append_cp"); 61 | 62 | str1 = mt_string_append_cp(str1, 588); 63 | 64 | assert(strcmp(str1, "new string|old stringɌ") == 0); 65 | 66 | /* checking if mt_string_append_sub works */ 67 | 68 | mt_log_debug("testing mt_string_append_sub"); 69 | 70 | str2 = mt_string_append_sub(str2, "WHAT THE", 2, 3); 71 | 72 | assert(strcmp(str2, "another cstringAT ") == 0); 73 | 74 | /* checking if mt_string_delete_utf_codepoints works */ 75 | 76 | mt_log_debug("testing mt_string_delete_utf_codepoints"); 77 | 78 | str1 = mt_string_delete_utf_codepoints(str1, 4, 18); 79 | 80 | assert(strcmp(str1, "new ") == 0); 81 | 82 | /* checking if mt_string_tokenize works */ 83 | 84 | mt_log_debug("testing mt_string_tokenize"); 85 | 86 | mt_vector_t* vec = mt_string_tokenize("ONE TWO THREE", " "); 87 | 88 | assert(vec->length == 3); 89 | assert(strcmp(vec->data[0], "ONE") == 0); 90 | assert(strcmp(vec->data[1], "TWO") == 0); 91 | assert(strcmp(vec->data[2], "THREE") == 0); 92 | 93 | REL(vec); 94 | REL(str1); 95 | REL(str2); 96 | REL(str3); 97 | } 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/mt_core_test/mt_vector_test.c: -------------------------------------------------------------------------------- 1 | #ifndef mt_vector_test_h 2 | #define mt_vector_test_h 3 | 4 | void mt_vector_test_main(); 5 | 6 | #endif 7 | 8 | #if __INCLUDE_LEVEL__ == 0 9 | 10 | #include "mt_log.c" 11 | #include "mt_vector.c" 12 | 13 | void mt_vector_test_main() 14 | { 15 | char* text1 = "Test text 1"; 16 | char* text2 = "Test text 2"; 17 | char* text3 = "Test text 3"; 18 | char* text4 = "Test text 4"; 19 | 20 | char* ttext1 = mt_memory_stack_to_heap(strlen(text1) + 1, NULL, NULL, (char*) text1); 21 | char* ttext2 = mt_memory_stack_to_heap(strlen(text2) + 1, NULL, NULL, (char*) text2); 22 | char* ttext3 = mt_memory_stack_to_heap(strlen(text3) + 1, NULL, NULL, (char*) text3); 23 | char* ttext4 = mt_memory_stack_to_heap(strlen(text4) + 1, NULL, NULL, (char*) text4); 24 | 25 | /* checking if vector allocated correctly */ 26 | 27 | mt_log_debug("testing mt_vector_new"); 28 | 29 | mt_vector_t* vec1 = mt_vector_new(); 30 | 31 | assert(vec1 != NULL); 32 | assert(vec1->length == 0); 33 | 34 | /* checking if add works correctly */ 35 | 36 | mt_log_debug("testing mt_vector_add"); 37 | 38 | mt_vector_add(vec1, ttext1); 39 | 40 | assert(vec1->length == 1); 41 | assert(vec1->data[0] == ttext1); 42 | 43 | /* checking if add release works correctly */ 44 | 45 | mt_log_debug("testing mt_vector_add_rel"); 46 | 47 | mt_vector_add_rel(vec1, ttext2); 48 | 49 | assert(vec1->length == 2); 50 | assert(vec1->data[1] == ttext2); 51 | assert(mt_memory_retaincount(ttext2) == 1); 52 | 53 | /* checking if insert works correctly */ 54 | 55 | mt_log_debug("testing mt_vector_insert"); 56 | 57 | mt_vector_ins(vec1, ttext3, 1); 58 | 59 | assert(vec1->length == 3); 60 | assert(vec1->data[1] == ttext3); 61 | 62 | /* checking if insert release works correctly */ 63 | 64 | mt_log_debug("testing mt_vector_insert_rel"); 65 | 66 | mt_vector_ins_rel(vec1, ttext4, 2); 67 | 68 | assert(vec1->length == 4); 69 | assert(vec1->data[2] == ttext4); 70 | assert(mt_memory_retaincount(ttext4) == 1); 71 | 72 | RET(ttext4); 73 | 74 | /* checking if remove data works correctly */ 75 | 76 | mt_log_debug("testing mt_vector_rem"); 77 | 78 | mt_vector_rem(vec1, ttext1); 79 | 80 | assert(vec1->length == 3); 81 | assert(vec1->data[0] == ttext3); 82 | 83 | /* checking if remove index works correctly */ 84 | 85 | mt_log_debug("testing mt_vector_rem_index"); 86 | 87 | mt_vector_rem_index(vec1, 1); 88 | 89 | assert(vec1->length == 2); 90 | assert(vec1->data[1] == ttext2); 91 | 92 | /* checking if remove range works correctly */ 93 | 94 | mt_log_debug("testing mt_vector_rem_range"); 95 | 96 | mt_vector_rem_range(vec1, 0, 1); 97 | 98 | assert(vec1->length == 0); 99 | 100 | /* checking add in vector */ 101 | 102 | mt_vector_t* vec2 = mt_vector_new(); 103 | mt_vector_add(vec2, ttext1); 104 | mt_vector_add(vec2, ttext2); 105 | mt_vector_add(vec2, ttext3); 106 | mt_vector_add(vec2, ttext4); 107 | 108 | mt_log_debug("testing mt_vector_add_in_vector"); 109 | 110 | mt_vector_add_in_vector(vec1, vec2); 111 | 112 | assert(vec1->length == 4); 113 | assert(vec1->data[3] == ttext4); 114 | 115 | /* checking remove in vector */ 116 | 117 | mt_log_debug("testing mt_vector_rem_in_vector"); 118 | 119 | mt_vector_rem_in_vector(vec1, vec2); 120 | 121 | assert(vec1->length == 0); 122 | 123 | /* checking head and tail */ 124 | 125 | mt_vector_add(vec1, ttext1); 126 | mt_vector_add(vec1, ttext2); 127 | mt_vector_add(vec1, ttext3); 128 | mt_vector_add(vec1, ttext4); 129 | 130 | mt_log_debug("testing mt_vector_head"); 131 | 132 | assert(mt_vector_head(vec1) == ttext1); 133 | 134 | mt_log_debug("testing mt_vector_tail"); 135 | 136 | assert(mt_vector_tail(vec1) == ttext4); 137 | 138 | /* checking reverse */ 139 | 140 | mt_log_debug("testing mt_vector_reverse"); 141 | 142 | mt_vector_reverse(vec1); 143 | 144 | assert(vec1->length == 4); 145 | assert(vec1->data[0] == ttext4); 146 | assert(vec1->data[3] == ttext1); 147 | 148 | /* checking sort */ 149 | 150 | mt_log_debug("testing mt_vector_sort"); 151 | 152 | mt_vector_sort(vec1, (int (*)(void*, void*)) strcmp); 153 | 154 | assert(vec1->length == 4); 155 | assert(vec1->data[0] == ttext1); 156 | assert(vec1->data[3] == ttext4); 157 | 158 | /* checking index of */ 159 | 160 | assert(mt_vector_index_of_data(vec1, ttext2) == 1); 161 | 162 | REL(vec1); 163 | REL(vec2); 164 | REL(ttext1); 165 | REL(ttext2); 166 | REL(ttext3); 167 | REL(ttext4); 168 | REL(ttext4); 169 | } 170 | 171 | #endif 172 | -------------------------------------------------------------------------------- /src/mt_math/mt_vector_2d.c: -------------------------------------------------------------------------------- 1 | #ifndef mt_vector_2d_h 2 | #define mt_vector_2d_h 3 | 4 | #include 5 | #include 6 | 7 | typedef struct _v2_t v2_t; 8 | struct _v2_t 9 | { 10 | float x, y; 11 | }; 12 | 13 | v2_t v2_init(float x, float y); 14 | v2_t v2_add(v2_t a, v2_t b); 15 | v2_t v2_sub(v2_t a, v2_t b); 16 | v2_t v2_scale(v2_t vector, float ratio); 17 | v2_t v2_resize(v2_t a, float size); 18 | v2_t v2_rotate(v2_t vector, float newangle); 19 | v2_t v2_rotate_90_left(v2_t vector); 20 | v2_t v2_rotate_90_right(v2_t vector); 21 | 22 | v2_t v2_midpoints(v2_t pointa, v2_t pointb); 23 | float v2_length(v2_t a); 24 | float v2_angle_x(v2_t a); 25 | float v2_circular_angle_between(v2_t a, v2_t b); 26 | char v2_equals(v2_t a, v2_t b); 27 | void v2_describe(v2_t vector); 28 | float v2_longside(v2_t a); 29 | 30 | #endif 31 | 32 | #if __INCLUDE_LEVEL__ == 0 33 | 34 | #ifndef M_PI 35 | #define M_PI 3.14159265358979323846 36 | #endif 37 | 38 | /* creates vector2 */ 39 | 40 | v2_t v2_init(float x, float y) 41 | { 42 | v2_t result; 43 | 44 | result.x = x; 45 | result.y = y; 46 | 47 | return result; 48 | } 49 | 50 | /* adds two vectors */ 51 | 52 | v2_t v2_add(v2_t a, v2_t b) 53 | { 54 | v2_t result; 55 | 56 | result.x = a.x + b.x; 57 | result.y = a.y + b.y; 58 | 59 | return result; 60 | } 61 | 62 | /* substracts b from a */ 63 | 64 | v2_t v2_sub(v2_t a, v2_t b) 65 | { 66 | v2_t result; 67 | 68 | result.x = a.x - b.x; 69 | result.y = a.y - b.y; 70 | 71 | return result; 72 | } 73 | 74 | /* multiplies vector with ratio */ 75 | 76 | v2_t v2_scale(v2_t vector, float ratio) 77 | { 78 | v2_t result; 79 | 80 | result.x = vector.x * ratio; 81 | result.y = vector.y * ratio; 82 | 83 | return result; 84 | } 85 | 86 | /* resizes vector */ 87 | 88 | v2_t v2_resize(v2_t a, float size) 89 | { 90 | float length = sqrtf(a.x * a.x + a.y * a.y); 91 | float ratio = size / length; 92 | a.x *= ratio; 93 | a.y *= ratio; 94 | return a; 95 | } 96 | 97 | /* rotates vector with given radians */ 98 | 99 | v2_t v2_rotate(v2_t vector, float newangle) 100 | { 101 | float angle = v2_angle_x(vector); 102 | float length = v2_length(vector); 103 | angle += newangle; 104 | return v2_init(cos(angle) * length, sin(angle) * length); 105 | } 106 | 107 | /* rotates vector to left with 90 degrees */ 108 | 109 | v2_t v2_rotate_90_left(v2_t vector) 110 | { 111 | return v2_init(-vector.y, vector.x); 112 | } 113 | 114 | /* rotates vector to right with 90 degrees */ 115 | 116 | v2_t v2_rotate_90_right(v2_t vector) 117 | { 118 | return v2_init(vector.y, -vector.x); 119 | } 120 | 121 | /* returns middle point */ 122 | 123 | v2_t v2_midpoints(v2_t pointa, v2_t pointb) 124 | { 125 | v2_t pointc = v2_sub(pointb, pointa); 126 | 127 | pointc = v2_scale(pointc, 0.5); 128 | pointc = v2_add(pointa, pointc); 129 | 130 | return pointc; 131 | } 132 | 133 | /* returns vector length */ 134 | 135 | float v2_length(v2_t a) 136 | { 137 | return sqrtf(a.x * a.x + a.y * a.y); 138 | } 139 | 140 | /* returns vector angel on x axis */ 141 | 142 | float v2_angle_x(v2_t a) 143 | { 144 | return atan2(a.y, a.x); 145 | } 146 | 147 | /* returns angle between two vector as a circular CCW angle where angle 0 is 148 | * vector a */ 149 | 150 | float v2_circular_angle_between(v2_t a, v2_t b) 151 | { 152 | float anglea = v2_angle_x(a); 153 | float angleb = v2_angle_x(b); 154 | 155 | float anglere = angleb - anglea; 156 | if (anglere < 0.0) 157 | anglere += 2 * M_PI; 158 | return anglere; 159 | } 160 | 161 | /* compares two vectors */ 162 | 163 | char v2_equals(v2_t a, v2_t b) 164 | { 165 | return a.x == b.x && a.y == b.y; 166 | } 167 | 168 | /* describes vector */ 169 | 170 | void v2_describe(v2_t vector) 171 | { 172 | printf("%f %f ", vector.x, vector.y); 173 | } 174 | 175 | /* returns longer side projected to x */ 176 | 177 | float v2_longside(v2_t a) 178 | { 179 | float x = fabs(a.x); 180 | float y = fabs(a.y); 181 | return x > y ? x : y; 182 | } 183 | 184 | #endif 185 | -------------------------------------------------------------------------------- /src/mt_math/mt_vector_4d.c: -------------------------------------------------------------------------------- 1 | #ifndef mt_vector_4d_h 2 | #define mt_vector_4d_h 3 | 4 | #include "mt_vector_3d.c" 5 | 6 | typedef struct _v4_t v4_t; 7 | struct _v4_t 8 | { 9 | float x, y, z, w; 10 | }; 11 | 12 | v4_t v4_init(float x, float y, float z, float w); 13 | v4_t v4_add(v4_t a, v4_t b); 14 | v4_t v4_sub(v4_t a, v4_t b); 15 | v4_t v4_scale(v4_t a, float f); 16 | void v4_describe(v4_t vector); 17 | 18 | #endif 19 | #if __INCLUDE_LEVEL__ == 0 20 | 21 | #include 22 | 23 | /* creates vector */ 24 | 25 | v4_t v4_init(float x, float y, float z, float w) 26 | { 27 | v4_t result; 28 | 29 | result.x = x; 30 | result.y = y; 31 | result.z = z; 32 | result.w = w; 33 | 34 | return result; 35 | } 36 | 37 | /* adds two vectors */ 38 | 39 | v4_t v4_add(v4_t a, v4_t b) 40 | { 41 | v4_t result; 42 | 43 | result.x = a.x + b.x; 44 | result.y = a.y + b.y; 45 | result.z = a.z + b.z; 46 | result.w = a.w + b.w; 47 | 48 | return result; 49 | } 50 | 51 | /* substract b from a */ 52 | 53 | v4_t v4_sub(v4_t a, v4_t b) 54 | { 55 | v4_t result; 56 | 57 | result.x = a.x - b.x; 58 | result.y = a.y - b.y; 59 | result.z = a.z - b.z; 60 | result.w = a.w - b.w; 61 | 62 | return result; 63 | } 64 | 65 | /* scales vector */ 66 | 67 | v4_t v4_scale(v4_t a, float f) 68 | { 69 | v4_t result; 70 | 71 | result.x = a.x * f; 72 | result.y = a.y * f; 73 | result.z = a.z * f; 74 | result.w = a.w * f; 75 | 76 | return result; 77 | } 78 | 79 | /* describes vector4 */ 80 | 81 | void v4_describe(v4_t vector) 82 | { 83 | printf("x : %f y : %f z : %f w : %f", vector.x, vector.y, vector.z, vector.w); 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/mt_math_test/mt_math_2d_test.c: -------------------------------------------------------------------------------- 1 | #include "mt_log.c" 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | mt_log_set_level(MT_LOG_DEBUG); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /svg/accept.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 29 | 30 | 58 | 61 | 62 | 64 | 65 | 67 | image/svg+xml 68 | 70 | 71 | 72 | 73 | 78 | 82 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /svg/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 29 | 30 | 58 | 61 | 62 | 64 | 65 | 67 | image/svg+xml 68 | 70 | 71 | 72 | 73 | 78 | 88 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /svg/maximize.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 29 | 30 | 58 | 61 | 62 | 64 | 65 | 67 | image/svg+xml 68 | 70 | 71 | 72 | 73 | 78 | 85 | 92 | 100 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /svg/minus.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 49 | 54 | 55 | 57 | 58 | 60 | image/svg+xml 61 | 63 | 64 | 65 | 66 | 90 | 95 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /svg/next.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 29 | 30 | 58 | 61 | 62 | 64 | 65 | 67 | image/svg+xml 68 | 70 | 71 | 72 | 73 | 78 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /svg/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 49 | 52 | 53 | 55 | 56 | 58 | image/svg+xml 59 | 61 | 62 | 63 | 64 | 88 | 93 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /svg/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 49 | 54 | 55 | 57 | 58 | 60 | image/svg+xml 61 | 63 | 64 | 65 | 66 | 73 | 81 | 82 | -------------------------------------------------------------------------------- /svg/prev.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 29 | 30 | 58 | 61 | 62 | 64 | 65 | 67 | image/svg+xml 68 | 70 | 71 | 72 | 73 | 78 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /svg/sidebar.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 38 | 42 | 46 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /svg/terminus.otb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/svg/terminus.otb -------------------------------------------------------------------------------- /svg/up.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 22 | 29 | 30 | 58 | 61 | 62 | 64 | 65 | 67 | image/svg+xml 68 | 70 | 71 | 72 | 73 | 78 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/.emacs hidden invalid file: -------------------------------------------------------------------------------- 1 | ;; load emacs 24's package system. Add MELPA repository. 2 | (when (>= emacs-major-version 24) 3 | (require 'package) 4 | (add-to-list 5 | 'package-archives 6 | ;; '("melpa" . "http://stable.melpa.org/packages/") ; many packages won't show if using stable 7 | '("melpa" . "https://melpa.org/packages/") 8 | t)) 9 | 10 | ;; Added by Package.el. This must come before configurations of 11 | ;; installed packages. Don't delete this line. If you don't want it, 12 | ;; just comment it out by adding a semicolon to the start of the line. 13 | ;; You may delete these explanatory comments. 14 | (package-initialize) 15 | 16 | 17 | (custom-set-variables 18 | ;; custom-set-variables was added by Custom. 19 | ;; If you edit it by hand, you could mess it up, so be careful. 20 | ;; Your init file should contain only one such instance. 21 | ;; If there is more than one, they won't work right. 22 | '(ansi-color-faces-vector 23 | [default default default italic underline success warning error]) 24 | '(ansi-color-names-vector 25 | ["black" "#d55e00" "#009e73" "#f8ec59" "#0072b2" "#cc79a7" "#56b4e9" "white"]) 26 | '(custom-safe-themes 27 | '("7675ffd2f5cb01a7aab53bcdd702fa019b56c764900f2eea0f74ccfc8e854386" "e61752b5a3af12be08e99d076aedadd76052137560b7e684a8be2f8d2958edc3" default)) 28 | '(package-selected-packages 29 | '(simpleclip clang-format+ clang-format magit org neotree paredit rainbow-delimiters cider)) 30 | '(safe-local-variable-values 31 | '((cider-shadow-default-options . "main") 32 | (cider-default-cljs-repl . shadow) 33 | (cider-preferred-build-tool . shadow-cljs) 34 | (cider-clojure-cli-global-options . "-A:dev") 35 | (cider-preferred-build-tool . clojure-cli))) 36 | '(show-paren-mode t)) 37 | 38 | 39 | (custom-set-faces 40 | ;; custom-set-faces was added by Custom. 41 | ;; If you edit it by hand, you could mess it up, so be careful. 42 | ;; Your init file should contain only one such instance. 43 | ;; If there is more than one, they won't work right. 44 | ) 45 | 46 | 47 | (global-hl-line-mode +1) 48 | (menu-bar-mode 0) 49 | (cider-mode) 50 | (toggle-truncate-lines) 51 | 52 | (add-hook 'cider-mode-hook #'eldoc-mode) 53 | 54 | (global-set-key (kbd "C-c 0") 'neotree) 55 | (global-set-key (kbd "") 'other-window) 56 | 57 | (load-theme 'wheatgrass) 58 | (load-file "~/.emacs.d/cljstyle-mode.el") 59 | 60 | ;; (defun add-clj-format-before-save () (interactive) 61 | ;; (add-hook 'before-save-hook 62 | ;; 'cljstyle 63 | ;; t t)) 64 | 65 | ;; (add-hook 'clojure-mode-hook 66 | ;; 'add-clj-format-before-save) 67 | 68 | (add-hook 'prog-mode-hook #'rainbow-delimiters-mode) 69 | ;;(add-hook 'prog-mode-hook #'paredit-mode) 70 | 71 | (put 'erase-buffer 'disabled nil) 72 | 73 | (setq scroll-preserve-screen-position t 74 | scroll-conservatively 0 75 | maximum-scroll-margin 0.5 76 | scroll-margin 99999) 77 | 78 | (setq css-fontify-colors nil) 79 | (setq visible-cursor nil) 80 | 81 | (setq exec-path (append exec-path '("clang-format"))) 82 | 83 | (defun clang-format-save-hook-for-this-buffer () 84 | "Create a buffer local save hook." 85 | (add-hook 'before-save-hook 86 | (lambda () 87 | (progn 88 | (when (locate-dominating-file "." ".clang-format") 89 | (clang-format-buffer) 90 | ) 91 | ;; Continue to save. 92 | nil)) 93 | nil 94 | ;; Buffer local hook. 95 | t)) 96 | 97 | ;; Run this for each mode you want to use the hook. 98 | (add-hook 'c-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 99 | (add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 100 | (add-hook 'glsl-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 101 | 102 | (setq magit-delete-by-moving-to-trash nil) 103 | 104 | (defun x-paste () 105 | "insert text on X11's clipboard to current buffer." 106 | (interactive) 107 | (insert-string (shell-command-to-string "xsel -b"))) 108 | 109 | (defun x-copy () 110 | "copy text on local kill-ring to X11's clipboard." 111 | (interactive) 112 | (copy-region-as-kill (point) (mark t)) 113 | (let ((process-connection-type nil)) 114 | (let ((proc (start-process "xsel" "*Messages*" "xsel" "-i" "-b"))) 115 | (process-send-string proc (car kill-ring)) 116 | (process-send-eof proc)))) 117 | -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/.fehbg executable invalid file: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | feh --no-fehbg --bg-scale 3 | -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/ADELE nocover nometa.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_delete_test/files_master/ADELE nocover nometa.aac -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/MOTHER nocover nometa.opus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_delete_test/files_master/MOTHER nocover nometa.opus -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/folder1/NOINLOVE cover meta.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_delete_test/files_master/folder1/NOINLOVE cover meta.mp3 -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/folder1/szurke patas.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_delete_test/files_master/folder1/szurke patas.odt -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/folder2/PHEV-MY14-5_Maintenance Schedule.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_delete_test/files_master/folder2/PHEV-MY14-5_Maintenance Schedule.pdf -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/folder2/ROYKSOPP nocover nometa.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_delete_test/files_master/folder2/ROYKSOPP nocover nometa.mp4 -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/screenshots/placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_delete_test/files_master/screenshots/placeholder -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/screenshots/screenshot000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_delete_test/files_master/screenshots/screenshot000.png -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/screenshots/screenshot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_delete_test/files_master/screenshots/screenshot001.png -------------------------------------------------------------------------------- /tst/file_delete_test/files_master/screenshots/screenshot002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_delete_test/files_master/screenshots/screenshot002.png -------------------------------------------------------------------------------- /tst/file_info_test/files_master/.emacs hidden invalid file: -------------------------------------------------------------------------------- 1 | ;; load emacs 24's package system. Add MELPA repository. 2 | (when (>= emacs-major-version 24) 3 | (require 'package) 4 | (add-to-list 5 | 'package-archives 6 | ;; '("melpa" . "http://stable.melpa.org/packages/") ; many packages won't show if using stable 7 | '("melpa" . "https://melpa.org/packages/") 8 | t)) 9 | 10 | ;; Added by Package.el. This must come before configurations of 11 | ;; installed packages. Don't delete this line. If you don't want it, 12 | ;; just comment it out by adding a semicolon to the start of the line. 13 | ;; You may delete these explanatory comments. 14 | (package-initialize) 15 | 16 | 17 | (custom-set-variables 18 | ;; custom-set-variables was added by Custom. 19 | ;; If you edit it by hand, you could mess it up, so be careful. 20 | ;; Your init file should contain only one such instance. 21 | ;; If there is more than one, they won't work right. 22 | '(ansi-color-faces-vector 23 | [default default default italic underline success warning error]) 24 | '(ansi-color-names-vector 25 | ["black" "#d55e00" "#009e73" "#f8ec59" "#0072b2" "#cc79a7" "#56b4e9" "white"]) 26 | '(custom-safe-themes 27 | '("7675ffd2f5cb01a7aab53bcdd702fa019b56c764900f2eea0f74ccfc8e854386" "e61752b5a3af12be08e99d076aedadd76052137560b7e684a8be2f8d2958edc3" default)) 28 | '(package-selected-packages 29 | '(simpleclip clang-format+ clang-format magit org neotree paredit rainbow-delimiters cider)) 30 | '(safe-local-variable-values 31 | '((cider-shadow-default-options . "main") 32 | (cider-default-cljs-repl . shadow) 33 | (cider-preferred-build-tool . shadow-cljs) 34 | (cider-clojure-cli-global-options . "-A:dev") 35 | (cider-preferred-build-tool . clojure-cli))) 36 | '(show-paren-mode t)) 37 | 38 | 39 | (custom-set-faces 40 | ;; custom-set-faces was added by Custom. 41 | ;; If you edit it by hand, you could mess it up, so be careful. 42 | ;; Your init file should contain only one such instance. 43 | ;; If there is more than one, they won't work right. 44 | ) 45 | 46 | 47 | (global-hl-line-mode +1) 48 | (menu-bar-mode 0) 49 | (cider-mode) 50 | (toggle-truncate-lines) 51 | 52 | (add-hook 'cider-mode-hook #'eldoc-mode) 53 | 54 | (global-set-key (kbd "C-c 0") 'neotree) 55 | (global-set-key (kbd "") 'other-window) 56 | 57 | (load-theme 'wheatgrass) 58 | (load-file "~/.emacs.d/cljstyle-mode.el") 59 | 60 | ;; (defun add-clj-format-before-save () (interactive) 61 | ;; (add-hook 'before-save-hook 62 | ;; 'cljstyle 63 | ;; t t)) 64 | 65 | ;; (add-hook 'clojure-mode-hook 66 | ;; 'add-clj-format-before-save) 67 | 68 | (add-hook 'prog-mode-hook #'rainbow-delimiters-mode) 69 | ;;(add-hook 'prog-mode-hook #'paredit-mode) 70 | 71 | (put 'erase-buffer 'disabled nil) 72 | 73 | (setq scroll-preserve-screen-position t 74 | scroll-conservatively 0 75 | maximum-scroll-margin 0.5 76 | scroll-margin 99999) 77 | 78 | (setq css-fontify-colors nil) 79 | (setq visible-cursor nil) 80 | 81 | (setq exec-path (append exec-path '("clang-format"))) 82 | 83 | (defun clang-format-save-hook-for-this-buffer () 84 | "Create a buffer local save hook." 85 | (add-hook 'before-save-hook 86 | (lambda () 87 | (progn 88 | (when (locate-dominating-file "." ".clang-format") 89 | (clang-format-buffer) 90 | ) 91 | ;; Continue to save. 92 | nil)) 93 | nil 94 | ;; Buffer local hook. 95 | t)) 96 | 97 | ;; Run this for each mode you want to use the hook. 98 | (add-hook 'c-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 99 | (add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 100 | (add-hook 'glsl-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 101 | 102 | (setq magit-delete-by-moving-to-trash nil) 103 | 104 | (defun x-paste () 105 | "insert text on X11's clipboard to current buffer." 106 | (interactive) 107 | (insert-string (shell-command-to-string "xsel -b"))) 108 | 109 | (defun x-copy () 110 | "copy text on local kill-ring to X11's clipboard." 111 | (interactive) 112 | (copy-region-as-kill (point) (mark t)) 113 | (let ((process-connection-type nil)) 114 | (let ((proc (start-process "xsel" "*Messages*" "xsel" "-i" "-b"))) 115 | (process-send-string proc (car kill-ring)) 116 | (process-send-eof proc)))) 117 | -------------------------------------------------------------------------------- /tst/file_info_test/files_master/.fehbg executable invalid file: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | feh --no-fehbg --bg-scale 3 | -------------------------------------------------------------------------------- /tst/file_info_test/files_master/ADELE nocover nometa.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/ADELE nocover nometa.aac -------------------------------------------------------------------------------- /tst/file_info_test/files_master/MOTHER nocover nometa.opus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/MOTHER nocover nometa.opus -------------------------------------------------------------------------------- /tst/file_info_test/files_master/folder1/Airspeeder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/folder1/Airspeeder.png -------------------------------------------------------------------------------- /tst/file_info_test/files_master/folder1/NOINLOVE cover meta.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/folder1/NOINLOVE cover meta.mp3 -------------------------------------------------------------------------------- /tst/file_info_test/files_master/folder1/szurke patas.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/folder1/szurke patas.odt -------------------------------------------------------------------------------- /tst/file_info_test/files_master/folder2/PHEV-MY14-5_Maintenance Schedule.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/folder2/PHEV-MY14-5_Maintenance Schedule.pdf -------------------------------------------------------------------------------- /tst/file_info_test/files_master/folder2/ROYKSOPP nocover nometa.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/folder2/ROYKSOPP nocover nometa.mp4 -------------------------------------------------------------------------------- /tst/file_info_test/files_master/screenshots/placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/screenshots/placeholder -------------------------------------------------------------------------------- /tst/file_info_test/files_master/screenshots/screenshot000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/screenshots/screenshot000.png -------------------------------------------------------------------------------- /tst/file_info_test/files_master/screenshots/screenshot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/screenshots/screenshot001.png -------------------------------------------------------------------------------- /tst/file_info_test/files_master/screenshots/screenshot002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/screenshots/screenshot002.png -------------------------------------------------------------------------------- /tst/file_info_test/files_master/screenshots/screenshot003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/screenshots/screenshot003.png -------------------------------------------------------------------------------- /tst/file_info_test/files_master/screenshots/screenshot004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_info_test/files_master/screenshots/screenshot004.png -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/.emacs hidden invalid file: -------------------------------------------------------------------------------- 1 | ;; load emacs 24's package system. Add MELPA repository. 2 | (when (>= emacs-major-version 24) 3 | (require 'package) 4 | (add-to-list 5 | 'package-archives 6 | ;; '("melpa" . "http://stable.melpa.org/packages/") ; many packages won't show if using stable 7 | '("melpa" . "https://melpa.org/packages/") 8 | t)) 9 | 10 | ;; Added by Package.el. This must come before configurations of 11 | ;; installed packages. Don't delete this line. If you don't want it, 12 | ;; just comment it out by adding a semicolon to the start of the line. 13 | ;; You may delete these explanatory comments. 14 | (package-initialize) 15 | 16 | 17 | (custom-set-variables 18 | ;; custom-set-variables was added by Custom. 19 | ;; If you edit it by hand, you could mess it up, so be careful. 20 | ;; Your init file should contain only one such instance. 21 | ;; If there is more than one, they won't work right. 22 | '(ansi-color-faces-vector 23 | [default default default italic underline success warning error]) 24 | '(ansi-color-names-vector 25 | ["black" "#d55e00" "#009e73" "#f8ec59" "#0072b2" "#cc79a7" "#56b4e9" "white"]) 26 | '(custom-safe-themes 27 | '("7675ffd2f5cb01a7aab53bcdd702fa019b56c764900f2eea0f74ccfc8e854386" "e61752b5a3af12be08e99d076aedadd76052137560b7e684a8be2f8d2958edc3" default)) 28 | '(package-selected-packages 29 | '(simpleclip clang-format+ clang-format magit org neotree paredit rainbow-delimiters cider)) 30 | '(safe-local-variable-values 31 | '((cider-shadow-default-options . "main") 32 | (cider-default-cljs-repl . shadow) 33 | (cider-preferred-build-tool . shadow-cljs) 34 | (cider-clojure-cli-global-options . "-A:dev") 35 | (cider-preferred-build-tool . clojure-cli))) 36 | '(show-paren-mode t)) 37 | 38 | 39 | (custom-set-faces 40 | ;; custom-set-faces was added by Custom. 41 | ;; If you edit it by hand, you could mess it up, so be careful. 42 | ;; Your init file should contain only one such instance. 43 | ;; If there is more than one, they won't work right. 44 | ) 45 | 46 | 47 | (global-hl-line-mode +1) 48 | (menu-bar-mode 0) 49 | (cider-mode) 50 | (toggle-truncate-lines) 51 | 52 | (add-hook 'cider-mode-hook #'eldoc-mode) 53 | 54 | (global-set-key (kbd "C-c 0") 'neotree) 55 | (global-set-key (kbd "") 'other-window) 56 | 57 | (load-theme 'wheatgrass) 58 | (load-file "~/.emacs.d/cljstyle-mode.el") 59 | 60 | ;; (defun add-clj-format-before-save () (interactive) 61 | ;; (add-hook 'before-save-hook 62 | ;; 'cljstyle 63 | ;; t t)) 64 | 65 | ;; (add-hook 'clojure-mode-hook 66 | ;; 'add-clj-format-before-save) 67 | 68 | (add-hook 'prog-mode-hook #'rainbow-delimiters-mode) 69 | ;;(add-hook 'prog-mode-hook #'paredit-mode) 70 | 71 | (put 'erase-buffer 'disabled nil) 72 | 73 | (setq scroll-preserve-screen-position t 74 | scroll-conservatively 0 75 | maximum-scroll-margin 0.5 76 | scroll-margin 99999) 77 | 78 | (setq css-fontify-colors nil) 79 | (setq visible-cursor nil) 80 | 81 | (setq exec-path (append exec-path '("clang-format"))) 82 | 83 | (defun clang-format-save-hook-for-this-buffer () 84 | "Create a buffer local save hook." 85 | (add-hook 'before-save-hook 86 | (lambda () 87 | (progn 88 | (when (locate-dominating-file "." ".clang-format") 89 | (clang-format-buffer) 90 | ) 91 | ;; Continue to save. 92 | nil)) 93 | nil 94 | ;; Buffer local hook. 95 | t)) 96 | 97 | ;; Run this for each mode you want to use the hook. 98 | (add-hook 'c-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 99 | (add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 100 | (add-hook 'glsl-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 101 | 102 | (setq magit-delete-by-moving-to-trash nil) 103 | 104 | (defun x-paste () 105 | "insert text on X11's clipboard to current buffer." 106 | (interactive) 107 | (insert-string (shell-command-to-string "xsel -b"))) 108 | 109 | (defun x-copy () 110 | "copy text on local kill-ring to X11's clipboard." 111 | (interactive) 112 | (copy-region-as-kill (point) (mark t)) 113 | (let ((process-connection-type nil)) 114 | (let ((proc (start-process "xsel" "*Messages*" "xsel" "-i" "-b"))) 115 | (process-send-string proc (car kill-ring)) 116 | (process-send-eof proc)))) 117 | -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/.fehbg executable invalid file: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | feh --no-fehbg --bg-scale 3 | -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/ADELE nocover nometa.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/ADELE nocover nometa.aac -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/MOTHER nocover nometa.opus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/MOTHER nocover nometa.opus -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/folder1/Airspeeder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/folder1/Airspeeder.png -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/folder1/NOINLOVE cover meta.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/folder1/NOINLOVE cover meta.mp3 -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/folder1/szurke patas.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/folder1/szurke patas.odt -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/folder1/testf/.emacs hidden invalid file: -------------------------------------------------------------------------------- 1 | ;; load emacs 24's package system. Add MELPA repository. 2 | (when (>= emacs-major-version 24) 3 | (require 'package) 4 | (add-to-list 5 | 'package-archives 6 | ;; '("melpa" . "http://stable.melpa.org/packages/") ; many packages won't show if using stable 7 | '("melpa" . "https://melpa.org/packages/") 8 | t)) 9 | 10 | ;; Added by Package.el. This must come before configurations of 11 | ;; installed packages. Don't delete this line. If you don't want it, 12 | ;; just comment it out by adding a semicolon to the start of the line. 13 | ;; You may delete these explanatory comments. 14 | (package-initialize) 15 | 16 | 17 | (custom-set-variables 18 | ;; custom-set-variables was added by Custom. 19 | ;; If you edit it by hand, you could mess it up, so be careful. 20 | ;; Your init file should contain only one such instance. 21 | ;; If there is more than one, they won't work right. 22 | '(ansi-color-faces-vector 23 | [default default default italic underline success warning error]) 24 | '(ansi-color-names-vector 25 | ["black" "#d55e00" "#009e73" "#f8ec59" "#0072b2" "#cc79a7" "#56b4e9" "white"]) 26 | '(custom-safe-themes 27 | '("7675ffd2f5cb01a7aab53bcdd702fa019b56c764900f2eea0f74ccfc8e854386" "e61752b5a3af12be08e99d076aedadd76052137560b7e684a8be2f8d2958edc3" default)) 28 | '(package-selected-packages 29 | '(simpleclip clang-format+ clang-format magit org neotree paredit rainbow-delimiters cider)) 30 | '(safe-local-variable-values 31 | '((cider-shadow-default-options . "main") 32 | (cider-default-cljs-repl . shadow) 33 | (cider-preferred-build-tool . shadow-cljs) 34 | (cider-clojure-cli-global-options . "-A:dev") 35 | (cider-preferred-build-tool . clojure-cli))) 36 | '(show-paren-mode t)) 37 | 38 | 39 | (custom-set-faces 40 | ;; custom-set-faces was added by Custom. 41 | ;; If you edit it by hand, you could mess it up, so be careful. 42 | ;; Your init file should contain only one such instance. 43 | ;; If there is more than one, they won't work right. 44 | ) 45 | 46 | 47 | (global-hl-line-mode +1) 48 | (menu-bar-mode 0) 49 | (cider-mode) 50 | (toggle-truncate-lines) 51 | 52 | (add-hook 'cider-mode-hook #'eldoc-mode) 53 | 54 | (global-set-key (kbd "C-c 0") 'neotree) 55 | (global-set-key (kbd "") 'other-window) 56 | 57 | (load-theme 'wheatgrass) 58 | (load-file "~/.emacs.d/cljstyle-mode.el") 59 | 60 | ;; (defun add-clj-format-before-save () (interactive) 61 | ;; (add-hook 'before-save-hook 62 | ;; 'cljstyle 63 | ;; t t)) 64 | 65 | ;; (add-hook 'clojure-mode-hook 66 | ;; 'add-clj-format-before-save) 67 | 68 | (add-hook 'prog-mode-hook #'rainbow-delimiters-mode) 69 | ;;(add-hook 'prog-mode-hook #'paredit-mode) 70 | 71 | (put 'erase-buffer 'disabled nil) 72 | 73 | (setq scroll-preserve-screen-position t 74 | scroll-conservatively 0 75 | maximum-scroll-margin 0.5 76 | scroll-margin 99999) 77 | 78 | (setq css-fontify-colors nil) 79 | (setq visible-cursor nil) 80 | 81 | (setq exec-path (append exec-path '("clang-format"))) 82 | 83 | (defun clang-format-save-hook-for-this-buffer () 84 | "Create a buffer local save hook." 85 | (add-hook 'before-save-hook 86 | (lambda () 87 | (progn 88 | (when (locate-dominating-file "." ".clang-format") 89 | (clang-format-buffer) 90 | ) 91 | ;; Continue to save. 92 | nil)) 93 | nil 94 | ;; Buffer local hook. 95 | t)) 96 | 97 | ;; Run this for each mode you want to use the hook. 98 | (add-hook 'c-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 99 | (add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 100 | (add-hook 'glsl-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 101 | 102 | (setq magit-delete-by-moving-to-trash nil) 103 | 104 | (defun x-paste () 105 | "insert text on X11's clipboard to current buffer." 106 | (interactive) 107 | (insert-string (shell-command-to-string "xsel -b"))) 108 | 109 | (defun x-copy () 110 | "copy text on local kill-ring to X11's clipboard." 111 | (interactive) 112 | (copy-region-as-kill (point) (mark t)) 113 | (let ((process-connection-type nil)) 114 | (let ((proc (start-process "xsel" "*Messages*" "xsel" "-i" "-b"))) 115 | (process-send-string proc (car kill-ring)) 116 | (process-send-eof proc)))) 117 | -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/folder1/testf/.fehbg executable invalid file: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | feh --no-fehbg --bg-scale 3 | -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/folder2/PHEV-MY14-5_Maintenance Schedule.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/folder2/PHEV-MY14-5_Maintenance Schedule.pdf -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/folder2/ROYKSOPP nocover nometa.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/folder2/ROYKSOPP nocover nometa.mp4 -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/screenshots/placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/screenshots/placeholder -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/screenshots/screenshot000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/screenshots/screenshot000.png -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/screenshots/screenshot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/screenshots/screenshot001.png -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/screenshots/screenshot002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/screenshots/screenshot002.png -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/screenshots/screenshot003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/screenshots/screenshot003.png -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/screenshots/screenshot004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/screenshots/screenshot004.png -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/screenshots/screenshot005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/screenshots/screenshot005.png -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/screenshots/screenshot006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/screenshots/screenshot006.png -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/screenshots/screenshot007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/screenshots/screenshot007.png -------------------------------------------------------------------------------- /tst/file_ops_test/files_master/screenshots/screenshot008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_ops_test/files_master/screenshots/screenshot008.png -------------------------------------------------------------------------------- /tst/file_play_test/files_master/.emacs hidden invalid file: -------------------------------------------------------------------------------- 1 | ;; load emacs 24's package system. Add MELPA repository. 2 | (when (>= emacs-major-version 24) 3 | (require 'package) 4 | (add-to-list 5 | 'package-archives 6 | ;; '("melpa" . "http://stable.melpa.org/packages/") ; many packages won't show if using stable 7 | '("melpa" . "https://melpa.org/packages/") 8 | t)) 9 | 10 | ;; Added by Package.el. This must come before configurations of 11 | ;; installed packages. Don't delete this line. If you don't want it, 12 | ;; just comment it out by adding a semicolon to the start of the line. 13 | ;; You may delete these explanatory comments. 14 | (package-initialize) 15 | 16 | 17 | (custom-set-variables 18 | ;; custom-set-variables was added by Custom. 19 | ;; If you edit it by hand, you could mess it up, so be careful. 20 | ;; Your init file should contain only one such instance. 21 | ;; If there is more than one, they won't work right. 22 | '(ansi-color-faces-vector 23 | [default default default italic underline success warning error]) 24 | '(ansi-color-names-vector 25 | ["black" "#d55e00" "#009e73" "#f8ec59" "#0072b2" "#cc79a7" "#56b4e9" "white"]) 26 | '(custom-safe-themes 27 | '("7675ffd2f5cb01a7aab53bcdd702fa019b56c764900f2eea0f74ccfc8e854386" "e61752b5a3af12be08e99d076aedadd76052137560b7e684a8be2f8d2958edc3" default)) 28 | '(package-selected-packages 29 | '(simpleclip clang-format+ clang-format magit org neotree paredit rainbow-delimiters cider)) 30 | '(safe-local-variable-values 31 | '((cider-shadow-default-options . "main") 32 | (cider-default-cljs-repl . shadow) 33 | (cider-preferred-build-tool . shadow-cljs) 34 | (cider-clojure-cli-global-options . "-A:dev") 35 | (cider-preferred-build-tool . clojure-cli))) 36 | '(show-paren-mode t)) 37 | 38 | 39 | (custom-set-faces 40 | ;; custom-set-faces was added by Custom. 41 | ;; If you edit it by hand, you could mess it up, so be careful. 42 | ;; Your init file should contain only one such instance. 43 | ;; If there is more than one, they won't work right. 44 | ) 45 | 46 | 47 | (global-hl-line-mode +1) 48 | (menu-bar-mode 0) 49 | (cider-mode) 50 | (toggle-truncate-lines) 51 | 52 | (add-hook 'cider-mode-hook #'eldoc-mode) 53 | 54 | (global-set-key (kbd "C-c 0") 'neotree) 55 | (global-set-key (kbd "") 'other-window) 56 | 57 | (load-theme 'wheatgrass) 58 | (load-file "~/.emacs.d/cljstyle-mode.el") 59 | 60 | ;; (defun add-clj-format-before-save () (interactive) 61 | ;; (add-hook 'before-save-hook 62 | ;; 'cljstyle 63 | ;; t t)) 64 | 65 | ;; (add-hook 'clojure-mode-hook 66 | ;; 'add-clj-format-before-save) 67 | 68 | (add-hook 'prog-mode-hook #'rainbow-delimiters-mode) 69 | ;;(add-hook 'prog-mode-hook #'paredit-mode) 70 | 71 | (put 'erase-buffer 'disabled nil) 72 | 73 | (setq scroll-preserve-screen-position t 74 | scroll-conservatively 0 75 | maximum-scroll-margin 0.5 76 | scroll-margin 99999) 77 | 78 | (setq css-fontify-colors nil) 79 | (setq visible-cursor nil) 80 | 81 | (setq exec-path (append exec-path '("clang-format"))) 82 | 83 | (defun clang-format-save-hook-for-this-buffer () 84 | "Create a buffer local save hook." 85 | (add-hook 'before-save-hook 86 | (lambda () 87 | (progn 88 | (when (locate-dominating-file "." ".clang-format") 89 | (clang-format-buffer) 90 | ) 91 | ;; Continue to save. 92 | nil)) 93 | nil 94 | ;; Buffer local hook. 95 | t)) 96 | 97 | ;; Run this for each mode you want to use the hook. 98 | (add-hook 'c-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 99 | (add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 100 | (add-hook 'glsl-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 101 | 102 | (setq magit-delete-by-moving-to-trash nil) 103 | 104 | (defun x-paste () 105 | "insert text on X11's clipboard to current buffer." 106 | (interactive) 107 | (insert-string (shell-command-to-string "xsel -b"))) 108 | 109 | (defun x-copy () 110 | "copy text on local kill-ring to X11's clipboard." 111 | (interactive) 112 | (copy-region-as-kill (point) (mark t)) 113 | (let ((process-connection-type nil)) 114 | (let ((proc (start-process "xsel" "*Messages*" "xsel" "-i" "-b"))) 115 | (process-send-string proc (car kill-ring)) 116 | (process-send-eof proc)))) 117 | -------------------------------------------------------------------------------- /tst/file_play_test/files_master/.fehbg executable invalid file: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | feh --no-fehbg --bg-scale 3 | -------------------------------------------------------------------------------- /tst/file_play_test/files_master/ADELE nocover nometa.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_play_test/files_master/ADELE nocover nometa.aac -------------------------------------------------------------------------------- /tst/file_play_test/files_master/MOTHER nocover nometa.opus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_play_test/files_master/MOTHER nocover nometa.opus -------------------------------------------------------------------------------- /tst/file_play_test/files_master/folder1/Airspeeder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_play_test/files_master/folder1/Airspeeder.png -------------------------------------------------------------------------------- /tst/file_play_test/files_master/folder1/NOINLOVE cover meta.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_play_test/files_master/folder1/NOINLOVE cover meta.mp3 -------------------------------------------------------------------------------- /tst/file_play_test/files_master/folder1/szurke patas.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_play_test/files_master/folder1/szurke patas.odt -------------------------------------------------------------------------------- /tst/file_play_test/files_master/folder2/PHEV-MY14-5_Maintenance Schedule.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_play_test/files_master/folder2/PHEV-MY14-5_Maintenance Schedule.pdf -------------------------------------------------------------------------------- /tst/file_play_test/files_master/folder2/ROYKSOPP nocover nometa.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_play_test/files_master/folder2/ROYKSOPP nocover nometa.mp4 -------------------------------------------------------------------------------- /tst/file_play_test/files_master/screenshots/placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_play_test/files_master/screenshots/placeholder -------------------------------------------------------------------------------- /tst/file_play_test/files_master/screenshots/screenshot000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_play_test/files_master/screenshots/screenshot000.png -------------------------------------------------------------------------------- /tst/file_view_test/files_master/.emacs hidden invalid file: -------------------------------------------------------------------------------- 1 | ;; load emacs 24's package system. Add MELPA repository. 2 | (when (>= emacs-major-version 24) 3 | (require 'package) 4 | (add-to-list 5 | 'package-archives 6 | ;; '("melpa" . "http://stable.melpa.org/packages/") ; many packages won't show if using stable 7 | '("melpa" . "https://melpa.org/packages/") 8 | t)) 9 | 10 | ;; Added by Package.el. This must come before configurations of 11 | ;; installed packages. Don't delete this line. If you don't want it, 12 | ;; just comment it out by adding a semicolon to the start of the line. 13 | ;; You may delete these explanatory comments. 14 | (package-initialize) 15 | 16 | 17 | (custom-set-variables 18 | ;; custom-set-variables was added by Custom. 19 | ;; If you edit it by hand, you could mess it up, so be careful. 20 | ;; Your init file should contain only one such instance. 21 | ;; If there is more than one, they won't work right. 22 | '(ansi-color-faces-vector 23 | [default default default italic underline success warning error]) 24 | '(ansi-color-names-vector 25 | ["black" "#d55e00" "#009e73" "#f8ec59" "#0072b2" "#cc79a7" "#56b4e9" "white"]) 26 | '(custom-safe-themes 27 | '("7675ffd2f5cb01a7aab53bcdd702fa019b56c764900f2eea0f74ccfc8e854386" "e61752b5a3af12be08e99d076aedadd76052137560b7e684a8be2f8d2958edc3" default)) 28 | '(package-selected-packages 29 | '(simpleclip clang-format+ clang-format magit org neotree paredit rainbow-delimiters cider)) 30 | '(safe-local-variable-values 31 | '((cider-shadow-default-options . "main") 32 | (cider-default-cljs-repl . shadow) 33 | (cider-preferred-build-tool . shadow-cljs) 34 | (cider-clojure-cli-global-options . "-A:dev") 35 | (cider-preferred-build-tool . clojure-cli))) 36 | '(show-paren-mode t)) 37 | 38 | 39 | (custom-set-faces 40 | ;; custom-set-faces was added by Custom. 41 | ;; If you edit it by hand, you could mess it up, so be careful. 42 | ;; Your init file should contain only one such instance. 43 | ;; If there is more than one, they won't work right. 44 | ) 45 | 46 | 47 | (global-hl-line-mode +1) 48 | (menu-bar-mode 0) 49 | (cider-mode) 50 | (toggle-truncate-lines) 51 | 52 | (add-hook 'cider-mode-hook #'eldoc-mode) 53 | 54 | (global-set-key (kbd "C-c 0") 'neotree) 55 | (global-set-key (kbd "") 'other-window) 56 | 57 | (load-theme 'wheatgrass) 58 | (load-file "~/.emacs.d/cljstyle-mode.el") 59 | 60 | ;; (defun add-clj-format-before-save () (interactive) 61 | ;; (add-hook 'before-save-hook 62 | ;; 'cljstyle 63 | ;; t t)) 64 | 65 | ;; (add-hook 'clojure-mode-hook 66 | ;; 'add-clj-format-before-save) 67 | 68 | (add-hook 'prog-mode-hook #'rainbow-delimiters-mode) 69 | ;;(add-hook 'prog-mode-hook #'paredit-mode) 70 | 71 | (put 'erase-buffer 'disabled nil) 72 | 73 | (setq scroll-preserve-screen-position t 74 | scroll-conservatively 0 75 | maximum-scroll-margin 0.5 76 | scroll-margin 99999) 77 | 78 | (setq css-fontify-colors nil) 79 | (setq visible-cursor nil) 80 | 81 | (setq exec-path (append exec-path '("clang-format"))) 82 | 83 | (defun clang-format-save-hook-for-this-buffer () 84 | "Create a buffer local save hook." 85 | (add-hook 'before-save-hook 86 | (lambda () 87 | (progn 88 | (when (locate-dominating-file "." ".clang-format") 89 | (clang-format-buffer) 90 | ) 91 | ;; Continue to save. 92 | nil)) 93 | nil 94 | ;; Buffer local hook. 95 | t)) 96 | 97 | ;; Run this for each mode you want to use the hook. 98 | (add-hook 'c-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 99 | (add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 100 | (add-hook 'glsl-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 101 | 102 | (setq magit-delete-by-moving-to-trash nil) 103 | 104 | (defun x-paste () 105 | "insert text on X11's clipboard to current buffer." 106 | (interactive) 107 | (insert-string (shell-command-to-string "xsel -b"))) 108 | 109 | (defun x-copy () 110 | "copy text on local kill-ring to X11's clipboard." 111 | (interactive) 112 | (copy-region-as-kill (point) (mark t)) 113 | (let ((process-connection-type nil)) 114 | (let ((proc (start-process "xsel" "*Messages*" "xsel" "-i" "-b"))) 115 | (process-send-string proc (car kill-ring)) 116 | (process-send-eof proc)))) 117 | -------------------------------------------------------------------------------- /tst/file_view_test/files_master/.fehbg executable invalid file: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | feh --no-fehbg --bg-scale 3 | -------------------------------------------------------------------------------- /tst/file_view_test/files_master/ADELE nocover nometa.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/ADELE nocover nometa.aac -------------------------------------------------------------------------------- /tst/file_view_test/files_master/MOTHER nocover nometa.opus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/MOTHER nocover nometa.opus -------------------------------------------------------------------------------- /tst/file_view_test/files_master/folder1/Airspeeder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/folder1/Airspeeder.png -------------------------------------------------------------------------------- /tst/file_view_test/files_master/folder1/NOINLOVE cover meta.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/folder1/NOINLOVE cover meta.mp3 -------------------------------------------------------------------------------- /tst/file_view_test/files_master/folder1/szurke patas.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/folder1/szurke patas.odt -------------------------------------------------------------------------------- /tst/file_view_test/files_master/folder2/PHEV-MY14-5_Maintenance Schedule.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/folder2/PHEV-MY14-5_Maintenance Schedule.pdf -------------------------------------------------------------------------------- /tst/file_view_test/files_master/folder2/ROYKSOPP nocover nometa.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/folder2/ROYKSOPP nocover nometa.mp4 -------------------------------------------------------------------------------- /tst/file_view_test/files_master/screenshots/placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/screenshots/placeholder -------------------------------------------------------------------------------- /tst/file_view_test/files_master/screenshots/screenshot000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/screenshots/screenshot000.png -------------------------------------------------------------------------------- /tst/file_view_test/files_master/screenshots/screenshot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/screenshots/screenshot001.png -------------------------------------------------------------------------------- /tst/file_view_test/files_master/screenshots/screenshot002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/screenshots/screenshot002.png -------------------------------------------------------------------------------- /tst/file_view_test/files_master/screenshots/screenshot003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/screenshots/screenshot003.png -------------------------------------------------------------------------------- /tst/file_view_test/files_master/screenshots/screenshot004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/screenshots/screenshot004.png -------------------------------------------------------------------------------- /tst/file_view_test/files_master/screenshots/screenshot005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/screenshots/screenshot005.png -------------------------------------------------------------------------------- /tst/file_view_test/files_master/screenshots/screenshot006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/screenshots/screenshot006.png -------------------------------------------------------------------------------- /tst/file_view_test/files_master/screenshots/screenshot007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/screenshots/screenshot007.png -------------------------------------------------------------------------------- /tst/file_view_test/files_master/screenshots/screenshot008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/file_view_test/files_master/screenshots/screenshot008.png -------------------------------------------------------------------------------- /tst/record.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # usage of script : 4 | # record.sh TEST_NAME=generic_test TEST_FOLDER=tst EXECUTABLE=build/mmfm RESOURCES=res FRAME=1200x800 FONT=svg/terminus.otb 5 | 6 | TEST_NAME=generic_test 7 | TEST_FOLDER=tst 8 | EXECUTABLE=build/mmfm 9 | RESOURCES=res 10 | FRAME=1200x800 11 | FONT=svg/terminus.otb 12 | 13 | # parse arguments 14 | 15 | for ARGUMENT in "$@" 16 | do 17 | KEY=$(echo $ARGUMENT | cut -f1 -d=) 18 | KEY_LENGTH=${#KEY} 19 | VALUE="${ARGUMENT:$KEY_LENGTH+1}" 20 | export "$KEY"="$VALUE" 21 | done 22 | 23 | SOURCE_LIB="$TEST_FOLDER/test_files" 24 | TARGET_LIB="$TEST_FOLDER/$TEST_NAME/files_master" 25 | SESSION="$TEST_FOLDER/$TEST_NAME/session.rec" 26 | 27 | rm -rf $TARGET_LIB 28 | mkdir -p "$TEST_FOLDER/$TEST_NAME" 29 | cp -r $SOURCE_LIB $TARGET_LIB 30 | 31 | echo "RECORDING $TEST_NAME" 32 | echo "COMMAND: $EXECUTABLE \ 33 | -v \ 34 | --resources=$RESOURCES \ 35 | --record=$SESSION \ 36 | --directory=$TARGET_LIB \ 37 | --frame=1200x800 \ 38 | --font=$FONT" 39 | 40 | $EXECUTABLE \ 41 | -v \ 42 | --resources=$RESOURCES \ 43 | --record=$SESSION \ 44 | --directory=$TARGET_LIB \ 45 | --frame=1200x800 \ 46 | --font=$FONT 47 | 48 | echo "RECORDING FINISHED" 49 | -------------------------------------------------------------------------------- /tst/replay.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # usage of script : 4 | # replay.sh TEST_NAME=generic_test TEST_FOLDER=tst EXECUTABLE=build/mmfm RESOURCES=res FRAME=1200x800 FONT=svg/terminus.otb 5 | 6 | TEST_NAME=generic_test 7 | TEST_FOLDER=tst 8 | EXECUTABLE=build/mmfm 9 | RESOURCES=res 10 | FRAME=1200x800 11 | FONT=svg/terminus.otb 12 | 13 | # parse arguments 14 | 15 | for ARGUMENT in "$@" 16 | do 17 | KEY=$(echo $ARGUMENT | cut -f1 -d=) 18 | KEY_LENGTH=${#KEY} 19 | VALUE="${ARGUMENT:$KEY_LENGTH+1}" 20 | export "$KEY"="$VALUE" 21 | done 22 | 23 | SOURCE_LIB="$TEST_FOLDER/test_files" 24 | MASTER_LIB="$TEST_FOLDER/$TEST_NAME/files_master" 25 | TARGET_LIB="$TEST_FOLDER/$TEST_NAME/files_test" 26 | SESSION="$TEST_FOLDER/$TEST_NAME/session.rec" 27 | 28 | rm -rf $TARGET_LIB 29 | cp -r $SOURCE_LIB $TARGET_LIB 30 | 31 | echo "REPLAYING $TEST_NAME" 32 | echo "COMMAND: $EXECUTABLE \ 33 | --resources=$RESOURCES \ 34 | --replay=$SESSION \ 35 | --directory=$TARGET_LIB \ 36 | --frame=1200x800 \ 37 | --font=$FONT \ 38 | -v" 39 | 40 | $EXECUTABLE \ 41 | --resources=$RESOURCES \ 42 | --replay=$SESSION \ 43 | --directory=$TARGET_LIB \ 44 | --frame=1200x800 \ 45 | --font=$FONT \ 46 | -v 47 | 48 | echo "REPLAYING FINISHED" 49 | 50 | # remove empty dirs from both directiories to make diff work 51 | 52 | find $MASTER_LIB -empty -type d -delete 53 | find $TARGET_LIB -empty -type d -delete 54 | 55 | diff -r $MASTER_LIB $TARGET_LIB 56 | 57 | error=$? 58 | if [ $error -eq 0 ] 59 | then 60 | echo "No differences found between master and test folders" 61 | exit 0 62 | elif [ $error -eq 1 ] 63 | then 64 | echo "Differences found between master and result folders" 65 | exit 1 66 | else 67 | echo "Differences found between master and result folders" 68 | exit 1 69 | fi 70 | -------------------------------------------------------------------------------- /tst/rerecord.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # usage of script : 4 | # rerecord.sh TEST_NAME=generic_test TEST_FOLDER=tst EXECUTABLE=build/mmfm RESOURCES=res FRAME=1200x800 FONT=svg/terminus.otb 5 | 6 | TEST_NAME=generic_test 7 | TEST_FOLDER=tst 8 | EXECUTABLE=build/mmfm 9 | RESOURCES=res 10 | FRAME=1200x800 11 | FONT=svg/terminus.otb 12 | 13 | # parse arguments 14 | 15 | for ARGUMENT in "$@" 16 | do 17 | KEY=$(echo $ARGUMENT | cut -f1 -d=) 18 | KEY_LENGTH=${#KEY} 19 | VALUE="${ARGUMENT:$KEY_LENGTH+1}" 20 | export "$KEY"="$VALUE" 21 | done 22 | 23 | SOURCE_LIB="$TEST_FOLDER/test_files" 24 | TARGET_LIB="$TEST_FOLDER/$TEST_NAME/files_master" 25 | SESSION="$TEST_FOLDER/$TEST_NAME/session.rec" 26 | 27 | rm -rf $TARGET_LIB 28 | cp -r $SOURCE_LIB $TARGET_LIB 29 | 30 | echo "RECORDING $TEST_NAME" 31 | echo "COMMAND: $EXECUTABLE \ 32 | -v \ 33 | --resources=$RESOURCES \ 34 | --record=$SESSION \ 35 | --directory=$TARGET_LIB \ 36 | --frame=1200x800 \ 37 | --font=$FONT \ 38 | -v" 39 | 40 | $EXECUTABLE \ 41 | --resources=$RESOURCES \ 42 | --replay=$SESSION \ 43 | --directory=$TARGET_LIB \ 44 | --frame=1200x800 \ 45 | --font=$FONT \ 46 | -v 47 | 48 | echo "RECORDING FINISHED" 49 | -------------------------------------------------------------------------------- /tst/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # usage of script : 4 | # ./tst/test_run.sh BUILD_PATH=build PROJECT_ROOT=. 5 | 6 | BUILD_PATH=build 7 | PROJECT_ROOT=. 8 | 9 | # parse arguments 10 | 11 | for ARGUMENT in "$@" 12 | do 13 | KEY=$(echo $ARGUMENT | cut -f1 -d=) 14 | KEY_LENGTH=${#KEY} 15 | VALUE="${ARGUMENT:$KEY_LENGTH+1}" 16 | export "$KEY"="$VALUE" 17 | done 18 | 19 | echo "TEST_RUN BUILD PATH = $BUILD_PATH PROJECT_ROOT = $PROJECT_ROOT" 20 | 21 | EXECUTABLE="$BUILD_PATH/mmfm" 22 | RESOURCES="$PROJECT_ROOT/res" 23 | 24 | for FOLDER in $PROJECT_ROOT/tst/*test; do 25 | echo "tst/replay.sh EXECUTABLE=$EXECUTABLE TST_FOLDER=tst TEST_NAME=$(basename $FOLDER)" 26 | 27 | tst/replay.sh \ 28 | EXECUTABLE=$EXECUTABLE \ 29 | TEST_FOLDER=tst \ 30 | TEST_NAME=$(basename $FOLDER) 31 | 32 | error=$? 33 | if [ $error -eq 0 ] 34 | then 35 | echo "No differences found between master and result images" 36 | elif [ $error -eq 1 ] 37 | then 38 | echo "Differences found between master and result images" 39 | exit 1 40 | else 41 | echo "Differences found between master and result images" 42 | exit 1 43 | fi 44 | 45 | done 46 | 47 | exit 0 48 | -------------------------------------------------------------------------------- /tst/test_files/.emacs hidden invalid file: -------------------------------------------------------------------------------- 1 | ;; load emacs 24's package system. Add MELPA repository. 2 | (when (>= emacs-major-version 24) 3 | (require 'package) 4 | (add-to-list 5 | 'package-archives 6 | ;; '("melpa" . "http://stable.melpa.org/packages/") ; many packages won't show if using stable 7 | '("melpa" . "https://melpa.org/packages/") 8 | t)) 9 | 10 | ;; Added by Package.el. This must come before configurations of 11 | ;; installed packages. Don't delete this line. If you don't want it, 12 | ;; just comment it out by adding a semicolon to the start of the line. 13 | ;; You may delete these explanatory comments. 14 | (package-initialize) 15 | 16 | 17 | (custom-set-variables 18 | ;; custom-set-variables was added by Custom. 19 | ;; If you edit it by hand, you could mess it up, so be careful. 20 | ;; Your init file should contain only one such instance. 21 | ;; If there is more than one, they won't work right. 22 | '(ansi-color-faces-vector 23 | [default default default italic underline success warning error]) 24 | '(ansi-color-names-vector 25 | ["black" "#d55e00" "#009e73" "#f8ec59" "#0072b2" "#cc79a7" "#56b4e9" "white"]) 26 | '(custom-safe-themes 27 | '("7675ffd2f5cb01a7aab53bcdd702fa019b56c764900f2eea0f74ccfc8e854386" "e61752b5a3af12be08e99d076aedadd76052137560b7e684a8be2f8d2958edc3" default)) 28 | '(package-selected-packages 29 | '(simpleclip clang-format+ clang-format magit org neotree paredit rainbow-delimiters cider)) 30 | '(safe-local-variable-values 31 | '((cider-shadow-default-options . "main") 32 | (cider-default-cljs-repl . shadow) 33 | (cider-preferred-build-tool . shadow-cljs) 34 | (cider-clojure-cli-global-options . "-A:dev") 35 | (cider-preferred-build-tool . clojure-cli))) 36 | '(show-paren-mode t)) 37 | 38 | 39 | (custom-set-faces 40 | ;; custom-set-faces was added by Custom. 41 | ;; If you edit it by hand, you could mess it up, so be careful. 42 | ;; Your init file should contain only one such instance. 43 | ;; If there is more than one, they won't work right. 44 | ) 45 | 46 | 47 | (global-hl-line-mode +1) 48 | (menu-bar-mode 0) 49 | (cider-mode) 50 | (toggle-truncate-lines) 51 | 52 | (add-hook 'cider-mode-hook #'eldoc-mode) 53 | 54 | (global-set-key (kbd "C-c 0") 'neotree) 55 | (global-set-key (kbd "") 'other-window) 56 | 57 | (load-theme 'wheatgrass) 58 | (load-file "~/.emacs.d/cljstyle-mode.el") 59 | 60 | ;; (defun add-clj-format-before-save () (interactive) 61 | ;; (add-hook 'before-save-hook 62 | ;; 'cljstyle 63 | ;; t t)) 64 | 65 | ;; (add-hook 'clojure-mode-hook 66 | ;; 'add-clj-format-before-save) 67 | 68 | (add-hook 'prog-mode-hook #'rainbow-delimiters-mode) 69 | ;;(add-hook 'prog-mode-hook #'paredit-mode) 70 | 71 | (put 'erase-buffer 'disabled nil) 72 | 73 | (setq scroll-preserve-screen-position t 74 | scroll-conservatively 0 75 | maximum-scroll-margin 0.5 76 | scroll-margin 99999) 77 | 78 | (setq css-fontify-colors nil) 79 | (setq visible-cursor nil) 80 | 81 | (setq exec-path (append exec-path '("clang-format"))) 82 | 83 | (defun clang-format-save-hook-for-this-buffer () 84 | "Create a buffer local save hook." 85 | (add-hook 'before-save-hook 86 | (lambda () 87 | (progn 88 | (when (locate-dominating-file "." ".clang-format") 89 | (clang-format-buffer) 90 | ) 91 | ;; Continue to save. 92 | nil)) 93 | nil 94 | ;; Buffer local hook. 95 | t)) 96 | 97 | ;; Run this for each mode you want to use the hook. 98 | (add-hook 'c-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 99 | (add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 100 | (add-hook 'glsl-mode-hook (lambda () (clang-format-save-hook-for-this-buffer))) 101 | 102 | (setq magit-delete-by-moving-to-trash nil) 103 | 104 | (defun x-paste () 105 | "insert text on X11's clipboard to current buffer." 106 | (interactive) 107 | (insert-string (shell-command-to-string "xsel -b"))) 108 | 109 | (defun x-copy () 110 | "copy text on local kill-ring to X11's clipboard." 111 | (interactive) 112 | (copy-region-as-kill (point) (mark t)) 113 | (let ((process-connection-type nil)) 114 | (let ((proc (start-process "xsel" "*Messages*" "xsel" "-i" "-b"))) 115 | (process-send-string proc (car kill-ring)) 116 | (process-send-eof proc)))) 117 | -------------------------------------------------------------------------------- /tst/test_files/.fehbg executable invalid file: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | feh --no-fehbg --bg-scale 3 | -------------------------------------------------------------------------------- /tst/test_files/ADELE nocover nometa.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/test_files/ADELE nocover nometa.aac -------------------------------------------------------------------------------- /tst/test_files/MOTHER nocover nometa.opus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/test_files/MOTHER nocover nometa.opus -------------------------------------------------------------------------------- /tst/test_files/folder1/Airspeeder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/test_files/folder1/Airspeeder.png -------------------------------------------------------------------------------- /tst/test_files/folder1/NOINLOVE cover meta.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/test_files/folder1/NOINLOVE cover meta.mp3 -------------------------------------------------------------------------------- /tst/test_files/folder1/szurke patas.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/test_files/folder1/szurke patas.odt -------------------------------------------------------------------------------- /tst/test_files/folder2/PHEV-MY14-5_Maintenance Schedule.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/test_files/folder2/PHEV-MY14-5_Maintenance Schedule.pdf -------------------------------------------------------------------------------- /tst/test_files/folder2/ROYKSOPP nocover nometa.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/test_files/folder2/ROYKSOPP nocover nometa.mp4 -------------------------------------------------------------------------------- /tst/test_files/screenshots/placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milgra/mmfm/75e7131a92e9f1bf8286718bd2cc0f20ae5be27b/tst/test_files/screenshots/placeholder --------------------------------------------------------------------------------