LINUX.ORG.RU

Избранные сообщения LINUX-ORG-RU

Создание экосистемы свободного ПО для процессоров «Эльбрус»

Новости — Open Source
Группа Open Source

В ТАСС состоится пресс-конференция, посвященная развитию экосистемы свободно-распространяемого ПО для платформы «Эльбрус».

( читать дальше... )

>>> Подробности

 

monk
()

Не могу подписаться на тред

Форум — Linux-org-ru

Нажатие на «глаз» открывает ссылку www.linux.org.ru/# и не подписывает на тред. Пробовал отключать js, но ничего не поменялось. Когда-то работало

 , ,

mittorn
()

Lua Base64

Форум — Development

Наговнокодил вот, может кому пригодится, работает под

  • LuaJit
  • Lua5.1 с дополнительным внешним модулем bit32
  • Lua5.2
  • Lua5.3
  • Lua5.4

Пример:

local base64 = require("base64")
local base = base64.encode("Hello World!")
local text = base64.decode("SGVsbG8gV29ybGQh")
print(base,text)

Свой алфавит кодирования

local base64 = require("base64")

local basename = 'mybase64'
local alphabet = 'ABCDEFGcdefghijHIJKLMN0123456789*?abkOPQRSTUVWXYZlmnopqrstuvwxyz'
local endcode  = '@'

assert(base64.register(basename,alphabet,endcode))
local base = base64.encode("Hello World!","mybase64")
local text = base64.decode("KGNV5Gw*Nqxm5GI?","mybase64")
print(base,text)

Днищекод:

Вроде правильно работает.
Всякую фигню принимал в base64 из сети, вроде норм.
Досвиданья

Перемещено leave из talks

 ,

LINUX-ORG-RU
()

Как создать еще одну кодосекцию в ELF?

Форум — Development

Каким образом можно создать еще одну секцию кода в эльф файле , на Си ? На Асме оно понятно как, т.е.

.code
...
.code1
..

а как здесь? Или невозможно?

 , ,

zer0cat
()

Свистопердулька для вашего ПеКа

Форум — Talks

Ой всё! Устал, надоело пока, ничего не работает! Наверное заброшу но буду пытаться!, поэтому вываливаю как есть.
Работает кое-как только под Cinnamon и конечно X11

Валва она же Wallwa это дура на Lua которая позволяет запускать окошечки в режиме «обоев», это скрипт использующий другие программы для свое работы, может жрать ссылки, видеофайлы, картинки и прочее что умеет жрать mpv и показывать как живые обои, запускать просто программы и программы в прозрачном терминале. После запуска приложения хранит их состояния, можно поставить всё на паузу, закрыть и открыть разом, вернуть в обычный режим для позиционирования, позиционировать выжделением мышкой, прозрачность там, центрирование и прочее. Каждой программе даётся имя начинающиеся с @ а далее либо имя программы, либо ссылка или файл. Для запуска программы в прозрачном терминале нужно написать + передименем программы.

Видео презентация на память

Негодники (+пердолинг со сборкой вспомогательных утилит там ещё)

Расписывать и описывать что да как лень, один фиг это не до конца готовое, поэтому просто скопирую сюда выхлоп --help.

Usage: wallwa [URL|FILE|APPLICATION|+APPLICATION]

 This utilite execute GUI application or open mediafile
 or execute CLI application in transparent terminal and
 move any this variants to desktop background like wallpaper.
 Working only under X11 Xorg.

 Wallwa command line options give maximum 2 arguments
 first afrument is string ID started at '@' symbol it
 wallwa item name, after item can be URL,FILE or executable app
 wallwa use mpv for play mediacontent every time in fullscreen mode
 as wallpaper, wallwa use urxvt terminal in transparent mode for CLI.

 If first argument not set, automanicly set and use @default item

Arguments:

    -h  --help         Show this help message
    -i  --info         Show items list
    -l  --load         Load selected item
    -la --load-all     Load all items
    -m  --mouse        Select item position and size uses mouse
    -g  --get          Get selected item as normal window
    -ga --get-all      Get all active items as normal window
    -s  --set          Set selected item to background
    -s  --set-all      Set all active items to background
    -t  --top          In background mode move selected item to up
    -t  --top-all      In background mode restack all items in forward range
    -b  --back         In background mode move selected item to down
    -b  --back-all     In background mode restack all items in backward range
    -k  --kill         Kill selected item
    -ka --kill-all     Kill all active items
    -d  --del          Delete selected item and kill
    -da --del-all      Delete all items and kill
    -p  --pause        Pause selected item
    -pa --pause-all    Pause all active items
    -r  --resume       Resume selected item
    -ra --resume-all   Resume all items from "pause"
    -c  --center       Reposition selected item in screen center
    -ca --center-all   Rereposition all items in screen center
    -f  --full         Resize selected item to fullscreen
    -fa --full-all     Resize all items in fullscreen

    [FILE]             Open mediafile in mpv
    [URL]              Open mediastream in mpv
    application        Execute any* GUI applications in background mode
    +application       Execute any  CLI applications in transparent terminal

    [NUMBER]%                Set opacity for selected item
    [NUMBER]%%               Set opacity for all items
    [NUMBER]x[NUMBER]        Set size for selected item
    [NUMBER]:[NUMBER]        Set pose for selected item
    [NUMBER]x[NUMBER]-center Set item size for selected item
                             and centred item in screen
    *[NUMBER]x[NUMBER]       Relative change size for selected item
    *[NUMBER]:[NUMBER]       Relative change pose for selected item

In relative mode +[NUMBER] add value, -[NUMBER] sub value, [0] no change
For example:
     @itemname *+50:0   #move window to left on 50px
     @itemname *-10x+20 #sub in window width size 10px and add 20px height

More examples:
     This example show case when you have live video wallpaper and htop in
     background mode, you have 2 items @default and @wallpaper and manipulate
     this items resize, move, restack, pause, resume, close and open again, you
     can make many @items and manipulate each individually or all of them at once

     wallwa +htop             #execute htop in transparent terminal as @default item
     wallwa -m                #resize and repose htop window
     wallwa -k                #kill @default item
     wallwa -l                #load again @default item
     wallwa @wallpaper w.mp4  #play video wallpaper in fullscreen mode
     wallwa @default -t       #raise htop above the wallpaper
     wallwa @wallpaper 50%    #set transparent value for wallpaper
     wallwa -pa               #pause @default and @wallpaper
     wallwa -ra               #resume @default and @wallpaper
     wallwa -ka               #close
     wallwa -la               #run again
     wallwa -da               #delete all items and start playing again :D

     If you command for wallwa have multiple words use quotes
     For example you can run another (not urxvt) terminal

     wallwa @myhtop "xterm -fg white -bg black -e htop"

     Wallwa save size and cood position for item you can
     execute another application in current pose and size item

     ./wallwa @myhtop "xterm -fg white -bg black -e htop"
     ./wallwa @myhtop "xterm -fg red -bg blue -e htop"
     ./wallwa @myhtop +htop
     ./wallwa @myhtop +btop
     ./wallwa @myhtop "xterm -e top"

     Current wallwa implemented as Lua script and uses
     other awesome applications for its work such as

     * mpv      for playing any media content
     * urxvt    for transparent terminal for CLI applications
     * ps       for get PIDs
     * slop     for use mouse for repose and resize item window
     * xprop    for set and get window parameters
     * wmctrl   for get WID from PID (no used now)
     * xwidpid  for get WID from PID (used now)
     * xlower   for move window to low stack
     * xdotool  for relative change size and pose
     * xwininfo for information about window visible
     * realpath for give absolute path for files and applications

Notice:

     WALLWA EXECUTE PROGRAMS FROM COMMAND LINE, NO RUN DANGER
     COMMANDS, YOU SELF CHECK VALID URL, PLEASE BE CAREFUL WHAT
     COMMANDS YOU PASS TO RUN. This doesn't just apply to any terminal input.

     wallwa can make "Bad Window" erros, becouse Xorg async.
     If you see "Bad Window" error try

        #reload all items
        wallwa -ka ; #kill all
        wallwa -la ; #load all

        #or delete all items
        wallwa -da

    *Some GUI applications work uncorrect in background mode, for example
     chromium,firefox,tilix,gnome-terminal and maybe other applications
     not work correctly in background mode or no change state to background
     This windows have multiple WID`s and now correctly spawn in background
     but uncorrect behavior with options -g, -s, -b, -t manipulations.
     If window have single WID all works fine

     wallwa is prototype util, maybe reimplemented in future.

Под Cinnamon тоже есть косяки, иногда окно продолжает держать фокус
и нужно кликнуть по рабочему столу куда-то. С другими WM/DE бедные беды
на большиснтве идёт перекрытие рабочего стола, в xfce4 всё проваливается под него.
Там делает кто как у некоторых рабочие столы без _NET_WM_WINDOW_TYPE_DESKTOP пашут.
Не всё так красиво под иксами тоже. Пока думаю, может чего и придумаю. Идеи есть, но…

А иногда всё нормально, может генерировать Bad Window
Может быть кому-то пригодится
Досвиданья :(

 , , wallwa, , живые обои

LINUX-ORG-RU
()

Получить WID из PID

Форум — Development

Запускаю через скрипт приложение

  • (appname 2>&1 > /dev/null) & echo $!
  • Читаю результат $! получив PID отпочковавшейся дочки
  • Запускаю wmctrl -lp ищу в строке PID и забираю соответствующий WID
  • Всё, я довольный, могу через WID манипулировать окном и пришибать процесс через PID точно зная что есть активная пара PID/WID и я не пришибу случайно что-то иное.

Всё работает. Но с некоторыми приложениями например glxgears беда. PID я его получаю, а вот WID найти не могу, да я могу wmctrl без параметров запустить, мышкой кликнуть на окошечко и получить WID, но это не то, не получается зная лишь PID получить WID. С большинством приложений проблем нет, а тут уже не знаю где искать. Сейчас ситуация такая что я запускаю приложеньку, жду несколько секунд пытаясь получить WID окна, если не получилось, грохаю процесс, ну и типа фиг с ним, не судьба :(

Не сообщает _NET_WM_PID оно, жопка такая. Выхода нет? Ключ поверни и по-ле-те-ли И однозначно не определить?

Варианты поиска по заголовкам окон и по содержанию командной строки не прокатят, заголовка может не быть вовсе и могут быть много окон с пустыми заголовками. Блин :(

Решение:

 , window id, ,

LINUX-ORG-RU
()

Разбраинфакaлка данных на вашем ПеКа

Форум — Talks

В прошлый раз данные на домашних ПеКа захренакались, настало время их расхренакать обратно с помощью квинтэссенции говнокода, обычно все хвалятся что пишут brainfuck интерпретатор там в 200 байт, а то и меньше, но у инвалидов мозга типа меня своя олимпиада, поэтому размер интерпретатора 1200+ строк и 45+ килобайт весом. И это я ещё сократил, оставив попытки раскручивать циклы поняв что это глупая затея лишь тогда когда сделал действительно корректную раскрутку циклов во время исполнения через собственно генерацию раскрученных трасс циклов. Ну и ладно.

Собственно вот зачем интерпретатор

Для возможности непрерывно исполнять код который генерируется через Браинфакалка данных вашего ПеКа по мере его генерации , а не просто загрузить всё и потом выполнять.

Конечно Lua не для этого и тормоза, но в режиме исполнения под Luajit вполне себе терпимо

Да, это в режиме тупой транcляции в Lua код и его исполнения.

Всё вроде бы я наигрался, эксперимент закончен. Может кому надо, есть утилита и модуль который можно использовать самостоятельно, дебаг, трассировка исполнения, возможность отключать часть или все оптимизации, и запускать из под разных реализаций Lua не через правку исходника, а через ключик. Всякая хрень с учётом типа конца строк EOL ,\r,\r\n,\n и поведения окончания данных EOF ибо некоторые браинфук программы хотят специфичных вещей.

Описание параметров

Usage:  braintractor -i [FILE] -o [FILE]
        braintractor -e ',+.+.+.+.+.+.+'
        cat mandelbrot.bf | braintractor

 Execute input brainfuck code with or without
 different optimisations like transplitter to
 lua code and execute him, repeated operations
 optimisation and cycles jump optimisation.
 Cheking brainfuck syntax is correct.
 Handle debug symbol `#` and allow trace all code
 in execution time with trace lua function.
 This brainfuck language interpretor not very faster but flexibly.

