GithubHelp home page GithubHelp logo

llloret / osmid Goto Github PK

View Code? Open in Web Editor NEW
71.0 9.0 11.0 3.24 MB

osmid is a tool to bridge MIDI and OSC. It is currently in use in Sonic Pi

License: Other

CMake 0.20% Makefile 0.09% C++ 86.83% Batchfile 0.02% C 7.19% Ruby 0.05% Shell 0.03% Objective-C++ 2.03% Objective-C 0.54% Java 2.85% Python 0.02% Vim Script 0.14%
midi osc osc-messages juce portable midi-port midi-device osc-address sonic-pi

osmid's Introduction

Build Status

osmid

osmid aims to provide a lightweight, portable, easy to use tool to convert MIDI to OSC and OSC to MIDI.

It is the software handling the communication with MIDI devices in Sonic Pi.

osmid is divided in 2 tools:

  • m2o: MIDI to OSC conversion
  • o2m: OSC to MIDI conversion

Having two separate tools follows Unix ideas of having a number of smaller standalone tools instead of bigger monolithic ones. Since some projects might want to use just one direction for the conversion, it makes sense to keep this separation.

m2o features

  • Portable: Works under Windows, Linux and Mac
  • Compact
  • Very low latency
  • Customizable: can open a number of midi inputs, or all, and can configure the output UDP socket (if it is necessary to forward differnet MIDI devices to different OSC destinations, it is possible to do that invoking the program multiple times, with the appropriate arguments)
  • OSC address templates, that is, the format of the OSC address can be passed as an argument to the program. If the template parameter is not passed, then templates are NOT used (for example, if you REALLY care about latency - but we are talking about tens of microseconds here...).

o2m features

  • Portable: Works under Windows, Linux and Mac
  • Compact
  • Very low latency
  • For a list of the OSC messages that o2m supports see below in "o2m incoming OSC message format"

Building

For build instruction see INSTALL.md.

osmid is built using C++14 features. The build system is based on cmake. Tested target compiler in Windows is MSVC 2015 Win64, in Linux is gcc 4.9 or later, and on Mac, clang 5.1 or later. Under Windows, prepare using something like: cmake -G "Visual Studio 16 2019" -A x64 .. . On Linux and Mac cmake .. should be enough.

osmid uses the following libs:

  • JUCE for the midi handling and OSC handling (included in the tree)
  • oscpack, for the OSC handling and UDP networking (included in the tree)
  • spdlog, for logging (included in the tree)
  • cxxopts, for program options parsing (included in the tree)

m2o parameters

  • --midiin or -i : open the specified input device - can be specified multiple times to open more than one device. By default it will open all input devices and the ones that are connected live
  • --oschost or -H : send the OSC output to the specified host
  • --oscport or -o : send the OSC output to the specified port - can be specified multiple times to send to more than one port
  • --osctemplate or -t : use the specified OSC output template (use $n: midi port name, $i midi port id, $c: midi channel, $m: message_type). For example: -t /midi/$c/$m
  • --oscrawmidimessage or -r: send the raw MIDI data in the OSC message, instead of a decoded version
  • --monitor or -m: logging level. Number from 0 to 6. Smaller numbers are more verbose
  • --list or -l: List input MIDI devices
  • --heartbeat or -b: sends OSC heartbeat message
  • --help: Display this help message
  • --version: Show the version number

m2o outgoing OSC message format

The address by default is: /midi//(if the message contains channel information). The address can be templated with the -t argument.

The message body is:

  • By default: (int), (string), (i.e. for note_on messages, it will be 2 integers: note, velocity)
  • if -r specified: (int), (string), (blob).

There is also an optional heartbeat message which sends periodic messages with the following format: OSC address pattern: /midi/heartbeat. Message body is OSC array of pairs ,

o2m parameters

  • --list or -l: List output MIDI devices
  • --midiout or -o: open the specified output device - can be specified multiple times to open more than one device. By default it will open all output devices and the ones that are connected live
  • --oscport or -i: OSC Input port (default:57200)
  • --heartbeat or -b: sends OSC heartbeat message. See oscoutputhost and oscoutputport arguments.
  • --oscoutputhost or -H, host to send OSC messages to (default:127.0.0.1). Used for heartbeat
  • --oscoutputport or -O:host to send OSC messages to (default:57120). Used for heartbeat
  • --monitor or -m: logging level. Number from 0 to 6. Smaller numbers are more verbose
  • --help: Display this help message
  • --version: Show the version number

