Now faster. And with more Jenny Holzer.
This commit is contained in:
parent
bd5b1b6267
commit
7878aa1d45
10 changed files with 528 additions and 64 deletions
|
|
@ -1,6 +1,12 @@
|
||||||
|
|
||||||
all: main.c font.c font.h color.c color.h
|
all: libml libbdf
|
||||||
gcc -shared -fPIC -std=gnu11 -Wall -lm -o libbdf.so -g -O0 main.c font.c color.c
|
|
||||||
|
|
||||||
|
libml: usb.c color.c color.h
|
||||||
|
gcc -shared -fPIC -std=gnu11 -Wall -lm -lusb-1.0 -o libml.so -g usb.c color.c
|
||||||
|
|
||||||
|
libbdf: main.c font.c font.h color.c color.h
|
||||||
|
gcc -shared -fPIC -std=gnu11 -Wall -lm -o libbdf.so -g main.c font.c color.c
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm libbdf.so
|
rm libbdf.so libml.so
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,13 @@
|
||||||
|
|
||||||
/* For easier memsetting we use an inverted alpha channel, i.e. 0 ≘ fully opaque; 255 ≘ fully transparent */
|
/* For easier memsetting we use an inverted alpha channel, i.e. 0 ≘ fully opaque; 255 ≘ fully transparent */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t r;
|
uint8_t r, g, b, a;
|
||||||
uint8_t g;
|
|
||||||
uint8_t b;
|
|
||||||
uint8_t a;
|
|
||||||
} color_t;
|
} color_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t r, g, b;
|
||||||
|
} rgb_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
color_t *data;
|
color_t *data;
|
||||||
size_t w;
|
size_t w;
|
||||||
|
|
|
||||||
259
host/default.lines
Normal file
259
host/default.lines
Normal file
|
|
@ -0,0 +1,259 @@
|
||||||
|
\x1B[38;5;214mabstraction is a type of decadence
|
||||||
|
\x1B[38;5;214mit's important to stay clean on all levels
|
||||||
|
\x1B[38;5;214mexpiring for love is beautiful but stupid
|
||||||
|
\x1B[38;5;214mlack of charisma can be fatal
|
||||||
|
\x1B[38;5;214mambition is just as dangerous as complacency
|
||||||
|
\x1B[38;5;214mslipping into madness is good for the sake of comparison
|
||||||
|
\x1B[38;5;214mplanning for the future is escapism
|
||||||
|
\x1B[38;5;214mtrue freedom is frightful
|
||||||
|
\x1B[92mMate Light\x1B[0m powered by \x1B[95mData Becker™ \x1B[96mLaufschriftstudio 2000® Platinum Edition
|
||||||
|
\x1B[38;5;214mreligion causes as many problems as it solves
|
||||||
|
\x1B[38;5;214mdisorganization is a kind of anesthesia
|
||||||
|
\x1B[38;5;214mpursuing pleasure for the sake of pleasure will ruin you
|
||||||
|
\x1B[38;5;214manger or hate can be a useful motivating force
|
||||||
|
\x1B[38;5;214mjust believing something can make it happen
|
||||||
|
\x1B[38;5;214mtrading a life for a life is fair enough
|
||||||
|
\x1B[38;5;214mlisten when your body talks
|
||||||
|
\x1B[38;5;214mfake or real indifference is a powerful personal weapon
|
||||||
|
\x1B[38;5;214mcalm is more conductive to creativity than is anxiety
|
||||||
|
\x1B[38;5;214mthere are too few immutable truths today
|
||||||
|
\x1B[38;5;214mbeing happy is more important than anything else
|
||||||
|
\x1B[38;5;214mit can be helpful to keep going no matter what
|
||||||
|
\x1B[38;5;214mbelieving in rebirth is the same as admitting defeat
|
||||||
|
\x1B[38;5;214mit's vital to live in harmony with nature
|
||||||
|
\x1B[38;5;214mdisgust is the appropriate response to most situations
|
||||||
|
\x1B[38;5;214mnothing upsets the balance of good and evil
|
||||||
|
\x1B[38;5;214mrandom mating is good for debunking sex myths
|
||||||
|
\x1B[38;5;214manimalism is perfectly healthy
|
||||||
|
\x1B[92mMate Light\x1B[0m powered by \x1B[95mSiemens™ \x1B[96mLaufschrift® v.0.1.2b fuer Intel™ Pentium®
|
||||||
|
\x1B[38;5;214msalvation can't be bought and sold
|
||||||
|
\x1B[38;5;214mextreme self-consciousness leads to perversion
|
||||||
|
\x1B[38;5;214mroutine small excesses are worse than then the occasional debauch
|
||||||
|
\x1B[38;5;214mwe must make sacrifices to maintain our quality of life
|
||||||
|
\x1B[38;5;214mmuch was decided before you were born
|
||||||
|
\x1B[38;5;214ma positive attitude means all the difference in the world
|
||||||
|
\x1B[38;5;214myou must have one grand passion
|
||||||
|
\x1B[38;5;214mit is heroic to try to stop time
|
||||||
|
\x1B[38;5;214moccasionally principles are more valuable than people
|
||||||
|
\x1B[38;5;214ma sense of timing is the mark of genius
|
||||||
|
\x1B[38;5;214mexpressing anger is necessary
|
||||||
|
\x1B[38;5;214mroutine is a link with the past
|
||||||
|
\x1B[38;5;214mtorture is barbaric
|
||||||
|
\x1B[38;5;214melaboration is a form of pollution
|
||||||
|
\x1B[38;5;214mpeople are responsible for what they do unless they are insane
|
||||||
|
\x1B[38;5;214mromantic love was invented to manipulate women
|
||||||
|
\x1B[38;5;214msex differences are here to stay
|
||||||
|
\x1B[38;5;214mthe unattainable is invariable attractive
|
||||||
|
\x1B[38;5;214ma man can't know what it is to be a mother
|
||||||
|
\x1B[38;5;214mthere's nothing except what you sense
|
||||||
|
\x1B[38;5;214msurvival of the fittest applies to men and animals
|
||||||
|
\x1B[38;5;214man elite is inevitable
|
||||||
|
\x1B[38;5;214mit is man's fate to outsmart himself
|
||||||
|
\x1B[38;5;214mpeople won't behave if they have nothing to lose
|
||||||
|
\x1B[38;5;214mpeople are nuts if they think they are important
|
||||||
|
\x1B[38;5;214many surplus is immoral
|
||||||
|
\x1B[38;5;214mremember you always have freedom of choice
|
||||||
|
\x1B[38;5;214ma lot of professionals are crackpots
|
||||||
|
\x1B[38;5;214msacrificing yourself for a bad cause is not a moral act
|
||||||
|
\x1B[38;5;214mit's better to be naive than jaded
|
||||||
|
\x1B[38;5;214mdependence can be a meal ticket
|
||||||
|
\x1B[38;5;214mkeep something in reserve for emergencies
|
||||||
|
\x1B[38;5;214mold friends are better left in the past
|
||||||
|
\x1B[38;5;214mmoney creates taste
|
||||||
|
\x1B[38;5;214mto disagree presupposes moral integrity
|
||||||
|
\x1B[38;5;214mbeing sure of yourself means you're a fool
|
||||||
|
\x1B[38;5;214myou must know where you stop and the world begins
|
||||||
|
\x1B[38;5;214mideals are replaced by conventional goals at a certain age
|
||||||
|
\x1B[38;5;214mmost people are not fit to rule themselves
|
||||||
|
\x1B[38;5;214mguilt and self-laceration are indulgences
|
||||||
|
\x1B[38;5;214mit's better to be lonely than to be with inferior people
|
||||||
|
\x1B[38;5;214mdying and coming back gives you considerable perspective
|
||||||
|
\x1B[38;5;214mabsolute submission can be a form of freedom
|
||||||
|
\x1B[38;5;214mfear is the greatest incapacitator
|
||||||
|
\x1B[38;5;214mholding back protects your vital energies
|
||||||
|
\x1B[38;5;214mwhen something terrible happens people wake up
|
||||||
|
\x1B[38;5;214mensure that your life stays in flux
|
||||||
|
\x1B[38;5;214mbeing judgmental is a sign of life
|
||||||
|
\x1B[38;5;214mfreedom is a luxury not a necessity
|
||||||
|
\x1B[38;5;214mdrama often obscures the real issues
|
||||||
|
\x1B[38;5;214mwith perseverance you can discover any truth
|
||||||
|
\x1B[38;5;214mhumanism is obsolete
|
||||||
|
\x1B[38;5;214myou must disagree with authority figures
|
||||||
|
\x1B[38;5;214mmyth can make reality more intelligible
|
||||||
|
\x1B[38;5;214mhabitual contempt doesn't reflect a finer sensibility
|
||||||
|
\x1B[38;5;214msterilization is a weapon of the rulers
|
||||||
|
\x1B[38;5;214myour oldest fears are the worst ones
|
||||||
|
\x1B[38;5;214moffer very little information about yourself
|
||||||
|
\x1B[38;5;214mthreatening someone sexually is a horrible act
|
||||||
|
\x1B[38;5;214mbeing alone with yourself is increasingly unpopular
|
||||||
|
\x1B[38;5;214myou are a victim of the rules you live by
|
||||||
|
\x1B[38;5;214mto volunteer is reactionary
|
||||||
|
\x1B[38;5;214myou have to hurt others to be extraordinary
|
||||||
|
\x1B[38;5;214mabuse of power comes as no surprise
|
||||||
|
\x1B[38;5;214mrecluses always get weak
|
||||||
|
\x1B[38;5;214mawful punishment awaits really bad people
|
||||||
|
\x1B[38;5;214mchildren are the most cruel of all
|
||||||
|
\x1B[38;5;214mthe cruelest disappointment is when you let yourself down
|
||||||
|
\x1B[38;5;214mgo all out in romance and let the chips fall where they may
|
||||||
|
\x1B[38;5;214mthe only way to be pure is to stay by yourself
|
||||||
|
\x1B[38;5;214mspending too much time on self-improvement is antisocial
|
||||||
|
\x1B[38;5;214mknowing yourself lets you understand others
|
||||||
|
\x1B[38;5;214mresolutions serve to ease our conscience
|
||||||
|
\x1B[38;5;214mwar is a purification rite
|
||||||
|
\x1B[38;5;214mgiving free rein to your emotions is an honest way to live
|
||||||
|
\x1B[38;5;214mpeople who go crazy are too sensitive
|
||||||
|
\x1B[38;5;214mit's better to study the living fact than to analyze history
|
||||||
|
\x1B[38;5;214mmen are not monogamous by nature
|
||||||
|
\x1B[38;5;214mclass action is a nice idea with no substance
|
||||||
|
\x1B[38;5;214mdreaming while awake is a frightening contradiction
|
||||||
|
\x1B[38;5;214millness is a state of mind
|
||||||
|
\x1B[38;5;214myou are responsible for constituting the meaning of things
|
||||||
|
\x1B[38;5;214mit's good to give extra money to charity
|
||||||
|
\x1B[38;5;214mit's better to be a good person than a famous person
|
||||||
|
\x1B[38;5;214moften you should act like you are sexless
|
||||||
|
\x1B[38;5;214mpeople who don't work with their hands are parasites
|
||||||
|
\x1B[38;5;214mmonomania is a prerequisite of success
|
||||||
|
\x1B[38;5;214mchasing the new is dangerous to society
|
||||||
|
\x1B[38;5;214mrevolution begins with changes in the individual
|
||||||
|
\x1B[38;5;214mselflessness is the highest achievement
|
||||||
|
\x1B[38;5;214msymbols are more meaningful than things themselves
|
||||||
|
\x1B[38;5;214ma strong sense of duty imprisons you
|
||||||
|
\x1B[38;5;214mautomation is deadly
|
||||||
|
\x1B[38;5;214mopacity is an irresistible challenge
|
||||||
|
\x1B[38;5;214mmurder has its sexual side
|
||||||
|
\x1B[38;5;214mat times inactivity is preferable to mindless functioning
|
||||||
|
\x1B[38;5;214mmostly you should mind your own business
|
||||||
|
\x1B[38;5;214mthe mundane is to be cherished
|
||||||
|
\x1B[38;5;214mselfishness is the most basic motivation
|
||||||
|
\x1B[38;5;214msloppy thinking gets worse over time
|
||||||
|
\x1B[38;5;214myou can't expect people to be something they're not
|
||||||
|
\x1B[38;5;214mambivalence can ruin your life
|
||||||
|
\x1B[38;5;214munquestioning love demonstrates largesse of spirit
|
||||||
|
\x1B[38;5;214mlabor is a life-destroying activity
|
||||||
|
\x1B[38;5;214mgovernment is a burden on the people
|
||||||
|
\x1B[38;5;214mdecency is a relative thing
|
||||||
|
\x1B[38;5;214myour actions ae pointless if no one notices
|
||||||
|
\x1B[38;5;214mdying should be as easy as falling off a log
|
||||||
|
\x1B[38;5;214martificial desires are despoiling the earth
|
||||||
|
\x1B[38;5;214mcategorizing fear is calming
|
||||||
|
\x1B[38;5;214mit's just an accident that your parents are your parents
|
||||||
|
\x1B[38;5;214meven your family can betray you
|
||||||
|
\x1B[38;5;214mbad intentions can yield good results
|
||||||
|
\x1B[38;5;214mif you have many desires your life will be interesting
|
||||||
|
\x1B[92mMate Light\x1B[93m@\x1B[92mPlay store or \x1B[94;101mtcp://ml.jaseg.net:1337\x1B[0;91m ♥
|
||||||
|
\x1B[38;5;214mit's not good to operate on credit
|
||||||
|
\x1B[38;5;214mdescription is more important than metaphor
|
||||||
|
\x1B[38;5;214mhiding your emotions is despicable
|
||||||
|
\x1B[38;5;214mthe desire to reproduce is a death wish
|
||||||
|
\x1B[38;5;214mpush yourself to the limit as often as possible
|
||||||
|
\x1B[38;5;214mextreme behavior has its basis in pathological psychology
|
||||||
|
\x1B[38;5;214mthere's nothing redeeming in toil
|
||||||
|
\x1B[38;5;214myou are guileless in your dreams
|
||||||
|
\x1B[38;5;214manything is a legitimate area of investigation
|
||||||
|
\x1B[38;5;214mdeviants are sacrificed to increase group solidarity
|
||||||
|
\x1B[38;5;214myou can't fool others if you're fooling yourself
|
||||||
|
\x1B[38;5;214myou can understand someone of your sex only
|
||||||
|
\x1B[38;5;214mraise boys and girls the same way
|
||||||
|
\x1B[38;5;214mit's not good to hold too many absolutes
|
||||||
|
\x1B[38;5;214mkilling is unavoidable but nothing to be proud of
|
||||||
|
\x1B[38;5;214myou should study as much as possible
|
||||||
|
\x1B[38;5;214malienation produces eccentrics or revolutionaries
|
||||||
|
\x1B[38;5;214mtimidity is laughable
|
||||||
|
\x1B[38;5;214mfathers often use too much force
|
||||||
|
\x1B[38;5;214mgrass roots agitation is the only hope
|
||||||
|
\x1B[38;5;214mstrong emotional attachment stems from basic insecurity
|
||||||
|
\x1B[38;5;214mrechanneling destructive impulses is a sign of maturity
|
||||||
|
\x1B[92mMate Light\x1B[0m powered by \x1B[95mApple™ \x1B[96miScroll®'
|
||||||
|
\x1B[38;5;214msometimes science advances faster than it should
|
||||||
|
\x1B[38;5;214ma sincere effort is all you can ask
|
||||||
|
\x1B[38;5;214myou owe the world not the other way around
|
||||||
|
\x1B[38;5;214mmothers shouldn't make too many sacrifices
|
||||||
|
\x1B[38;5;214mloving animals is a substitute activity
|
||||||
|
\x1B[38;5;214mchange is valuable when the oppressed become tyrants
|
||||||
|
\x1B[38;5;214msolitude is enriching
|
||||||
|
\x1B[38;5;214msometimes things seem to happen of their own accord
|
||||||
|
\x1B[38;5;214mviolence is permissible even desirable occasionally
|
||||||
|
\x1B[38;5;214mall things are delicately interconnected
|
||||||
|
\x1B[38;5;214mplaying it safe can cause a lot of damage in the long run
|
||||||
|
\x1B[38;5;214mdecadence can be an end in itself
|
||||||
|
\x1B[92mMate Light\x1B[0;91m ♥ \x1B[92mUnicode
|
||||||
|
\x1B[38;5;214meveryone's work is equally important
|
||||||
|
\x1B[38;5;214mtaking a strong stand publicizes the opposite position
|
||||||
|
\x1B[38;5;214mpain can be a very positive thing
|
||||||
|
\x1B[38;5;214mclass structure is as artificial as plastic
|
||||||
|
\x1B[38;5;214mthe world operates according to discoverable laws
|
||||||
|
\x1B[38;5;214mteasing people sexually can have ugly consequences
|
||||||
|
\x1B[38;5;214mredistributing wealth is imperative
|
||||||
|
\x1B[38;5;214maction causes more trouble than thought
|
||||||
|
\x1B[38;5;214mignoring enemies is the best way to fight
|
||||||
|
\x1B[38;5;214mnoise can be hostile
|
||||||
|
\x1B[38;5;214mwishing things away is not effective
|
||||||
|
\x1B[38;5;214mit is a gift to the world not to have babies
|
||||||
|
\x1B[38;5;214mthe sum of your actions determines what you are
|
||||||
|
\x1B[38;5;214ma name means a lot just by itself
|
||||||
|
\x1B[38;5;214mthinking too much can only cause problems
|
||||||
|
\x1B[38;5;214msin is a means of social control
|
||||||
|
\x1B[38;5;214mchildren are the hope of the future
|
||||||
|
\x1B[38;5;214min some instances it's better to die than to continue
|
||||||
|
\x1B[38;5;214mself-awareness can be crippling
|
||||||
|
\x1B[38;5;214mprivate property created crime
|
||||||
|
\x1B[38;5;214mlow expectations are good protection
|
||||||
|
\x1B[38;5;214meverything that's interesting is new
|
||||||
|
\x1B[38;5;214mdon't place to much trust in experts
|
||||||
|
\x1B[38;5;214mstupid people shouldn't breed
|
||||||
|
\x1B[38;5;214ma relaxed man is not necessarily a better man
|
||||||
|
\x1B[38;5;214mleisure time is a gigantic smoke screen
|
||||||
|
\x1B[38;5;214mexceptional people deserve special concessions
|
||||||
|
\x1B[38;5;214mstasis is a dream state
|
||||||
|
\x1B[38;5;214mgood deeds eventually are rewarded
|
||||||
|
\x1B[38;5;214menjoy yourself because you can't change anything anyway
|
||||||
|
\x1B[38;5;214mthe new is nothing but a restatement of the old
|
||||||
|
\x1B[38;5;214mit's crucial to have an active fantasy life
|
||||||
|
\x1B[38;5;214mworrying can help you prepare
|
||||||
|
\x1B[38;5;214minheritance must be abolished
|
||||||
|
\x1B[38;5;214mpeople are boring unless they are extremists
|
||||||
|
\x1B[38;5;214mconfusing yourself is a way to stay honest
|
||||||
|
\x1B[38;5;214mstarvation is nature's way
|
||||||
|
\x1B[38;5;214mhumor is a release
|
||||||
|
\x1B[38;5;214mcrime against property is relatively unimportant
|
||||||
|
\x1B[38;5;214mat times your unconsciousness is truer than your conscious mind
|
||||||
|
\x1B[38;5;214mself-contempt can do more harm than good
|
||||||
|
\x1B[38;5;214mtalking is used to hide one's inability to act
|
||||||
|
\x1B[38;5;214mthe idea of revolution is an adolescent fantasy
|
||||||
|
\x1B[38;5;214mif you live simply there is nothing to worry about
|
||||||
|
\x1B[38;5;214ma single event can have infinitely many interpretations
|
||||||
|
\x1B[38;5;214mgoing with the flow is soothing but risky
|
||||||
|
\x1B[38;5;214mmanual labor can be refreshing and wholesome
|
||||||
|
\x1B[38;5;214mpotential counts for nothing until it's realized
|
||||||
|
\x1B[38;5;214myou are the past present and future
|
||||||
|
\x1B[38;5;214mtechnology will make or break us
|
||||||
|
\x1B[38;5;214mevery achievement requires a sacrifice
|
||||||
|
\x1B[38;5;214mthe family is living on borrowed time
|
||||||
|
\x1B[38;5;214mphysical culture is second best
|
||||||
|
\x1B[38;5;214munique things must be the most valuable
|
||||||
|
\x1B[38;5;214ma solid home base builds a sense of self
|
||||||
|
\x1B[38;5;214mthe idiosyncratic has lost its authority
|
||||||
|
\x1B[38;5;214mlooking back is the first sign of aging and decay
|
||||||
|
\x1B[38;5;214mrepetition is the best way to learn
|
||||||
|
\x1B[38;5;214mknowledge should be advanced at all costs
|
||||||
|
\x1B[38;5;214mif you aren't political your personal life should be exemplary
|
||||||
|
\x1B[38;5;214mboredom makes you do crazy things
|
||||||
|
\x1B[38;5;214myou must be intimate with a token few
|
||||||
|
\x1B[38;5;214myou can live on through your descendants
|
||||||
|
\x1B[38;5;214mseparatism is the way to a new beginning
|
||||||
|
\x1B[38;5;214mthe idea of transcendence is used to obscure oppression
|
||||||
|
\x1B[38;5;214mpolitics is used for personal gain
|
||||||
|
\x1B[38;5;214meating too much is criminal
|
||||||
|
\x1B[38;5;214mimposing order is man's vocation for chaos is hell
|
||||||
|
\x1B[38;5;214myou don't know what's what until you support yourself
|
||||||
|
\x1B[38;5;214mif you can't leave your mark give up
|
||||||
|
\x1B[38;5;214ma little knowledge can go a long way
|
||||||
|
\x1B[38;5;214musing force to stop force is absurd
|
||||||
|
\x1B[38;5;214mmorals are for little people
|
||||||
|
\x1B[38;5;214mwords tend to be inadequate
|
||||||
|
\x1B[38;5;214memotional responses ar as valuable as intellectual responses
|
||||||
|
\x1B[92mMate Light\x1B[0m powered by \x1B[95mMicrosoft™ \x1B[96mMarquee Manager® Professional OEM
|
||||||
|
\x1B[38;5;214mthe most profound things are inexpressible
|
||||||
|
\x1B[38;5;214mfaithfulness is a social not a biological law
|
||||||
|
\x1B[38;5;214mrelativity is no boon to mankind
|
||||||
|
\x1B[38;5;214mmoderation kills the spirit
|
||||||
11
host/main.c
11
host/main.c
|
|
@ -3,7 +3,6 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "net.h"
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
@ -65,7 +64,7 @@ framebuffer_t *framebuffer_render_text(char *s, glyphtable_t *glyph_table){
|
||||||
p += inc;
|
p += inc;
|
||||||
|
|
||||||
if(c > glyph_table->size){
|
if(c > glyph_table->size){
|
||||||
fprintf(stderr, "Error rendering string: Codepoint 0x%lx out of valid range (0-%ld).\n", (long int)c, glyph_table->size);
|
fprintf(stderr, "Error rendering string: Codepoint 0x%lx out of valid range (0-%zd).\n", (long int)c, glyph_table->size);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,7 +86,7 @@ framebuffer_t *framebuffer_render_text(char *s, glyphtable_t *glyph_table){
|
||||||
size_t gbufsize = gbufwidth*gbufheight;
|
size_t gbufsize = gbufwidth*gbufheight;
|
||||||
gbuf = calloc(gbufsize, sizeof(color_t));
|
gbuf = calloc(gbufsize, sizeof(color_t));
|
||||||
if(!gbuf){
|
if(!gbuf){
|
||||||
fprintf(stderr, "Cannot malloc() %lu bytes.\n", gbufsize*sizeof(color_t));
|
fprintf(stderr, "Cannot malloc() %zu bytes.\n", gbufsize*sizeof(color_t));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
memset(gbuf, 0, gbufsize*sizeof(color_t));
|
memset(gbuf, 0, gbufsize*sizeof(color_t));
|
||||||
|
|
@ -296,7 +295,7 @@ framebuffer_t *framebuffer_render_text(char *s, glyphtable_t *glyph_table){
|
||||||
}
|
}
|
||||||
framebuffer_t *fb = malloc(sizeof(framebuffer_t));
|
framebuffer_t *fb = malloc(sizeof(framebuffer_t));
|
||||||
if(!fb){
|
if(!fb){
|
||||||
fprintf(stderr, "Cannot malloc() %lu bytes.\n", sizeof(framebuffer_t));
|
fprintf(stderr, "Cannot malloc() %zu bytes.\n", sizeof(framebuffer_t));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
fb->w = gbufwidth;
|
fb->w = gbufwidth;
|
||||||
|
|
@ -311,7 +310,7 @@ error:
|
||||||
void console_render_buffer(color_t *data, size_t w, size_t h){
|
void console_render_buffer(color_t *data, size_t w, size_t h){
|
||||||
/* Render framebuffer to terminal, two pixels per character using Unicode box drawing stuff */
|
/* Render framebuffer to terminal, two pixels per character using Unicode box drawing stuff */
|
||||||
color_t lastfg = {0, 0, 0}, lastbg = {0, 0, 0};
|
color_t lastfg = {0, 0, 0}, lastbg = {0, 0, 0};
|
||||||
printf("\e[38;5;0;48;5;0m");
|
printf("\e[38;5;0;48;5;0m\e[K");
|
||||||
for(size_t y=0; y < h; y+=2){
|
for(size_t y=0; y < h; y+=2){
|
||||||
for(size_t x=0; x < w; x++){
|
for(size_t x=0; x < w; x++){
|
||||||
/* Da magicks: ▀█▄ */
|
/* Da magicks: ▀█▄ */
|
||||||
|
|
@ -350,7 +349,7 @@ void console_render_buffer(color_t *data, size_t w, size_t h){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n\e[K");
|
||||||
}
|
}
|
||||||
printf("\033[0m");
|
printf("\033[0m");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import usb
|
|
||||||
import colorsys
|
import colorsys
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from itertools import product
|
from itertools import product
|
||||||
|
from ctypes import c_size_t, c_uint8, c_void_p, c_float, CDLL, Structure, POINTER
|
||||||
|
import time
|
||||||
|
|
||||||
CRATE_WIDTH = 5
|
CRATE_WIDTH = 5
|
||||||
CRATE_HEIGHT = 4
|
CRATE_HEIGHT = 4
|
||||||
|
|
@ -19,7 +20,14 @@ GAMMA = 2.5
|
||||||
# Brightness of the LEDs in percent. 1.0 means 100%.
|
# Brightness of the LEDs in percent. 1.0 means 100%.
|
||||||
BRIGHTNESS = 0.2
|
BRIGHTNESS = 0.2
|
||||||
|
|
||||||
dev = usb.core.find(idVendor=0x1cbe, idProduct=0x0003)
|
ml = CDLL('./libml.so')
|
||||||
|
ml.matelight_open.restype = c_void_p
|
||||||
|
|
||||||
|
if ml.matelight_usb_init():
|
||||||
|
raise OSError('Cannot initialize USB library')
|
||||||
|
matelights = ml.matelight_open()
|
||||||
|
if matelights is None:
|
||||||
|
raise ImportError('Cannot open any Mate Light devices')
|
||||||
|
|
||||||
def sendframe(framedata):
|
def sendframe(framedata):
|
||||||
""" Send a frame to the display
|
""" Send a frame to the display
|
||||||
|
|
@ -27,15 +35,25 @@ def sendframe(framedata):
|
||||||
The argument contains a h * w array of 3-tuples of (r, g, b)-data or 4-tuples of (r, g, b, a)-data where the a
|
The argument contains a h * w array of 3-tuples of (r, g, b)-data or 4-tuples of (r, g, b, a)-data where the a
|
||||||
channel is ignored.
|
channel is ignored.
|
||||||
"""
|
"""
|
||||||
# Gamma correction
|
# just use the first Mate Light available
|
||||||
framedata = (((framedata/255) ** GAMMA) * BRIGHTNESS * 255).astype(np.uint8)
|
buf = framedata.ctypes.data_as(POINTER(c_uint8))
|
||||||
for cx, cy in product(range(CRATES_X), range(CRATES_Y)):
|
ml.matelight_send_frame(matelights, buf, c_size_t(CRATES_X), c_size_t(CRATES_Y), c_float(BRIGHTNESS), True)
|
||||||
datar = framedata[cy*CRATE_HEIGHT:(cy+1)*CRATE_HEIGHT, cx*CRATE_WIDTH:(cx+1)*CRATE_WIDTH, :3]
|
|
||||||
data = datar.flat
|
|
||||||
if len(data) != CRATE_SIZE:
|
|
||||||
raise ValueError('Invalid frame data. Expected {} bytes, got {}.'.format(CRATE_SIZE, len(data)))
|
|
||||||
# Send framebuffer data
|
|
||||||
dev.write(0x01, bytes([0, cx, cy])+bytes(data))
|
|
||||||
# Send latch command
|
|
||||||
dev.write(0x01, b'\x01')
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
#foo = np.array([[(0, 0, 0, 0)]*DISPLAY_WIDTH]*DISPLAY_HEIGHT)
|
||||||
|
#bar = np.array([[(255, 0, 255, 0)]*DISPLAY_WIDTH]*DISPLAY_HEIGHT)
|
||||||
|
x,y = 0,0
|
||||||
|
while True:
|
||||||
|
x += 1
|
||||||
|
if x == DISPLAY_WIDTH:
|
||||||
|
x = 0
|
||||||
|
y += 1
|
||||||
|
if y == DISPLAY_HEIGHT:
|
||||||
|
y = 0
|
||||||
|
foo = np.array([[(64, 0, 0, 255)]*DISPLAY_WIDTH]*DISPLAY_HEIGHT, dtype=np.uint8)
|
||||||
|
foo[y,x,:] = (0,64,0,255)
|
||||||
|
#from terminal import printframe
|
||||||
|
sendframe(foo)
|
||||||
|
#printframe(foo)
|
||||||
|
#sendframe(bar)
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
|
||||||
18
host/net.h
18
host/net.h
|
|
@ -1,18 +0,0 @@
|
||||||
#ifndef __NET_H__
|
|
||||||
#define __NET_H__
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t r, g, b;
|
|
||||||
} rgb_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t magic, seq;
|
|
||||||
uint16_t width, height;
|
|
||||||
rgb_t data[DISPLAY_WIDTH*DISPLAY_HEIGHT];
|
|
||||||
} ml_packet_t;
|
|
||||||
|
|
||||||
#define UDP_BUF_SIZE sizeof(ml_packet_t)
|
|
||||||
|
|
||||||
#endif//__NET_H__
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
from socketserver import *
|
from socketserver import *
|
||||||
from time import time, strftime, sleep
|
from time import time, strftime, sleep
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from itertools import product
|
from itertools import product, cycle
|
||||||
import threading
|
import threading
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
@ -49,19 +49,21 @@ def printframe(fb):
|
||||||
print('\0337\033[H', end='')
|
print('\0337\033[H', end='')
|
||||||
print('Rendering frame @{}'.format(time()))
|
print('Rendering frame @{}'.format(time()))
|
||||||
bdf.console_render_buffer(fb.ctypes.data_as(POINTER(c_uint8)), w, h)
|
bdf.console_render_buffer(fb.ctypes.data_as(POINTER(c_uint8)), w, h)
|
||||||
print('\033[0mCurrently rendering', current_entry.entrytype, 'from', current_entry.remote, ':', current_entry.text, '\0338', end='')
|
print('\033[0m\033[KCurrently rendering', current_entry.entrytype, 'from', current_entry.remote, ':', current_entry.text, '\0338', end='')
|
||||||
printlock.release()
|
printlock.release()
|
||||||
|
|
||||||
def scroll(text):
|
def scroll(text):
|
||||||
""" Returns whether it could scroll all the text uninterrupted """
|
""" Returns whether it could scroll all the text uninterrupted """
|
||||||
|
log('Scrolling', text)
|
||||||
fb = render_text(text);
|
fb = render_text(text);
|
||||||
h,w,_ = fb.shape
|
h,w,_ = fb.shape
|
||||||
for i in range(-DISPLAY_WIDTH,w+1):
|
for i in range(-DISPLAY_WIDTH,w+1):
|
||||||
if current_entry.entrytype == 'udp' or (current_entry in defaulttexts and textqueue):
|
# if current_entry.entrytype == 'udp' or (textqueue and current_entry in defaulttexts):
|
||||||
return False
|
# log('Aborting rendering due to new input')
|
||||||
leftpad = np.zeros((DISPLAY_HEIGHT, max(-i, 0), 4), dtype=np.uint8)
|
# return False
|
||||||
framedata = fb[:, max(0, i):min(i+DISPLAY_WIDTH, w)]
|
leftpad = np.zeros((DISPLAY_HEIGHT, max(-i, 0), 4), dtype=np.uint8)
|
||||||
rightpad = np.zeros((DISPLAY_HEIGHT, min(DISPLAY_WIDTH, max(0, i+DISPLAY_WIDTH-w)), 4), dtype=np.uint8)
|
framedata = fb[:, max(0, i):min(i+DISPLAY_WIDTH, w)]
|
||||||
|
rightpad = np.zeros((DISPLAY_HEIGHT, min(DISPLAY_WIDTH, max(0, i+DISPLAY_WIDTH-w)), 4), dtype=np.uint8)
|
||||||
dice = np.concatenate((leftpad, framedata, rightpad), 1)
|
dice = np.concatenate((leftpad, framedata, rightpad), 1)
|
||||||
sendframe(dice)
|
sendframe(dice)
|
||||||
printframe(dice)
|
printframe(dice)
|
||||||
|
|
@ -69,21 +71,16 @@ def scroll(text):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
QueueEntry = namedtuple('QueueEntry', ['entrytype', 'remote', 'timestamp', 'text'])
|
QueueEntry = namedtuple('QueueEntry', ['entrytype', 'remote', 'timestamp', 'text'])
|
||||||
defaulttexts = [QueueEntry('text', '127.0.0.1', 0, t) for t in [
|
defaultlines = [ QueueEntry('text', '127.0.0.1', 0, l[:-1].replace('\\x1B', '\x1B')) for l in open('default.lines').readlines() ]
|
||||||
'\x1B[92mMate Light\x1B[93m@\x1B[92mPlay store or \x1B[94;101mtcp://ml.jaseg.net:1337\x1B[0;91m ♥',
|
random.shuffle(defaultlines)
|
||||||
'\x1B[92mMate Light\x1B[0;91m ♥ \x1B[92mUnicode',
|
defaulttexts = cycle(defaultlines)
|
||||||
'\x1B[92mMate Light\x1B[0m powered by \x1B[95mMicrosoft™ \x1B[96mMarquee Manager® Professional OEM',
|
current_entry = next(defaulttexts)
|
||||||
'\x1B[92mMate Light\x1B[0m powered by \x1B[95mData Becker™ \x1B[96mLaufschriftstudio 2000® Platinum Edition',
|
|
||||||
'\x1B[92mMate Light\x1B[0m powered by \x1B[95mApple™ \x1B[96miScroll®',
|
|
||||||
'\x1B[92mMate Light\x1B[0m powered by \x1B[95mSiemens™ \x1B[96mLaufschrift® v.0.1.2b fuer Intel™ Pentium®',
|
|
||||||
]]
|
|
||||||
current_entry = random.choice(defaulttexts)
|
|
||||||
conns = {}
|
conns = {}
|
||||||
textqueue = []
|
textqueue = []
|
||||||
|
|
||||||
def log(*args):
|
def log(*args):
|
||||||
printlock.acquire()
|
printlock.acquire()
|
||||||
print(strftime('[%m-%d %H:%M:%S]'), *args)
|
print(strftime('[%m-%d %H:%M:%S]'), ' '.join(str(arg) for arg in args), '\x1B[0m')
|
||||||
printlock.release()
|
printlock.release()
|
||||||
|
|
||||||
class MateLightUDPHandler(BaseRequestHandler):
|
class MateLightUDPHandler(BaseRequestHandler):
|
||||||
|
|
@ -159,12 +156,12 @@ if __name__ == '__main__':
|
||||||
if conns:
|
if conns:
|
||||||
current_entry = random.choice(list(conns.values()))
|
current_entry = random.choice(list(conns.values()))
|
||||||
else:
|
else:
|
||||||
current_entry = random.choice(defaulttexts)
|
current_entry = next(defaulttexts)
|
||||||
if current_entry.entrytype != 'udp' and textqueue:
|
if current_entry.entrytype != 'udp' and textqueue:
|
||||||
current_entry = textqueue[0]
|
current_entry = textqueue[0]
|
||||||
if current_entry.entrytype == 'udp':
|
if current_entry.entrytype == 'udp':
|
||||||
if time() - current_entry.timestamp > UDP_TIMEOUT:
|
if time() - current_entry.timestamp > UDP_TIMEOUT:
|
||||||
current_entry = random.choice(defaulttexts)
|
current_entry = next(defaulttexts)
|
||||||
else:
|
else:
|
||||||
sleep(0.2)
|
sleep(0.1)
|
||||||
|
|
||||||
|
|
|
||||||
19
host/terminal.py
Normal file
19
host/terminal.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
from pixelterm.pixelterm import termify_pixels
|
||||||
|
|
||||||
|
class MockImage:
|
||||||
|
def __init__(self, nparray):
|
||||||
|
self.nparray = nparray
|
||||||
|
self.im = self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self):
|
||||||
|
h, w, _ = self.nparray.shape
|
||||||
|
return (w, h)
|
||||||
|
|
||||||
|
def getpixel(self, pos):
|
||||||
|
x, y = pos
|
||||||
|
return tuple(self.nparray[y][x])
|
||||||
|
|
||||||
|
def printframe(framedata):
|
||||||
|
print(termify_pixels(MockImage(framedata)))
|
||||||
|
|
||||||
156
host/usb.c
Normal file
156
host/usb.c
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
#include "color.h"
|
||||||
|
#include "usb.h"
|
||||||
|
|
||||||
|
int matelight_usb_init(){
|
||||||
|
int rc = 0;
|
||||||
|
rc = libusb_init(NULL);
|
||||||
|
if(rc){
|
||||||
|
fprintf(stderr, "LIBML: Cannot initialize libusb\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void matelight_usb_destroy(){
|
||||||
|
libusb_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int matelight_cmp_str_desc(libusb_device_handle *dev, uint8_t index, char *value){
|
||||||
|
char data[256];
|
||||||
|
if(libusb_get_string_descriptor_ascii(dev, index, (unsigned char*)data, sizeof(data)) < 0){
|
||||||
|
fprintf(stderr, "LIBML: Cannot read device string descriptor\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return strcmp(data, value) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
matelight_handle *matelight_open(){
|
||||||
|
matelight_handle *out = NULL;
|
||||||
|
libusb_device** device_list;
|
||||||
|
struct libusb_device_descriptor desc;
|
||||||
|
ssize_t res = libusb_get_device_list(NULL, &device_list);
|
||||||
|
if(res == 0){
|
||||||
|
fprintf(stderr, "LIBML: Cannot find any connected matelight\n");
|
||||||
|
goto error;
|
||||||
|
}else if(res < 0){
|
||||||
|
fprintf(stderr, "LIBML: Error enumerating connected USB devices\n");
|
||||||
|
goto error;
|
||||||
|
}else{
|
||||||
|
out = calloc(res+1, sizeof(matelight_handle));
|
||||||
|
if(!out){
|
||||||
|
fprintf(stderr, "LIBML: Cannot allocate memory\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
memset(out, 0, (res+1)*sizeof(matelight_handle));
|
||||||
|
unsigned int found = 0;
|
||||||
|
for(ssize_t i=0; i<res; i++){
|
||||||
|
libusb_get_device_descriptor(device_list[i], &desc);
|
||||||
|
if(desc.idVendor == MATELIGHT_VID && desc.idProduct == MATELIGHT_PID){
|
||||||
|
libusb_device_handle *handle;
|
||||||
|
if(libusb_open(device_list[i], &(handle))){
|
||||||
|
fprintf(stderr, "LIBML: Cannot open Mate Light USB device\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
out[found].handle = handle;
|
||||||
|
if(matelight_cmp_str_desc(handle, desc.iManufacturer, "Gold & Apple"))
|
||||||
|
if(matelight_cmp_str_desc(handle, desc.iProduct, "Mate Light")){
|
||||||
|
#define BUF_SIZE 256
|
||||||
|
char *serial = malloc(BUF_SIZE);
|
||||||
|
if(!serial){
|
||||||
|
fprintf(stderr, "LIBML: Cannot allocate memory\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if(libusb_get_string_descriptor_ascii(out[found].handle, desc.iSerialNumber, (unsigned char*)serial, BUF_SIZE) < 0){
|
||||||
|
fprintf(stderr, "LIBML: Cannot read device string descriptor\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#undef BUF_SIZE
|
||||||
|
out[found].serial = serial;
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out[found].handle = NULL;
|
||||||
|
out[found].serial = NULL;
|
||||||
|
}
|
||||||
|
libusb_free_device_list(device_list, 1);
|
||||||
|
return out;
|
||||||
|
error:
|
||||||
|
if(res>0 && out){
|
||||||
|
for(ssize_t i=0; i<res; i++){
|
||||||
|
if(out[i].handle)
|
||||||
|
libusb_close(out[i].handle);
|
||||||
|
free(out[i].serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(out);
|
||||||
|
libusb_free_device_list(device_list, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
uint8_t opcode;
|
||||||
|
uint8_t x, y;
|
||||||
|
rgb_t buf[CRATE_WIDTH*CRATE_HEIGHT];
|
||||||
|
} crate_frame_t;
|
||||||
|
|
||||||
|
int matelight_send_frame(matelight_handle *ml, void *buf, size_t w, size_t h, float brightness, int alpha){
|
||||||
|
// fprintf(stderr, "\nFRAME START\n");
|
||||||
|
for(size_t cy=0; cy<h; cy++){
|
||||||
|
// fprintf(stderr, "##### NEXT ROW\n");
|
||||||
|
for(size_t cx=0; cx<w; cx++){
|
||||||
|
crate_frame_t frame;
|
||||||
|
frame.opcode = 0;
|
||||||
|
frame.x = cx;
|
||||||
|
frame.y = cy;
|
||||||
|
// fprintf(stderr, "CRATE %d %d\n", cx, cy);
|
||||||
|
for(size_t x=0; x<CRATE_WIDTH; x++){
|
||||||
|
for(size_t y=0; y<CRATE_HEIGHT; y++){
|
||||||
|
size_t dpos = y*CRATE_WIDTH + x;
|
||||||
|
size_t spos = w*CRATE_WIDTH*(cy*CRATE_HEIGHT+y) + cx*CRATE_WIDTH+x;
|
||||||
|
color_t *src = (((color_t*)buf)+spos);
|
||||||
|
rgb_t *dst = frame.buf+dpos;
|
||||||
|
/* Gamma correction */
|
||||||
|
#define GAMMA_APPLY(c) ((uint8_t)roundf(powf((c/255.0F), GAMMA) * brightness * 255))
|
||||||
|
dst->r = GAMMA_APPLY(src->r);
|
||||||
|
dst->g = GAMMA_APPLY(src->g);
|
||||||
|
dst->b = GAMMA_APPLY(src->b);
|
||||||
|
// fprintf(stderr, "%c", ((dst->r > 1) ? '#' : '.'));
|
||||||
|
#undef GAMMA_APPLY
|
||||||
|
}
|
||||||
|
// fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
int transferred = 0;
|
||||||
|
int rc = libusb_bulk_transfer(ml->handle, MATELIGHT_FRAMEDATA_ENDPOINT, (unsigned char*)&frame, sizeof(frame), &transferred, MATELIGHT_TIMEOUT);
|
||||||
|
if(rc){
|
||||||
|
fprintf(stderr, "LIBML: Cannot write frame data\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(transferred != sizeof(frame)){
|
||||||
|
fprintf(stderr, "LIBML: Could not transfer all frame data. Only transferred %d out of %d bytes.\n", transferred, sizeof(frame));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t payload = 0x01;
|
||||||
|
int transferred = 0;
|
||||||
|
int rc = libusb_bulk_transfer(ml->handle, MATELIGHT_FRAMEDATA_ENDPOINT, &payload, sizeof(uint8_t), &transferred, MATELIGHT_TIMEOUT);
|
||||||
|
if(rc){
|
||||||
|
fprintf(stderr, "LIBML: Cannot write frame data\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(transferred != sizeof(uint8_t)){
|
||||||
|
fprintf(stderr, "LIBML: Could not transfer all frame data. Only transferred %d out of %d bytes.\n", transferred, sizeof(uint8_t));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
27
host/usb.h
Normal file
27
host/usb.h
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef __USB_H__
|
||||||
|
#define __USB_H__
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
#define MATELIGHT_VID 0x1cbe
|
||||||
|
#define MATELIGHT_PID 0x0003
|
||||||
|
|
||||||
|
#define CRATE_WIDTH 5
|
||||||
|
#define CRATE_HEIGHT 4
|
||||||
|
|
||||||
|
#define MATELIGHT_FRAMEDATA_ENDPOINT 0x01
|
||||||
|
#define MATELIGHT_TIMEOUT 1000
|
||||||
|
|
||||||
|
#define GAMMA 2.5F
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
libusb_device_handle *handle;
|
||||||
|
char *serial;
|
||||||
|
} matelight_handle;
|
||||||
|
|
||||||
|
int matelight_usb_init(void);
|
||||||
|
void matelight_usb_destroy(void);
|
||||||
|
matelight_handle *matelight_open(void);
|
||||||
|
int matelight_send_frame(matelight_handle *ml, void *buf, size_t w, size_t h, float brightness, int alpha);
|
||||||
|
|
||||||
|
#endif//__USB_H__
|
||||||
Loading…
Add table
Add a link
Reference in a new issue