Arguments:
   -h --help      This help information
   -              Execute brainfuck source code from stdin
   -i [FILE]      Execute filename with brainfuck source code
   -e [TEXT]      Execute brainfuck source code from string
   -o [FILE]      Output filename for write execution output
                  if output not set out writed to stdout

   -fi [FILE]     Send data to brainfuck programm from file
   -si [TEXT]     Send data to brainfuck programm from string


   -dj            Disable cycles jump optimisation
   -dr            Disable repeated operations optimisation
   -dt            Disable transplitter to lua optimisation
   -dz            Disable zero cell [+] [-] [<] [>] optimisations
   -da            Disable all optimisations

   -ds            Disable stream execution

   -dl            Disable set newline after terminal ouput
   -dd            Disable '#' symbol in brainfuck source code
   -do            Disable (force) any output (tracer worked)

   -sb [NUMBER]   Source buffer size for stream execution
                  minimum=1, maximum=2^31. (Default:100)
                  If posible braintractor execute this
                  chunks size or load more source code

   -tr [TEXT]     Lua function for trace brainfuck execution

   -dn            Disable check newline in input reader.
                  By default enabled checking '\n' if
                  input data ended but no have '\n' force
                  add this EOL LF symbol as last input symbol
                  this useful for varian set input as string
                  like -s 'someinput' -> 'someinput\n' you
                  can set other variant for EOL not '\n'

   -l [TEXT]      Select lua implementation for execute
                  lua5.1, lua5.2, lua5.3, lua5.4, luajit
                  By default used system '#!/usr/bin/env lua'

   Some brainfuck programs expect different behavior for
   end of line. Setting bottom transparent fix input for
   different behavior end of line. LF , CR, CRLF. You can
   enable only one variant. If set more last disable other
   By default enabled -eof_lf if input no have '\n' in line end
   force added '\n' in last input data. Use -dn for disable it

   -eol_lf        Enable check end of line and force set LF == '\n'
                  if input have '\r' or '\r\n' this option
                  change it to single '\n'. (nix way)

   -eol_cr        Enable check end of line and force set CR == '\r'
                  if input have '\n' or '\r\n' this option
                  change it to single '\r'. (old osx way)

   -eol_crlf      Enable check end of line and force set CRLF == '\r\n'
                  if input have '\n' or '\r' this option change
                  it to two end of line symbols '\r\n'. (windows way)

   Some brainfuck programs expect different behavior for end of file
   some expect write '0' in memory cell, some need save cell value
   and skip write other value in cell and some needed write -1 in cell
   Options bottom can enable one of varians. By default enabled -eol_zero
   You can enable only one varian. If set more last disable other.

    -eof_zero      If no have data to read, write 0 in memory cell m[i]=0

    -eof_eof       If no have data to read, write -1 in memory cell m[i]=-1

    -eof_skip      if no have data save cell value m[i]=m[i] (it like clamp)

    -eof_same      same as -eof_skip, just alias, it's easier to remember :)


   Notice about default execution mode and configuration:

   By default execute source maked in strem mode, brainfuck
   source load in small chunck, chunck optimised and executed
   this makes it possible to execute code as it is received,
   without waiting for it to be fully loaded. Also, this is
   only possible if it is possible to isolate independent parts
   from the flow that are not included in the body of any loop
   You can set minimal buffer for load or disable stream mode

   By default debug symbol '#' executed, you can disable it
   No cell memory limit, you can use over 30000 cells
   No memory position limit, brainfuck code can use
   negative cell indexes. If you need check memory limit
   or check index allowed ranges you can use tracer -tr

   Notice about optimisations:

                  By default all optimisations is enabled.
                  You can disable some one or all. The more
                  you disable, the slower the code will run

   Notice about input data variants:

                  If input data taked from PIPE and brainfuck
                  have read ',' command need use -fi or -si options
                  for send data in brainfuck reader ',' command.

                  If input data from file -i or string -e
                  brainfuck read from stdin. Imposible
                  use PIPE for load source code and for
                  take input for brainfuck code. Or or.

   braintractor -e ',..'                   # ok - you take interactive input
   braintractor -i code.b                  # ok - you take interactive input
   echo ',..' | braintractor -fi /dev/tty  # ok - you take interactive input
   echo ',..' | braintractor -fi input.txt # ok - input from file
   echo ',..' | braintractor -si 'a'       # ok - input from string

   echo ',..' | braintractor              # error, stdin empty after PIPE
                                          # need direct send input data
                                          # need directly use -f or -s

   About trace function:

   If you set trace function, this function be executed
   in brainfuck execution loop for any operations. But
   if you no disable repeater optimisation -dr, tracer miss
   some repeated operations, for example this code
   '+++.+++' in tracer show 3 trace becouse +++ combine
   to single '+' next one '.' and again single '+'
   if you set -dr tracer show full 7 operations per symbol.

   Example tracer:

   c - brainfuck code symbol
   i - brainfuck cell memory index
   v - brainfuck cell memory value
   r - repeated counter after operations or 1
   p - source code position, depend of optimisations, set -da -ds for correct

   -tr 'function(c,i,v,r,p) print(c,i,v,r,p) end'

   For example you can disable output -do and all optimisations
   and just use custom tracer debugger for you brainfuck code

   For example check memory usage no more 10 cells, and check negative index

   -tr 'function(_,i) if i > 10 then error('MEM OVERFLOW!')   end end'
   -tr 'function(_,i) if i <  0 then error('NEGATIVE INDEX!') end end'

   Warning: tracer execute any lua code, ANY LUA CODE! This mean
   you need set correct code, no use copypaste code from internet.
   If tracer function incorrect this application crashed.

Код и документация тут:

Запускать можно прям из каталога, модуль подхватится который рядом лежит.

Локальные установка и удаление в $HOME/.local/

#Установка
make PREFIX=$HOME/.local install install-cli
#Удаление
make PREFIX=$HOME/.local uninstall uninstall-cli

Баги и чиcтка кода, оооой всё потом. Потому что нет времени очередная поделочка в процессе. Так и живём, тяп ляп и готово :)

Досвиданья.

 , , , ,

LINUX-ORG-RU
()

Записи докладов с C++Russia 2023

Форум — Development

В преддверии конференции C++Russia 2024 организаторы выложили на YouTube записи докладов с прошлогодней C++Russia 2023. Публикация прошлогодних докладов началась месяца три назад но по одному докладу в неделю, а пару дней назад вроде как выложили вообще все.

На данный момент на канале конференции доступны следующие видео (если к докладу прилагались слайды, то рядом приведена и ссылка на PDF-ку):

Евгений Григорчук — GPU Driven Rendering Pipeline, или Как пишется графика в современных видеоиграх, PDF

Юрий Грибов — Как правильно писать компараторы, PDF

Илья Казаков — Кастомизируем ASIO, PDF

Дмитрий Мельник — Безопасный компилятор: надежная оптимизация и улучшение защищенности кода, PDF

Эрнест Асанов — Модель асинхронности в C++: теория и практика

Антон Сысоев — Dynamic Libraries for Bare Metal, PDF

Илья Шишков — Что-то у меня тормозит: заглядываем внутрь С++ контейнеров, PDF

Тот самый стендап от Павла Филонова на C++ Russia 2023

Дмитрий Ермолов — Roren — С++ фреймворк для описания пайплайнов распределенных вычислений, PDF

Ростислав Михеев — Эффективное использование GPU на примере разработки игр, PDF

Олег Сенин — Sizecoding: взгляд изнутри

Максим Кита — Техники оптимизации производительности, PDF

Александр Еналдиев — C++ Experiments: The Battle Continues: Cpp2 vs Carbon, PDF

Иван Смирнов — YsonStruct: дешевая сериализация иерархических JSON-структур, PDF

Владимир Ситников — B-tree индексы в базах данных на примере SQLite и PostgreSQL

Артем Хорошев — Ускоряем синтез: от TensorRT до CUDA C++, PDF

Аяз Салихов — Имплементируем класс tuple в 100 строк кода, PDF

Ashot Vardanian — Advanced Linux Kernel Bypass Techniques in 2023

Егор Суворов — Санитайзеры и стандарт не спасут, PDF

Александр Ганюхин — Машина состояний: непридуманная история

Rainer Grimm — Concurrency Patterns, PDF

Денис Легезо — Злые фреймворки и генерируемый ими позиционно-независимый код, PDF

Елена Веселовская — Как перейти от ученичества к работе, PDF

Андрей Аксенов — Про алгоритмы в поисковых движках

Техническое интервью: Архитектурная секция

Сергей Ларин, Владислав Столяров — Как сделать фронтенд компилятора в домашних условиях, PDF

Антон Потапов, Антон Малахов — Учим Кукушку Летать, или ConcurrentHashMap with Seqlocks, PDF

Александр Фокин — Designing Robust APIs: C++ Code that’s Safe, Extensible, Efficient & Easy to Use, PDF

Дмитрий Стародубцев, Ольга Кузьмичева — Практическое применение dev-контейнеров, PDF

Степан Дятковский — Почти полноценный RTTI с контролируемым overhead, PDF

Иван Афанасьев — Loop unrolling в деталях, PDF

Александр Ляпунов — Максимально быстрый и максимально удобный С++ msgpack-кодек

Марсель Галимуллин — Back to Basics: Lock-free, PDF

Алексей Степанов, Евгений Зуев — Исходный код: скрытое знание и как его показать?, PDF

Павел Новиков — Про flat_map, PDF

Антон Ласточкин — Мониторим FSM во встраиваемом ПО, PDF

Александр Бычук — Производство ПО глазами разработчика и менеджера, PDF

Константин Владимиров — Семантические процессы в C++

Александр Кирсанов — nocc — распределенный компилятор для гигантских проектов на C++, PDF

Евгений Ерохин — Back Deep to Basics: Наследование и виртуальность в C++ (Часть 1), PDF

Евгений Опарин — Опыт использования Bazel

Семен Буденков — С Conan за кроссплатформенностью, PDF

Сергей Талантов — С++ и безопасность: правда ли все так плохо?, PDF

Александр Боргардт — Колоночное хранилище в памяти: void* и шаблоны

Петр Советов — Автоматизация программирования в СССР. Трансляторы (60–70-е годы), PDF

Александр Корнилов — Идея по улучшению многопоточного кода, PDF

Александр Кухаренко — Демосцена: в погоне за wow-фактором, PDF

Виктор Шампаров — Компилятор LCC и оптимизация слияния кода, PDF

Евгений Зощук — Вперед в прошлое, или Разрабатываем фреймворк под Windows 95 в 2023 году, PDF

Михаил Лукин — Практика программирования тензорных ядер

Вадим Винник — Элементы функционального программирования в языке C++, PDF

Антон Соснин — С++ в мемах, PDF

Антон Полухин — C++ трюки из userver

Нужны ли профсоюзы в IT?

Тренды от HR

Интервью с Максимом Бабенко

PS. Практически все доклады перечислены в том порядке, в котором их мне показывает YouTube, никакой сортировки по какому-либо принципу здесь нет.

PPS. Сам ничего из этого не смотрел, никаких рекомендаций на тему «интересно/не интересно» дать не могу.

 

eao197
()

Браинфакалка данных вашего ПеКа

Форум — Talks

Договнокодил очередное ненужно. А именно транслятор произвольных данных в код на brainfuck который будучи исполненным выводит закодированные в нём данные. Текст, картинка, чво угодно.

Типа cat /dev/random | brainfucktor -o bigbrainfuck.b

Или устроить «матрицу» brainfucktor -i /dev/random