o2m incoming OSC message format

  • The expected OSC address pattern is /(string)"out midi device name or global"/(string)"midi command". You can use * in the device name to send to all devices
  • Recognized midi commands, and the expected OSC body:
    • raw: send a midi command as is. Body can be either a blob or a sequence of int32s
    • note_on: Body is (int32)channel, (int32)note, (int32)velocity
    • note_off: Body is (int32)channel, (int32)note, (int32)velocity
    • control_change: Body is (int32)channel, (int32)control number, (int32)control value
    • pitch_bend: Body is (int32)channel, (int32)value
    • channel_pressure: Body is (int32)channel, (int32)value
    • poly_pressure: Body is (int32)channel, (int32)note, (int32)value
    • program_change: Body is (int32)channel, (int32)program number
    • clock: Body is empty
    • start: Body is empty
    • stop: Body is empty
    • continue: Body is empty
    • active_sense: Body is empty
    • log_level: Body is (int32)log_level. Value from 0 to 6. The smaller the number the more verbose the output.
    • log_to_osc: Body is (int32)enable. 0 -> disable, 1 -> enable

LICENSE

See LICENSE.md file for details.

osmid's People

Contributors

kant2002 avatar llloret avatar samaaron avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

osmid's Issues

m2o in background from script not running

I am running m2o under Debian11 like from command prompt in a bash terminal:
m2o -v m2oMidi -o 7700

works fine.

If I run it it background like:
m2o -v m2oMidi -o 7700 &
it also works.

But if I do the same from within a script:

#!/bin/bash
m2o -v m2oMidi -o 7700 &

while true
do
    #some more stuff until ctrl-c
    # want to start a midi note generator here and then aconnect it to m2o (or disconnect)
done

in another terminal:
ps -elf does not show the m2o task. I tried it with nohup in front of the line with the same result. The same with disown at the end of the line.

Any ideas how I can run m2o in background from the script?

thanks

release for packaging

I'd like to package the latest sonic-pi for Arch Linux' [community] repository. Osmid is a dependency and therefore has to be packaged as well.

Can you please tag a release of this software, so I can package it?

Linux Midi port names

On a linux system the alsa midi port names are prefixed by the device name and conain a ":", which is not allowed by the regex in OscInProcessor::ProcessMessage
it works when the regex gets changed to

regex addressRegex("/(([[:alnum:]]|\\:|\\s|\\*)+)/(([[:alnum:]]|_)+)");

Send MIDI channel with offset 1, not 0

Can you send the channel as a value from 1-16
Not zero indexed
(In the Incoming OSC messages)
Currently something on channel 1 looks like /midi/0/0/note_on
When it should be /midi/0/1/note_on

allow devendoring of spdlog

Hi! I'm maintaining osmid for Arch Linux.

As on most Linux distributions, we already have spdlog (and in a much newer version) it would be great to allow proper devendoring of the library (e.g. via CMake option).

Vendoring (aka bundling) of libraries (especially very old ones) is never a good idea. Fedora has a good writeup as to why that is.

The spdlog library offers both pkgconfig and cmake integration out-of-the-box, so discovery and integration of a system version should be trivial.

OSC message format is not "symmetric"

Hello,
I just compiled m2o and o2m from commit a1205b4 on Arch Linux.
In one terminal, I run:

$ m2o --list
Found 2 MIDI inputs.
   (0): Midi Through Port-0
   (1): UA-25 MIDI 1
$ m2o --oschost 127.0.0.1

In another terminal, I run:

$ o2m --oscport 57120

I expected o2m to receive OSC and forward MIDI events. But if I play a note on a connected MIDI keyboard (connected to UA-25 MIDI 1), o2m starts printing

[2021-10-06 11:04:31.190] [console] [info] Received OSC message with address pattern: /logging
[2021-10-06 11:04:31.190] [console] [error] No match on address pattern: /logging
...

