├── LICENSE ├── README.md ├── example ├── example_gl_video.go └── example_video.go └── mpv ├── consts.go ├── error.go ├── mpv.go ├── mpvgl.go ├── node.go ├── node_test.go └── procaddr.go /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GO-MPV 2 | 3 | Golang bindings for libmpv 4 | 5 | ## Node not implemented 6 | 7 | 8 | # Examples 9 | - https://github.com/aykevl93/plaincast 10 | - https://github.com/dz0ny/champ#usage-spinwheel 11 | - https://github.com/YouROK/SRadio 12 | -------------------------------------------------------------------------------- /example/example_gl_video.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "runtime" 6 | 7 | "github.com/go-gl/gl/v3.2-core/gl" 8 | "github.com/go-gl/glfw/v3.1/glfw" 9 | "github.com/yourok/go-mpv/mpv" 10 | ) 11 | 12 | func init() { 13 | runtime.LockOSThread() 14 | } 15 | 16 | func main() { 17 | //Init gl 18 | err := glfw.Init() 19 | if err != nil { 20 | log.Println(err) 21 | panic(err) 22 | } 23 | defer glfw.Terminate() 24 | 25 | window, err := glfw.CreateWindow(640, 480, "Testing", nil, nil) 26 | if err != nil { 27 | panic(err) 28 | } 29 | 30 | window.MakeContextCurrent() 31 | 32 | if err := gl.Init(); err != nil { 33 | panic(err) 34 | } 35 | 36 | //init mpv 37 | m := mpv.Create() 38 | defer m.TerminateDestroy() 39 | 40 | m.SetOption("no-resume-playback", mpv.FORMAT_FLAG, true) 41 | m.SetOption("softvol", mpv.FORMAT_STRING, "yes") 42 | m.SetOption("volume", mpv.FORMAT_INT64, 20) 43 | m.SetOption("mute", mpv.FORMAT_FLAG, true) 44 | m.SetOptionString("hwdec", "auto") 45 | 46 | //cache 47 | m.SetOption("cache-default", mpv.FORMAT_INT64, 160) 48 | m.SetOption("cache-seek-min", mpv.FORMAT_INT64, 16) 49 | 50 | //GL 51 | m.SetOptionString("vo", "opengl-cb") 52 | 53 | err = m.Initialize() 54 | if err != nil { 55 | log.Println("Mpv init:", err.Error()) 56 | return 57 | } 58 | //Set video file 59 | m.Command([]string{"loadfile", "http://techslides.com/demos/sample-videos/small.webm"}) 60 | 61 | //Init mpv gl 62 | mgl := m.GetSubApiGL() 63 | if mgl == nil { 64 | return 65 | } 66 | 67 | mgl.InitGL() 68 | defer mgl.UninitGL() 69 | 70 | //Draw 71 | for !window.ShouldClose() { 72 | mgl.Draw(0, 640, 480) 73 | window.SwapBuffers() 74 | glfw.PollEvents() 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /example/example_video.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | // "time" 6 | 7 | "github.com/yourok/go-mpv/mpv" 8 | ) 9 | 10 | func eventListener(m *mpv.Mpv) chan *mpv.Event { 11 | c := make(chan *mpv.Event) 12 | go func() { 13 | for { 14 | e := m.WaitEvent(1) 15 | c <- e 16 | } 17 | }() 18 | return c 19 | } 20 | 21 | func main() { 22 | m := mpv.Create() 23 | c := eventListener(m) 24 | log.Println("no-resume-playback", m.SetOption("no-resume-playback", mpv.FORMAT_FLAG, true)) 25 | log.Println("volume", m.SetOption("volume", mpv.FORMAT_INT64, 20)) 26 | log.Println("terminal", m.SetOptionString("terminal", "yes")) 27 | log.Println("softvol", m.SetOptionString("softvol", "yes")) 28 | 29 | // Disable video in three ways. 30 | //m.SetOption("no-video", mpv.FORMAT_FLAG, true) 31 | //m.SetOption("vo", mpv.FORMAT_STRING, "null") 32 | //m.SetOption("vid", mpv.FORMAT_STRING, "") 33 | 34 | //cache 35 | log.Println("cache-default", m.SetOption("cache-default", mpv.FORMAT_INT64, 160)) // 10 seconds 36 | log.Println("cache-seek-min", m.SetOption("cache-seek-min", mpv.FORMAT_INT64, 16)) // 1 second 37 | 38 | err := m.Initialize() 39 | if err != nil { 40 | log.Println("Mpv init:", err.Error()) 41 | return 42 | } 43 | //Set video file 44 | log.Println("loadfile", m.Command([]string{"loadfile", "http://techslides.com/demos/sample-videos/small.webm"})) 45 | 46 | for { 47 | e := <-c 48 | log.Println(e) 49 | if e.Event_Id == mpv.EVENT_END_FILE { 50 | break 51 | } 52 | 53 | /*{ 54 | pos, err := m.GetProperty("time-pos", mpv.FORMAT_DOUBLE) 55 | if err != nil { 56 | log.Println("time-pos", err) 57 | continue 58 | } 59 | vol, err := m.GetProperty("volume", mpv.FORMAT_DOUBLE) 60 | //log.Println(pos.(float64)) 61 | if err != nil { 62 | log.Println("volume", err) 63 | continue 64 | } 65 | { 66 | position := pos.(float64) 67 | if position < 0 { 68 | position = 0 69 | } 70 | log.Println(time.Duration(position * float64(time.Second))) 71 | log.Println(vol) 72 | } 73 | }*/ 74 | 75 | } 76 | m.TerminateDestroy() 77 | } 78 | -------------------------------------------------------------------------------- /mpv/consts.go: -------------------------------------------------------------------------------- 1 | package mpv 2 | 3 | //#include 4 | import "C" 5 | 6 | //Errors mpv_error 7 | const ( 8 | /** 9 | * No error happened (used to signal successful operation). 10 | * Keep in mind that many API functions returning error codes can also 11 | * return positive values, which also indicate success. API users can 12 | * hardcode the fact that ">= 0" means success. 13 | */ 14 | ERROR_SUCCESS Error = C.MPV_ERROR_SUCCESS 15 | /** 16 | * The event ringbuffer is full. This means the client is choked, and can't 17 | * receive any events. This can happen when too many asynchronous requests 18 | * have been made, but not answered. Probably never happens in practice, 19 | * unless the mpv core is frozen for some reason, and the client keeps 20 | * making asynchronous requests. (Bugs in the client API implementation 21 | * could also trigger this, e.g. if events become "lost".) 22 | */ 23 | ERROR_EVENT_QUEUE_FULL Error = C.MPV_ERROR_EVENT_QUEUE_FULL 24 | /** 25 | * Memory allocation failed. 26 | */ 27 | ERROR_NOMEM Error = C.MPV_ERROR_NOMEM 28 | /** 29 | * The mpv core wasn't configured and initialized yet. See the notes in 30 | * mpv_create(). 31 | */ 32 | ERROR_UNINITIALIZED Error = C.MPV_ERROR_UNINITIALIZED 33 | /** 34 | * Generic catch-all error if a parameter is set to an invalid or 35 | * unsupported value. This is used if there is no better error code. 36 | */ 37 | ERROR_INVALID_PARAMETER Error = C.MPV_ERROR_INVALID_PARAMETER 38 | /** 39 | * Trying to set an option that doesn't exist. 40 | */ 41 | ERROR_OPTION_NOT_FOUND Error = C.MPV_ERROR_OPTION_NOT_FOUND 42 | /** 43 | * Trying to set an option using an unsupported MPV_FORMAT. 44 | */ 45 | ERROR_OPTION_FORMAT Error = C.MPV_ERROR_OPTION_FORMAT 46 | /** 47 | * Setting the option failed. Typically this happens if the provided option 48 | * value could not be parsed. 49 | */ 50 | ERROR_OPTION_ERROR Error = C.MPV_ERROR_OPTION_ERROR 51 | /** 52 | * The accessed property doesn't exist. 53 | */ 54 | ERROR_PROPERTY_NOT_FOUND Error = C.MPV_ERROR_PROPERTY_NOT_FOUND 55 | /** 56 | * Trying to set or get a property using an unsupported MPV_FORMAT. 57 | */ 58 | ERROR_PROPERTY_FORMAT Error = C.MPV_ERROR_PROPERTY_FORMAT 59 | /** 60 | * The property exists, but is not available. This usually happens when the 61 | * associated subsystem is not active, e.g. querying audio parameters while 62 | * audio is disabled. 63 | */ 64 | ERROR_PROPERTY_UNAVAILABLE Error = C.MPV_ERROR_PROPERTY_UNAVAILABLE 65 | /** 66 | * Error setting or getting a property. 67 | */ 68 | ERROR_PROPERTY_ERROR Error = C.MPV_ERROR_PROPERTY_ERROR 69 | /** 70 | * General error when running a command with mpv_command and similar. 71 | */ 72 | ERROR_COMMAND Error = C.MPV_ERROR_COMMAND 73 | /** 74 | * Generic error on loading (used with mpv_event_end_file.error). 75 | */ 76 | ERROR_LOADING_FAILED Error = C.MPV_ERROR_LOADING_FAILED 77 | /** 78 | * Initializing the audio output failed. 79 | */ 80 | ERROR_AO_INIT_FAILED Error = C.MPV_ERROR_AO_INIT_FAILED 81 | /** 82 | * Initializing the video output failed. 83 | */ 84 | ERROR_VO_INIT_FAILED Error = C.MPV_ERROR_VO_INIT_FAILED 85 | /** 86 | * There was no audio or video data to play. This also happens if the 87 | * file was recognized, but did not contain any audio or video streams, 88 | * or no streams were selected. 89 | */ 90 | ERROR_NOTHING_TO_PLAY Error = C.MPV_ERROR_NOTHING_TO_PLAY 91 | /** 92 | * When trying to load the file, the file format could not be determined, 93 | * or the file was too broken to open it. 94 | */ 95 | ERROR_UNKNOWN_FORMAT Error = C.MPV_ERROR_UNKNOWN_FORMAT 96 | /** 97 | * Generic error for signaling that certain system requirements are not 98 | * fulfilled. 99 | */ 100 | ERROR_UNSUPPORTED Error = C.MPV_ERROR_UNSUPPORTED 101 | /** 102 | * The API function which was called is a stub only. 103 | */ 104 | MPV_ERROR_NOT_IMPLEMENTED Error = C.MPV_ERROR_UNSUPPORTED 105 | ) 106 | 107 | type Format int 108 | 109 | //Format mpv_format 110 | const ( 111 | FORMAT_NONE Format = C.MPV_FORMAT_NONE 112 | /** 113 | * The basic type is char*. It returns the raw property string, like 114 | * using ${=property} in input.conf (see input.rst). 115 | * 116 | * NULL isn't an allowed value. 117 | * 118 | * Warning: although the encoding is usually UTF-8, this is not always the 119 | * case. File tags often store strings in some legacy codepage, 120 | * and even filenames don't necessarily have to be in UTF-8 (at 121 | * least on Linux). If you pass the strings to code that requires 122 | * valid UTF-8, you have to sanitize it in some way. 123 | * On Windows, filenames are always UTF-8, and libmpv converts 124 | * between UTF-8 and UTF-16 when using win32 API functions. See 125 | * the "Encoding of filenames" section for details. 126 | * 127 | * Example for reading: 128 | * 129 | * char *result = NULL; 130 | * if (mpv_get_property(ctx, "property", FORMAT_STRING, = C.MPV_FORMAT_STRING, 131 | * goto error; 132 | * printf("%s\n", result); 133 | * mpv_free(result); 134 | * 135 | * Or just use mpv_get_property_string(). 136 | * 137 | * Example for writing: 138 | * 139 | * char *value = "the new value"; 140 | * // yep, you pass the address to the variable 141 | * // (needed for symmetry with other types and mpv_get_property) 142 | * mpv_set_property(ctx, "property", FORMAT_STRING, = C.MPV_FORMAT_STRING, 143 | * 144 | * Or just use mpv_set_property_string(). 145 | * 146 | */ 147 | FORMAT_STRING Format = C.MPV_FORMAT_STRING 148 | /** 149 | * The basic type is char*. It returns the OSD property string, like 150 | * using ${property} in input.conf (see input.rst). In many cases, this 151 | * is the same as the raw string, but in other cases it's formatted for 152 | * display on OSD. It's intended to be human readable. Do not attempt to 153 | * parse these strings. 154 | * 155 | * Only valid when doing read access. The rest works like MPV_FORMAT_STRING. 156 | */ 157 | FORMAT_OSD_STRING Format = C.MPV_FORMAT_OSD_STRING 158 | /** 159 | * The basic type is int. The only allowed values are 0 ("no") 160 | * and 1 ("yes"). 161 | * 162 | * Example for reading: 163 | * 164 | * int result; 165 | * if (mpv_get_property(ctx, "property", FORMAT_FLAG, = C.MPV_FORMAT_FLAG, 166 | * goto error; 167 | * printf("%s\n", result ? "true" : "false"); 168 | * 169 | * Example for writing: 170 | * 171 | * int flag = 1; 172 | * mpv_set_property(ctx, "property", FORMAT_STRING, = C.MPV_FORMAT_STRING, 173 | */ 174 | FORMAT_FLAG Format = C.MPV_FORMAT_FLAG 175 | /** 176 | * The basic type is int64_t. 177 | */ 178 | FORMAT_INT64 Format = C.MPV_FORMAT_INT64 179 | /** 180 | * The basic type is double. 181 | */ 182 | FORMAT_DOUBLE Format = C.MPV_FORMAT_DOUBLE 183 | /** 184 | * The type is mpv_node. 185 | * 186 | * For reading, you usually would pass a pointer to a stack-allocated 187 | * mpv_node value to mpv, and when you're done you call 188 | * mpv_free_node_contents(&node). 189 | * You're expected not to write to the data - if you have to, copy it 190 | * first (which you have to do manually). 191 | * 192 | * For writing, you construct your own mpv_node, and pass a pointer to the 193 | * API. The API will never write to your data (and copy it if needed), so 194 | * you're free to use any form of allocation or memory management you like. 195 | * 196 | * Warning: when reading, always check the mpv_node.format member. For 197 | * example, properties might change their type in future versions 198 | * of mpv, or sometimes even during runtime. 199 | * 200 | * Example for reading: 201 | * 202 | * mpv_node result; 203 | * if (mpv_get_property(ctx, "property", FORMAT_NODE, = C.MPV_FORMAT_NODE, 204 | * goto error; 205 | * printf("format=%d\n", (int)result.format); 206 | * mpv_free_node_contents(&result). 207 | * 208 | * Example for writing: 209 | * 210 | * mpv_node value; 211 | * value.format = MPV_FORMAT_STRING; 212 | * value.u.string = "hello"; 213 | * mpv_set_property(ctx, "property", FORMAT_NODE, = C.MPV_FORMAT_NODE, 214 | */ 215 | FORMAT_NODE Format = C.MPV_FORMAT_NODE 216 | /** 217 | * Used with mpv_node only. Can usually not be used directly. 218 | */ 219 | FORMAT_NODE_ARRAY Format = C.MPV_FORMAT_NODE_ARRAY 220 | /** 221 | * See MPV_FORMAT_NODE_ARRAY. 222 | */ 223 | FORMAT_NODE_MAP Format = C.MPV_FORMAT_NODE_MAP 224 | /** 225 | * A raw, untyped byte array. Only used only with mpv_node, and only in 226 | * some very special situations. (Currently, only for the screenshot_raw 227 | * command.) 228 | */ 229 | FORMAT_BYTE_ARRAY = C.MPV_FORMAT_BYTE_ARRAY 230 | ) 231 | 232 | type EventId int 233 | 234 | //EventId mpv_event_id 235 | const ( 236 | /** 237 | * Nothing happened. Happens on timeouts or sporadic wakeups. 238 | */ 239 | EVENT_NONE EventId = C.MPV_EVENT_NONE 240 | /** 241 | * Happens when the player quits. The player enters a state where it tries 242 | * to disconnect all clients. Most requests to the player will fail, and 243 | * mpv_wait_event() will always return instantly (returning new shutdown 244 | * events if no other events are queued). The client should react to this 245 | * and quit with mpv_detach_destroy() as soon as possible. 246 | */ 247 | EVENT_SHUTDOWN EventId = C.MPV_EVENT_SHUTDOWN 248 | /** 249 | * See mpv_request_log_messages(). 250 | */ 251 | EVENT_LOG_MESSAGE EventId = C.MPV_EVENT_LOG_MESSAGE 252 | /** 253 | * Reply to a mpv_get_property_async() request. 254 | * See also mpv_event and mpv_event_property. 255 | */ 256 | EVENT_GET_PROPERTY_REPLY EventId = C.MPV_EVENT_GET_PROPERTY_REPLY 257 | /** 258 | * Reply to a mpv_set_property_async() request. 259 | * (Unlike EVENT_GET_PROPERTY, = C.MPV_EVENT_GET_PROPERTY, 260 | */ 261 | EVENT_SET_PROPERTY_REPLY EventId = C.MPV_EVENT_SET_PROPERTY_REPLY 262 | /** 263 | * Reply to a mpv_command_async() request. 264 | */ 265 | EVENT_COMMAND_REPLY EventId = C.MPV_EVENT_COMMAND_REPLY 266 | /** 267 | * Notification before playback start of a file (before the file is loaded). 268 | */ 269 | EVENT_START_FILE EventId = C.MPV_EVENT_START_FILE 270 | /** 271 | * Notification after playback end (after the file was unloaded). 272 | * See also mpv_event and mpv_event_end_file. 273 | */ 274 | EVENT_END_FILE EventId = C.MPV_EVENT_END_FILE 275 | /** 276 | * Notification when the file has been loaded (headers were read etc.), and 277 | * decoding starts. 278 | */ 279 | EVENT_FILE_LOADED EventId = C.MPV_EVENT_FILE_LOADED 280 | /** 281 | * The list of video/audio/subtitle tracks was changed. (E.g. a new track 282 | * was found. This doesn't necessarily indicate a track switch; for this, 283 | * EVENT_TRACK_SWITCHED = C.MPV_EVENT_TRACK_SWITCHED 284 | * 285 | * @deprecated This is equivalent to using mpv_observe_property() on the 286 | * "track-list" property. The event is redundant, and might 287 | * be removed in the far future. 288 | */ 289 | EVENT_TRACKS_CHANGED EventId = C.MPV_EVENT_TRACKS_CHANGED 290 | /** 291 | * A video/audio/subtitle track was switched on or off. 292 | * 293 | * @deprecated This is equivalent to using mpv_observe_property() on the 294 | * "vid", "aid", and "sid" properties. The event is redundant, 295 | * and might be removed in the far future. 296 | */ 297 | EVENT_TRACK_SWITCHED EventId = C.MPV_EVENT_TRACK_SWITCHED 298 | /** 299 | * Idle mode was entered. In this mode, no file is played, and the playback 300 | * core waits for new commands. (The command line player normally quits 301 | * instead of entering idle mode, unless --idle was specified. If mpv 302 | * was started with mpv_create(), idle mode is enabled by default.) 303 | */ 304 | EVENT_IDLE EventId = C.MPV_EVENT_IDLE 305 | /** 306 | * Playback was paused. This indicates the user pause state. 307 | * 308 | * The user pause state is the state the user requested (changed with the 309 | * "pause" property). There is an internal pause state too, which is entered 310 | * if e.g. the network is too slow (the "core-idle" property generally 311 | * indicates whether the core is playing or waiting). 312 | * 313 | * This event is sent whenever any pause states change, not only the user 314 | * state. You might get multiple events in a row while these states change 315 | * independently. But the event ID sent always indicates the user pause 316 | * state. 317 | * 318 | * If you don't want to deal with this, use mpv_observe_property() on the 319 | * "pause" property and ignore EVENT_PAUSE/UNPAUSE. = C.MPV_EVENT_PAUSE/UNPAUSE. 320 | * "core-idle" property tells you whether video is actually playing or not. 321 | * 322 | * @deprecated The event is redundant with mpv_observe_property() as 323 | * mentioned above, and might be removed in the far future. 324 | */ 325 | EVENT_PAUSE EventId = C.MPV_EVENT_PAUSE 326 | /** 327 | * Playback was unpaused. See EVENT_PAUSE = C.MPV_EVENT_PAUSE 328 | * 329 | * @deprecated The event is redundant with mpv_observe_property() as 330 | * explained in the EVENT_PAUSE = C.MPV_EVENT_PAUSE 331 | * removed in the far future. 332 | */ 333 | EVENT_UNPAUSE EventId = C.MPV_EVENT_UNPAUSE 334 | /** 335 | * Sent every time after a video frame is displayed. Note that currently, 336 | * this will be sent in lower frequency if there is no video, or playback 337 | * is paused - but that will be removed in the future, and it will be 338 | * restricted to video frames only. 339 | */ 340 | EVENT_TICK EventId = C.MPV_EVENT_TICK 341 | /** 342 | * @deprecated This was used internally with the internal "script_dispatch" 343 | * command to dispatch keyboard and mouse input for the OSC. 344 | * It was never useful in general and has been completely 345 | * replaced with "script_binding". 346 | * This event never happens anymore, and is included in this 347 | * header only for compatibility. 348 | */ 349 | EVENT_SCRIPT_INPUT_DISPATCH EventId = C.MPV_EVENT_SCRIPT_INPUT_DISPATCH 350 | /** 351 | * Triggered by the script_message input command. The command uses the 352 | * first argument of the command as client name (see mpv_client_name()) to 353 | * dispatch the message, and passes along all arguments starting from the 354 | * second argument as strings. 355 | * See also mpv_event and mpv_event_client_message. 356 | */ 357 | EVENT_CLIENT_MESSAGE EventId = C.MPV_EVENT_CLIENT_MESSAGE 358 | /** 359 | * Happens after video changed in some way. This can happen on resolution 360 | * changes, pixel format changes, or video filter changes. The event is 361 | * sent after the video filters and the VO are reconfigured. Applications 362 | * embedding a mpv window should listen to this event in order to resize 363 | * the window if needed. 364 | * Note that this event can happen sporadically, and you should check 365 | * yourself whether the video parameters really changed before doing 366 | * something expensive. 367 | */ 368 | EVENT_VIDEO_RECONFIG EventId = C.MPV_EVENT_VIDEO_RECONFIG 369 | /** 370 | * Similar to EVENT_VIDEO_RECONFIG. = C.MPV_EVENT_VIDEO_RECONFIG. 371 | * because there is no such thing as audio output embedding. 372 | */ 373 | EVENT_AUDIO_RECONFIG EventId = C.MPV_EVENT_AUDIO_RECONFIG 374 | /** 375 | * Happens when metadata (like file tags) is possibly updated. (It's left 376 | * unspecified whether this happens on file start or only when it changes 377 | * within a file.) 378 | * 379 | * @deprecated This is equivalent to using mpv_observe_property() on the 380 | * "metadata" property. The event is redundant, and might 381 | * be removed in the far future. 382 | */ 383 | EVENT_METADATA_UPDATE EventId = C.MPV_EVENT_METADATA_UPDATE 384 | /** 385 | * Happens when a seek was initiated. Playback stops. Usually it will 386 | * resume with EVENT_PLAYBACK_RESTART = C.MPV_EVENT_PLAYBACK_RESTART 387 | */ 388 | EVENT_SEEK EventId = C.MPV_EVENT_SEEK 389 | /** 390 | * There was a discontinuity of some sort (like a seek), and playback 391 | * was reinitialized. Usually happens after seeking, or ordered chapter 392 | * segment switches. The main purpose is allowing the client to detect 393 | * when a seek request is finished. 394 | */ 395 | EVENT_PLAYBACK_RESTART EventId = C.MPV_EVENT_PLAYBACK_RESTART 396 | /** 397 | * Event sent due to mpv_observe_property(). 398 | * See also mpv_event and mpv_event_property. 399 | */ 400 | EVENT_PROPERTY_CHANGE EventId = C.MPV_EVENT_PROPERTY_CHANGE 401 | /** 402 | * Happens when the current chapter changes. 403 | * 404 | * @deprecated This is equivalent to using mpv_observe_property() on the 405 | * "chapter" property. The event is redundant, and might 406 | * be removed in the far future. 407 | */ 408 | EVENT_CHAPTER_CHANGE EventId = C.MPV_EVENT_CHAPTER_CHANGE 409 | /** 410 | * Happens if the internal per-mpv_handle ringbuffer overflows, and at 411 | * least 1 event had to be dropped. This can happen if the client doesn't 412 | * read the event queue quickly enough with mpv_wait_event(), or if the 413 | * client makes a very large number of asynchronous calls at once. 414 | * 415 | * Event delivery will continue normally once this event was returned 416 | * (this forces the client to empty the queue completely). 417 | */ 418 | EVENT_QUEUE_OVERFLOW EventId = C.MPV_EVENT_QUEUE_OVERFLOW 419 | // Internal note: adjust INTERNAL_EVENT_BASE when adding new events. 420 | ) 421 | 422 | func (eid EventId) String() string { 423 | switch eid { 424 | case EVENT_NONE: 425 | { 426 | return "EVENT_NONE" 427 | } 428 | case EVENT_SHUTDOWN: 429 | { 430 | return "EVENT_SHUTDOWN" 431 | } 432 | case EVENT_LOG_MESSAGE: 433 | { 434 | return "EVENT_LOG_MESSAGE" 435 | } 436 | case EVENT_GET_PROPERTY_REPLY: 437 | { 438 | return "EVENT_GET_PROPERTY_REPLY" 439 | } 440 | case EVENT_SET_PROPERTY_REPLY: 441 | { 442 | return "EVENT_SET_PROPERTY_REPLY" 443 | } 444 | case EVENT_COMMAND_REPLY: 445 | { 446 | return "EVENT_COMMAND_REPLY" 447 | } 448 | case EVENT_START_FILE: 449 | { 450 | return "EVENT_START_FILE" 451 | } 452 | case EVENT_END_FILE: 453 | { 454 | return "EVENT_END_FILE" 455 | } 456 | case EVENT_FILE_LOADED: 457 | { 458 | return "EVENT_FILE_LOADED" 459 | } 460 | case EVENT_TRACKS_CHANGED: 461 | { 462 | return "EVENT_TRACKS_CHANGED" 463 | } 464 | case EVENT_TRACK_SWITCHED: 465 | { 466 | return "EVENT_TRACK_SWITCHED" 467 | } 468 | case EVENT_IDLE: 469 | { 470 | return "EVENT_IDLE" 471 | } 472 | case EVENT_PAUSE: 473 | { 474 | return "EVENT_PAUSE" 475 | } 476 | case EVENT_UNPAUSE: 477 | { 478 | return "EVENT_UNPAUSE" 479 | } 480 | case EVENT_TICK: 481 | { 482 | return "EVENT_TICK" 483 | } 484 | case EVENT_SCRIPT_INPUT_DISPATCH: 485 | { 486 | return "EVENT_SCRIPT_INPUT_DISPATCH" 487 | } 488 | case EVENT_CLIENT_MESSAGE: 489 | { 490 | return "EVENT_CLIENT_MESSAGE" 491 | } 492 | case EVENT_VIDEO_RECONFIG: 493 | { 494 | return "EVENT_VIDEO_RECONFIG" 495 | } 496 | case EVENT_AUDIO_RECONFIG: 497 | { 498 | return "EVENT_AUDIO_RECONFIG" 499 | } 500 | case EVENT_METADATA_UPDATE: 501 | { 502 | return "EVENT_METADATA_UPDATE" 503 | } 504 | case EVENT_SEEK: 505 | { 506 | return "EVENT_SEEK" 507 | } 508 | case EVENT_PLAYBACK_RESTART: 509 | { 510 | return "EVENT_PLAYBACK_RESTART" 511 | } 512 | case EVENT_PROPERTY_CHANGE: 513 | { 514 | return "EVENT_PROPERTY_CHANGE" 515 | } 516 | case EVENT_CHAPTER_CHANGE: 517 | { 518 | return "EVENT_CHAPTER_CHANGE" 519 | } 520 | case EVENT_QUEUE_OVERFLOW: 521 | { 522 | return "EVENT_QUEUE_OVERFLOW" 523 | } 524 | } 525 | return "UNKNOWN_EVENT" 526 | } 527 | 528 | //Log level mpv_log_level 529 | const ( 530 | LOG_LEVEL_NONE = C.MPV_LOG_LEVEL_NONE /// "no" - disable absolutely all messages 531 | LOG_LEVEL_FATAL = C.MPV_LOG_LEVEL_FATAL /// "fatal" - critical/aborting errors 532 | LOG_LEVEL_ERROR = C.MPV_LOG_LEVEL_ERROR /// "error" - simple errors 533 | LOG_LEVEL_WARN = C.MPV_LOG_LEVEL_WARN /// "warn" - possible problems 534 | LOG_LEVEL_INFO = C.MPV_LOG_LEVEL_INFO /// "info" - informational message 535 | LOG_LEVEL_V = C.MPV_LOG_LEVEL_V /// "v" - noisy informational message 536 | LOG_LEVEL_DEBUG = C.MPV_LOG_LEVEL_DEBUG /// "debug" - very noisy technical information 537 | LOG_LEVEL_TRACE = C.MPV_LOG_LEVEL_TRACE /// "trace" - extremely noisy 538 | ) 539 | 540 | type EndFileReason int 541 | 542 | //EndFileReason mpv_end_file_reason 543 | const ( 544 | /** 545 | * The end of file was reached. Sometimes this may also happen on 546 | * incomplete or corrupted files, or if the network connection was 547 | * interrupted when playing a remote file. It also happens if the 548 | * playback range was restricted with --end or --frames or similar. 549 | */ 550 | END_FILE_REASON_EOF EndFileReason = C.MPV_END_FILE_REASON_EOF 551 | /** 552 | * Playback was stopped by an external action (e.g. playlist controls). 553 | */ 554 | END_FILE_REASON_STOP EndFileReason = C.MPV_END_FILE_REASON_STOP 555 | /** 556 | * Playback was stopped by the quit command or player shutdown. 557 | */ 558 | END_FILE_REASON_QUIT EndFileReason = C.MPV_END_FILE_REASON_QUIT 559 | /** 560 | * Some kind of error happened that lead to playback abort. Does not 561 | * necessarily happen on incomplete or broken files (in these cases, both 562 | * MPV_END_FILE_REASON_ERROR or MPV_END_FILE_REASON_EOF are possible). 563 | * 564 | * mpv_event_end_file.error will be set. 565 | */ 566 | END_FILE_REASON_ERROR EndFileReason = C.MPV_END_FILE_REASON_ERROR 567 | /** 568 | * The file was a playlist or similar. When the playlist is read, its 569 | * entries will be appended to the playlist after the entry of the current 570 | * file, the entry of the current file is removed, and a MPV_EVENT_END_FILE 571 | * event is sent with reason set to MPV_END_FILE_REASON_REDIRECT. Then 572 | * playback continues with the playlist contents. 573 | * Since API version 1.18. 574 | */ 575 | END_FILE_REASON_REDIRECT EndFileReason = C.MPV_END_FILE_REASON_REDIRECT 576 | ) 577 | 578 | func (efr EndFileReason) String() string { 579 | switch efr { 580 | case END_FILE_REASON_EOF: 581 | return "END_FILE_REASON_EOF" 582 | case END_FILE_REASON_STOP: 583 | return "END_FILE_REASON_STOP" 584 | case END_FILE_REASON_QUIT: 585 | return "END_FILE_REASON_QUIT" 586 | case END_FILE_REASON_ERROR: 587 | return "END_FILE_REASON_ERROR" 588 | case END_FILE_REASON_REDIRECT: 589 | return "END_FILE_REASON_REDIRECT" 590 | default: 591 | return "END_FILE_REASON_UNKNOWN" 592 | } 593 | } 594 | 595 | type SubApi int 596 | 597 | //mpv_sub_api 598 | const ( 599 | /** 600 | * For using mpv's OpenGL renderer on an external OpenGL context. 601 | * mpv_get_sub_api(MPV_SUB_API_OPENGL_CB) returns mpv_opengl_cb_context*. 602 | * This context can be used with mpv_opengl_cb_* functions. 603 | * Will return NULL if unavailable (if OpenGL support was not compiled in). 604 | * See opengl_cb.h for details. 605 | */ 606 | SUB_API_OPENGL_CB SubApi = C.MPV_SUB_API_OPENGL_CB 607 | ) 608 | -------------------------------------------------------------------------------- /mpv/error.go: -------------------------------------------------------------------------------- 1 | package mpv 2 | 3 | //#include 4 | import "C" 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | type Error int 11 | 12 | //const char *mpv_error_string(int error); 13 | func NewError(errcode C.int) error { 14 | if errcode == C.MPV_ERROR_SUCCESS { 15 | return nil 16 | } 17 | return Error(errcode) 18 | } 19 | 20 | func (m Error) Error() string { 21 | return fmt.Sprintln(int(m), C.GoString(C.mpv_error_string(C.int(m)))) 22 | } 23 | -------------------------------------------------------------------------------- /mpv/mpv.go: -------------------------------------------------------------------------------- 1 | package mpv 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #cgo LDFLAGS: -lmpv 8 | 9 | char** makeCharArray1(int size) { 10 | return calloc(sizeof(char*), size); 11 | } 12 | void setArrayString1(char** a, int i, char* s) { 13 | a[i] = s; 14 | } 15 | 16 | */ 17 | import "C" 18 | 19 | import ( 20 | "unsafe" 21 | ) 22 | 23 | type Mpv struct { 24 | handle *C.mpv_handle 25 | wakeup_callbackVar interface{} 26 | wakeup_callbackFunc func(d interface{}) 27 | } 28 | 29 | func Create() *Mpv { 30 | ctx := C.mpv_create() 31 | if ctx == nil { 32 | return nil 33 | } 34 | return &Mpv{ctx, nil, nil} 35 | } 36 | 37 | func (m *Mpv) ClientName() string { 38 | return C.GoString(C.mpv_client_name(m.handle)) 39 | } 40 | 41 | func (m *Mpv) Initialize() error { 42 | return NewError(C.mpv_initialize(m.handle)) 43 | } 44 | 45 | func (m *Mpv) DetachDestroy() { 46 | C.mpv_detach_destroy(m.handle) 47 | } 48 | 49 | func (m *Mpv) TerminateDestroy() { 50 | C.mpv_terminate_destroy(m.handle) 51 | } 52 | 53 | func (m *Mpv) CreateClient(name string) *Mpv { 54 | cname := C.CString(name) 55 | defer C.free(unsafe.Pointer(cname)) 56 | cmpv := C.mpv_create_client(m.handle, cname) 57 | if cmpv != nil { 58 | return &Mpv{cmpv, nil, nil} 59 | } 60 | return nil 61 | } 62 | 63 | func (m *Mpv) LoadConfigFile(fileName string) error { 64 | cfn := C.CString(fileName) 65 | defer C.free(unsafe.Pointer(cfn)) 66 | return NewError(C.mpv_load_config_file(m.handle, cfn)) 67 | } 68 | 69 | func (m *Mpv) Suspend() { 70 | C.mpv_suspend(m.handle) 71 | } 72 | 73 | func (m *Mpv) Resume() { 74 | C.mpv_resume(m.handle) 75 | } 76 | 77 | func (m *Mpv) GetTimeUS() int64 { 78 | return int64(C.mpv_get_time_us(m.handle)) 79 | } 80 | 81 | func (m *Mpv) SetOption(name string, format Format, data interface{}) error { 82 | cname := C.CString(name) 83 | defer C.free(unsafe.Pointer(cname)) 84 | ptr := data2Ptr(format, data) 85 | return NewError(C.mpv_set_option(m.handle, cname, C.mpv_format(format), ptr)) 86 | } 87 | 88 | func (m *Mpv) SetOptionString(name, data string) error { 89 | cname := C.CString(name) 90 | cdata := C.CString(data) 91 | defer C.free(unsafe.Pointer(cname)) 92 | defer C.free(unsafe.Pointer(cdata)) 93 | return NewError(C.mpv_set_option_string(m.handle, cname, cdata)) 94 | } 95 | 96 | func (m *Mpv) Command(command []string) error { 97 | cArray := C.makeCharArray1(C.int(len(command) + 1)) 98 | if cArray == nil { 99 | panic("got NULL from calloc") 100 | } 101 | defer C.free(unsafe.Pointer(cArray)) 102 | 103 | for i, s := range command { 104 | cStr := C.CString(s) 105 | C.setArrayString1(cArray, C.int(i), cStr) 106 | defer C.free(unsafe.Pointer(cStr)) 107 | } 108 | 109 | return NewError(C.mpv_command(m.handle, cArray)) 110 | } 111 | 112 | func (m *Mpv) CommandNode(command []string) int { 113 | //int mpv_command_node(mpv_handle *ctx, mpv_node *args, mpv_node *result); 114 | //TODO 115 | panic("Not supported command") 116 | return -1 117 | } 118 | 119 | func (m *Mpv) CommandString(command string) error { 120 | ccmd := C.CString(command) 121 | defer C.free(unsafe.Pointer(ccmd)) 122 | return NewError(C.mpv_command_string(m.handle, ccmd)) 123 | } 124 | 125 | func (m *Mpv) CommandAsync(replyUserdata uint64, command []string) error { 126 | cArray := C.makeCharArray1(C.int(len(command) + 1)) 127 | if cArray == nil { 128 | panic("got NULL from calloc") 129 | } 130 | defer C.free(unsafe.Pointer(cArray)) 131 | 132 | for i, s := range command { 133 | cStr := C.CString(s) 134 | C.setArrayString1(cArray, C.int(i), cStr) 135 | defer C.free(unsafe.Pointer(cStr)) 136 | } 137 | 138 | return NewError(C.mpv_command_async(m.handle, C.uint64_t(replyUserdata), cArray)) 139 | } 140 | 141 | func (m *Mpv) CommandNodeAsync(command []string) int { 142 | //int mpv_command_node_async(mpv_handle *ctx, uint64_t reply_userdata, mpv_node *args); 143 | //TODO 144 | panic("Not supported command") 145 | return -1 146 | } 147 | 148 | func (m *Mpv) SetProperty(name string, format Format, data interface{}) error { 149 | cname := C.CString(name) 150 | defer C.free(unsafe.Pointer(cname)) 151 | ptr := data2Ptr(format, data) 152 | return NewError(C.mpv_set_property(m.handle, cname, C.mpv_format(format), ptr)) 153 | } 154 | 155 | func (m *Mpv) SetPropertyString(name, data string) error { 156 | cname := C.CString(name) 157 | cdata := C.CString(data) 158 | defer C.free(unsafe.Pointer(cname)) 159 | defer C.free(unsafe.Pointer(cdata)) 160 | return NewError(C.mpv_set_property_string(m.handle, cname, cdata)) 161 | } 162 | 163 | func (m *Mpv) SetPropertyAsync(name string, replyUserdata uint64, format Format, data interface{}) error { 164 | cname := C.CString(name) 165 | defer C.free(unsafe.Pointer(cname)) 166 | ptr := data2Ptr(format, data) 167 | return NewError(C.mpv_set_property_async(m.handle, C.uint64_t(replyUserdata), cname, C.mpv_format(format), ptr)) 168 | } 169 | 170 | func (m *Mpv) GetProperty(name string, format Format) (interface{}, error) { 171 | cname := C.CString(name) 172 | defer C.free(unsafe.Pointer(cname)) 173 | 174 | switch format { 175 | case FORMAT_STRING, FORMAT_OSD_STRING: 176 | { 177 | var cval *C.char 178 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval))) 179 | if err != nil { 180 | return nil, err 181 | } 182 | defer C.mpv_free(unsafe.Pointer(cval)) 183 | return C.GoString(cval), nil 184 | } 185 | case FORMAT_INT64: 186 | { 187 | var cval C.int64_t 188 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval))) 189 | if err != nil { 190 | return nil, err 191 | } 192 | return int64(cval), nil 193 | } 194 | case FORMAT_DOUBLE: 195 | { 196 | var cval C.double 197 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval))) 198 | if err != nil { 199 | return nil, err 200 | } 201 | return float64(cval), nil 202 | } 203 | case FORMAT_FLAG: 204 | { 205 | var cval C.int 206 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval))) 207 | if err != nil { 208 | return nil, err 209 | } 210 | return cval == 1, nil 211 | } 212 | case FORMAT_NONE: 213 | { 214 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), nil)) 215 | if err != nil { 216 | return nil, err 217 | } 218 | return nil, nil 219 | } 220 | case FORMAT_NODE: 221 | { 222 | var cval C.mpv_node 223 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval))) 224 | if err != nil { 225 | return nil, err 226 | } 227 | return GetNode(&cval) 228 | } 229 | case FORMAT_NODE_ARRAY: 230 | { 231 | var cval C.mpv_node_list 232 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval))) 233 | if err != nil { 234 | return nil, err 235 | } 236 | return GetNodeList(&cval) 237 | } 238 | case FORMAT_NODE_MAP: 239 | { 240 | var cval C.mpv_node_list 241 | err := NewError(C.mpv_get_property(m.handle, cname, C.mpv_format(format), unsafe.Pointer(&cval))) 242 | if err != nil { 243 | return nil, err 244 | } 245 | return GetNodeMap(cval) 246 | } 247 | default: 248 | panic("Not supported format") 249 | } 250 | } 251 | 252 | func (m *Mpv) GetPropertyString(name string) string { 253 | cname := C.CString(name) 254 | defer C.free(unsafe.Pointer(cname)) 255 | 256 | cstr := C.mpv_get_property_string(m.handle, cname) 257 | if cstr != nil { 258 | str := C.GoString(cstr) 259 | C.mpv_free(unsafe.Pointer(cstr)) 260 | return str 261 | } 262 | 263 | return "" 264 | } 265 | 266 | func (m *Mpv) GetPropertyOsdString(name string) string { 267 | cname := C.CString(name) 268 | defer C.free(unsafe.Pointer(cname)) 269 | cstr := C.mpv_get_property_osd_string(m.handle, cname) 270 | if cstr != nil { 271 | str := C.GoString(cstr) 272 | C.mpv_free(unsafe.Pointer(cstr)) 273 | return str 274 | } 275 | 276 | return "" 277 | } 278 | 279 | func (m *Mpv) GetPropertyAsync(name string, replyUserdata uint64, format Format) error { 280 | cname := C.CString(name) 281 | defer C.free(unsafe.Pointer(cname)) 282 | 283 | return NewError(C.mpv_get_property_async(m.handle, C.uint64_t(replyUserdata), cname, C.mpv_format(format))) 284 | } 285 | 286 | func (m *Mpv) ObserveProperty(replyUserdata uint64, name string, format Format) error { 287 | cname := C.CString(name) 288 | defer C.free(unsafe.Pointer(cname)) 289 | return NewError(C.mpv_observe_property(m.handle, C.uint64_t(replyUserdata), cname, C.mpv_format(format))) 290 | } 291 | 292 | func (m *Mpv) UnObserveProperty(registeredReplyUserdata uint64) error { 293 | return NewError(C.mpv_unobserve_property(m.handle, C.uint64_t(registeredReplyUserdata))) 294 | } 295 | 296 | func (m *Mpv) RequestEvent(event EventId, enable bool) error { 297 | var en C.int = 0 298 | if enable { 299 | en = 1 300 | } 301 | return NewError(C.mpv_request_event(m.handle, C.mpv_event_id(event), en)) 302 | } 303 | 304 | func (m *Mpv) RequestLogMessages(minLevel string) error { 305 | clevel := C.CString(minLevel) 306 | defer C.free(unsafe.Pointer(clevel)) 307 | return NewError(C.mpv_request_log_messages(m.handle, clevel)) 308 | } 309 | 310 | func (m *Mpv) WaitEvent(timeout float32) *Event { 311 | var cevent *C.mpv_event 312 | cevent = C.mpv_wait_event(m.handle, C.double(timeout)) 313 | if cevent == nil { 314 | return nil 315 | } 316 | 317 | e := &Event{} 318 | 319 | e.Event_Id = EventId(cevent.event_id) 320 | e.Reply_Userdata = uint64(cevent.reply_userdata) 321 | e.Error = NewError(cevent.error) 322 | if e.Event_Id == EVENT_END_FILE { 323 | var eef *C.mpv_event_end_file = (*C.struct_mpv_event_end_file)(cevent.data) 324 | efr := EventEndFile{} 325 | efr.Reason = EndFileReason(eef.reason) 326 | efr.ErrCode = Error(eef.error) 327 | e.Data = efr 328 | } else { 329 | e.Data = cevent.data 330 | } 331 | return e 332 | } 333 | 334 | func (m *Mpv) Wakeup() { 335 | C.mpv_wakeup(m.handle) 336 | } 337 | 338 | func (m *Mpv) SetWakeupCallback(callback func(d interface{}), d interface{}) { 339 | /*callbackFunc = callback 340 | callbackVar = d*/ 341 | // C.mpv_set_wakeup_callback(m.handle,,unsafe.Pointer(d)) 342 | //TODO void mpv_set_wakeup_callback(mpv_handle *ctx, void (*cb)(void *d), void *d); 343 | panic("Not supported mpv_set_wakeup_callback") 344 | } 345 | 346 | func (m *Mpv) GetWakeupPipe() int { 347 | return int(C.mpv_get_wakeup_pipe(m.handle)) 348 | } 349 | 350 | func (m *Mpv) WaitAsyncRequests() { 351 | C.mpv_wait_async_requests(m.handle) 352 | } 353 | 354 | func (m *Mpv) GetSubApi(api SubApi) unsafe.Pointer { 355 | return unsafe.Pointer(C.mpv_get_sub_api(m.handle, C.mpv_sub_api(api))) 356 | } 357 | 358 | func (m *Mpv) GetSubApiGL() *MpvGL { 359 | mgl := &MpvGL{} 360 | mgl.ctx = (*C.mpv_opengl_cb_context)(C.mpv_get_sub_api(m.handle, C.MPV_SUB_API_OPENGL_CB)) 361 | if mgl.ctx == nil { 362 | return nil 363 | } 364 | return mgl 365 | } 366 | 367 | func data2Ptr(format Format, data interface{}) unsafe.Pointer { 368 | var ptr unsafe.Pointer = nil 369 | switch format { 370 | case FORMAT_STRING, FORMAT_OSD_STRING: 371 | { 372 | ptr = unsafe.Pointer(&[]byte(data.(string))[0]) 373 | } 374 | case FORMAT_INT64: 375 | { 376 | i, ok := data.(int64) 377 | if !ok { 378 | i = int64(data.(int)) 379 | } 380 | val := C.int64_t(i) 381 | ptr = unsafe.Pointer(&val) 382 | } 383 | case FORMAT_DOUBLE: 384 | { 385 | val := C.double(data.(float64)) 386 | ptr = unsafe.Pointer(&val) 387 | } 388 | case FORMAT_FLAG: 389 | { 390 | val := C.int(0) 391 | if data.(bool) { 392 | val = 1 393 | } 394 | ptr = unsafe.Pointer(&val) 395 | } 396 | case FORMAT_NONE: 397 | { 398 | return nil 399 | } 400 | 401 | case FORMAT_NODE: 402 | { 403 | val := (data.(*Node)) 404 | cnode := val.GetCNode() 405 | ptr = unsafe.Pointer(cnode) 406 | } 407 | 408 | case FORMAT_NODE_ARRAY, FORMAT_NODE_MAP: 409 | { 410 | return nil 411 | } 412 | } 413 | return ptr 414 | } 415 | 416 | type Event struct { 417 | Event_Id EventId 418 | Error error 419 | Reply_Userdata uint64 420 | Data interface{} 421 | } 422 | 423 | type EventEndFile struct { 424 | Reason EndFileReason 425 | ErrCode Error 426 | } 427 | -------------------------------------------------------------------------------- /mpv/mpvgl.go: -------------------------------------------------------------------------------- 1 | package mpv 2 | 3 | /* 4 | #include 5 | extern void* getProcAddr(void*fn_ctx,char* text); 6 | 7 | */ 8 | import "C" 9 | 10 | import ( 11 | "unsafe" 12 | ) 13 | 14 | type MpvGL struct { 15 | ctx *C.mpv_opengl_cb_context 16 | } 17 | 18 | type get_proc_addr func(string) unsafe.Pointer 19 | 20 | var callback_get_proc_address_fn get_proc_addr 21 | 22 | //export getProcAddr 23 | func getProcAddr(fn_ctx unsafe.Pointer, name *C.char) unsafe.Pointer { 24 | if callback_get_proc_address_fn != nil { 25 | return callback_get_proc_address_fn(C.GoString(name)) 26 | } 27 | return nil 28 | } 29 | 30 | func (mgl *MpvGL) InitGL() error { 31 | callback_get_proc_address_fn = getProcAddress 32 | return NewError(C.mpv_opengl_cb_init_gl(mgl.ctx, 33 | nil, 34 | (*[0]byte)(C.getProcAddr), 35 | nil)) 36 | } 37 | 38 | func (mgl *MpvGL) Draw(fbo, width, height int) int { 39 | return int(C.mpv_opengl_cb_draw(mgl.ctx, C.int(fbo), C.int(width), C.int(-height))) 40 | } 41 | 42 | //@deprecated 43 | func (mgl *MpvGL) Render(fbo int, vp []int) int { 44 | return int(C.mpv_opengl_cb_render(mgl.ctx, C.int(fbo), (*C.int)(unsafe.Pointer(&vp[0])))) 45 | } 46 | 47 | func (mgl *MpvGL) ReportFlip(time int64) error { 48 | return NewError(C.mpv_opengl_cb_report_flip(mgl.ctx, C.int64_t(time))) 49 | } 50 | 51 | func (mgl *MpvGL) UninitGL() error { 52 | return NewError(C.mpv_opengl_cb_uninit_gl(mgl.ctx)) 53 | } 54 | -------------------------------------------------------------------------------- /mpv/node.go: -------------------------------------------------------------------------------- 1 | package mpv 2 | 3 | /* 4 | #include 5 | 6 | struct mpv_node* GetNodeFromList(struct mpv_node* list,int i){ 7 | return &list[i]; 8 | } 9 | 10 | char* GetString(char** strings,int i){ 11 | return strings[i]; 12 | } 13 | 14 | */ 15 | import "C" 16 | import ( 17 | "bytes" 18 | "encoding/binary" 19 | "log" 20 | "unsafe" 21 | ) 22 | 23 | type Node struct { 24 | value interface{} 25 | format Format 26 | } 27 | 28 | func NewNode(value interface{}, format Format) *Node { 29 | n := &Node{} 30 | n.value = value 31 | n.format = format 32 | return n 33 | } 34 | 35 | func (n *Node) GetVal() interface{} { 36 | return n.value 37 | } 38 | 39 | func (n *Node) GetCNode() *C.mpv_node { 40 | ptr := data2Ptr(n.format, n.value) 41 | if ptr == nil { 42 | return nil 43 | } 44 | writer := new(bytes.Buffer) 45 | err := binary.Write(writer, binary.LittleEndian, uint64(uintptr(ptr))) 46 | if err != nil { 47 | log.Println("Error write bin", err) 48 | return nil 49 | } 50 | buf := writer.Bytes() 51 | node := &C.mpv_node{} 52 | for i := 0; i < len(buf) && i < 8; i++ { 53 | node.u[i] = buf[i] 54 | } 55 | node.format = C.mpv_format(n.format) 56 | return node 57 | } 58 | 59 | func GetNode(node *C.mpv_node) (*Node, error) { 60 | n := &Node{} 61 | var err error 62 | n.value, err = GetValue(node) 63 | n.format = Format(node.format) 64 | return n, err 65 | } 66 | 67 | func FreeMpvNode(cnode *C.mpv_node) { 68 | C.mpv_free_node_contents(cnode) 69 | } 70 | 71 | func GetValue(node *C.mpv_node) (interface{}, error) { 72 | format := Format(node.format) 73 | buf := bytes.NewReader(C.GoBytes(unsafe.Pointer(&node.u[0]), 8)) 74 | var ptr uint64 75 | err := binary.Read(buf, binary.LittleEndian, &ptr) 76 | if err != nil { 77 | log.Println("Error binary read", err) 78 | return nil, err 79 | } 80 | switch format { 81 | case FORMAT_STRING: 82 | { 83 | var ret *C.char 84 | ret = (*C.char)((unsafe.Pointer)(uintptr(ptr))) 85 | return C.GoString(ret), nil 86 | } 87 | case FORMAT_FLAG: 88 | { 89 | var ret bool 90 | ret = *(*C.int)((unsafe.Pointer)(uintptr(ptr))) != 0 91 | return ret, nil 92 | } 93 | case FORMAT_INT64: 94 | { 95 | var ret C.int64_t 96 | ret = *(*C.int64_t)((unsafe.Pointer)(uintptr(ptr))) 97 | return int64(ret), nil 98 | } 99 | case FORMAT_DOUBLE: 100 | { 101 | var ret C.double 102 | ret = *(*C.double)((unsafe.Pointer)(uintptr(ptr))) 103 | return float64(ret), nil 104 | } 105 | case FORMAT_NODE: 106 | { 107 | var ret C.mpv_node 108 | ret = *(*C.mpv_node)((unsafe.Pointer)(uintptr(ptr))) 109 | return GetNode(&ret) 110 | } 111 | case FORMAT_NODE_ARRAY: 112 | { 113 | var ret C.mpv_node_list 114 | ret = *(*C.mpv_node_list)((unsafe.Pointer)(uintptr(ptr))) 115 | return GetNodeList(&ret) 116 | } 117 | case FORMAT_NODE_MAP: 118 | { 119 | var ret C.mpv_node_list 120 | ret = *(*C.mpv_node_list)((unsafe.Pointer)(uintptr(ptr))) 121 | return GetNodeMap(ret) 122 | } 123 | case FORMAT_BYTE_ARRAY: 124 | { 125 | var ret C.mpv_byte_array 126 | ret = *(*C.mpv_byte_array)((unsafe.Pointer)(uintptr(ptr))) 127 | return C.GoBytes(ret.data, C.int(ret.size)), nil 128 | } 129 | default: 130 | { 131 | return nil, nil 132 | } 133 | } 134 | } 135 | 136 | func GetNodeList(clist *C.mpv_node_list) ([]*Node, error) { 137 | nodes := make([]*Node, clist.num) 138 | var err error 139 | var n C.int 140 | for n = 0; n < clist.num; n++ { 141 | nodes[n], err = GetNode(C.GetNodeFromList(clist.values, n)) 142 | if err != nil { 143 | return nil, err 144 | } 145 | } 146 | return nodes, nil 147 | } 148 | 149 | func GetCNodeList(list []*Node) *C.mpv_node_list { 150 | /*if len(list) <= 0 { 151 | return nil 152 | } 153 | cnlist := &C.mpv_node_list{} 154 | cnlist.num = C.int(len(list)) 155 | carr := unsafe.NewArray(C.mpv_node, len(list)) 156 | for i, n := range list { 157 | carr[i] = *n.GetCNode() 158 | }*/ 159 | return nil 160 | } 161 | 162 | func GetNodeMap(cmap C.mpv_node_list) (map[string]*Node, error) { 163 | nodes, err := GetNodeList(&cmap) 164 | if err != nil { 165 | return nil, err 166 | } 167 | var mapnode map[string]*Node 168 | for i, n := range nodes { 169 | mapnode[C.GoString(C.GetString(cmap.keys, C.int(i)))] = n 170 | } 171 | return mapnode, nil 172 | } 173 | -------------------------------------------------------------------------------- /mpv/node_test.go: -------------------------------------------------------------------------------- 1 | package mpv 2 | 3 | import ( 4 | "log" 5 | "testing" 6 | ) 7 | 8 | func TestNode(t *testing.T) { 9 | { 10 | val := "123456789" 11 | format := FORMAT_STRING 12 | node := NewNode(val, format) 13 | cnode := node.GetCNode() 14 | node, err := GetNode(cnode) 15 | log.Println("CNode:", cnode, "Node val:", node.GetVal().(string), "Error:", err) 16 | if cnode == nil { 17 | log.Fatal("Fail node convert string") 18 | } 19 | } 20 | { 21 | val := int64(0x7FFFFFFFFFFFFFFF) 22 | format := FORMAT_INT64 23 | node := NewNode(val, format) 24 | cnode := node.GetCNode() 25 | node, err := GetNode(cnode) 26 | log.Println("CNode:", cnode, "Node val:", node.GetVal(), "Error:", err) 27 | if cnode == nil { 28 | log.Fatal("Fail node convert int64") 29 | } 30 | } 31 | { 32 | val := bool(true) 33 | format := FORMAT_FLAG 34 | node := NewNode(val, format) 35 | cnode := node.GetCNode() 36 | node, err := GetNode(cnode) 37 | log.Println("CNode:", cnode, "Node val:", node.GetVal(), "Error:", err) 38 | if cnode == nil { 39 | log.Fatal("Fail node convert int64") 40 | } 41 | } 42 | 43 | { 44 | val := float64(1.7976931348623157E+308) 45 | format := FORMAT_DOUBLE 46 | node := NewNode(val, format) 47 | cnode := node.GetCNode() 48 | node, err := GetNode(cnode) 49 | log.Println("CNode:", cnode, "Node val:", node.GetVal(), "Error:", err) 50 | if cnode == nil { 51 | log.Fatal("Fail node convert int64") 52 | } 53 | } 54 | 55 | { 56 | val := NewNode(123, FORMAT_INT64) 57 | format := FORMAT_NODE 58 | node := NewNode(val, format) 59 | cnode := node.GetCNode() 60 | node, err := GetNode(cnode) 61 | log.Println("CNode:", cnode, "Node val:", node.GetVal(), "Error:", err) 62 | if cnode == nil { 63 | log.Fatal("Fail node convert int64") 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /mpv/procaddr.go: -------------------------------------------------------------------------------- 1 | package mpv 2 | 3 | //From go-gl 4 | 5 | /* 6 | #cgo windows CFLAGS: -DTAG_WINDOWS 7 | #cgo windows LDFLAGS: -lopengl32 8 | #cgo darwin CFLAGS: -DTAG_DARWIN 9 | #cgo darwin LDFLAGS: -framework OpenGL 10 | #cgo linux CFLAGS: -DTAG_LINUX 11 | #cgo linux LDFLAGS: -lGL 12 | #cgo egl CFLAGS: -DTAG_EGL 13 | #cgo egl LDFLAGS: -lEGL 14 | // Check the EGL tag first as it takes priority over the platform's default 15 | // configuration of WGL/GLX/CGL. 16 | #if defined(TAG_EGL) 17 | #include 18 | #include 19 | void* glGetProcAddress(const char* name) { 20 | return eglGetProcAddress(name); 21 | } 22 | #elif defined(TAG_WINDOWS) 23 | #define WIN32_LEAN_AND_MEAN 1 24 | #include 25 | #include 26 | static HMODULE ogl32dll = NULL; 27 | void* glGetProcAddress(const char* name) { 28 | void* pf = wglGetProcAddress((LPCSTR) name); 29 | if (pf) { 30 | return pf; 31 | } 32 | if (ogl32dll == NULL) { 33 | ogl32dll = LoadLibraryA("opengl32.dll"); 34 | } 35 | return GetProcAddress(ogl32dll, (LPCSTR) name); 36 | } 37 | #elif defined(TAG_DARWIN) 38 | #include 39 | #include 40 | void* glGetProcAddress(const char* name) { 41 | return dlsym(RTLD_DEFAULT, name); 42 | } 43 | #elif defined(TAG_LINUX) 44 | #include 45 | #include 46 | void* glGetProcAddress(const char* name) { 47 | return glXGetProcAddress(name); 48 | } 49 | #endif 50 | */ 51 | import "C" 52 | import "unsafe" 53 | 54 | func getProcAddress(namea string) unsafe.Pointer { 55 | cname := C.CString(namea) 56 | defer C.free(unsafe.Pointer(cname)) 57 | return C.glGetProcAddress(cname) 58 | } 59 | --------------------------------------------------------------------------------