Так то это просто ради экспериментов, но может кому надо я фиг знаю, кодировщик в виде модуля Lua конечно же и утилита командной строки покрывающая все его возможности, из возможностей просто игра генерирования разного brainfuck кода из одних и тех же данных. Работает на любой версии Lua от 5.1 до 5.4+

Код тормоз, такой же как и я. Для оптимизации его надо целиком переписывать и на Сях, но в этом нет смысла, это забава для небольших данных, хотя жрать может любые размеры, перегнать 10 мегабайт уже вечность, так что это просто для мелочи, если вдруг надо :D

Описание параметров

Usage:  brainfucktor -i [FILE] -o [FILE]
        brainfucktor -e 'encode this text to brainfuck'
        cat file | brainfucktor - #read from pipe
        brainfuck photo.png -o photo.bf

Encode input data to code in brainfuck language

Arguments:

   -h --help     This help information
   -             Input read from stdin
   -i  [FILE]    Input  filename for read
   -o  [FILE]    Output filename for write
   -e  [TEXT]    Input from command line argument

   -cb [NUMBER]  Cycle body size factor (>=1 default=2 )
   -cs [NUMBER]  Cycle split factor     (>=1 default=16)
   -cd [NUMBER]  Cycle distance factor  (>=1 default=64)
   -vd [NUMBER]  Value distance factor  (>=1 default=8 )
   -ch [NUMBER]  Separate input by chunks size (>=1 default=1024 bytes)
   -ml [NUMBER]  Set max line size for split output ( >=1 default 80 bytes)
   -sl           Create single line output (this disabled -ml option)
   -pc           Print currect configuration for code generation

You can skip -i option and just set filename, but filename expect first

Пример вывода Hello World! с немного разными настройками генерации

brainfucktor -e 'Hello World!'
+++++++++++[>+++++++<-]>-----.>+++++[<++++++>-]<-.+++++++..+++.>+++++++[>+++++<
-]>---.>++++++++++[<++++++>-]<-----.>+++++[<+++++>-]<-.+++.------.--------.>+++
+++[>++++++<-]>---.
brainfucktor -e 'Hello World!' -vd 50
+++++++++++[>+++++++<-]>-----.+++++++++++++++++++++++++++++.+++++++..+++.>+++++
++[>+++++<-]>---.>++++++++++[<++++++>-]<-----.++++++++++++++++++++++++.+++.----
--.--------.>++++++[>++++++<-]>---.
brainfucktor -e 'Hello World!' -cd 4
+++++++++++[>+++++++<-]>-----.>++++++++++++[>+++++++++<-]>-------.+++++++..+++.
>+++++++[>+++++<-]>---.>++++++++++[>+++++++++<-]>---.>+++++++++++++[>+++++++++<
-]>------.+++.------.--------.>++++++[>++++++<-]>---.
brainfucktor -e "Hello World!" -vd 128
+++++++++++[>+++++++<-]>-----.+++++++++++++++++++++++++++++.+++++++..+++.-------
------------------------------------------------------------------------.+++++++
++++++++++++++++++++++++++++++++++++++++++++++++.++++++++++++++++++++++++.+++.--
----.--------.------------------------------------------------------------------
-.
brainfucktor -e "Hello World!" -vd 1 -cs 8
>+++[<++++>-]<-[>+++++++<-]>-----.>+++++[<++++++>-]<-.>+++[<+++>-]<--..>+[<+++>-
]<.>+++++++[>+++++<-]>---.>++++++++++[<++++++>-]<-----.>+++++[<+++++>-]<-.>+[<++
+>-]<.>++[<--->-]<.>+++[<--->-]<+.>++++++[>++++++<-]>---.

Если использовать модуль напрямую, то он гибкий, может жрать таблицу, файл, строку
и выплёвывать возвратом строки от функции или писать в таблицу, файл, функцию. Ввод обрабатывается поблочно, чанками его размер регулируется от 1 до 2^31.

Сгенерированный код при исполнении жрёт ячеек памяти в максимуме N*2 где N количество закодированных байт, в минимуме жрёт всего 2 ячейки памяти, а дальше их переиспользует. Для исполнения больших 50+ мегебайт блоков кода с циклами нужен интерпретатор brainfuck без ограничений на память в 30000 ячеек. :D

Код жирный, прям как я, поэтому сюда не влезет несмотря на то что я влез. Как мы недавно узнали нейроидиоты не могут в браинфук,
а это значит у нас есть средство борьбы со скайнетом, когда терминаторы придут и роботы заполонят эту плонету, мы будем общаться на этом простом и красивом языке :)

- использовать на свой страх и риск

Код и документация тут

Запускать можно прям из каталога, модуль подхватится который рядом лежит.

Локальные установка и удаление в $HOME/.local/

#Установка
make PREFIX=$HOME/.local install install-cli
#Удаление
make PREFIX=$HOME/.local uninstall uninstall-cli

Хоп и твой дистрибутив стал почти как Slackware :D

Изначально было всего 15 строчек. Но я нахлобучил дублирующегося кода и лапши на ifах до ~500 строк :D
Двойные комментарии ваще шедевр, надо было ещё и на китайском написать лол. Вроде всё.

Досвиданья.

 , , , пора спать,

LINUX-ORG-RU
()

Видео записывалка для вашего ПеКа

Форум — Talks

Я внезапно открыл для себя утилиту slop, очень удобная и полезная в домашних делах. Ага я слоупок.
Надо было записать кусочек экрана несколько раз и удобно выделять мышкой область на экране для записи видео.

Наваял вот, может кому пригодится.

  • Переменная use_recorder задаёт то чем вы ходите записывать
    • ffmpeg
    • recordmydesktop
  • Если передать скрипту аргументы то они прокинутся к утилите записи
    • например record --no-sound если используется recordmydesktop
      • но прокидывайе аргументы с умом рм рф и прочую копипасту туда писать не надо.

Ключи под себя

  • ffmpeg быстро пишет и сразу кодирует без звука.
  • recordmydesktop со звуком и отложенным долгим кодированием

Сам использую нубский recordmydesktop так как вокруг него не надо с бубном бегать по поводу звука (он меня сломан на ПК и чисто программный идёт по сети)

touch $HOME/.local/bin/record
#copy-paste code
chmod +x $HOME/.local/bin/record
  • Прерывать запись через ctrl+C
  • Зависимости в теле написаны какие надо.

Если кажется многословным перепишете на bash, всё можно переписать на bash :)

#!/usr/bin/env lua
-----------------------------------------
-- Depends for recordmydesktop: ogv out
-- apt install lua slop recordmydesktop
-----------------------------------------
-- Depends for ffmpeg: mp4 out
-- apt install lua slop ffmpeg
-----------------------------------------
-- Use ffmpeg or recordmydesktop recorder
--local use_recorder = 'ffmpeg'
local use_recorder = 'recordmydesktop'
-------------------------------------------------------------------------------
local separator = ' '
local arguments = table.concat({...},separator)
local visualfmt = '-b 5 -c 0.5,1.0,0.5,0.8 -o'
local slop_pipe = io.popen('slop -f "%x %y %w %h" '..visualfmt)
local x,y , w,h = slop_pipe:read('*l'):match('(%d+) (%d+) (%d+) (%d+)')
-------------------------------------------------------------------------------
local out_filename = os.date('%Y-%m-%H-%M-%S');
-------------------------------------------------------------------------------
local command = {};
-------------------------------------------------------------------------------
if use_recorder == 'ffmpeg' then
   command = table.concat(
   {
       'ffmpeg ','-f x11grab';
                 '-video_size',w..'x'..h;
                 '-grab_x',x;
                 '-grab_y',y;
                 '-i :0.0';
                 '-framerate 60';
                 '-vcodec libx264';
                  arguments;
                  out_filename..'.mp4';
   },separator)
   print('Run command:\n'..command)
   os.execute(command)
   return 0
end
-------------------------------------------------------------------------------
if use_recorder == 'recordmydesktop' then
   command = table.concat(
   {
       'recordmydesktop','-x='..x;
                         '-y='..y;
                         '--width='..w;
                         '--height='..h;
                         '--fps=60';
                          arguments;
                         '-o',out_filename..'.ogv';
   },separator)
   print('Run command:\n'..command)
   os.execute(command)
   return 0
end
-------------------------------------------------------------------------------
print("[ERROR]: Bad 'use_recorder' value.")
return 1

Вроде мелочёвка, а очень и очень удобно.
Всё. Досвиданья.

 , slop, , ,

LINUX-ORG-RU
()

Отрицательная масса у фундаментальных (и не только) «частиц»

Форум — Science & Engineering

Беседа с физиком теоретиком: Анатолием Григорьевичем Шкловским и его теоретические выкладки по поводу отрицательной массы и как она проявляется. Влияя и объясняя как фундаментальные так и макроскопические процессы и явления.

Кратко – Допущение существования элементарных частиц с отрицательной массой. И объяснение через них таких вещей к примеру как наличие воды на земле как косвенное следствие вытеснения протонов из земного ядра и регистрируемые сверх энергетические космические лучи с энергиями в терраэлектронвольт и многое многое другое включая прямое объяснение огромного количества других уже существующих физических эффектов, явлений, наблюдений. То есть при должной теоретической части уже подтверждается текущими экспериментами (вернее теория объясняет то что в них происходит)

Исходя из описания имеет базу достаточную для экспериментальной проверки, а так же имеет теоретический фундамент вписывающийся в текущую фундаментальную модель мира, дополняя её, но явно заявленная как альтернативная теория в качестве основы которой стоит принцип наименьшего действия по модулю из которого следует лавина эффектов проявляющаяся в виде того что мы называем вселенная и тех явлений что мы пытаемся объяснить через науку называемую физикой. Принцип наименьшего действия по модулю это ключевая особенность теории (по мнению меня) позволяющая не нарушая законов и не создавая парадоксов дать новый взгляд (или проявить истинный) на фундаментальные механизмы образования и строения материи как таковой.

Ты физик? Жопа горит? :) Опровергни или бабабол :D
Дискас.

 , , , ,

LINUX-ORG-RU
()

Качалка COUB для вашего ПеКа

Форум — Talks