in an endless loop at 100% CPU. Within this huge chunk of messages, there is one mention of a MIDI Note-on:

[2021-10-06 11:04:31.191] [console] [info] Received OSC message with address pattern: /midi/ua-25_midi_1/1/1/note_on
[2021-10-06 11:04:31.192] [console] [error] Unknown command on OSC message: ua-25_midi_1/1/1/note_on. Ignoring

However, if I run oscdump as a receiver,

$ oscdump osc.udp://:57120

I notice, there is no endless stream of /logging s "..." and /midi/ua-25_midi_1/1/1/note_on ii 50 86 looks fine to me.
Am I doing something wrong? I get the same results, using an --oschost in the LAN and with any setting of --monitor.

Feedback from Sam

Some of these will probably be moved to their own issue. For now, I put them here to not forget about them.

  • It currently sends out OSC bundles which Sonic Pi can't handle at this stage. Could you change it so it outputs simple OSC messages?
    [Luis] Ok, I will do that.
  • It could totally do with a 'debug mode' so you can see what's coming in and also what it's sending out
    [Luis] Yes, that's a good idea.
  • It would be great to put the MIDI info in the OSC message - or at least some sort of integer identifier (I mean the device info - manufacturer, description etc. There should be some way for Sonic Pi to access that)
    [Luis] Do you mean the note_on or note_off part of the message, for example? Now the midi message type is put into the message address. You can use raw mode (-r), and then you will get a blob with the raw midi message in a blob. What would like to do here?
  • It would also be great if the integer identifiers were persistent for the session - regardless of other devices being plugged in/out.
    [Luis] The integer are managed by RtMIDI, so I am not sure that we can make them persistent. My idea was to work with the names instead of with the integer ids. If ids are wanted, we can implement another set of integer ids at our MidiInput layer, and map them to RtMIDI ids. We would also like to map them to the device names to see if they are really the same.
  • Not useful for Sonic Pi - but it would be cool to specify an an external IP address to send the OSC messages to.
    [Luis] This is already planned, and it is taken into account in the insides... Need to make it accessible through a parameter.

well, basically Sonic Pi should have a way of knowing the device info of a given MIDI message
so either the integer ID of the MIDI device should be embedded in each OSC message
or the full string description/info
the integer ID is probably sufficient - provided osmidi also sends out a heartbeat message of integer ID -> description info for all devices

prollem with osmid on raspberry pi 64bit OS

Just built 64bit Sonic Pi 3.2.2 on raspberry pi 64bit beta OS It works OK including using OSC messages but no midi.. Both m2o and o2m are giving error messages.

o2m: /home/pi/Downloads/osmid/external_libs/oscpack_1_1_0/osc/OscOutboundPacketStream.cpp:166: osc::OutboundPacketStream::OutboundPacketStream(char*, std::size_t): Assertion `sizeof(osc::int32) == 4' failed.
m2o: /home/pi/Downloads/osmid/external_libs/oscpack_1_1_0/osc/OscOutboundPacketStream.cpp:166: osc::OutboundPacketStream::OutboundPacketStream(char*, std::size_t): Assertion `sizeof(osc::int32) == 4' failed.

Not sure if the problem is in SP or osmid. I have built o0n other 64bit OS eg ubuntu 20.04 without problem. Any ideas appreciated about whre to start looking.
both m2o and o2m behave ok when listing midi sources using -l parameter.

Debian Bullseye needs libx11-dev

Using 2021-10-30-raspios-bullseye-armhf disk image I ended up with an error on make

/usr/bin/ld: cannot find -lX11
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/o2m.dir/build.make:258: o2m] Error 1

Seems that libx11-dev needs to be listed as a dependency.

compile went normally after installing libx11-dev

m2o fails on Ubuntu 16.04 when used with Sonic Pi midi

I am using the latest osmid commit 72538fe [Fri Jun 23 11:17:45 2017 +0100] and recent Sonic Pi commit a8cbd26c8022bb80a189fea025bf84edb546c17 [Sun Jun 25 09:52:59 2017 +0000]