Драсти опять я к вам со своим lua говнокодом. Товарищ @superuser скоромно сбросил в толксы свою качалку на баше. Не будем скромничать код по ссылке Coub закрывается (комментарий) Более того он ещё патчи исправления скидывает, похвала. Я взял смелость и переписал на lua немножко расширив список возможностей и теперь у нас конкурирующий бизънес! :D Вот вы хихи да хаха, а люди за скачивание даже платят, пруфов не дам :o) Скрипт качалка ниже совместим с версией от @superuser по части хранения coub`ов.

Как пользоваться.

  • В качестве входных параметров может выступать

    • ссылка на coub https://coub.com/view/2ppitj
    • идентификатор на coub 2dnd59
    • название уже скачанного coub Дело_говорит_Симпсоны
    • путь ~/COUB/Дело_говорит_Симпсоны
    • комбинация идентификатора, ссылки, пути и имени
    • 14ns7i,https://coub.com/view/2djrec,Дело_говорит_Симпсоны,2cljbw
    • список файлов должен идти в конце параметров и разделятся запятыми (впритык!)
    • список можно прочитать из файла cat mycoubs.txt | coub - или через ls из каталога
    • в файле разделять можно запятыми или переводом строки
  • Ключ -l задаёт количество повторений inf бесконечность

    • если задана последовательность coub то каждый из них проиграется столько раз сколько
      задано ключом -l если для последовательности coub’ов задан -l inf то каждый из ниж будет проигрываться вечно, при это наглядевшись на один нужно руками закрыть окно плеера откроется следующее видео и также будет по кругу идти, это удобно так как coub’ы часто смотрят по многу раз.
  • Ключ -d говорит о том что нужно просто скачать один или несколько coub’ов, проигрываться ничего не будет

Скрипт не ищет на coub по названиям типа Дело_говорит_Симпсоны этот запрос к программе для поиска локального файла.

Коубы указанные идентификатором или ссылкой всегда скачиваются, нет проверки был ли уже скачан коуб. Для уже скачанных используйте названия из ~/home/$USER/COUB .

Обработка параметров идёт через жъёпу! В начале ключи потом ссылки/id/имена или -. Значения разделены от ключей пробелом -l 3, урлы,id,имена запятыми без пробелов

Зависимости apt install lua wget лол


#! /bin/env lua
local coub = {} -- initial table for export like module
---------------------------------------------------------
coub.config =
{   -- coub save location, you can play from this dir
    storages = '/home/'..os.getenv('USER')..'/COUB';
    -- mp3, mp4 donwnload location, maybe userfull
    download = '/home/'..os.getenv('USER')..'/COUB/DATA';
}
---------------------------------------------------------
function coub.msg(text)
    print("\x1b[32m"..text.."\x1b[39m")
end

function coub.err(text)
    print("\x1b[31m"..text.."\x1b[39m")
end
---------------------------------------------------------
function coub.usage()
help = [[
Use: coub [-h] [-l Num] source

Options:
    -h  - Help and exit;
    -l  - Repeat audio Num times or inf for infinity;
    -d  - Download only
    -   - Read coub or coub list from stdin
    you can use full url or coub id
    source - url | id | file.mp4

Examples:
    # play single coub
    coub https://coub.com/view/38yafx
    # play single coub from storage
    coub ~/COUB/Don_t_be_egoistic
    # play single looped coub
    coub -l inf 38yafx
    # download single coub, no play this
    coub -d https://coub.com/view/38yafx
    # download multiply coubs with separated
    coub -d 38yafx,https://coub.com/view/38yafx
    coub -d 38yafx[newline]https://coub.com/view/38yafx
    cat mycoubs.txt | coub -d -
    # download and play multiply coubs (no looped)
    coub -d 38yafx,38yafx
    # play multiply coubs from file id list
    cat mycoubs | coub -
    ]]
    print(help)
end
-----------------------------------------------------------
local function filter_get_between(body,a,b)
    local s , e = 1 , 1;
    local out = ""
        s,e = body:find(a,1,true);
        if s == nil or e == nil then return end
        local ss,ee = body:find(b,s,true);
        if ss == nil or ee == nil then return end
        out = out .. body:sub(e+1,ss-1);
        body = body:sub(ee,#body)

    return out;
end
-----------------------------------------------------------
function coub:run()
    -- stupid handle va_args
    for k,v in ipairs(arg) do
        if self.xoop then self.loop = v; self.xoop = nil; end
        if v == '-h' then self.usage();     end
        if v == '-l' then self.xoop = 1;    end
        if v == '-d' then self.dl_only = 1; end
        self.resource = v
    end
    if not self.loop then
        self.loop = 0;
    elseif self.loop == 'inf' then
        -- do nothing
    else
        self.loop = tonumber(self.loop);
        if self.loop > 0 then
           self.loop = self.loop - 1;
        end
    end

    -- decrement loop value becouse loop value =  N+1
    -- mpv --loop=0 is once play and --loop=1 twoo play


    if not self.resource then
        coub.err("Bad coub: no have input");
        coub.usage()
    end

    -- read input from stdin
    local cnt = 1;
    if self.resource == '-' then
       self.resource = io.read("*all");
    end
    -- check is resource contains data
    -- min 2 symbol coub id (yea?)
    if #self.resource < 2 then
        coub.err('Bad data: Input source is empty');
        return; 
    end
    -- tokenization play lists, and concat to URL
    -- тут ещё нужно проверить может нужные коубы уже скачаны
    self.playlist = {}
    for resource in string.gmatch(self.resource, '([^,\n]+)') do
        if resource:find('https',1,true) then
            self.playlist[cnt] = resource;
        elseif resource:find('/',1,true) or resource:find('.',1,true) then
            self.playlist[cnt] = resource;
        else
            self.playlist[cnt] = 'https://coub.com/view/'..resource;
        end
        cnt = cnt + 1;
    end
    -- always make needed directory
    assert(os.execute('mkdir -p '..self.config.storages),"Storage no writable");
    assert(os.execute('mkdir -p '..self.config.download),"Storage no writable");
    -- download coubs & play coubs --------------------------------------------
    for i,v in ipairs(self.playlist) do

        local exec = io.popen('wget -q -O- '..v);
        local html = exec:read('*all'); exec:close();
        -- wget 
        if  html:match('%a+') then
            local json = filter_get_between(html,"<script id='coubPageCoubJson' type='text/json'>",'</script>');
            local url_video = filter_get_between(json,'"video":{"higher":{"url":',',');
            -- some video no have higher resulution
            -- try get lowless
            if not url_video then
                 url_video = filter_get_between(json,'"video":{"high":{"url":',',');
            end
            local url_audio = filter_get_between(json,'"audio":{"high":{"url":',',');
            local coubtitle = filter_get_between(json,'"title":"','",');
            coubtitle = coubtitle:gsub('[%p+%s+]','_');
            local coubid    = v:gsub('https://coub.com/view/','');
            coub.msg('Download:['..i..'] '..v..' | '..coubtitle)
            -- check file format befor try handle data
            if url_video and url_video:find('.mp4',1,true) and url_audio and url_audio:find('.mp3',1,true) then
               local file_to_save = self.config.download..'/'..coubid;
               os.execute('wget -q -Y off -c -O '..file_to_save..'.mp4 '..url_video);
               os.execute('wget -q -Y off -c -O '..file_to_save..'.mp3 '..url_audio);
               os.execute('ln -s '..file_to_save..'.mp4 '..self.config.storages..'/'..coubtitle..' 2>/dev/null');

               -- do not play if need just download video
               if not self.dl_only then
                   -- play audio in background with infinity loop
                   os.execute('( mpv --loop=inf '..file_to_save..'.mp3 ) 1> /dev/null  & '..
                              -- play video, after video ends we kill previos mpv 
                              -- stdout to /dev/null becouse kill broke terminal stdin
                              -- maybe becouse mpv use '\r' for output info about playing
                              ' mpv --loop='..self.loop..' '..file_to_save..'.mp4 1> /dev/null ; kill -INT $! ');
               end
            else
                coub.err('Bad coub:['..i..'] file formats no mp3 and mp4 '..v);
            end
        else
            if v:find('~',1,true) then
                v = v:gsub('~',os.getenv('HOME'))
            else 
                v = self.config.storages..'/'..v:gsub('https://coub.com/view/','');
            end
            local justplay = io.open(v,'r');
            if justplay then
               justplay:close();
                  if not self.dl_only then 
                    coub.msg('PlayFile:['..i..'] '..v)
                    local link = io.popen(' readlink -e '..v);
                    local file = link:read('*all'); link:close();
                    os.execute('( mpv --loop=inf '..file:gsub('mp4','mp3')..' ) 1>/dev/null  & '..
                          ' mpv --loop='..self.loop..' '..file..' 1>/dev/null ; kill -INT $! ');
                  else
                    coub.msg('Ignore..:['..i..'] coub '..v..' is downloaded')
                  end
            else 
                coub.err('Bad coub:['..i..'] coub not found '..v);
                coub.err('Bad coub:['..i..'] coub not found https://coub.com/view/'..
                        v:gsub(os.getenv('HOME')..self.config.storages,''));
            end
        end
    end
end

coub:run()

- Баги косяки, тупак, есть?
- Да. 
- Исправлять будешь? 
- Нет. 
- А почему? 
- Ну модет потом... 
- А нахера всё это? 
- А тебе не пофиг?
- Пофиг
- Ну и всё
- Ну и ладно
- Ненужно!
- Согласен
- А зачем тогда?
- Потому что.
- Потому что что?
- Потому что понедельник!
- Ой всё.
- Вот и я о том.

Подборочка

coub yaik,s08ov,8ek0p,7aenz,bslpw,5g1j9,wm3bk,14zilh,7l1rdrfc,2b5izx,2aatx2,29jdfr,29k4yq
coub 29n55n,29j3j1,10a9jk,297dvo,280v0q,29adcz,29aon6,29gzt6,1qrxao,334db,15egdcy8,lvd3c

Фъъсьооо!

 coub, , , ,

LINUX-ORG-RU
()

Как сделать Makefile пригодным для опакечивания?

Форум — Linux-install

Обычно все программы используют autotools, и там всё из коробке. Но вот попалась программа, которая собирается просто при помощи Makefile (и это очень простой файл, не следует никаким соглашениям).

Что надо сделать с Makefile, чтобы он стал пригодным для опакечивания? И как потом к нему писать .ebuild? Есть ли статьи на эту тему?

В то же время, насколько я знаю, для Gentoo надо, чтобы поддерживалась переменная DESTDIR, для того, чтобы можно было собирать программы в PREFIX.


О том, что можно писа́ть
make prefix=/usr
а не только PREFIX=/usr make
сказано в пункте 9.5 Overriding Variables руководства по GNU make.

«If you specify a value in this way, all ordinary assignments of the same variable in the makefile are ignored; we say they have been overridden by the command line argument.»


В каких случаях как надо делать:

  1. make --prefix=/usr
  2. PREFIX=/usr make
  3. make prefix=/usr
  4. make PREFIX=/usr

первое не сработает, потому что параметры make принимает другие
второе не сработает, потому что буквы заглавные, а не строчные
четвёртое тоже не сработает


Почему PREFIX и prefix пишут то большими, то маленькими буквами?
Маленькими буквами написан пример в пункте 16.5 Variables for Installation Directories

«Installers are expected to override these values when calling make (e.g., make prefix=/usr install) or configure (e.g., configure –prefix=/usr).»

И пришло такое написание в руководство GNU make из пункта 7.2.5 Variables for Installation Directories документа GNU Coding Standards

Большими буквами называется переменная окружения EPREFIX, описанная в Gentoo wiki.

В autotools.eclass существует функция eautoreconf, которая вызывает что-то там…

«autotools_run_tool –at-m4flags autoconf «$@»»

Пример использования eautoreconf в ebuild-файле:

src_configure() {
    # Вызывать autoreconf должны авторы распространяемого архива
    # где-то внутри make dist
    # Но если автор ебилда пробует архив стянуть с github, то 
    # отсутствие документации для make dist вручную это косяк Gentoo
    # не проводить же сначала локальную сборку архива make dist
    # а затем распаковку и всё это только чтобы вызов make прошел
    # Просто поместить eautoreconf билде недостаточно

    econf
}

функции autotools_src_configure не видно, поэтому явный вызов eautoreconf надо (если надо) вписывать в текст .ebuild-файла.

В документации на ./configure пишут:

«There are two ways to change the default: when creating configure, and when running it.»
«To accomplish that, use the AC_PREFIX_DEFAULT macro.»
«The user of configure can select a different prefix using the –prefix and –exec-prefix options.»

И написано там это маленькими буквами:

# AC_PREFIX_DEFAULT(PREFIX)
# -------------------------
AC_DEFUN([AC_PREFIX_DEFAULT],
[m4_divert_text([DEFAULTS], [ac_default_prefix=$1])])

Вызвать только eautoreconf недостаточно, ещё можно вызвать пару функций из autotools.eclass

eautoconf Runs autoconf.
eautomake Runs automake.

Вызов программы ./configure выполняется при помощи функции econf внутри src_configure

Передача переменной окружения EPREFIX через параметр --prefix задокументирована в руководстве по разработке ебилдов:

«econf is designed to work with configure scripts generated by GNU Autoconf. It first passes the default options listed below to the configure script, followed by any additional parameters passed to econf.

--prefix="${EPREFIX}"/usr
--libdir is set from the value of the LIBDIR_${ABI} variable in profiles.

Как параметр –prefix обрабатывается внутри ./configure остаётся загадкой. Но из написанного можно предположить, что название PREFIX заглавными буквами (без первой буквы E) это фантазия и нигде не используется.


Зачем в Gentoo назвали переменную EPREFIX, если переменной c именем PREFIX нигде нет? Зачем было добавлять лишнюю букву?

https://devmanual.gentoo.org/ebuild-writing/variables/index.html

EPREFIX The normalised offset-prefix path of an offset installation. See Gentoo Prefix Technical Documentation for more information.

но там тоже про PREFIX ничего нет.

Зато есть в вопросах у пользователей Ubuntu - https://askubuntu.com/questions/891835/what-does-prefix-do-exactly-when-used-in-configure

вероятно негентушные дистрибутивы всё-таки имеют слово PREFIX заглавными буквами? Что там в документации по Debian? И в примере попроще и в примере посложнее используются конкретные значения, переменная окружения PREFIX не упоминается.

Может GNU make не учитывает регистр в названиях переменных?
В пункте 6 How to Use Variables написано:

«Variable names are case-sensitive.»

В пункте 6.10 Variables from the Environment написано:

«Every environment variable that make sees when it starts up is transformed into a make variable with the same name and value.»

А вот здесь мало того, что предлагают использовать заглавные буквы, так ещё и пишут, что это работает. Странно, не должно бы.

И по факту не работает:

$ cat Makefile
.SILENT: all
.PHONY: all

all:
	echo prefix=$(prefix)
$ make prefix=/usr
prefix=/usr
$ PREFIX=/usr make
prefix=

Где вообще описан «стандарт» установки программ при помощи

./configure  
make  
make install  

Почему надо делать именно так? В большом количестве книг? Пользователи привыкли? Так GNU Make не единственная, есть другие, (но они хуже, к ним не пользователи не привыкли)

Использование emake прописано прямо в Package Manager Specification (PMS).
Поэтому использование операционной системы Gentoo тормозит прогресс и переход на Cmake.

 , ,

Shushundr
()

Debain + openbox прозрачность части окна возможна?

Форум — Desktop

Интересует не частичная прозрачность равномерно всего окна, а использование альфа-канала в SDL-приложении, так чтобы было видно нижележащие окна.

Такое вообще возможно? Какой нужен композитор? Где читать/смотреть примеры? Кто делал?

 , , ,

pihter
()

Как юзернейм выводит ускоренную 2D-графику на рокчипе без иксов?

Форум — Development

Смеркалось.

Потребовалось мне SDL-приложение на Rockchip RK3588 борде. На нее есть дебиан и убунта, и, соответственно, тулчейн есть прямо на плате, казалось бы, че тут собирать, просто собери так же как и на десктоп. Так-то оно так, собрал и работает, но – под иксами.

А как правильно собирать в бездесктопное? SDL поддерживает в качестве бекэндов много всякого, мне, если я правильно помню удавалось заводить в конфигурации SDL2 + directfb без иксов. Но директфби – еще, блин хуже. Как надо-то? У кого выведать, где почитать? Через OpenGL ES собранный под этот чип? Или еще куда? ЗА день нагуглить даже 100% рабочего направлдения не удалось.

Обсчем, взываю к коллективному разуму

 ,

pihter
()

Makefile для сборки Love2d под Андроид/AppImage

Форум — Development

Сидел вот тут ковырялся, пересобирал и пердолился.
Подумал что стоит выложить, дабы другие пердолились поменьше.
Ниже описание, я его для себя писал и ещё ниже сам Makefile. Никаких изысков и красивостей. Собирает и ладно.
Кому надо под себя поправите, а кому не неадо, тому не надо.

- ИСПОЛЬЗОВАТЬ НА СВОЙ СТРАХ И РИСК, Я НЕ НЕСУ НИКАКОЙ ОТВЕТСТВЕННОСТИ
- ВСЁ ПРЕДОСТАВЛЯЕТСЯ КАК ЕСТЬ, ЛЮБЫЕ СОМНЕНИЯ ДОЛЖНЫ ВЕСТИ
- К ОТКАЗУ ОТ ИСПОЛЬЗОВАНИЯ, НЕ ПОНИМАЕШЬ ЧТО ЭТО, НЕ ТРОГАЙ

Love Distrib

Makefile упрощающий создание готовых Love2D сборок c включением вашего приложения позволяет

  • Собрать apk файл для Android
  • Собрать love файл для всех
  • Собрать AppImage файл для Linux x86_64

Положить Makefile в корень Love2D программы и отредактировать

  • app_name=имя программы
  • description=однострочное описание

Для Android дополнительно поправить

  • android_app_version_name=версия.приложения любая
  • android_app_version_code=число целое число

Важно android_app_version_code должно иметь значение
всегда увеличивающееся на 1 при каждой новой сборке, это
требуется для того чтобы при установке на Android apk
файла, уже установленное приложение обновлялось. Иначе
установка не произойдёт с выводом ошибки или вообще без неё.

Теперь однократно нужно развернуть зависимости для Android

  • make android-depends

Предполагается что sudo настроен, нужно установить java и
прочие мелочи, на запрос пароля ввести пароль для sudo затем
будут сгенерированны два ключа подписей и предварительно пароль

  • debug.keystore
  • release.keystore
  • .android_pass

На вопросы всякие можно просто нажимать ENTER, а когда спросят
всё ли верно Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct? написать yes и снова нажать ENTER. sdkmanager
тоже спросит, Review licenses that have not been accepted (y/N)?
согласны ли вы с условиями предоставления иструментов
для Android SDK/NDK тоже написать y и нажать ENTER
Ключи и пароль можно подменить на свои готовые
(только молю бога не совать основные ЗАТРЁТСЯ МОЖЕТ БЫТЬ!)
Пусть сгенерируется всё само. Суть в том что без подписей пакетов
Android просто молча не установит apk, просто не даст установить.

А вот теперь уже можно, редактировать свой код и пересобирать

  • make lovefile просто обычный app.love
  • make android выполнить сборку app.apk, app.abb
  • make appimage выполнить сборку app.AppImage

Первый раз apk будет собираться долго, но все последующие уже быстро
так как компиляции уже не будет, а просто будут обновляться lua файлики
из проекта. Вроде всё.


Проблемы

  • make android валится с ошибкой Решения
  • Запускать make android ещё раз и ещё раз. Бывает отпускает.
  • Грохнуть java killall java (там несколько процессов может быть) и ещё раз запустить make android
  • Удалить /.love-android-build-dir и заного выполнить
    • make android-depends подготовку зависимостей
    • make android попытку сборки apk

Нельзя отменять сборку через CTRL+C это сломает всё,
придётся вышеописанный квест пройти опять, с большой долей вероятности.
Перемудрёные механизмы системы сборки для Android дают о себе знать. :3

SRC=$(shell pwd)
app_name=appname
description=app short description
##########################################################
android_app_name=$(app_name) for Android
android_app_version_name=0.1
android_app_version_code=1
android_enableJetifier=true
android_useAndroidX=true
android_app_application_id=org.$(app_name).android
android_app_orientation=portrait
#########################################################
SECRET_PASSWORD_FOR_KEYGEN=$(HOME)/.android_pass
#########################################################
android_sign_release=true
##########################################################
DEVELOPMENT_ROOT_DIR=$(HOME)/.love-android-build-dir
DEVELOPMENT_KEYS_DIR=$(HOME)/.love-android-keys-dir
##########################################################
ANDROID_SDK_ROOT_DIR=$(DEVELOPMENT_ROOT_DIR)/ANDROID-SDK/
ANDROID_LOVE_ROOT_DIR=$(DEVELOPMENT_ROOT_DIR)/LOVE-ANDROID/
APPIMAGE_LOVE_ROOT_DIR=$(DEVELOPMENT_ROOT_DIR)/APPIMAGE/
##########################################################
PROPERTIES=$(ANDROID_LOVE_ROOT_DIR)/gradle.properties

all:
	echo "make android-depends - create depends for android apk build"
	echo "make android         - build android apk/aabb pakages"
	echo "make lovefile        - create portable app.love file"
	echo "make appimage        - create portable x86_64 executable file"

android-depends:
	$(MAKE) install-love-android;
	$(MAKE) install-system-depends;
	$(MAKE) install-android-sdk-ndk;
	$(MAKE) generate-android-debug-keys;
	$(MAKE) generate-android-release-keys;

android:
	$(MAKE) generate-android-properties;
	$(MAKE) generate-application-icons;
	$(MAKE) packeges-build;
	$(MAKE) packeges-copy;
ifeq ($(android_sign_release),true)

	$(MAKE) packeges-sign-release;
else
	$(MAKE) packeges-sign-debug;
endif
	$(MAKE) packeges-sign-verify;

lovefile:
	zip -9 -r $(app_name).love . -x Makefile -x ./*.apk -x ./*.aab -x ./*.AppImage


SRC_IMAGE_ICON="NONE"
ifneq ($(wildcard $(SRC)/icon.png),)
SRC_IMAGE_ICON=$(SRC)/icon.png
DST_IMAGE_PATH=$(ANDROID_LOVE_ROOT_DIR)/app/src/main/res/drawable
endif
ifneq ($(wildcard $(SRC)/assets/icon.png),)
SRC_IMAGE_ICON=$(SRC)/assets/icon.png
DST_IMAGE_PATH=$(ANDROID_LOVE_ROOT_DIR)/app/src/main/res/drawable
endif
ifneq ($(wildcard $(SRC)/assets/images/icon.png),)
SRC_IMAGE_ICON=$(SRC)/assets/images/icon.png
DST_IMAGE_PATH=$(ANDROID_LOVE_ROOT_DIR)/app/src/main/res/drawable
endif




appimage:lovefile
	mkdir -p $(APPIMAGE_LOVE_ROOT_DIR);
ifeq ($(wildcard $(APPIMAGE_LOVE_ROOT_DIR)/love-11.5-x86_64.AppImage),)
	wget https://github.com/love2d/love/releases/download/11.5/love-11.5-x86_64.AppImage -O $(APPIMAGE_LOVE_ROOT_DIR)/love-11.5-x86_64.AppImage
	wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage  -O $(APPIMAGE_LOVE_ROOT_DIR)/appimagetool-x86_64.AppImage
endif
	cd $(APPIMAGE_LOVE_ROOT_DIR);                       \
	-rm -rd squashfs-root;                              \
	chmod +x love-11.5-x86_64.AppImage;                 \
	chmod +x appimagetool-x86_64.AppImage;              \
	./love-11.5-x86_64.AppImage --appimage-extract;     \
	cat squashfs-root/bin/love $(SRC)/$(app_name).love > squashfs-root/bin/$(app_name); \
	rm  squashfs-root/bin/love;                         \
	chmod +x squashfs-root/bin/$(app_name);             \
	sed 's/love/$(app_name)/g' -i squashfs-root/AppRun; \
	convert $(SRC_IMAGE_ICON) -resize 256x256 squashfs-root/$(app_name).png;  \
	echo ""                                   > squashfs-root/love.desktop;   \
	echo "[Desktop Entry]"                   >> squashfs-root/love.desktop;   \
	echo "Name=$(app_name)"                  >> squashfs-root/love.desktop;   \
	echo "Comment=$(description)"            >> squashfs-root/love.desktop;   \
	echo "MimeType=application/x-love-game;" >> squashfs-root/love.desktop;   \
	echo "Exec=$(app_name) %f"               >> squashfs-root/love.desktop;   \
	echo "Type=Application"                  >> squashfs-root/love.desktop;   \
	echo "Categories=Game;"                  >> squashfs-root/love.desktop;   \
	echo "Terminal=false"                    >> squashfs-root/love.desktop;   \
	echo "Icon=/$(app_name)"                 >> squashfs-root/love.desktop;   \
	echo "NoDisplay=true"                    >> squashfs-root/love.desktop;   \
	./appimagetool-x86_64.AppImage squashfs-root $(SRC)/$(app_name).AppImage;



install-love-android:
	-`git clone --recurse-submodules https://github.com/love2d/love-android/ $(ANDROID_LOVE_ROOT_DIR)`

generate-android-properties:
	echo "" > $(PROPERTIES)
	echo "app.name=$(android_app_name)" >> $(PROPERTIES)
	echo "app.version_name=$(android_app_version_name)" >> $(PROPERTIES)
	echo "app.version_code=$(android_app_version_code)" >> $(PROPERTIES)
	echo "android.enableJetifier=$(android_enableJetifier)" >> $(PROPERTIES)
	echo "android.useAndroidX=$(android_useAndroidX)" >> $(PROPERTIES)
	echo "app.application_id=$(android_app_application_id)" >> $(PROPERTIES)
	echo "app.orientation=$(android_app_orientation)" >> $(PROPERTIES)

install-system-depends:
	sudo apt install imagemagick openjdk-17-jdk openjdk-17-jre-headless sdkmanager

install-android-sdk-ndk:
	mkdir -p $(ANDROID_SDK_ROOT_DIR);                \
	export ANDROID_SDK_ROOT=$(ANDROID_SDK_ROOT_DIR); \
	sdkmanager --install "platforms;android-33";    \
	sdkmanager --install "ndk;23.2.8568313";        \
	sdkmanager --install "platform-tools;33.0.0";   \
	sdkmanager --install "build-tools;33.0.0";      \
	sdkmanager --install "cmdline-tools;latest";    \
	sdkmanager --licenses;