When testing Sonic Pi midi I notice that the m2o process dies with a segmentation fault and no sound is heard from my Fluid softsynth (midi device)

If I try running m2o from the command line I get the following, ultimately returning a segmentation fault; looks to me like there is some kind of infinite loop with respect to midi port lookup

Many thanks

$ ./build/m2o
Found 6 MIDI inputs.
(0): Midi Through: Midi Through Port-0
(1): Juce Midi Output: Midi Through Port-0 (1)
(2): Juce Midi Output: Synth input port (3613:0) (1)
(3): Juce Midi Output: Midi Through Port-0 (2)
(4): Juce Midi Output: Midi Through Port-0 (3)
(5): Juce Midi Output: Synth input port (3613:0) (2)
Found 9 MIDI inputs.
(0): Midi Through: Midi Through Port-0
(1): Juce Midi Output: Midi Through Port-0 (1)
(2): Juce Midi Output: Synth input port (3613:0) (1)
(3): Juce Midi Output: Midi Through Port-0 (2)
(4): Juce Midi Output: Midi Through Port-0 (3)
(5): Juce Midi Output: Synth input port (3613:0) (2)
(6): Juce Midi Output: Midi Through Port-0 (4)
(7): Juce Midi Output: Midi Through Port-0 (5)
(8): Juce Midi Output: Synth input port (3613:0) (3)
Found 12 MIDI inputs.
(0): Midi Through: Midi Through Port-0
(1): Juce Midi Output: Midi Through Port-0 (1)
(2): Juce Midi Output: Synth input port (3613:0) (1)
(3): Juce Midi Output: Midi Through Port-0 (2)
(4): Juce Midi Output: Midi Through Port-0 (3)
(5): Juce Midi Output: Synth input port (3613:0) (2)
(6): Juce Midi Output: Midi Through Port-0 (4)
(7): Juce Midi Output: Midi Through Port-0 (5)
(8): Juce Midi Output: Synth input port (3613:0) (3)
(9): Juce Midi Output: Midi Through Port-0 (6)
(10): Juce Midi Output: Midi Through Port-0 (7)
(11): Juce Midi Output: Synth input port (3613:0) (4)
Found 15 MIDI inputs.
(0): Midi Through: Midi Through Port-0
(1): Juce Midi Output: Midi Through Port-0 (1)
(2): Juce Midi Output: Synth input port (3613:0) (1)
(3): Juce Midi Output: Midi Through Port-0 (2)
(4): Juce Midi Output: Midi Through Port-0 (3)
(5): Juce Midi Output: Synth input port (3613:0) (2)
(6): Juce Midi Output: Midi Through Port-0 (4)
(7): Juce Midi Output: Midi Through Port-0 (5)
(8): Juce Midi Output: Synth input port (3613:0) (3)
(9): Juce Midi Output: Midi Through Port-0 (6)
(10): Juce Midi Output: Midi Through Port-0 (7)
(11): Juce Midi Output: Synth input port (3613:0) (4)
(12): Juce Midi Output: Midi Through Port-0 (8)
(13): Juce Midi Output: Midi Through Port-0 (9)
(14): Juce Midi Output: Synth input port (3613:0) (5)
Found 18 MIDI inputs.
(0): Midi Through: Midi Through Port-0
(1): Juce Midi Output: Midi Through Port-0 (1)
(2): Juce Midi Output: Synth input port (3613:0) (1)
(3): Juce Midi Output: Midi Through Port-0 (2)
(4): Juce Midi Output: Midi Through Port-0 (3)
(5): Juce Midi Output: Synth input port (3613:0) (2)
(6): Juce Midi Output: Midi Through Port-0 (4)
(7): Juce Midi Output: Midi Through Port-0 (5)
(8): Juce Midi Output: Synth input port (3613:0) (3)
(9): Juce Midi Output: Midi Through Port-0 (6)
(10): Juce Midi Output: Midi Through Port-0 (7)
(11): Juce Midi Output: Synth input port (3613:0) (4)
(12): Juce Midi Output: Midi Through Port-0 (8)
(13): Juce Midi Output: Midi Through Port-0 (9)
(14): Juce Midi Output: Synth input port (3613:0) (5)
(15): Juce Midi Output: Midi Through Port-0 (10)
(16): Juce Midi Output: Midi Through Port-0 (11)
(17): Juce Midi Output: Synth input port (3613:0) (6)
Found 21 MIDI inputs.
(0): Midi Through: Midi Through Port-0
(1): Juce Midi Output: Midi Through Port-0 (1)
(2): Juce Midi Output: Synth input port (3613:0) (1)
(3): Juce Midi Output: Midi Through Port-0 (2)
(4): Juce Midi Output: Midi Through Port-0 (3)
(5): Juce Midi Output: Synth input port (3613:0) (2)
(6): Juce Midi Output: Midi Through Port-0 (4)
(7): Juce Midi Output: Midi Through Port-0 (5)
(8): Juce Midi Output: Synth input port (3613:0) (3)
(9): Juce Midi Output: Midi Through Port-0 (6)
(10): Juce Midi Output: Midi Through Port-0 (7)
(11): Juce Midi Output: Synth input port (3613:0) (4)
(12): Juce Midi Output: Midi Through Port-0 (8)
(13): Juce Midi Output: Midi Through Port-0 (9)
(14): Juce Midi Output: Synth input port (3613:0) (5)
(15): Juce Midi Output: Midi Through Port-0 (10)
(16): Juce Midi Output: Midi Through Port-0 (11)
(17): Juce Midi Output: Synth input port (3613:0) (6)
(18): Juce Midi Output: Midi Through Port-0 (12)
(19): Juce Midi Output: Midi Through Port-0 (13)
(20): Juce Midi Output: Synth input port (3613:0) (7)
Found 24 MIDI inputs.
(0): Midi Through: Midi Through Port-0
(1): Juce Midi Output: Midi Through Port-0 (1)
(2): Juce Midi Output: Synth input port (3613:0) (1)
(3): Juce Midi Output: Midi Through Port-0 (2)
(4): Juce Midi Output: Midi Through Port-0 (3)
(5): Juce Midi Output: Synth input port (3613:0) (2)
(6): Juce Midi Output: Midi Through Port-0 (4)
(7): Juce Midi Output: Midi Through Port-0 (5)
(8): Juce Midi Output: Synth input port (3613:0) (3)
(9): Juce Midi Output: Midi Through Port-0 (6)
(10): Juce Midi Output: Midi Through Port-0 (7)
(11): Juce Midi Output: Synth input port (3613:0) (4)
(12): Juce Midi Output: Midi Through Port-0 (8)
(13): Juce Midi Output: Midi Through Port-0 (9)
(14): Juce Midi Output: Synth input port (3613:0) (5)
(15): Juce Midi Output: Midi Through Port-0 (10)
(16): Juce Midi Output: Midi Through Port-0 (11)
(17): Juce Midi Output: Synth input port (3613:0) (6)
(18): Juce Midi Output: Midi Through Port-0 (12)
(19): Juce Midi Output: Midi Through Port-0 (13)
(20): Juce Midi Output: Synth input port (3613:0) (7)
(21): Juce Midi Output: Midi Through Port-0 (14)
(22): Juce Midi Output: Midi Through Port-0 (15)
(23): Juce Midi Output: Synth input port (3613:0) (8)
Found 27 MIDI inputs.
(0): Midi Through: Midi Through Port-0
(1): Juce Midi Output: Midi Through Port-0 (1)
(2): Juce Midi Output: Synth input port (3613:0) (1)
(3): Juce Midi Output: Midi Through Port-0 (2)
(4): Juce Midi Output: Midi Through Port-0 (3)
(5): Juce Midi Output: Synth input port (3613:0) (2)
(6): Juce Midi Output: Midi Through Port-0 (4)
(7): Juce Midi Output: Midi Through Port-0 (5)
(8): Juce Midi Output: Synth input port (3613:0) (3)
(9): Juce Midi Output: Midi Through Port-0 (6)
(10): Juce Midi Output: Midi Through Port-0 (7)
(11): Juce Midi Output: Synth input port (3613:0) (4)
(12): Juce Midi Output: Midi Through Port-0 (8)
(13): Juce Midi Output: Midi Through Port-0 (9)
(14): Juce Midi Output: Synth input port (3613:0) (5)
(15): Juce Midi Output: Midi Through Port-0 (10)
(16): Juce Midi Output: Midi Through Port-0 (11)
(17): Juce Midi Output: Synth input port (3613:0) (6)
(18): Juce Midi Output: Midi Through Port-0 (12)
(19): Juce Midi Output: Midi Through Port-0 (13)
(20): Juce Midi Output: Synth input port (3613:0) (7)
(21): Juce Midi Output: Midi Through Port-0 (14)
(22): Juce Midi Output: Midi Through Port-0 (15)
(23): Juce Midi Output: Synth input port (3613:0) (8)
(24): Juce Midi Output: Midi Through Port-0 (16)
(25): Juce Midi Output: Midi Through Port-0 (17)
(26): Juce Midi Output: Synth input port (3613:0) (9)
Segmentation fault (core dumped)
jhw@jhw-ThinkPad-X220:~/work/osmid$

Virtual MIDI port enhancements

  • MIDI port should only be compiled on Mac and Linux.
  • Add the possibility of assigning a name to the Virtual Port (add to -v parameter)

Support for multiple similar out ports

With two similar USB MIDI ports connected, I am only able to send MIDI events to one of the devices despite using the * identifier.

Here's the MIDI input listing:

λ ./m2o -l
Found 4 MIDI inputs.
   (0): E-MU Xmidi 2x2 Midi In 1
   (1): E-MU Xmidi 2x2 Midi In 2
   (2): E-MU Xmidi 2x2 Midi In 1
   (3): E-MU Xmidi 2x2 Midi In 2

However, MIDI events sent to * only appear on one of the devices.

This raises an additional question: how do I refer to each device independently? Is the sticky index part of its name?

OSC bundles are not decoded (in Sonic Pi at least)

Hi, I've opened sonic-pi-net/sonic-pi#2085 today and was directed to report the issue here. I don't understand where the boundary of Sonic-Pi and osmid is exactly so apologies if this includes irrelevant info.

Hi, I'm trying to use OSC to receive messages in Sonic Pi. Specifically I'm sending these messages from VCV Rack using the Trowasoft modules in a way described here. I'm facing a small issue that make the experience slightly annoying. I'm not sure whether the issue lies with Sonic Pi, Trowasoft's implementation of OSC, or a mix of both.