generate-android-debug-keys:
	mkdir -p $(DEVELOPMENT_KEYS_DIR);
ifeq ($(wildcard $(SECRET_PASSWORD_FOR_KEYGEN)),"")
	uuidgen > $(SECRET_PASSWORD_FOR_KEYGEN)
endif
ifeq ($(wildcard $(DEVELOPMENT_KEYS_DIR)/debug.keystore),"")
	keytool -genkey  \
			-v -keystore $(DEVELOPMENT_KEYS_DIR)/debug.keystore \
			-storepass:file   $(SECRET_PASSWORD_FOR_KEYGEN)     \
			-alias debug      \
			-keyalg RSA       \
			-keysize 2048     \
			-validity 100000
endif

generate-android-release-keys:
	mkdir -p $(DEVELOPMENT_KEYS_DIR);
ifeq ($(wildcard $(SECRET_PASSWORD_FOR_KEYGEN)),"")
	uuidgen > $(SECRET_PASSWORD_FOR_KEYGEN)
endif
ifeq ("$(wildcard $(DEVELOPMENT_KEYS_DIR)/release.keystore)","")
	keytool -genkey  \
			-v -keystore $(DEVELOPMENT_KEYS_DIR)/release.keystore \
			-storepass:file  $(SECRET_PASSWORD_FOR_KEYGEN)        \
			-alias release    \
			-keyalg RSA       \
			-keysize 2048     \
			-validity 100000
endif

generate-application-icons:
ifneq ($(SRC_IMAGE_ICON),"NONE")
	convert $(SRC_IMAGE_ICON) -resize 72x72   $(DST_IMAGE_PATH)-hdpi/love.png
	convert $(SRC_IMAGE_ICON) -resize 48x48   $(DST_IMAGE_PATH)-mdpi/love.png
	convert $(SRC_IMAGE_ICON) -resize 96x96   $(DST_IMAGE_PATH)-xhdpi/love.png
	convert $(SRC_IMAGE_ICON) -resize 144x144 $(DST_IMAGE_PATH)-xxhdpi/love.png
	convert $(SRC_IMAGE_ICON) -resize 192x192 $(DST_IMAGE_PATH)-xxxhdpi/love.png
endif

packeges-build:
	rm $(SRC)/*.apk;                                                \
	rm $(SRC)/*.aab;                                                \
	rm $(SRC)/*.love;                                               \
	rm $(SRC)/*.AppImage;                                           \
	export ANDROID_SDK_ROOT=$(ANDROID_SDK_ROOT_DIR);                \
	export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64;            \
	cp /bin/python3 $(HOME)/.local/bin/python;                      \
	rm -rd $(ANDROID_LOVE_ROOT_DIR)/app/src/embed/assets;           \
	mkdir -p $(ANDROID_LOVE_ROOT_DIR)/app/src/embed/assets;         \
	cp -r $(SRC)/* $(ANDROID_LOVE_ROOT_DIR)/app/src/embed/assets;   \
	rm $(ANDROID_LOVE_ROOT_DIR)/app/src/embed/assets/Makefile;      \
	cp $(ANDROID_LOVE_ROOT_DIR)/license.txt $(ANDROID_LOVE_ROOT_DIR)/app/src/embed/assets/love-licenses.txt;\
	cd $(ANDROID_LOVE_ROOT_DIR);                                    \
	chmod +x gradlew;                                               \
	./gradlew assembleNormalRecord;                                 \
	./gradlew assembleEmbedNoRecordRelease;                         \
	./gradlew bundleEmbedNoRecordRelease;

packeges-copy:
	cp $(ANDROID_LOVE_ROOT_DIR)/app/build/outputs/apk/embedNoRecord/release/app-embed-noRecord-release-unsigned.apk $(SRC)/;
	cp $(ANDROID_LOVE_ROOT_DIR)/app/build/outputs/bundle/embedNoRecordRelease/app-embed-noRecord-release.aab $(SRC)/;
	cp $(ANDROID_LOVE_ROOT_DIR)/app/build/outputs/apk/normalRecord/release/app-normal-record-release-unsigned.apk $(SRC)/;

packeges-sign-debug:
	jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/debug.keystore -storepass:file  $(SECRET_PASSWORD_FOR_KEYGEN)  $(SRC)/app-embed-noRecord-release-unsigned.apk debug;
	jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/debug.keystore -storepass:file  $(SECRET_PASSWORD_FOR_KEYGEN)  $(SRC)/app-embed-noRecord-release.aab debug;
	jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/debug.keystore -storepass:file  $(SECRET_PASSWORD_FOR_KEYGEN)  $(SRC)/app-normal-record-release-unsigned.apk debug;

packeges-sign-release:
	jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/release.keystore -storepass:file  $(SECRET_PASSWORD_FOR_KEYGEN) $(SRC)/app-embed-noRecord-release-unsigned.apk release;
	jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/release.keystore -storepass:file  $(SECRET_PASSWORD_FOR_KEYGEN) $(SRC)/app-embed-noRecord-release.aab release;
	jarsigner -verbose -keystore $(DEVELOPMENT_KEYS_DIR)/release.keystore -storepass:file  $(SECRET_PASSWORD_FOR_KEYGEN) $(SRC)/app-normal-record-release-unsigned.apk release;

packeges-sign-verify:
	jarsigner -verify $(SRC)/app-embed-noRecord-release-unsigned.apk release;
	jarsigner -verify $(SRC)/app-embed-noRecord-release.aab release;
	jarsigner -verify $(SRC)/app-normal-record-release-unsigned.apk release;
.SILENT:all

 , , , ,

LINUX-ORG-RU
()

QEMU в реальную сеть через WiFi

Форум — General

Проблема проста. Есть ноутбук подключенный к сети через WiFi.

Надо обеспечить доступ виртуальной машины на QEMU в эту же сеть.

Я понимаю, что для этого теоретически, надо создать tap сетевой адаптер и создать мост включающий его и сетевую карту, через которую реальная машина подключена к сети.

Вот тут и проблема - нельзя просто взять и создать мост с WiFi картой. Или как-то можно?

Подскажите пожалуйста. Возможно есть другие пути?

Виртуалка просто должна работать в реальной сети как еще один компьютер.

Интересует именно QEMU, как это сделать с Virtualbox я знаю, но он не подходит.

#####РЕШЕНИЕ#######

Спасибо @Pinkbyte! Я осилил по твоему совету.

Включаем Proxy ARP

# sysctl net.ipv4.conf.all.proxy_arp=1

Включаем IP Forwarding

# sysctl net.ipv4.ip_forward=1

Создаем tap сетевой интерфейс, доступный для пользователя (важно! qemu работает от пользователя !)

# tunctl -p -t tap0 -u <username>

Создаем маршрут для ip адреса виртуалки через tap0

ip route add 192.168.1.199 dev tap0

Запускаем QEMU с параметрами сети

-netdev tap,id=mynet0,ifname=tap0,script=no,downscript=no -device virtio-net-pci,netdev=mynet0

На гостевой системе - настраиваем статический ip адрес 192.168.1.199.

После этого все работает, виртуалка видна по своему адресу снаружи как отдельный компьютер.

 ,

James_Holden
()

Дублирующиеся теги

Форум — Linux-org-ru

Некоторые, наверное, уже заметили, что я начал войну с ветряными мельницами дублирующимися тегами. Извините, если вам вдруг придёт десяток уведомлений по какому-нибудь невезучему тегу. Не хочу повторить историю с cetjs2.
Кидайте в эту тему дублирующиеся теги, которые нужно почистить.
Например, были теги «параноя», «паранойа», «паранойя», остался только «паранойя», «rubyonrails» -> «ruby on rails» и т.д.

 

CYB3R
()

Бекапилка вашего ПекА

Форум — Talks
- АХТУНГ, ВАХТУНГ, БАХТУНГ, ДРЯХТУНГ, АЛЯРМ, ВНИМАНИЕ
- ЭТОТ СКРИПТ ПРЕДОСТАВЛЯЕТСЯ КАК ЕСТЬ, Я НЕ НЕСУ НИКАКОЙ
- ОТВЕТСТВЕННОСТИ ЯВНОЙ ИЛИ КОСВЕННОЙ, ВАМ ЛИБО КОМУ ТО ЕЩЁ
- ПО ПРИЧИНЕ, ПОРЧИ И/ИЛИ УНИЧТОЖЕНИИ ВАШИХ ДАННЫХ 
- ЕСЛИ ВЫ НЕСОГЛАСНЫ, Я ЗАПРЕЩАЮ ВАМ ЗАПУСКАТЬ ЭТОТ КОД
- ДЕЙСТВУЙТЕ НА СВОЙ СТРАХ И РИСК, ВАШИ ЛЮБЫЕ СОМНЕНИЯ 
- КАСАТЕЛЬНО СКРИПТА ДОЛЖНЫ ВЕСТИ К ОТКАЗУ ОТ ЕГО ИСПОЛЬЗОВАНИЯ

Всё, теперь если у вас что-то пойдёт не так, то я чист.
И меня никто не будет ругать, гы :) Просто будте внимательный с тем,
какой каталог указывается для сохранения бекапов. А то ведь так и затереть чего важного можно случайно.
Вопщем решил поделится прост. Пусть будет.

Простой скрипт ручного бекапа наиболее важных файлов, использует
rsync и zip Настройка производится внутри стрипта. Описание
настройки бекапа тоже распологается внутри скрипта.
Типичное использование это ручной запуск в конце дня или по
завершению какой либо важной работы или перед сном :)
Используйте для бекапа, отдельный диск где нет ничего кроме бекапа!
Просто иначе, в бекапе нет никакого смысла.
Лично я просто на панельку кнопочку сделал, и перед отплытием в люльку тыкаю кнопочку.
Комп я не выключаю обычно, а если выключаю до явно дожидаюсь окончания бекапа, не проверял что будет если увести в сон во время бекапа, так что, лучше дождаться окончания.

Зависимости

mkdir zip rsync notify-send lua

Использование

Настроить скрипт, после чего просто его запускать. Так как вам удобно.

  • Обязательные параметры
    • source каталог или файл источник
    • dest каталог приёмник
  • Дополнительные параметры
    • secure применить пароль (требуется zip=true)
    • zip сжать в архив
    • mirror сделать точную копию и обновить им текущий каталог бекапа( или архив если zip=true)
    • versions сделать точную копию и пометить датой в отдельном каталоге (или архиве если zip=true)

Пример поля конфигурации:

  • {secure=true, zip=true, versions=true, source='~/.ssh/', dest='ssh'};

Значит что нужно сделать рекурсивный бекап каталога с ключами ssh и расположить бекап в каталоге с именем ssh. secure=true означает что данные будут запаролены, а zip что будут сжаты, versions=true означает что каждый новый бекап будет создавать новую копию ~/.ssh помеченную датой. Описание того какие есть ключи и как они работают друг с другом есть внутри скрипта, вместе с примерами уже готовой настройки.

Ключи можно опускать (не указывать) обязательными являются только source и dest Не указанные ключи считаются заданными как false так что вот такая запись валидна

  • {source='~/Изображения/', dest='картинки'}

И означает сделать копию каталога ~/Изображения в каталоге картинки внутри общего каталога бекапа backup_path=... при этом если это второй или последующий бекап и в каталоге ~/Изображения/ была удалена картинка, она не будет удалена в каталоге картинки это сделано специально, дабы максимизировать сохраняемые данные. Если нужна точная копия с удалением того чего уже нет в каталоге источнике то нужно дополнительно явно указать опцию mirror=true это же правило работает если включить флаг zip=true будет всё тоже самое, но уже в виде архива.

На заметку

В каталоге относительно котрого исполняется скрипт будет лог бекапа, на рабочий стол будут приходить уведомление о текущем статусе выполнения, в случае ошибки будет показaн код возврата В лог попадает информация о том какая именно команда потерпела неудачу, пароль присутцвующий в команде заменяется на звёздочки. В зависимости от типа настроенного бекапа(первый бекап будет всегда долгим), а вот последующие при отсуцтвии изменений будут быстрыми исключение это mirror и versions оба создают точную копию с нуля, а не пытаются обновить текущее содержимое бекапа. В случае если любая программа вернёт код возврата отличный от 0 выполнение всего бекапа прерывается, и повторно он не запустится пока не будет удалён lock файл, это сделано специально, чтобы выяснить причину, исправить её и в ручном режиме удалить lock файл название котрого есть в срипте, в логах и уведомлении на рабочий стол.:

Если вы бекапите например ~./vimrc в dest каталог myvimrc то он будет там лежать как есть, с точкой. Так что так же чтобы его увидеть в каталоге бекапа нужно нажимать ctrl+h. Ну, я так. На всякий случай.

Удалять из бекапов лишнее, и вообще контролировать влезет ли всё, это ваша забота =)
Нет опции отключения уведомлений. Предпочитаю явно знать что всё прошло гладко.
Логи бекапа тоже руками удалять.

Дадада, пароль на zip для ssh и gpg ключей хахахаха, но хоть что-то.
Сам внешний накопитель держите шифрованным если туда важное сохраняется.

Сам сриптик. Взял его как есть.

#!/usr/env lua
local backup_rule =
{
    --каталог куда будут размещаться все бекапы
    backup_path = '/media/$USER/STORAGE_SSD/backup';
    --пароль если используется secure=true, лучше использовать файл с паролем
    backup_pass = nil;
    --пароль для важныйх файлов, можно записать в файл дабы не светить
    backup_pass_file = "/home/$USER/Документы/backup_pass";
    ---------------------------------------------------------------------------
    backup_list =
    {
    -- backup critical --
    {secure=true, zip=true, versions=true, source='~/.ssh/',     dest='ssh'    };
    {secure=true, zip=true, versions=true, source='~/.gnupg/',   dest='gpg'    };
    {secure=true, zip=true, mirror=true,   source='~/.config/',  dest='cfg'    };
    {secure=true, zip=true, mirror=true,   source='~/.mozilla/', dest='firefox'};
    {secure=true, zip=true, mirror=true,   source='~/Документы/',dest='doc'    };

    -- diffrerent media --
    {secure=false,zip=true, mirror=true, source='~/Книги/', dest='book'};
    {secure=false,zip=true, mirror=true, source='~/Музыка/',dest='music'};

    -- backup multimedia --
    {secure=false, zip=false, versions=false, source='~/FAMILY_ARCHIVE/', dest='family'};

    -- backup dev stuff  --
    {secure=false, zip=false, versions=true, source='~/.gitconfig',dest='gitconfig'};
    {secure=false, zip=false, versions=true, source='~/.vimrc',    dest='vimrc'};
    {secure=false, zip=false, versions=true, source='~/.bashrc',   dest='bashrc'};
    {secure=false, zip=true,  versions=true, source='~/.vim/',     dest='vim'};

    -- backups source code --
    {secure=false, zip=true, mirror=true, source='/mnt/STORAGE/', dest='code'};

    };
};
-------------------------------------------------------------------------------
-- :secure=true   - шифровать ли сжатый бекап с паролем.
--                  создать архив и запаролить, zip должен быть zip=true
--                  явное указание zip=false или отсуцтвие ключа создаст ошибку
-- ----------------------------------------------------------------------------
-- :secure=false  - тоже самое поведение что и при zip=false
-- ----------------------------------------------------------------------------
-- :zip=true      - создать архив и добавить в него файлы если их нет в архиве
--                  если version=false то обновлять архив, добавляя новые
--                  файлы и обновля существующие, не удаляет отсуцтвующие
-------------------------------------------------------------------------------
-- :zip=false     - создавать бекап в каталоге dest если versions=false
--                  то клонировать source в dest, при повторном бекапе добавлять
--                  новые файлы и обновлять текущие, не удалять отсуцтвующие
--                  если versions=true создавать отдельный бекап в новом
--                  каталоге с датой бекапа, полностью отельный бекап.
-------------------------------------------------------------------------------
-- :versions=true - если zip=false то создать новый каталог с датой бекапа
--                  если zip=true  то создать новый архив с датой бекапа
-------------------------------------------------------------------------------
-- :mirror=true   - если zip=true то создаётся точная сжатая копия источника
--                  если при этом versions=false то текущий архив удаляет из
--                  себя файлы которых больше нет в источнике
--                  если zip=false то вместо архива создаётся точная копия
--                  источника с удалением файлов из каталога бекапа если их
--                  нет в источнике, тоже самое зеркалирование/клонирование
-------------------------------------------------------------------------------
-- :source        - файл или каталог который нужно бекапить, каталоги
--                  обрабатываются рекурсивно бекапя всё что есть
-------------------------------------------------------------------------------
-- :dest          - каталог внутри носителя для бекапа, оно же префикс
--                  добавляющийся к каталогам и/или архивам при versions=true
--                  отражает то бекап чего делается ОБЯЗАН БЫТЬ УНИКАЛЬНЫМ!!!!
-------------------------------------------------------------------------------
--        Если какого либо ключа нет то он считается равным false
-------------------------------------------------------------------------------
-- В случае если zip mkdir или rsync завершаться с кодом отличным от нуля
-- бекап тут же прекращается с уведомлением на рабочий стол и в лог ошибок
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
---- исполняет все команды, в случае ошибки прерывает всю работу
-------------------------------------------------------------------------------
local function execute(rule,command,exit_if_fail)
    local success, meta, code = os.execute(command..' >> backup-info.log');
    if (not success) then
       -- hide pass from output
       -- info log and messages
       if rule.backup_pass then
          command = command:gsub(rule.backup_pass,"********");
       end
       local msg = string.format('BACKUP ERROR %s %s %s',command,meta,code);
       io.stderr:write(msg..'\n');
       io.open('backup-error.log','a+'):write(msg);
       execute({},'notify-send  "'..msg..'" -u critical',false);
       if (exit_if_fail == true) then
          os.exit(127);
       end
       return success;
    end
    return success;
end
-------------------------------------------------------------------------------
--- информирует об ошибке и прерывает всю работу
-------------------------------------------------------------------------------
local function backup_fail(msg)
      io.stderr:write(msg..'\n');
      io.open('backup-error.log','a+'):write('\n'..msg..'\n');
      execute({},'notify-send -u critical "'..msg..'"',false);
      os.exit(127);
end
-------------------------------------------------------------------------------
--- просто информирует
-------------------------------------------------------------------------------
local function backup_info(msg)
      io.stdout:write(msg..'\n');
      local log = io.open('backup-info.log','a+');
      log:write('\n'..msg..'\n');
      log:close();
      execute({},'notify-send -u normal "'..msg..'"',false);
end
-------------------------------------------------------------------------------
--- проверяет используется ли в конфигурации пароль
-------------------------------------------------------------------------------
function check_need_pass(rule)
    for name,val in pairs(rule.backup_list) do
        if val.secure and val.secure == true then
           return true;
        end
    end
    return false;
end
-------------------------------------------------------------------------------
--- делает бекап K.O. :)
-------------------------------------------------------------------------------
local function make_backup(rule)
    if (rule.backup_path) then
       -- replaice $USER in path if we have ite
       rule.backup_path = rule.backup_path:gsub('$USER',os.getenv('USER'));
    else
       backup_fail('BACKUP ERROR backup_path not set, no place to save backup',true);
    end
    -- we use password?
    if (check_need_pass(rule) == true) then
        -- check pass contained in configuration
        if not rule.backup_pass and not rule.backup_pass_file then
           backup_fail('BACKUP ERROR you use secure option but backup_pass or backup_pass_file no set!',true);
        end
        -- if pass_file set read the password
        -- and override/write rule.backup_pass
        if (rule.backup_pass_file) then
           -- replaice $USER in path if we have ite
           rule.backup_pass_file = rule.backup_pass_file:gsub('$USER',os.getenv('USER'));
           local pass_file = io.open(rule.backup_pass_file);
           if (pass_file) then
              if rule.backup_pass then
                 backup_info('BACKUP WARNING rewrite backup_pass from backup_pass_file');
              end
              rule.backup_pass = pass_file:read('*l');
           else
              backup_fail('BACKUP ERROR '..rule.backup_pass_file..' no readable!',true);
           end
           pass_file:close();
        end
        -- maybe pass use only numbers force to string
        rule.backup_pass = tostring(rule.backup_pass);
        -- check small pass, no need but jut be
        if not rule.backup_pass or #rule.backup_pass <= 4 then -- kek cheburek 
           backup_info('BACKUP WARNING you backup_pass small, less or equal 4 symbols');
        end
    end
    -- info about starting
    backup_info("BACKUP START "..os.date());
    --first check, we have storage and access?
    execute(rule,'mkdir -p '..rule.backup_path, true);
    -- lockfile + uuid for exclude collisions
    local lockfile = '.lock-938448fc-1742-43e9-bff8-e2acf6d29710';
    -- check/create lock file
    -- if backup failed you self
    -- delete lock file your hands
    if not io.open(rule.backup_path..'/'..lockfile,'r') then
       io.open(rule.backup_path..'/'..lockfile,'w'):write('lock');
    else
       backup_fail("OTHER BACKUP PROCESS IS WORKING, SKIPPING THIS PROCESS\n"..
                   "IF YOU SURE DELETE LOCK FILE "..rule.backup_path..'/'..lockfile..'\n',true);
       ----------------------------------------------------------------------
       -- uncomment if after backup error no need locked backup for fix error
       ----------------------------------------------------------------------
       -- os.remove(rule.backup_path..'/'..lockfile);
    end
    for id,item in pairs(rule.backup_list) do
        local date = os.date("%Y-%m-%d_%X");
        local path = rule.backup_path;
        local pass = rule.backup_pass;
        local dest = item.dest;
        local source = item.source;

        if (not source) then
           backup_fail('BACKUP ERROR source path not set, what files backup?',true)
        end

        if (not dest) then
           backup_fail('BACKUP ERROR dest path not set, wheare dir name to save?',true)
        end

        execute(rule,'mkdir -p '..path..'/'..dest,true);
        backup_info('BACKUP: '..source);

        ------------------- secure: versionize backup data ---------------------
        ------------------------------------------------------------------------
        if (item.secure and item.zip and item.versions) then
            local target = string.format('%s/%s/%s-%s.zip',path,dest,dest,date);
            execute(rule,'zip -r9P '..pass..' '..target..' '..source,true);
            goto next_item;
        end
        ---------------- secure: update and append backup data -----------------
        ------------------------------------------------------------------------
        if (item.secure and item.zip and not item.versions) then
            local target = string.format('%s/%s/%s.zip',path,dest,dest);
            local opts = item.mirror and ' -rFS9P ' or ' -ru9P ';
            execute(rule,'zip '..opts..' '..pass..' '..target..' '..source,true);
            goto next_item;
        end
        ----------- no secure: zipped update and append backup data ------------
        ------------------------------------------------------------------------
        if (not item.secure and item.zip and not item.versions) then
           local target = string.format('%s/%s/%s.zip',path,dest,dest);
           local opts = item.mirror and ' -rFS9 ' or ' -ru9 ';
           execute(rule,'zip '..opts..' '..target..' '..source,true);
           goto next_item;
        end
        ----- no secure: zipped, versionize update and append backup data ------
        ------------------------------------------------------------------------
        if (not item.secure and item.zip and item.versions ) then
           local target = string.format('%s/%s/%s-%s.zip',path,dest,dest,date);
           execute(rule,'zip -r9 '..target..' '..source,true);
           goto next_item;
        end
        --------- no secure: versionize update and append, no delete -----------
        ------------------------------------------------------------------------
        if (not item.secure and not item.zip and item.versions ) then
           local target = string.format('%s/%s/%s-%s/',path,dest,dest,date);
           execute(rule,'mkdir -p '..target);
           execute(rule,'rsync -arv '..source..' '..target,true);
           goto next_item;
        end
        ----------------- no secure: update and append, no delete --------------
        ------------------------------------------------------------------------
        if (not item.secure and not item.zip and not item.versions) then
           local target = string.format('%s/%s/',path,dest);
           execute(rule,'mkdir -p '..target);
           local opts = item.mirror and ' -arv --delete ' or ' -arv ';
           execute(rule,'rsync '..opts..' '..source..' '..target,true);
           goto next_item;
        end
        ------------------------------------------------------------------------
        if (item.secure and not item.zip) then
            backup_fail('BACKUP ERROR UNSUPPORT SECURE WITCHOUT ZIP ARCHIVE :(');
        end
        ::next_item::
    end
    backup_info("BACKUP END "..os.date());
    os.remove(rule.backup_path..'/'..lockfile);
end

-- check depends
execute({},"zip --version",true);
execute({},"rsync --version",true);
--execute({},"mkdir --version",true);
execute({},"notify-send --version",true);
-- start backup now
make_backup(backup_rule)

Всё. Досвиданья.

 , , , ,

LINUX-ORG-RU
()

И Снег и Сугробы и Ёлки на вашем ПеКа

Форум — Talks
--           Зависимости              -
---------------------------------------
-- curl    -  загрузка ёлочек         -
-- scrot   -  снимок рабочего стола   -
-- love2d  -  запуск снежка и ёлочек  -
---------------------------------------
-- Создать каталог `новый_год`        -
-- Создать в каталоге файл `main.lua` -
-- Скопировать в файл этот код.       -
-- Используя терминал запутсить из    -
-- созданного каталога программу      -
--                                    -
--   Вот так запустить  `love .`      -
---------------------------------------
--            Управление              -
---------------------------------------
-- Нажать 1 - установит фон рабочего  -
--            стола в программе, как  -
--            будто на нём идёт снег  -
---------------------------------------
-- Нажать 2 - убрать сугробы, но снег -
--            то падает и они вырастут-
--            снова, но другие уже :) -
---------------------------------------
-- Нажать 3 - Загрузить и отобразить  -
--            просту ёлочку           -
---------------------------------------
-- Нажать 4 - Загрузить и установить  -
--            нарядную новогоднюю ёлку-
---------------------------------------
-- Нажать 5 - Вернуть чёрный фон      -
---------------------------------------
--    Нажать esc или q для выхода     -
---------------------------------------
-- Программа проверяет время и если   -
---------------------------------------
-- Время 23:45 - Загружается и отобра -
--               жается простая ёлочка-
---------------------------------------
-- Время 00:00 - Загружается и отобра -
--               жается нарядная ёлка -
---------------------------------------
-- Эти действия по времени происходят -
-- автоматически предупреждая о под-  -
-- ходе и наступлении нового года гы  -
---------------------------------------
-- Устанавливать ли фон автоматически -
---------------------------------------
local autobackround = false; --вкл/выкл
---------------------------------------
local sugrob = {}
local snow   = {};
local snow_opacity = 0;
local screen_width = 0;
local screen_height= 0;
local tree_image = nil;
local background = nil;
local tree_opacity = 0;
local tree_url =
{
  [1] = 'https://i.ibb.co/f24xCMp/1.png';
  [2] = 'https://i.ibb.co/KLpSKdZ/2.png';
};
local once_call_tree_1 = true;
local once_call_tree_2 = true;
----------------------------------------
function get_app_path()
    return love.filesystem.getSaveDirectory()..'/';
end
function load_tree(id)
   if love.system.getOS() == 'Android' then
      if id == 1 then
         tree_image = love.graphics.newImage('tree_1.png');
      end
      if id == 2 then
         tree_image = love.graphics.newImage('tree_2.png');
      end
      tree_opacity = 0;
      return;
   end
   local path = get_app_path();
   os.execute('curl '..tree_url[id]..' --output '..path..'tree.png');
   if love.filesystem.getInfo('tree.png')  then
      tree_image = love.graphics.newImage('tree.png');
      tree_opacity = 0;
   end
end
function draw_tree()
    if tree_image then
    local w = love.graphics.getWidth()
    local h = love.graphics.getHeight()
    local sx,sy = w/tree_image:getWidth(),h/tree_image:getHeight();
    love.graphics.setColor(1,1,1,tree_opacity);
       love.graphics.draw(tree_image,0,0,0,sx,sy);
    end
end
function update_tree(dt)
    if tree_opacity < 1 then
       tree_opacity = tree_opacity + 0.1 * dt;
    end
end
function create_sugrob()
    if love.system.getOS() == 'Android' then
       return;
    end
    local x = love.graphics.getWidth()
    local y = love.graphics.getHeight()
    local s = x/y;
    for i=1,50 do
        local xp = love.math.random(0,x);
        local cs = love.math.random(s*25,s*75);
        table.insert(sugrob,{'fill',xp,y,cs,150})
    end
end
function draw_sugrob()
    if love.system.getOS() == 'Android' then
       return;
    end
    love.graphics.setColor(0.95,0.95,1,1);
    for i=1,#sugrob do
        love.graphics.circle(sugrob[i][1],sugrob[i][2],sugrob[i][3]+sugrob[i][5],sugrob[i][4]);
    end
end
function update_sugrob(dt)
    local x,y = love.window.getMode();
    for i=1,#sugrob do
        if sugrob[i][5] > 0 then
           sugrob[i][5] = sugrob[i][5] - love.math.random(0.0,i*0.05)
        end
    end
end
function create_snow()
    local x = love.graphics.getWidth()
    local y = love.graphics.getHeight()
    local s = x/y;
    for i=1,60 do
        local xp = love.math.random(0,x);
        local xy = love.math.random(0,y);
        local cs = love.math.random(s*1,s*10);
        table.insert(snow,{'fill',xp,xy,cs,0})
    end
end
function draw_snow()
    for i=1,#snow do
        love.graphics.setColor(0.95,0.95,1,snow_opacity);
        love.graphics.circle(snow[i][1],snow[i][2],snow[i][3],snow[i][4]+snow_opacity);
    end
end
function lerp(from, to, t)
  return t < 0.5 and from + (to-from)*t or to + (from-to)*(1-t)
end
function update_snow(dt)
    local x,y = love.window.getMode();
    if snow_opacity < 0.7 then
       snow_opacity = snow_opacity + 0.1 * dt;
    end
    for i=1,#snow do
        snow[i][3] = snow[i][3] + i * 0.5;
        if snow[i][5] == 1 then
           snow[i][2] = snow[i][2] + i * 0.25 + i * 0.5 + love.math.random(0,3);
       elseif snow[i][5] == 0 then
           snow[i][2] = snow[i][2] - i * 0.25 + i * 0.5 + love.math.random(0,3);
        end
        if(snow[i][3] > y + snow[i][4]) then
          snow[i][3] = -snow[i][4];
          snow[i][2] = love.math.random(0,x);
          snow[i][5] = love.math.random(-1,1);
        end
    end
end
local button_colors =
{
    {0.5,0.0,0.0,1},
    {0.0,0.5,1.0,1},
    {0.0,0.0,1.0,1},
    {0.5,0.5,1.0,1},
    {0.0,0.5,1.0,1},
}
local button_circles = {}
local show_controls  = false;
function create_controls()
   local x = love.graphics.getWidth()
   local y = love.graphics.getHeight()
   local pose_y = (y * 0.5);
   local radius = (x * 0.01) * 5;
   for i=1,5 do
       local pose_x = radius*i * 3.5;
       table.insert(button_circles,{'fill',pose_x,pose_y,radius,button_colors[i]})
   end
end
function draw_controls()
   if show_controls then
      local b = button_circles;
      for i=1,#button_circles do
          love.graphics.setColor(unpack(b[i][5]));
          love.graphics.circle(b[i][1],b[i][2],b[i][3],b[i][4]);
      end
   end
end
function update_controls(px,py)
   if show_controls then
       local b = button_circles;
       for i=1,#button_circles do
           local cx,cy,cr = b[i][2],b[i][3],b[i][4];
           if((px - cx)^2 + (py - cy)^2 < cr^2) then
              if i == 1 then set_background(); end
              if i == 2 then sugrob = {}; create_sugrob(); end
              if i == 3 then load_tree(1);   end
              if i == 4 then load_tree(2);   end
              if i == 5 then background=nil; end
           end
       end
    end
end
function love.displayrotated(index, orientation)
    sugrob = {};
    create_sugrob();
    snow = {};
    create_snow();
    snow_opacity = 0;
    tree_opacity = 0;
    button_circles = {};
    create_controls();
end
function love.mousepressed(x,y)
    if love.system.getOS() ~= 'Android' then
       update_controls(x,y)
       show_controls = not show_controls;
    end
end
function love.touchpressed(b,x,y)
    update_controls(x,y)
    show_controls = not show_controls;
end
function love.load()
    love.filesystem.write('init','x',1);
    if love.filesystem.getInfo('icon.png') then
       love.window.setIcon(love.image.newImageData('icon.png'));
    end
    love.window.setTitle("Маааленькой ёёёлочке холодно зимооой.")
    if love.system.getOS() == 'Android' then
       love.window.setMode(1280,720,{fullscreen=true,resizable=true,vsync=true});
       screen_width = love.graphics.getWidth()
       screen_height = love.graphics.getHeight()
    else
       love.window.setMode(0,0,{resizable=true,borderless=true})
       love.window.setFullscreen(true,'desktop');
       screen_width = love.graphics.getWidth()
       screen_height = love.graphics.getHeight()
       love.window.setMode(0,0,{resizable=true,borderless=true})
       love.window.maximize()
    end
    create_sugrob()
    create_snow()
    create_controls()
end
function set_background()
   if love.system.getOS() == 'Android' then
      return;
   end
   local x,y = love.window.getMode();
   love.window.minimize()
   love.timer.sleep(1)
   local path = get_app_path()
   local status = os.execute('scrot -a '..screen_width-x..','..screen_height-y..','..x..','..y..' -o '..path..'screen.png');
   love.window.restore()
   love.window.maximize()
   if love.filesystem.getInfo('screen.png') then
      background = love.graphics.newImage('screen.png');
   end
end
if autobackround then
   set_background()
end
function love.keypressed(key)
   if key == 'q' or key == 'escape' then
      love.event.quit()
   end
   if key == '1' then set_background(); end
   if key == '2' then sugrob = {}; create_sugrob(); end
   if key == '3' then load_tree(1);   end
   if key == '4' then load_tree(2);   end
   if key == '5' then background=nil; end
end

function love.update(dt)
    if os.date('%H%M') == '2345' then
       if once_call_tree_1 then
          load_tree(1);
          once_call_tree_1 = false;
       end
    end
    if os.date('%H%M') == '0000' then
       if once_call_tree_2 then
          load_tree(2);
          once_call_tree_2 = false;
       end
    end
    update_snow(dt)
    update_tree(dt)
    update_sugrob(dt)
end
function love.draw()
    if background then
       love.graphics.setColor(1,1,1,1);
       love.graphics.draw(background)
    end
    draw_tree();
    draw_sugrob();
    draw_snow();
    draw_controls();
end

Внешний вид. Видео. Досвиданья.


По просьбе @apt_install_lrzsz сборки


Добавил кнопки появляются и исчезают по нажатию на экране.
Как альтернатива нажатия 1,2,3,4,5.
На Андроиде часть не работает.


В истории правок этого сообщения есть прошлая версия, если с этой пробелмы, но прошлая только для ПК.

 , , ,

LINUX-ORG-RU
()