I'm running a 3.2.0-dev build from commit ab31ae0 built with the ubuntu-18.04 script on Linux Mint (based on Ubuntu bionic). Receiving remote OSC messages is enabled.

Trowasoft's implementation sends all OSC messages as bundles. I don't know if that's bad, from my reading of the OSC docs it sounds like recipients should understand it just fine. But Sonic Pi shows the received messages as /osc:127.0.0.1:35042/#bundle [] in the cues list, and indeed trying to unpack the values using sync gives me an empty array ([]). From this it seems that Sonic Pi is just treating the bundle as an opaque blob and doesn't unpack the values inside. This means that all I can get is a cue that a bundle was received, without added info, and without a way to distinguish what path(s) the bundle contains.

Example code I'm using:

live_loop :receive do
  use_real_time
  use_osc_logging true
  voltage = sync "/osc:*/#bundle"
  print voltage   ## always prints `[]`
end

I've tried syncing on /osc:*/*, /osc:*/ch/1 (the path I'm sending to from VCV Rack), and variants of that to no avail.

I think ideally the bundle should be expanded (recursively if needed, as the spec says a bundle can contain other bundles) and each OSC message in the bundle should be processed as an incoming message from the same source as the parent bundle.

I'm not sure what version of osmid I'm using exactly, but the binaries under sonic-pi/app/server/native/osmid report version 0.2.0. Happy to provide any other info that could be useful.

OSC heartbeat uses nonstandard argument array type

For the greatest compatibility with existing OSC servers it is best to stick to the plain OSC 1.0 argument types i, s, f, and b.

It might be best to send the heartbeat OSC message with just a list of strings - one for each device.

This issue affects both m2o and o2m.

o2m -l does not terminate

The command o2m -l does not terminate (on macOS). A Ctrl-c is required to get the terminal prompt back again.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.